mimi-db 0.2.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67ce0ef4ee1bf56935424d8d4ea78fb43a1b502b
4
- data.tar.gz: bfca6acb463411916d0199a8c7cae5b657b792db
3
+ metadata.gz: eec89d0a86280f91bedbfb6593261807397f6ac1
4
+ data.tar.gz: e769745b46e668134cace4e827bd434a4cae4287
5
5
  SHA512:
6
- metadata.gz: 7eb1380db55e093e71b5a394bebb9667c6e1e028805a9543fdc0c3a187309e8dfb51750c196a2fb7611352449e034753d93e2933db17356262a84017a3f11498
7
- data.tar.gz: 0b1902f9fb5b5456cef3028175ac35e7c964f44cf3ea180a652592070bbda7db1d0cc89414c59467f577335542f603ad217fd5537005efff1d3308320eb1b478
6
+ metadata.gz: 0e330af2c6335bbab54cf6f8eb91416590adfa55dfbc5d3c2dc879b062e66cd67bd90e99b2d8b707c8f41724f12e0f4a182169572e49a94633d1ae168b012e56
7
+ data.tar.gz: aecc5b570e761ab14b13de6c19b50f65297ca46ac0d2be23404233f6b705add4c6ddaacfa4e95f97618d380c8b328c25bf2940c7c06015ecf70bf0cc2c97a518
data/examples/my_app.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ puts "Requiring mimi/db, mimi/logger"
3
4
  require 'mimi/db'
4
5
  require 'mimi/logger'
6
+ puts "DONE"
5
7
 
