sbf-dm-migrations 1.3.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +468 -0
  5. data/.travis.yml +52 -0
  6. data/Gemfile +61 -0
  7. data/LICENSE +20 -0
  8. data/README.rdoc +39 -0
  9. data/Rakefile +4 -0
  10. data/db/migrations/1_create_people_table.rb +12 -0
  11. data/db/migrations/2_add_dob_to_people.rb +13 -0
  12. data/db/migrations/config.rb +4 -0
  13. data/dm-migrations.gemspec +20 -0
  14. data/examples/Rakefile +149 -0
  15. data/examples/sample_migration.rb +58 -0
  16. data/examples/sample_migration_spec.rb +46 -0
  17. data/lib/dm-migrations/adapters/dm-do-adapter.rb +304 -0
  18. data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +306 -0
  19. data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +339 -0
  20. data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +152 -0
  21. data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +88 -0
  22. data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +184 -0
  23. data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +21 -0
  24. data/lib/dm-migrations/auto_migration.rb +227 -0
  25. data/lib/dm-migrations/exceptions/duplicate_migration.rb +6 -0
  26. data/lib/dm-migrations/migration.rb +323 -0
  27. data/lib/dm-migrations/migration_runner.rb +76 -0
  28. data/lib/dm-migrations/sql/column.rb +5 -0
  29. data/lib/dm-migrations/sql/mysql.rb +84 -0
  30. data/lib/dm-migrations/sql/oracle.rb +9 -0
  31. data/lib/dm-migrations/sql/postgres.rb +89 -0
  32. data/lib/dm-migrations/sql/sqlite.rb +59 -0
  33. data/lib/dm-migrations/sql/sqlserver.rb +9 -0
  34. data/lib/dm-migrations/sql/table.rb +15 -0
  35. data/lib/dm-migrations/sql/table_creator.rb +105 -0
  36. data/lib/dm-migrations/sql/table_modifier.rb +57 -0
  37. data/lib/dm-migrations/sql.rb +7 -0
  38. data/lib/dm-migrations/version.rb +5 -0
  39. data/lib/dm-migrations.rb +3 -0
  40. data/lib/spec/example/migration_example_group.rb +69 -0
  41. data/lib/spec/matchers/migration_matchers.rb +96 -0
  42. data/spec/integration/auto_migration_spec.rb +590 -0
  43. data/spec/integration/auto_upgrade_spec.rb +41 -0
  44. data/spec/integration/migration_runner_spec.rb +84 -0
  45. data/spec/integration/migration_spec.rb +156 -0
  46. data/spec/integration/sql_spec.rb +290 -0
  47. data/spec/isolated/require_after_setup_spec.rb +24 -0
  48. data/spec/isolated/require_before_setup_spec.rb +24 -0
  49. data/spec/isolated/require_spec.rb +23 -0
  50. data/spec/spec_helper.rb +16 -0
  51. data/spec/unit/migration_spec.rb +501 -0
  52. data/spec/unit/sql/column_spec.rb +14 -0
  53. data/spec/unit/sql/postgres_spec.rb +90 -0
  54. data/spec/unit/sql/sqlite_extensions_spec.rb +103 -0
  55. data/spec/unit/sql/table_creator_spec.rb +91 -0
  56. data/spec/unit/sql/table_modifier_spec.rb +47 -0
  57. data/spec/unit/sql/table_spec.rb +26 -0
  58. data/spec/unit/sql_spec.rb +7 -0
  59. data/tasks/spec.rake +21 -0
  60. data/tasks/yard.rake +9 -0
  61. data/tasks/yardstick.rake +19 -0
  62. metadata +120 -0