6
8
  CONFIG = {
7
9
  db_adapter: 'sqlite3',
@@ -12,18 +14,7 @@ CONFIG = {
12
14
  Mimi::DB.configure(CONFIG)
13
15
  Mimi::DB.start
14
16
 
15
- class MyModel < ActiveRecord::Base
16
- field :id, as: :integer, primary_key: true, not_null: true, autoincrement: true
17
- field :name, as: :string, limit: 64
18
- field :code, as: :string, default: -> { random_code }
19
- field :value, as: :decimal, precision: 10, scale: 3
20
-
21
- index :name
22
-
23
- def self.random_code
24
- SecureRandom.hex(16)
25
- end
26
- end # class MyModel
17
+ require_relative 'my_model'
27
18
 
28
19
  Mimi::DB.create_if_not_exist! # creates configured database
29
20
  Mimi::DB.update_schema!
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ puts "Requiring mimi/db, mimi/logger"
4
+ require 'mimi/db'
5
+ require 'mimi/logger'
6
+ puts "DONE"
7
+
8
+ CONFIG = {
9
+ db_adapter: 'sqlite3',
10
+ db_database: '../tmp/my_app_db',
11
+ db_log_level: :debug
12
+ }.freeze
13
+
14
+ Mimi::DB.configure(CONFIG)
15
+ Mimi::DB.start
16
+
17
+ require_relative 'my_model'
18
+
19
+ require 'pp'
20
+ pp Mimi::DB.diff_schema
@@ -0,0 +1,13 @@
1
+ class MyModel < Mimi::DB::Model
2
+ field :id, as: :integer, primary_key: true, not_null: true, auto_increment: true
3
+
4
+ field :name, as: :string, limit: 64
5
+ field :code, as: :blob, default: -> { random_code }
6
+ field :value, as: :decimal, precision: 10, scale: 3
7
+
8
+ index :name
9
+
10
+ def self.random_code
11
+ SecureRandom.hex(16)
12
+ end
13
+ end # class MyModel
@@ -52,8 +52,8 @@ module Mimi
52
52
  # Sets up a default as a block/Proc
53
53
  #
54
54
  def field_setup_default(name, block)
55
- before_validation on: :create do
56
- self.send :"#{name}=", block.call
55
+ self.before_validation do
56
+ send :"#{name}=", instance_exec(&block) unless send(name.to_sym)
57
57
  end
58
58
  end
59
59
  end # module DSL
@@ -9,10 +9,11 @@ module Mimi
9
9
  #
10
10
  # Returns nil if the DB table does not exist.
11
11
  #
12
- # @param table_name [String]
12
+ # @param table_name [String,Symbol]
13
13
  # @return [Mimi::DB::Dictate::SchemaDefinition,nil]
14
14
  #
15
15
  def self.discover_schema(table_name)
16
+ table_name = table_name.to_sym
16
17
  return nil unless connection.tables.include?(table_name)
17
18
  sd = Mimi::DB::Dictate::SchemaDefinition.new(table_name)
18
19
  discover_schema_columns(sd)
@@ -26,19 +27,20 @@ module Mimi
26
27
  # @param schema_definition [Mimi::DB::Dictate::SchemaDefinition]
27
28
  #
28
29
  def self.discover_schema_columns(schema_definition)
29
- columns = connection.columns(schema_definition.table_name)
30
- pk = connection.primary_key(schema_definition.table_name)
31
- columns.each do |c|
30
+ columns = connection.schema(schema_definition.table_name).to_h
31
+ columns.each do |name, c|
32
32
  params = {
33
- as: c.type,
34
- limit: c.limit,
35
- primary_key: (pk == c.name),
36
- auto_increment: false, # FIXME: SQLite does not report autoincremented fields
37
- not_null: !c.null,
38
- default: c.default,
39
- sql_type: c.sql_type
33
+ as: c[:type],
34
+ type: c[:type],
35
+ size: c[:max_length],
36
+ primary_key: c[:primary_key],
37
+ auto_increment: c[:auto_increment], # FIXME: SQLite does not report autoincremented fields
38
+ null: c[:allow_null],
39
+ db_default: c[:default],
40
+ default: c[:default],
41
+ db_type: c[:db_type]
40
42
  }
41
- schema_definition.field(c.name, params)
43
+ schema_definition.field(name, params)
42
44
  end
43
45
  end
44
46
  private_class_method :discover_schema_columns
@@ -49,23 +51,35 @@ module Mimi
49
51
  # @param schema_definition [Mimi::DB::Dictate::SchemaDefinition]
50
52
  #
51
53
  def self.discover_schema_indexes(schema_definition)
52
- indexes = connection.indexes(schema_definition.table_name)
53
- pk = connection.primary_key(schema_definition.table_name)
54
- indexes.each do |idx|
54
+ indexes = connection.indexes(schema_definition.table_name).to_h
55
+ pk = discover_primary_key(schema_definition.table_name)
56
+ indexes.each do |idx_name, idx_data|
55
57
  params = {
56
- name: idx.name,
57
- primary_key: idx.columns == [pk],
58
- unique: idx.unique
58
+ name: idx_name,
59
+ primary_key: idx_data[:columns] == pk,
60
+ unique: idx_data[:unique]
59
61
  }
60
- schema_definition.index(idx.columns, params)
62
+ schema_definition.index(idx_data[:columns], params)
61
63
  end
62
64
  end
63
65
  private_class_method :discover_schema_indexes
64
66
 
67
+ # Discovers primary key of an existing DB table
68
+ #
69
+ # @private
70
+ # @param table_name [String,Symbol]
71
+ #
72
+ # @return [Array<Symbol>]
73
+ #
74
+ def self.discover_primary_key(table_name)
75
+ s = connection.schema(table_name).to_h
76
+ s.keys.select { |name| s[name][:primary_key] }
77
+ end
78
+
65
79
  # Returns ActiveRecord DB connection
66
80
  #
67
81
  def self.connection
68
- ActiveRecord::Base.connection
82
+ Mimi::DB.connection
69
83
  end
70
84
  end # module Explorer
71
85
  end # module Dictate
@@ -22,12 +22,12 @@ module Mimi
22
22
  # @param options [Hash]
23
23
  #
24
24
  def initialize(table_name, options)
25
- @table_name = table_name
25
+ @table_name = table_name.to_sym
26
26
  @options = DEFAULTS.merge(options.dup)
27
- @from_schema = self.class.db_schema_definition(table_name.to_s)
28
- @to_schema = Mimi::DB::Dictate.schema_definitions[table_name.to_s]
27
+ @from_schema = self.class.db_schema_definition(@table_name)
28
+ @to_schema = Mimi::DB::Dictate.schema_definitions[@table_name]
29
29
  if from_schema.nil? && to_schema.nil?
30
- raise "Failed to migrate '#{table_name}', no DB or target schema found"
30
+ raise "Failed to migrate '#{@table_name}', no DB or target schema found"
31
31
  end
32
32
  end
33
33
 
@@ -36,7 +36,7 @@ module Mimi
36
36
  end
37
37
 
38
38
  def db_connection
39
- ActiveRecord::Base.connection
39
+ Mimi::DB.connection
40
40
  end
41
41
 
42
42
  # Returns true if the Migrator is configured to do a dry run (no actual changes to DB)
@@ -54,9 +54,11 @@ module Mimi
54
54
  end
55
55
 
56
56
  def run!
57
- run_drop_table! if from_schema && to_schema.nil?
58
- run_change_table! if from_schema && to_schema
59
- run_create_table! if from_schema.nil? && to_schema
57
+ db_ddl_transaction do
58
+ run_drop_table! if from_schema && to_schema.nil?
59
+ run_change_table! if from_schema && to_schema
60
+ run_create_table! if from_schema.nil? && to_schema
61
+ end
60
62
  self.class.reset_db_schema_definition!(table_name)
61
63
  end
62
64
 
@@ -110,15 +112,13 @@ module Mimi
110
112
  def run_create_table!
111
113
  columns = to_schema.columns.values
112
114
  column_pk = to_schema.primary_key
113
- params =
114
- column_pk.params.select { |_, v| v }.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')
115
115
 
116
116
  # issue CREATE TABLE with primary key field
117
117
  logger.info "- CREATE TABLE: #{table_name}"
118
- logger.info "-- add column: #{table_name}.#{column_pk.name} (#{params})"
118
+ logger.info "-- add column: #{table_name}.#{column_pk}"
119
119
  unless dry_run?
120
- db_connection.create_table(table_name, id: false) do |t|
121
- t.column column_pk.name, column_pk.type, column_pk.to_ar_params
120
+ db_connection.create_table(table_name) do |_|
121
+ column column_pk.name, column_pk.sequel_type, column_pk.to_sequel_params
122
122
  end
123
123
  end
124
124
 
@@ -130,28 +130,34 @@ module Mimi
130
130
  def drop_column!(table_name, column_name)
131
131
  logger.info "-- drop column: #{table_name}.#{column_name}"
132
132
  return if dry_run? || !destructive?(:columns)
133
- db_connection.remove_column(table_name, column_name)
133
+ db_connection.drop_column(table_name, column_name)
134
134
  end
135
135
 
136
136
  def change_column!(table_name, column)
137
- params = column.params.select { |_, v| v }.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')
138
- logger.info "-- change column: #{table_name}.#{column.name} (#{params})"
137
+ logger.info "-- change column: #{table_name}.#{column}"
139
138
  return if dry_run?
140
- db_connection.change_column(table_name, column.name, column.type, column.to_ar_params)
139
+ db_connection.alter_table(table_name) do
140
+ set_column_type column.name, column.sequel_type, column.to_sequel_params.except(:default, :null)
141
+ set_column_default column.name, column.params[:default]
142
+ if column.to_sequel_params[:null]
143
+ set_column_allow_null column.name
144
+ else
145
+ set_column_not_null column.name
146
+ end
147
+ end
141
148
  end
142
149
 
143
150
  def add_column!(table_name, column)
144
- params = column.params.select { |_, v| v }.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')
145
- logger.info "-- add column: #{table_name}.#{column.name} (#{params})"
151
+ logger.info "-- add column: #{table_name}.#{column}"
146
152
  return if dry_run?
147
- db_connection.add_column(table_name, column.name, column.type, column.to_ar_params)
153
+ db_connection.add_column(table_name, column.name, column.sequel_type, column.to_sequel_params)
148
154
  end
149
155
 
150
156
  def drop_index!(table_name, idx)
151
157
  idx_column_names = idx.columns.join(', ')
152
158
  logger.info "-- drop index: #{idx.name} on #{table_name}(#{idx_column_names})"
153
159
  return if dry_run?
154
- db_connection.remove_index(table_name, column: idx.columns)
160
+ db_connection.drop_index(table_name, idx.columns)
155
161
  end
156
162
 
157
163
  def add_index!(table_name, idx)
@@ -161,6 +167,14 @@ module Mimi
161
167
  return if dry_run?
162
168
  db_connection.add_index(table_name, idx.columns, idx.params)
163
169
  end
170
+
171
+ def db_ddl_transaction(&_block)
172
+ supports_transactional_ddl =
173
+ db_connection.respond_to?(:supports_transactional_ddl?) &&
174
+ db_connection.supports_transactional_ddl?
175
+ return yield unless supports_transactional_ddl
176
+ db_connection.transaction { yield }
177
+ end
164
178
  end # class Migrator
165
179
  end # module Dictate
166
180
  end # module DB
@@ -12,28 +12,48 @@ module Mimi
12
12
  @indexes = []
13
13
  end
14
14
 
15
+ # Declares a field
16
+ #
17
+ # Example:
18
+ # field :s1, as: :string
19
+ # field :s2, type: :string, size: 64
20
+ # field :v1, as: :decimal, size: 10 # precision: 10
21
+ # field :v2, as: :decimal, size: [10, 3] # precision: 10, scale: 3
22
+ #
23
+ #
15
24
  def field(name, opts)
16
- name = name.to_s
25
+ name = name.to_sym
17
26
  raise "Cannot redefine field :#{name}" if @columns[name]
18
- if primary_key && (opts[:primary_key] || opts[:as] == :primary_key)
27
+ opts_type = opts[:type] || opts[:as]
28
+ if primary_key && (opts[:primary_key] || opts_type == :primary_key)
19
29
  raise "Cannot redefine primary key (:#{primary_key.name}) with :#{name}"
20
30
  end
21
31
  @columns[name] = Column.new(name, opts)
22
32
  end
23
33
 
34
+ # Declares an index
35
+ #
36
+ # Example:
37
+ # index :name
38
+ # index [:first_name, :last_name]
39
+ # index :ref_code, unique: true
40
+ #
41
+ # @param columns [String,Symbol,Array<String,Symbol>] columns to index on
42
+ # @param opts [Hash] index parameters (:unique, :name etc)
43
+ #
24
44
  def index(columns, opts)
25
45
  case columns
26
46
  when String, Symbol
27
- columns = [columns.to_s]
47
+ columns = [columns.to_sym]
28
48
  when Array
29
49
  unless columns.all? { |c| c.is_a?(String) || c.is_a?(Symbol) }
30
50
  raise "Invalid column reference in index definition [#{columns}]"
31
51
  end
32
- columns = columns.map(&:to_s)
52
+ columns = columns.map(&:to_sym)
33
53
  else
34
54
  raise 'Invalid columns argument to .index'
35
55
  end
36
- if columns == [primary_key]
56
+ if columns == [primary_key.name]
37
57
  # TODO: warn the primary key index is ignored
38
58
  end
39
59
  @indexes << Index.new(columns, opts)
@@ -57,24 +77,25 @@ module Mimi
57
77
  }
58
78
  end
59
79
 
80
+ # Represents a column in schema definition
81
+ #
60
82
  class Column
61
- DEFAULTS = {
62
- as: :string,
63
- limit: nil,
64
- primary_key: false,
65
- auto_increment: false,
66
- not_null: false,
67
- default: nil,
68
- sql_type: nil
69
- }.freeze
83
+ DEFAULT_TYPE = :string
70
84
 
71
- attr_reader :name, :type, :params
85
+ attr_reader :name, :type, :sequel_type, :params
72
86
 
87
+ # Creates a Column object
88
+ #
89
+ # @param name [String,Symbol]
90
+ # @param opts [Hash]
91
+ #
73
92
  def initialize(name, opts)
74
- @name = name
75
- @type = opts[:as] || DEFAULTS[:as]
76
- type_defaults = Mimi::DB::Dictate.type_defaults(type)
77
- @params = DEFAULTS.merge(type_defaults).merge(opts)
93
+ @name = name.to_sym
94
+ @params = opts.dup
95
+ @params[:type] ||= @params[:as] || DEFAULT_TYPE
96
+ @params = Mimi::DB::Dictate::TypeDefaults.infer_params(@params)
97
+ @type = @params[:type]
98
+ @sequel_type = @params[:sequel_type]
78
99
  end
79
100
 
80
101
  def to_h
@@ -84,28 +105,35 @@ module Mimi
84
105
  }
85
106
  end
86
107
 
87
- def to_ar_params
88
- p = params.dup
89
- p[:null] = !p[:not_null]
108
+ def to_sequel_params
109
+ p = params.dup.except(:type, :as)
110
+ p[:null] = !p[:not_null] if p.key?(:not_null)
90
111
  p
91
112
  end
92
113
 
114
+ def to_s
115
+ public_params = params.only(
116
+ :type, :primary_key, :auto_increment, :not_null, :default, :size
117
+ ).select { |_, v| v }.to_h
118
+ public_params = public_params.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')
119
+ "#{name}(#{public_params})"
120
+ end
121
+
93
122
  def ==(other)
94
123
  unless other.name == name
95
124
  raise ArgumentError, 'Cannot compare columns with different names'
96
125
  end
97
126
  equal = true
98
- equal &&= params[:as] == other.params[:as]
99
- equal &&= params[:limit] == other.params[:limit]
127
+ equal &&= params[:db_type] == other.params[:db_type]
100
128
  equal &&= params[:primary_key] == other.params[:primary_key]
101
- # FIXME: auto_increment ignored
102
129
  equal &&= params[:not_null] == other.params[:not_null]
103
- equal &&= params[:default].to_s == other.params[:default].to_s
104
- # FIXME: sql_type ignored
130
+ equal &&= params[:db_default].to_s == other.params[:db_default].to_s
105
131
  equal