@@ -0,0 +1,13 @@
1
+ migration 2, :add_dob_to_people do
2
+ up do
3
+ modify_table :people do
4
+ add_column :dob, DateTime, allow_nil: true
5
+ end
6
+ end
7
+
8
+ down do
9
+ modify_table :people do
10
+ drop_column :dob
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ DataMapper::Logger.new($stdout, :debug)
2
+ DataMapper.logger.debug('Starting Migration')
3
+
4
+ DataMapper.setup(:default, 'postgres://postgres@localhost/dm_core_test')
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../lib/dm-migrations/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ['Dan Kubb']
5
+ gem.email = ['dan.kubb@gmail.com']
6
+ gem.summary = 'DataMapper plugin for writing and spec-ing migrations'
7
+ gem.description = 'DataMapper plugin for modifying and maintaining database structure, triggers, stored procedures, and data'
8
+ gem.homepage = 'https://datamapper.org'
9
+ gem.license = 'Nonstandard'
10
+
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.extra_rdoc_files = %w(LICENSE README.rdoc)
13
+
14
+ gem.name = 'sbf-dm-migrations'
15
+ gem.require_paths = ['lib']
16
+ gem.version = DataMapper::Migrations::VERSION
17
+ gem.required_ruby_version = '>= 2.7.8'
18
+
19
+ gem.add_runtime_dependency('sbf-dm-core', '~> 1.3.0.beta')
20
+ end
data/examples/Rakefile ADDED
@@ -0,0 +1,149 @@
1
+ # Sample tasks using dm-migrations
2
+ # Roughly following Rails conventions, and mostly based on Padrino's dm:* tasks
3
+ #
4
+ # Cf. https://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/padrino-tasks/datamapper.rb
5
+ # https://github.com/firespring/dm-rails/blob/master/lib/dm-rails/railties/database.rake
6
+ #
7
+
8
+ require 'rake'
9
+
10
+ # replace this with however your app configures DataMapper repositor(ies)
11
+ task :environment do
12
+ require File.expand_path('boot', File.dirname(__FILE__))
13
+ end
14
+
15
+ namespace :db do
16
+
17
+ namespace :auto do
18
+
19
+ desc 'Perform auto-migration (reset your db data)'
20
+ task migrate: :environment do |t, _|
21
+ puts '=> Auto-migrating'
22
+ DataMapper.auto_migrate!
23
+ puts "<= #{t.name} done"
24
+ end
25
+
26
+ desc 'Perform non destructive auto-migration'
27
+ task upgrade: :environment do |t, _|
28
+ puts '=> Auto-upgrading'
29
+ DataMapper.auto_upgrade!
30
+ puts "<= #{t.name} done"
31
+ end
32
+
33
+ end
34
+
35
+ desc 'Run all pending migrations, or up to specified migration'
36
+ task :migrate, [:version] => :load_migrations do |t, args|
37
+ if (vers = args[:version] || ENV.fetch('VERSION', nil))
38
+ puts "=> Migrating up to version #{vers}"
39
+ migrate_up!(vers)
40
+ else
41
+ puts '=> Migrating up'
42
+ migrate_up!
43
+ end
44
+ puts "<= #{t.name} done"
45
+ end
46
+
47
+ desc 'Rollback down to specified migration, or rollback last STEP=x migrations (default 1)'
48
+ task :rollback, [:version] => :load_migrations do |t, args|
49
+ if (vers = args[:version] || ENV.fetch('VERSION', nil))
50
+ puts "=> Rolling back down to migration #{vers}"
51
+ migrate_down!(vers)
52
+ else
53
+ step = ENV['STEP'].to_i || 1
54
+ applied = migrations.delete_if(&:needs_up?).sort # NOTE: this is N queries as currently implemented
55
+ target = applied[-1 * step] || applied[0]
56
+ if target
57
+ puts "=> Rolling back #{step} step(s)"
58
+ migrate_down!(target.position - 1)
59
+ else
60
+ warn "No migrations to rollback: #{step} step(s)"
61
+ end
62
+ end
63
+ puts "<= #{t.name} done"
64
+ end
65
+
66
+ desc 'List migrations descending, showing which have been applied'
67
+ task migrations: :load_migrations do
68
+ puts(migrations.sort.reverse.map { |m| "#{m.position} #{m.name} #{m.needs_up? ? '' : 'APPLIED'}" })
69
+ end
70
+
71
+ task load_migrations: :environment do
72
+ require 'dm-migrations/migration_runner'
73
+ FileList['db/migrate/*.rb'].each do |migration|
74
+ load migration
75
+ end
76
+ end
77
+
78
+
79
+ desc 'Create the database'
80
+ task :create, [:repository] => :environment do |t, args|
81
+ repo = args[:repository] || ENV['REPOSITORY'] || :default
82
+ config = DataMapper.repository(repo)&.adapter&.options&.symbolize_keys
83
+ user = config[:user]
84
+ password = config[:password]
85
+ host = config[:host]
86
+ database = config[:database] || config[:path].sub('/', '')
87
+ charset = config[:charset] || ENV['CHARSET'] || 'utf8'
88
+ collation = config[:collation] || ENV['COLLATION'] || 'utf8_unicode_ci'
89
+ puts "=> Creating database '#{database}'"
90
+
91
+ case config[:adapter]
92
+ when 'postgres'
93
+ system('createdb', '-E', charset, '-h', host, '-U', user, database)
94
+ when 'mysql'
95
+ query = [
96
+ 'mysql', "--user=#{user}", (password.blank? ? '' : "--password=#{password}"), (%w(127.0.0.1 localhost).include?(host) ? '-e' : "--host=#{host} -e"),
97
+ "CREATE DATABASE #{database} DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}".inspect
98
+ ]
99
+ system(query.compact.join(' '))
100
+ when 'sqlite3'
101
+ DataMapper.setup(DataMapper.repository&.name, config)
102
+ else
103
+ raise "Adapter #{config[:adapter]} not supported for creating databases yet."
104
+ end
105
+ puts "<= #{t.name} done"
106
+ end
107
+
108
+ desc 'Drop the database'
109
+ task :drop, [:repository] => :environment do |t, args|
110
+ repo = args[:repository] || ENV['REPOSITORY'] || :default
111
+ config = DataMapper.repository(repo)&.adapter&.options&.symbolize_keys
112
+ user = config[:user]
113
+ password = config[:password]
114
+ host = config[:host]
115
+ database = config[:database] || config[:path].sub('/', '')
116
+ puts "=> Dropping database '#{database}'"
117
+ case config[:adapter]
118
+ when 'postgres'
119
+ system('dropdb', '-h', host, '-U', user, database)
120
+ when 'mysql'
121
+ query = [
122
+ 'mysql', "--user=#{user}",
123
+ (password.blank? ? '' : "--password=#{password}"),
124
+ (%w(127.0.0.1 localhost).include?(host) ? '-e' : "--host=#{host} -e"),
125
+ "DROP DATABASE IF EXISTS #{database}".inspect
126
+ ]
127
+ system(query.compact.join(' '))
128
+ when 'sqlite3'
129
+ FileUtils.rm_f(config[:path])
130
+ else
131
+ raise "Adapter #{config[:adapter]} not supported for dropping databases yet."
132
+ end
133
+ puts "<= #{t.name} done"
134
+ end
135
+
136
+ desc 'Load the seed data from db/seeds.rb'
137
+ task seed: :environment do |t, _|
138
+ puts '=> Loading seed data'
139
+ seed_file = File.expand_path('db/seeds.rb', File.dirname(__FILE__))
140
+ load(seed_file) if File.exist?(seed_file)
141
+ puts "<= #{t.name} done"
142
+ end
143
+
144
+ desc 'Drop the database, migrate from scratch and initialize with the seed data'
145
+ task reset: %i(drop setup)
146
+
147
+ desc 'Create the database, migrate and initialize with the seed data'
148
+ task setup: %i(create migrate seed)
149
+ end
@@ -0,0 +1,58 @@
1
+ require 'dm-migrations/migration_runner'
2
+
3
+ DataMapper.setup(:default, 'sqlite3::memory')
4
+
5
+ DataMapper::Logger.new(STDOUT, :debug)
6
+ DataMapper.logger.debug( 'Starting Migration' )
7
+
8
+ migration 1, :create_people_table do
9
+ up do
10
+ create_table :people do
11
+ column :id, Integer, serial: true
12
+ column :name, String, size: 50
13
+ column :age, Integer
14
+ end
15
+ end
16
+ down do
17
+ drop_table :people
18
+ end
19
+ end
20
+
21
+ migration 2, :add_dob_to_people do
22
+ up do
23
+ modify_table :people do
24
+ add_column :dob, DateTime, allow_nil: true
25
+ end
26
+ end
27
+
28
+ down do
29
+ modify_table :people do
30
+ drop_column :dob
31
+ end
32
+ end
33
+ end
34
+
35
+ # migrate_down!
36
+ # migrate_up!
37
+ #
38
+ # class Person
39
+ # include DataMapper::Resource
40
+ #
41
+ # property :id, Serial
42
+ # property :name, String, :size => 50
43
+ # property :age, Integer
44
+ # property :dob, DateTime, :default => proc { Time.now }
45
+ #
46
+ # end
47
+ #
48
+ # Person.create(:name => "Mark Bates", :age => 31)
49
+ # puts Person.first.inspect
50
+ # puts Person.all.inspect
51
+
52
+ if $0 == __FILE__
53
+ if $*.first == 'down'
54
+ migrate_down!
55
+ else
56
+ migrate_up!
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ require 'pathname'
2
+
3
+ dir = Pathname(__FILE__).dirname.expand_path
4
+
5
+ require "#{dir}sample_migration"
6
+ require "#{dir}../lib/spec/example/migration_example_group"
7
+
8
+ describe :create_people_table, type: :migration do
9
+ before do
10
+ run_migration
11
+ end
12
+
13
+ it 'creates a people table' do
14
+ expect(repository(:default)).to have_table(:people)
15
+ end
16
+
17
+ it 'has an id column as the primary key' do
18
+ expect(table(:people)).to have_column(:id)
19
+ expect(table(:people).column(:id).type).to eq 'integer'
20
+ # expect(table(:people).column(:id)).to be_primary_key
21
+ end
22
+
23
+ it 'has a name column as a string' do
24
+ expect(table(:people)).to have_column(:name)
25
+ expect(table(:people).column(:name).type).to eq 'character varying'
26
+ expect(table(:people).column(:name)).to permit_null
27
+ end
28
+
29
+ it 'has a nullable age column as a int' do
30
+ expect(table(:people)).to have_column(:age)
31
+ expect(table(:people).column(:age).type).to eq 'integer'
32
+ expect(table(:people).column(:age)).to permit_null
33
+ end
34
+ end
35
+
36
+ describe :add_dob_to_people, type: :migration do
37
+ before do
38
+ run_migration
39
+ end
40
+
41
+ it 'adds a dob column as a timestamp' do
42
+ expect(table(:people)).to have_column(:dob)
43
+ expect(table(:people).column(:dob).type).to eq 'timestamp without time zone'
44
+ expect(table(:people).column(:dob)).to permit_null
45
+ end
46
+ end
@@ -0,0 +1,304 @@
1
+ require 'dm-migrations/auto_migration'
2
+
3
+ module DataMapper
4
+ module Migrations
5
+ module DataObjectsAdapter
6
+ # Returns whether the storage_name exists.
7
+ #
8
+ # @param [String] storage_name
9
+ # a String defining the name of a storage, for example a table name.
10
+ #
11
+ # @return [Boolean]
12
+ # true if the storage exists
13
+ #
14
+ # @api semipublic
15
+ def storage_exists?(storage_name)
16
+ statement = DataMapper::Ext::String.compress_lines(<<-SQL)
17
+ SELECT COUNT(*)
18
+ FROM "information_schema"."tables"
19
+ WHERE "table_type" = 'BASE TABLE'
20
+ AND "table_schema" = ?
21
+ AND "table_name" = ?
22
+ SQL
23
+
24
+ select(statement, schema_name, storage_name).first > 0
25
+ end
26
+
27
+ # Returns whether the field exists.
28
+ #
29
+ # @param [String] storage_name
30
+ # a String defining the name of a storage, for example a table name.
31
+ # @param [String] column_name
32
+ # a String defining the name of a field, for example a column name.
33
+ #
34
+ # @return [Boolean]
35
+ # true if the field exists.
36
+ #
37
+ # @api semipublic
38
+ def field_exists?(storage_name, column_name)
39
+ statement = DataMapper::Ext::String.compress_lines(<<-SQL)
40
+ SELECT COUNT(*)
41
+ FROM "information_schema"."columns"
42
+ WHERE "table_schema" = ?
43
+ AND "table_name" = ?
44
+ AND "column_name" = ?
45
+ SQL
46
+
47
+ select(statement, schema_name, storage_name, column_name).first > 0
48
+ end
49
+
50
+ # @api semipublic
51
+ def upgrade_model_storage(model)
52
+ name = self.name
53
+ properties = model.properties_with_subclasses(name)
54
+
55
+ return properties if create_model_storage(model)
56
+
57
+ table_name = model.storage_name(name)
58
+
59
+ with_connection do |connection|
60
+ properties.map do |property|
61
+ schema_hash = property_schema_hash(property)
62
+ next if field_exists?(table_name, schema_hash[:name])
63
+
64
+ statement = alter_table_add_column_statement(connection, table_name, schema_hash)
65
+ command = connection.create_command(statement)
66
+ command.execute_non_query
67
+
68
+ # For simple :index => true columns, add an appropriate index.
69
+ # Upgrading doesn't know how to deal with complex indexes yet.
70
+ if property.options[:index] === true
71
+ statement = create_index_statement(model, property.name, [property.field])
72
+ command = connection.create_command(statement)
73
+ command.execute_non_query
74
+ end
75
+
76
+ property
77
+ end.compact
78
+ end
79
+ end
80
+
81
+ # @api semipublic
82
+ def create_model_storage(model)
83
+ name = self.name
84
+ properties = model.properties_with_subclasses(name)
85
+
86
+ return false if storage_exists?(model.storage_name(name))
87
+ return false if properties.empty?
88
+
89
+ with_connection do |connection|
90
+ statements = [create_table_statement(connection, model, properties)]
91
+ statements.concat(create_index_statements(model))
92
+ statements.concat(create_unique_index_statements(model))
93
+
94
+ statements.each do |statement|
95
+ command = connection.create_command(statement)
96
+ command.execute_non_query
97
+ end
98
+ end
99
+
100
+ true
101
+ end
102
+
103
+ # @api semipublic
104
+ def destroy_model_storage(model)
105
+ return true unless supports_drop_table_if_exists? || storage_exists?(model.storage_name(name))
106
+
107
+ execute(drop_table_statement(model))
108
+ true
109
+ end
110
+
111
+ module SQL # :nodoc:
112
+ # private ## This cannot be private for current migrations
113
+
114
+ # Adapters that support AUTO INCREMENT fields for CREATE TABLE
115
+ # statements should overwrite this to return true
116
+ #
117
+ # @api private
118
+ def supports_serial?
119
+ false
120
+ end
121
+
122
+ # @api private
123
+ def supports_drop_table_if_exists?
124
+ false
125
+ end
126
+
127
+ # @api private
128
+ def schema_name
129
+ raise NotImplementedError, "#{self.class}#schema_name not implemented"
130
+ end
131
+
132
+ # @api private
133
+ def alter_table_add_column_statement(connection, table_name, schema_hash)
134
+ "ALTER TABLE #{quote_name(table_name)} #{add_column_statement} #{property_schema_statement(connection, schema_hash)}"
135
+ end
136
+
137
+ # @api private
138
+ def create_table_statement(connection, model, properties)
139
+ DataMapper::Ext::String.compress_lines(<<-SQL)
140
+ CREATE TABLE #{quote_name(model.storage_name(name))}
141
+ (#{properties.map { |property| property_schema_statement(connection, property_schema_hash(property)) }.join(', ')},
142
+ PRIMARY KEY(#{properties.key.map { |property| quote_name(property.field) }.join(', ')}))
143
+ SQL
144
+ end
145
+
146
+ # @api private
147
+ def drop_table_statement(model)
148
+ table_name = quote_name(model.storage_name(name))
149
+ if supports_drop_table_if_exists?
150
+ "DROP TABLE IF EXISTS #{table_name}"
151
+ else
152
+ "DROP TABLE #{table_name}"
153
+ end
154
+ end
155
+
156
+ # @api private
157
+ def create_index_statements(model)
158
+ name = self.name
159
+ model.storage_name(name)
160
+
161
+ indexes(model).map do |index_name, fields|
162
+ create_index_statement(model, index_name, fields)
163
+ end
164
+ end
165
+
166
+ # @api private
167
+ def create_index_statement(model, index_name, fields)
168
+ table_name = model.storage_name(name)
169
+
170
+ DataMapper::Ext::String.compress_lines(<<-SQL)
171
+ CREATE INDEX #{quote_name("index_#{table_name}_#{index_name}")} ON
172
+ #{quote_name(table_name)} (#{fields.map { |field| quote_name(field) }.join(', ')})
173
+ SQL
174
+ end
175
+
176
+ # @api private
177
+ def create_unique_index_statements(model)
178
+ name = self.name
179
+ table_name = model.storage_name(name)
180
+ key = model.key(name).map(&:field)
181
+ unique_indexes = unique_indexes(model).reject { |_index_name, fields| fields == key }
182
+
183
+ unique_indexes.map do |index_name, fields|
184
+ DataMapper::Ext::String.compress_lines(<<-SQL)
185
+ CREATE UNIQUE INDEX #{quote_name("unique_#{table_name}_#{index_name}")} ON
186
+ #{quote_name(table_name)} (#{fields.map { |field| quote_name(field) }.join(', ')})
187
+ SQL
188
+ end
189
+ end
190
+
191
+ # @api private
192
+ def property_schema_hash(property)
193
+ dump_class = property.dump_class
194
+ type_by_property_class = self.class.type_by_property_class(property.class)
195
+
196
+ schema = (type_by_property_class || self.class.type_map[dump_class]).merge(name: property.field)
197
+
198
+ schema_primitive = schema[:primitive]
199
+
200
+ if dump_class.equal?(String) && schema_primitive != 'TEXT' && schema_primitive != 'CLOB' && schema_primitive != 'NVARCHAR' &&
201
+ schema_primitive != 'BYTEA' && schema_primitive != 'VARBINARY'
202
+ schema[:length] = property.length
203
+ elsif dump_class.equal?(BigDecimal) || dump_class.equal?(Float)
204
+ schema[:precision] = property.precision
205
+ schema[:scale] = property.scale
206
+ end
207
+
208
+ schema[:allow_nil] = property.allow_nil?
209
+ schema[:serial] = property.serial?
210
+
211
+ default = property.default
212
+
213
+ if default.nil? || default.respond_to?(:call)
214
+ # remove the default if the property does not allow nil
215
+ schema.delete(:default) unless schema[:allow_nil]
216
+ else
217
+ schema[:default] = property.dump(default)
218
+ end
219
+
220
+ schema
221
+ end
222
+
223
+ # @api private
224
+ def property_schema_statement(connection, schema)
225
+ statement = quote_name(schema[:name])
226
+ statement << " #{schema[:primitive]}"
227
+
228
+ length = schema[:length]
229
+
230
+ if schema[:precision] && schema[:scale]
231
+ statement << "(#{%i(precision scale).map { |key| connection.quote_value(schema[key]) }.join(', ')})"
232
+ elsif length == 'max'
233
+ statement << '(max)'
234
+ elsif length
235
+ statement << "(#{connection.quote_value(length)})"
236
+ end
237
+
238
+ default = schema[:default]
239
+ statement << " DEFAULT #{connection.quote_value(default)}" if default
240
+
241
+ statement << ' NOT NULL' unless schema[:allow_nil]
242
+
243
+ statement
244
+ end
245
+
246
+ # @api private
247
+ def indexes(model)
248
+ model.properties(name).indexes
249
+ end
250
+
251
+ # @api private
252
+ def unique_indexes(model)
253
+ model.properties(name).unique_indexes
254
+ end
255
+
256
+ # @api private
257
+ def add_column_statement
258
+ 'ADD COLUMN'
259
+ end
260
+ end
261
+
262
+ include SQL
263
+
264
+ module ClassMethods
265
+ # Default types for all data object based adapters.
266
+ #
267
+ # @return [Hash] default types for data objects adapters.
268
+ #
269
+ # @api private
270
+ def type_map
271
+ length = Property::String.length
272
+ precision = Property::Numeric.precision
273
+ scale = Property::Decimal.scale
274
+
275
+ {
276
+ Property::Binary => {primitive: 'BLOB'},
277
+ Object => {primitive: 'TEXT'},
278
+ Integer => {primitive: 'INTEGER'},
279
+ String => {primitive: 'VARCHAR', length: length},
280
+ Class => {primitive: 'VARCHAR', length: length},
281
+ BigDecimal => {primitive: 'DECIMAL', precision: precision, scale: scale},
282
+ Float => {primitive: 'FLOAT', precision: precision},
283
+ DateTime => {primitive: 'TIMESTAMP'},
284
+ Date => {primitive: 'DATE'},
285
+ Time => {primitive: 'TIMESTAMP'},
286
+ TrueClass => {primitive: 'BOOLEAN'},
287
+ Property::Text => {primitive: 'TEXT'}
288
+ }.freeze
289
+ end
290
+
291
+ # Finds a type for a given property.
292
+ #
293
+ # @return [Hash | nil] type matching the given property or one of the properties ancestors
294
+ #
295
+ # @api private
296
+ def type_by_property_class(property_class)
297
+ return nil unless property_class < DataMapper::Property
298
+
299
+ type_map[property_class] || type_by_property_class(property_class.superclass)
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end