106
132
  end
107
133
  end # class Column
108
134
 
135
+ # Represents an index in schema definition
136
+ #
109
137
  class Index
110
138
  DEFAULTS = {
111
139
  unique: false
@@ -113,9 +141,14 @@ module Mimi
113
141
 
114
142
  attr_reader :name, :columns, :params
115
143
 
144
+ # Creates an Index object
145
+ #
146
+ # @param columns [Array<String,Symbol>]
147
+ # @param params [Hash]
148
+ #
116
149
  def initialize(columns, params)
117
150
  @name = params[:name]
118
- @columns = columns
151
+ @columns = columns.map(&:to_sym)
119
152
  @params = DEFAULTS.merge(params)
120
153
  end
121
154
 
@@ -5,11 +5,6 @@ module Mimi
5
5
  module Dictate
6
6
  module SchemaDiff
7
7
  DEFAULT_OPTIONS = {
8
- # Force updates on fields defined as :primary_key type.
9
- # If disabled, the field definition will only be used in 'CREATE TABLE'.
10
- # (forced updates on :primary_key break on Postgres, at least)
11
- #
12
- force_primary_key: false
13
8
  }.freeze
14
9
 
15
10
  #
@@ -18,7 +13,7 @@ module Mimi
18
13
  # @return [Hash] :columns, :indexes => :from, :to
19
14
  #
20
15
  def self.diff(from, to, opts = {})
21
- options = DEFAULT_OPTIONS.merge(opts)
16
+ _options = DEFAULT_OPTIONS.merge(opts)
22
17
  result = { table_name: from.table_name, columns: {}, indexes: {} }
23
18
  all_column_names = (from.columns.values.map(&:name) + to.columns.values.map(&:name)).uniq
24
19
  all_column_names.each do |c|
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mimi
4
+ module DB
5
+ module Dictate
6
+ module TypeDefaults
7
+
8
+ # Constructs a Proc that returns "<type>" or "<type>(n)" depending on whether the size is provided
9
+ #
10
+ DEF_OPT_SIZE_PROC = lambda do |type, default_size_suffix = ''|
11
+ ->(p) { p[:size] ? { db_type: "#{type}(#{p[:size]})" } : { db_type: type + default_size_suffix } }
12
+ end
13
+
14
+ # Produces a "string" or "string(n)" depending on whether the size is provided
15
+ #
16
+ TYPE_STRING_PROC = DEF_OPT_SIZE_PROC.call('string')
17
+
18
+ # Produces an "integer" or "integer(n)" depending on whether size is provided
19
+ #
20
+ TYPE_INTEGER_PROC = DEF_OPT_SIZE_PROC.call('integer')
21
+
22
+ # Produces a "decimal", "decimal(p)" or "decimal(p,s)" depending on whether size is provided
23
+ #
24
+ TYPE_DECIMAL_PROC = lambda do |p|
25
+ p[:size] ? { db_type: "decimal(#{[*p[:size]].join(',')})" } : { db_type: 'decimal' }
26
+ end
27
+
28
+ # Produces a "decimal", "decimal(p)" or "decimal(p, s)" depending on whether size is provided
29
+ #
30
+ TYPE_SQLITE_DECIMAL_PROC = lambda do |p|
31
+ p[:size] ? { db_type: "decimal(#{[*p[:size]].join(', ')})" } : { db_type: 'decimal' }
32
+ end
33
+
34
+ # Produces a "numeric" or "numeric(p, s)" depending on whether size is provided
35
+ #
36
+ TYPE_POSTGRES_NUMERIC_PROC = lambda do |p|
37
+ if p[:size]
38
+ # p[:size] is either a number (precision) or an array (precision, scale)
39
+ p1, p2 = [*p[:size]]
40
+ { db_type: "numeric(#{p1},#{p2 || 0})" }
41
+ else
42
+ { db_type: 'numeric' }
43
+ end
44
+ end
45
+
46
+ # Produces a "character varying" or "character varying(n)" depending on whether the size is provided
47
+ #
48
+ TYPE_POSTGRES_VARCHAR_PROC = lambda do |p|
49
+ if p[:size]
50
+ { db_type: "character varying(#{p[:size]})", sequel_type: :varchar }
51
+ else
52
+ { db_type: 'character varying(255)', sequel_type: :varchar }
53
+ end
54
+ end
55
+
56
+ # Type converters, accept Sequel type (field as: ...) as a key,
57
+ # return:
58
+ # * a Hash of field params or
59
+ # * a Proc returning a Hash of field params
60
+ #
61
+ TYPE_MAP = {
62
+ default: {
63
+ },
64
+ sqlite: {
65
+ bigint: { db_type: 'bigint' },
66
+ integer: TYPE_INTEGER_PROC,
67
+ int: { db_type: 'integer', sequel_type: :integer },
68
+ smallint: { db_type: 'smallint' },
69
+
70
+ decimal: TYPE_SQLITE_DECIMAL_PROC,
71
+
72
+ string: DEF_OPT_SIZE_PROC.call('string'),
73
+ varchar: DEF_OPT_SIZE_PROC.call('varchar', '(255)'),
74
+ text: { db_type: 'text' },
75
+
76
+ bytes: { db_type: 'bytea', sequel_type: :bytea },
77
+ bytea: { db_type: 'bytea' },
78
+ blob: { db_type: 'blob' },
79
+
80
+ bool: { db_type: 'bool', sequel_type: :bool },
81
+ boolean: { db_type: 'bool', sequel_type: :bool },
82
+
83
+ date: { db_type: 'date' },
84
+ timestamp: { db_type: 'timestamp' },
85
+ datetime: { db_type: 'timestamp', sequel_type: :timestamp },
86
+
87
+ float: { db_type: 'double precision' }
88
+ },
89
+ postgres: {
90
+ bigserial: { db_type: 'bigint', db_default: "nextval('tests_id_seq'::regclass)" },
91
+ bigint: { db_type: 'bigint' },
92
+ integer: { db_type: 'integer', sequel_type: :integer },
93
+ int: { db_type: 'integer', sequel_type: :integer },
94
+ smallint: { db_type: 'smallint' },
95
+
96
+ decimal: TYPE_POSTGRES_NUMERIC_PROC,
97
+
98
+ string: TYPE_POSTGRES_VARCHAR_PROC,
99
+ varchar: TYPE_POSTGRES_VARCHAR_PROC,
100
+ text: { db_type: 'text' },
101
+
102
+ bytes: { db_type: 'bytea', sequel_type: :bytea },
103
+ bytea: { db_type: 'bytea' },
104
+ blob: { db_type: 'bytea', sequel_type: :bytea },
105
+
106
+ bool: { db_type: 'boolean' },
107
+ boolean: { db_type: 'boolean' },
108
+
109
+ date: { db_type: 'date' },
110
+ timestamp: { db_type: 'timestamp without time zone' },
111
+ datetime: { db_type: 'timestamp without time zone', sequel_type: :timestamp },
112
+
113
+ float: { db_type: 'double precision' }
114
+ },
115
+ cockroachdb: {
116
+ bigserial: { db_type: 'bigint', db_default: 'unique_rowid()' },
117
+ bigint: { db_type: 'bigint' },
118
+ integer: { db_type: 'bigint' },
119
+ int: { db_type: 'bigint', sequel_type: :integer },
120
+ smallint: { db_type: 'bigint', sequel_type: :integer },
121
+
122
+ decimal: { db_type: 'numeric' },
123
+
124
+ string: { db_type: 'text', sequel_type: :string },
125
+ varchar: { db_type: 'text', sequel_type: :string },
126
+ text: { db_type: 'text' },
127
+
128
+ bytes: { db_type: 'bytea' },
129
+ bytea: { db_type: 'bytea', sequel_type: :bytes },
130
+ blob: { db_type: 'bytea', sequel_type: :bytes },
131
+
132
+ bool: { db_type: 'boolean' },
133
+ boolean: { db_type: 'boolean' },
134
+
135
+ date: { db_type: 'date' },
136
+ timestamp: { db_type: 'timestamp without time zone' },
137
+ datetime: { db_type: 'timestamp without time zone', sequel_type: :timestamp },
138
+
139
+ float: { db_type: 'double precision' }
140
+ }
141
+ }.freeze
142
+
143
+ #
144
+ # The method infers column params based on column definition
145
+ #
146
+ # @param params [Hash]
147
+ # @return [Hash]
148
+ #
149
+ def self.infer_params(params)
150
+ type = params[:type].to_sym
151
+ defaults = {
152
+ db_type: type.to_s,
153
+ sequel_type: type,
154
+ primary_key: !!params[:primary_key],
155
+ not_null: !!params[:primary_key],
156
+ db_default: params[:default]
157
+ }
158
+ adapter_name = Mimi::DB.sequel_config[:adapter]
159
+ raise "Failed to infer_params, adapter is not set: #{adapter_name}" unless adapter_name
160
+ inferred_params = TYPE_MAP[adapter_name.to_sym][type] || TYPE_MAP[:default][type] || {}
161
+ inferred_params = inferred_params.call(params) if inferred_params.is_a?(Proc)
162
+ defaults.merge(inferred_params).merge(params)
163
+ end
164
+ end # module TypeDefaults
165
+ end # module Dictate
166
+ end # module DB
167
+ end # module Mimi