dm-migrations 0.10.2 → 1.0.0.rc1

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.
Files changed (33) hide show
  1. data/.gitignore +36 -0
  2. data/Gemfile +141 -0
  3. data/Rakefile +2 -3
  4. data/VERSION +1 -1
  5. data/dm-migrations.gemspec +50 -18
  6. data/lib/dm-migrations.rb +2 -0
  7. data/lib/dm-migrations/adapters/dm-do-adapter.rb +276 -0
  8. data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +283 -0
  9. data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +321 -0
  10. data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +159 -0
  11. data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +96 -0
  12. data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +177 -0
  13. data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +23 -0
  14. data/lib/dm-migrations/auto_migration.rb +238 -0
  15. data/lib/dm-migrations/migration.rb +3 -3
  16. data/lib/dm-migrations/sql.rb +2 -2
  17. data/lib/dm-migrations/sql/mysql.rb +3 -3
  18. data/lib/dm-migrations/sql/{postgresql.rb → postgres.rb} +3 -3
  19. data/lib/dm-migrations/sql/{sqlite3.rb → sqlite.rb} +3 -3
  20. data/spec/integration/auto_migration_spec.rb +506 -0
  21. data/spec/integration/migration_runner_spec.rb +12 -2
  22. data/spec/integration/migration_spec.rb +28 -14
  23. data/spec/integration/sql_spec.rb +22 -21
  24. data/spec/isolated/require_after_setup_spec.rb +30 -0
  25. data/spec/isolated/require_before_setup_spec.rb +30 -0
  26. data/spec/isolated/require_spec.rb +25 -0
  27. data/spec/spec_helper.rb +10 -25
  28. data/spec/unit/migration_spec.rb +320 -319
  29. data/spec/unit/sql/{postgresql_spec.rb → postgres_spec.rb} +17 -17
  30. data/spec/unit/sql/{sqlite3_extensions_spec.rb → sqlite_extensions_spec.rb} +14 -14
  31. data/tasks/local_gemfile.rake +18 -0
  32. data/tasks/spec.rake +0 -3
  33. metadata +72 -32
data/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+
19
+ ## PROJECT::GENERAL
20
+ *.gem
21
+ coverage
22
+ rdoc
23
+ pkg
24
+ tmp
25
+ doc
26
+ log
27
+ .yardoc
28
+ measurements
29
+
30
+ ## BUNDLER
31
+ .bundle
32
+ Gemfile.local
33
+ Gemfile.lock
34
+
35
+ ## PROJECT::SPECIFIC
36
+ spec/db/
data/Gemfile ADDED
@@ -0,0 +1,141 @@
1
+ # If you're working on more than one datamapper gem at a time, then it's
2
+ # recommended to create a local Gemfile and use this instead of the git
3
+ # sources. This will make sure that you are developing against your
4
+ # other local datamapper sources that you currently work on. Gemfile.local
5
+ # will behave identically to the standard Gemfile apart from the fact that
6
+ # it fetches the datamapper gems from local paths. This means that you can use
7
+ # the same environment variables, like ADAPTER(S) or PLUGIN(S) when running
8
+ # bundle commands. Gemfile.local is added to .gitignore, so you don't need to
9
+ # worry about accidentally checking local development paths into git.
10
+ # In order to create a local Gemfile, all you need to do is run:
11
+ #
12
+ # bundle exec rake local_gemfile
13
+ #
14
+ # This will give you a Gemfile.local file that points to your local clones of
15
+ # the various datamapper gems. It's assumed that all datamapper repo clones
16
+ # reside in the same directory. You can use the Gemfile.local like so for
17
+ # running any bundle command:
18
+ #
19
+ # BUNDLE_GEMFILE=Gemfile.local bundle foo
20
+ #
21
+ # You can also specify which adapter(s) should be part of the bundle by setting
22
+ # an environment variable. This of course also works when using the Gemfile.local
23
+ #
24
+ # bundle foo # dm-sqlite-adapter
25
+ # ADAPTER=mysql bundle foo # dm-mysql-adapter
26
+ # ADAPTERS=sqlite,mysql bundle foo # dm-sqlite-adapter and dm-mysql-adapter
27
+ #
28
+ # Of course you can also use the ADAPTER(S) variable when using the Gemfile.local
29
+ # and running specs against selected adapters.
30
+ #
31
+ # For easily working with adapters supported on your machine, it's recommended
32
+ # that you first install all adapters that you are planning to use or work on
33
+ # by doing something like
34
+ #
35
+ # ADAPTERS=sqlite,mysql,postgres bundle install
36
+ #
37
+ # This will clone the various repositories and make them available to bundler.
38
+ # Once you have them installed you can easily switch between adapters for the
39
+ # various development tasks. Running something like
40
+ #
41
+ # ADAPTER=mysql bundle exec rake spec
42
+ #
43
+ # will make sure that the dm-mysql-adapter is part of the bundle, and will be used
44
+ # when running the specs.
45
+ #
46
+ # You can also specify which plugin(s) should be part of the bundle by setting
47
+ # an environment variable. This also works when using the Gemfile.local
48
+ #
49
+ # bundle foo # dm-migrations
50
+ # PLUGINS=dm-validations bundle foo # dm-migrations and dm-validations
51
+ # PLUGINS=dm-validations,dm-types bundle foo # dm-migrations, dm-validations and dm-types
52
+ #
53
+ # Of course you can combine the PLUGIN(S) and ADAPTER(S) env vars to run specs
54
+ # for certain adapter/plugin combinations.
55
+ #
56
+ # Finally, to speed up running specs and other tasks, it's recommended to run
57
+ #
58
+ # bundle lock
59
+ #
60
+ # after running 'bundle install' for the first time. This will make 'bundle exec' run
61
+ # a lot faster compared to the unlocked version. With an unlocked bundle you would
62
+ # typically just run 'bundle install' from time to time to fetch the latest sources from
63
+ # upstream. When you locked your bundle, you need to run
64
+ #
65
+ # bundle install --relock
66
+ #
67
+ # to make sure to fetch the latest updates and then lock the bundle again. Gemfile.lock
68
+ # is added to the .gitignore file, so you don't need to worry about accidentally checking
69
+ # it into version control.
70
+
71
+ source 'http://rubygems.org'
72
+
73
+ DATAMAPPER = 'git://github.com/datamapper'
74
+ DM_VERSION = '~> 1.0.0.rc1'
75
+
76
+ group :runtime do # Runtime dependencies (as in the gemspec)
77
+
78
+ if ENV['EXTLIB']
79
+ gem 'extlib', '~> 0.9.15', :git => "#{DATAMAPPER}/extlib.git"
80
+ else
81
+ gem 'activesupport', '~> 3.0.0.beta3', :git => 'git://github.com/rails/rails.git', :require => nil
82
+ end
83
+
84
+ gem 'dm-core', DM_VERSION, :git => "#{DATAMAPPER}/dm-core.git"
85
+
86
+ end
87
+
88
+ group(:development) do # Development dependencies (as in the gemspec)
89
+
90
+ gem 'rake', '~> 0.8.7'
91
+ gem 'rspec', '~> 1.3'
92
+ gem 'jeweler', '~> 1.4'
93
+
94
+ end
95
+
96
+ group :quality do # These gems contain rake tasks that check the quality of the source code
97
+
98
+ gem 'metric_fu', '~> 1.3'
99
+ gem 'rcov', '~> 0.9.7'
100
+ gem 'reek', '~> 1.2.7'
101
+ gem 'roodi', '~> 2.1'
102
+ gem 'yard', '~> 0.5'
103
+ gem 'yardstick', '~> 0.1'
104
+
105
+ end
106
+
107
+ group :datamapper do # We need this because we want to pin these dependencies to their git master sources
108
+
109
+ adapters = ENV['ADAPTER'] || ENV['ADAPTERS']
110
+ adapters = adapters.to_s.gsub(',',' ').split(' ') - ['in_memory']
111
+
112
+ unless adapters.empty?
113
+
114
+ DO_VERSION = '~> 0.10.2'
115
+ DM_DO_ADAPTERS = %w[sqlite postgres mysql oracle sqlserver]
116
+
117
+ gem 'data_objects', DO_VERSION, :git => "#{DATAMAPPER}/do.git"
118
+
119
+ adapters.each do |adapter|
120
+ if DM_DO_ADAPTERS.any? { |dm_do_adapter| dm_do_adapter =~ /#{adapter}/ }
121
+ adapter = 'sqlite3' if adapter == 'sqlite'
122
+ gem "do_#{adapter}", DO_VERSION, :git => "#{DATAMAPPER}/do.git"
123
+ end
124
+ end
125
+
126
+ gem 'dm-do-adapter', DM_VERSION, :git => "#{DATAMAPPER}/dm-do-adapter.git"
127
+
128
+ adapters.each do |adapter|
129
+ gem "dm-#{adapter}-adapter", DM_VERSION, :git => "#{DATAMAPPER}/dm-#{adapter}-adapter.git"
130
+ end
131
+
132
+ end
133
+
134
+ plugins = ENV['PLUGINS'] || ENV['PLUGIN']
135
+ plugins = (plugins.to_s.gsub(',',' ').split(' ') + ['dm-migrations']).uniq
136
+
137
+ plugins.each do |plugin|
138
+ gem plugin, DM_VERSION, :git => "#{DATAMAPPER}/#{plugin}.git"
139
+ end
140
+
141
+ end
data/Rakefile CHANGED
@@ -15,10 +15,9 @@ begin
15
15
 
16
16
  gem.rubyforge_project = 'datamapper'
17
17
 
18
- gem.add_dependency 'dm-core', '~> 0.10.2'
18
+ gem.add_dependency 'dm-core', '~> 1.0.0.rc1'
19
19
 
20
- gem.add_development_dependency 'rspec', '~> 1.2.9'
21
- gem.add_development_dependency 'yard', '~> 0.4.0'
20
+ gem.add_development_dependency 'rspec', '~> 1.3'
22
21
  end
23
22
 
24
23
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.2
1
+ 1.0.0.rc1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dm-migrations}
8
- s.version = "0.10.2"
8
+ s.version = "1.0.0.rc1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Paul Sadauskas"]
12
- s.date = %q{2009-12-11}
12
+ s.date = %q{2010-05-19}
13
13
  s.description = %q{DataMapper plugin for writing and speccing migrations}
14
14
  s.email = %q{psadauskas [a] gmail [d] com}
15
15
  s.extra_rdoc_files = [
@@ -17,7 +17,9 @@ Gem::Specification.new do |s|
17
17
  "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
- "LICENSE",
20
+ ".gitignore",
21
+ "Gemfile",
22
+ "LICENSE",
21
23
  "README.rdoc",
22
24
  "Rakefile",
23
25
  "VERSION",
@@ -28,33 +30,46 @@ Gem::Specification.new do |s|
28
30
  "examples/sample_migration.rb",
29
31
  "examples/sample_migration_spec.rb",
30
32
  "lib/dm-migrations.rb",
33
+ "lib/dm-migrations/adapters/dm-do-adapter.rb",
34
+ "lib/dm-migrations/adapters/dm-mysql-adapter.rb",
35
+ "lib/dm-migrations/adapters/dm-oracle-adapter.rb",
36
+ "lib/dm-migrations/adapters/dm-postgres-adapter.rb",
37
+ "lib/dm-migrations/adapters/dm-sqlite-adapter.rb",
38
+ "lib/dm-migrations/adapters/dm-sqlserver-adapter.rb",
39
+ "lib/dm-migrations/adapters/dm-yaml-adapter.rb",
40
+ "lib/dm-migrations/auto_migration.rb",
31
41
  "lib/dm-migrations/migration.rb",
32
42
  "lib/dm-migrations/migration_runner.rb",
33
43
  "lib/dm-migrations/sql.rb",
34
44
  "lib/dm-migrations/sql/column.rb",
35
45
  "lib/dm-migrations/sql/mysql.rb",
36
- "lib/dm-migrations/sql/postgresql.rb",
37
- "lib/dm-migrations/sql/sqlite3.rb",
46
+ "lib/dm-migrations/sql/postgres.rb",
47
+ "lib/dm-migrations/sql/sqlite.rb",
38
48
  "lib/dm-migrations/sql/table.rb",
39
49
  "lib/dm-migrations/sql/table_creator.rb",
40
50
  "lib/dm-migrations/sql/table_modifier.rb",
41
51
  "lib/spec/example/migration_example_group.rb",
42
52
  "lib/spec/matchers/migration_matchers.rb",
53
+ "spec/integration/auto_migration_spec.rb",
43
54
  "spec/integration/migration_runner_spec.rb",
44
55
  "spec/integration/migration_spec.rb",
45
56
  "spec/integration/sql_spec.rb",
57
+ "spec/isolated/require_after_setup_spec.rb",
58
+ "spec/isolated/require_before_setup_spec.rb",
59
+ "spec/isolated/require_spec.rb",
46
60
  "spec/rcov.opts",
47
61
  "spec/spec.opts",
48
62
  "spec/spec_helper.rb",
49
63
  "spec/unit/migration_spec.rb",
50
64
  "spec/unit/sql/column_spec.rb",
51
- "spec/unit/sql/postgresql_spec.rb",
52
- "spec/unit/sql/sqlite3_extensions_spec.rb",
65
+ "spec/unit/sql/postgres_spec.rb",
66
+ "spec/unit/sql/sqlite_extensions_spec.rb",
53
67
  "spec/unit/sql/table_creator_spec.rb",
54
68
  "spec/unit/sql/table_modifier_spec.rb",
55
69
  "spec/unit/sql/table_spec.rb",
56
70
  "spec/unit/sql_spec.rb",
57
71
  "tasks/ci.rake",
72
+ "tasks/local_gemfile.rake",
58
73
  "tasks/metrics.rake",
59
74
  "tasks/spec.rake",
60
75
  "tasks/yard.rake",
@@ -64,26 +79,43 @@ Gem::Specification.new do |s|
64
79
  s.rdoc_options = ["--charset=UTF-8"]
65
80
  s.require_paths = ["lib"]
66
81
  s.rubyforge_project = %q{datamapper}
67
- s.rubygems_version = %q{1.3.5}
82
+ s.rubygems_version = %q{1.3.6}
68
83
  s.summary = %q{DataMapper plugin for writing and speccing migrations}
84
+ s.test_files = [
85
+ "spec/integration/auto_migration_spec.rb",
86
+ "spec/integration/migration_runner_spec.rb",
87
+ "spec/integration/migration_spec.rb",
88
+ "spec/integration/sql_spec.rb",
89
+ "spec/isolated/require_after_setup_spec.rb",
90
+ "spec/isolated/require_before_setup_spec.rb",
91
+ "spec/isolated/require_spec.rb",
92
+ "spec/spec_helper.rb",
93
+ "spec/unit/migration_spec.rb",
94
+ "spec/unit/sql/column_spec.rb",
95
+ "spec/unit/sql/postgres_spec.rb",
96
+ "spec/unit/sql/sqlite_extensions_spec.rb",
97
+ "spec/unit/sql/table_creator_spec.rb",
98
+ "spec/unit/sql/table_modifier_spec.rb",
99
+ "spec/unit/sql/table_spec.rb",
100
+ "spec/unit/sql_spec.rb",
101
+ "examples/sample_migration.rb",
102
+ "examples/sample_migration_spec.rb"
103
+ ]
69
104
 
70
105
  if s.respond_to? :specification_version then
71
106
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
72
107
  s.specification_version = 3
73
108
 
74
109
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
75
- s.add_runtime_dependency(%q<dm-core>, ["~> 0.10.2"])
76
- s.add_development_dependency(%q<rspec>, ["~> 1.2.9"])
77
- s.add_development_dependency(%q<yard>, ["~> 0.4.0"])
110
+ s.add_runtime_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
111
+ s.add_development_dependency(%q<rspec>, ["~> 1.3"])
78
112
  else
79
- s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
80
- s.add_dependency(%q<rspec>, ["~> 1.2.9"])
81
- s.add_dependency(%q<yard>, ["~> 0.4.0"])
113
+ s.add_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
114
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
82
115
  end
83
116
  else
84
- s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
85
- s.add_dependency(%q<rspec>, ["~> 1.2.9"])
86
- s.add_dependency(%q<yard>, ["~> 0.4.0"])
117
+ s.add_dependency(%q<dm-core>, ["~> 1.0.0.rc1"])
118
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
87
119
  end
88
120
  end
89
121
 
data/lib/dm-migrations.rb CHANGED
@@ -1 +1,3 @@
1
+ require 'dm-core'
1
2
  require 'dm-migrations/migration'
3
+ require 'dm-migrations/auto_migration'
@@ -0,0 +1,276 @@
1
+ require 'dm-migrations/auto_migration'
2
+
3
+ module DataMapper
4
+ module Migrations
5
+
6
+ module DataObjectsAdapter
7
+
8
+ # Returns whether the storage_name exists.
9
+ #
10
+ # @param [String] storage_name
11
+ # a String defining the name of a storage, for example a table name.
12
+ #
13
+ # @return [Boolean]
14
+ # true if the storage exists
15
+ #
16
+ # @api semipublic
17
+ def storage_exists?(storage_name)
18
+ statement = <<-SQL.compress_lines
19
+ SELECT COUNT(*)
20
+ FROM "information_schema"."tables"
21
+ WHERE "table_type" = 'BASE TABLE'
22
+ AND "table_schema" = ?
23
+ AND "table_name" = ?
24
+ SQL
25
+
26
+ select(statement, schema_name, storage_name).first > 0
27
+ end
28
+
29
+ # Returns whether the field exists.
30
+ #
31
+ # @param [String] storage_name
32
+ # a String defining the name of a storage, for example a table name.
33
+ # @param [String] field
34
+ # a String defining the name of a field, for example a column name.
35
+ #
36
+ # @return [Boolean]
37
+ # true if the field exists.
38
+ #
39
+ # @api semipublic
40
+ def field_exists?(storage_name, column_name)
41
+ statement = <<-SQL.compress_lines
42
+ SELECT COUNT(*)
43
+ FROM "information_schema"."columns"
44
+ WHERE "table_schema" = ?
45
+ AND "table_name" = ?
46
+ AND "column_name" = ?
47
+ SQL
48
+
49
+ select(statement, schema_name, storage_name, column_name).first > 0
50
+ end
51
+
52
+ # @api semipublic
53
+ def upgrade_model_storage(model)
54
+ name = self.name
55
+ properties = model.properties_with_subclasses(name)
56
+
57
+ if success = create_model_storage(model)
58
+ return properties
59
+ end
60
+
61
+ table_name = model.storage_name(name)
62
+
63
+ with_connection do |connection|
64
+ properties.map do |property|
65
+ schema_hash = property_schema_hash(property)
66
+ next if field_exists?(table_name, schema_hash[:name])
67
+
68
+ statement = alter_table_add_column_statement(connection, table_name, schema_hash)
69
+ command = connection.create_command(statement)
70
+ command.execute_non_query
71
+
72
+ property
73
+ end.compact
74
+ end
75
+ end
76
+
77
+ # @api semipublic
78
+ def create_model_storage(model)
79
+ name = self.name
80
+ properties = model.properties_with_subclasses(name)
81
+
82
+ return false if storage_exists?(model.storage_name(name))
83
+ return false if properties.empty?
84
+
85
+ with_connection do |connection|
86
+ statements = [ create_table_statement(connection, model, properties) ]
87
+ statements.concat(create_index_statements(model))
88
+ statements.concat(create_unique_index_statements(model))
89
+
90
+ statements.each do |statement|
91
+ command = connection.create_command(statement)
92
+ command.execute_non_query
93
+ end
94
+ end
95
+
96
+ true
97
+ end
98
+
99
+ # @api semipublic
100
+ def destroy_model_storage(model)
101
+ return true unless supports_drop_table_if_exists? || storage_exists?(model.storage_name(name))
102
+ execute(drop_table_statement(model))
103
+ true
104
+ end
105
+
106
+ module SQL #:nodoc:
107
+ # private ## This cannot be private for current migrations
108
+
109
+ # Adapters that support AUTO INCREMENT fields for CREATE TABLE
110
+ # statements should overwrite this to return true
111
+ #
112
+ # @api private
113
+ def supports_serial?
114
+ false
115
+ end
116
+
117
+ # @api private
118
+ def supports_drop_table_if_exists?
119
+ false
120
+ end
121
+
122
+ # @api private
123
+ def schema_name
124
+ raise NotImplementedError, "#{self.class}#schema_name not implemented"
125
+ end
126
+
127
+ # @api private
128
+ def alter_table_add_column_statement(connection, table_name, schema_hash)
129
+ "ALTER TABLE #{quote_name(table_name)} ADD COLUMN #{property_schema_statement(connection, schema_hash)}"
130
+ end
131
+
132
+ # @api private
133
+ def create_table_statement(connection, model, properties)
134
+ statement = <<-SQL.compress_lines
135
+ CREATE TABLE #{quote_name(model.storage_name(name))}
136
+ (#{properties.map { |property| property_schema_statement(connection, property_schema_hash(property)) }.join(', ')},
137
+ PRIMARY KEY(#{ properties.key.map { |property| quote_name(property.field) }.join(', ')}))
138
+ SQL
139
+
140
+ statement
141
+ end
142
+
143
+ # @api private
144
+ def drop_table_statement(model)
145
+ table_name = quote_name(model.storage_name(name))
146
+ if supports_drop_table_if_exists?
147
+ "DROP TABLE IF EXISTS #{table_name}"
148
+ else
149
+ "DROP TABLE #{table_name}"
150
+ end
151
+ end
152
+
153
+ # @api private
154
+ def create_index_statements(model)
155
+ name = self.name
156
+ table_name = model.storage_name(name)
157
+ indexes(model).map do |index_name, fields|
158
+ <<-SQL.compress_lines
159
+ CREATE INDEX #{quote_name("index_#{table_name}_#{index_name}")} ON
160
+ #{quote_name(table_name)} (#{fields.map { |field| quote_name(field) }.join(', ')})
161
+ SQL
162
+ end
163
+ end
164
+
165
+ # @api private
166
+ def create_unique_index_statements(model)
167
+ name = self.name
168
+ table_name = model.storage_name(name)
169
+ unique_indexes(model).map do |index_name, fields|
170
+ <<-SQL.compress_lines
171
+ CREATE UNIQUE INDEX #{quote_name("unique_#{table_name}_#{index_name}")} ON
172
+ #{quote_name(table_name)} (#{fields.map { |field| quote_name(field) }.join(', ')})
173
+ SQL
174
+ end
175
+ end
176
+
177
+ # @api private
178
+ def property_schema_hash(property)
179
+ primitive = property.primitive
180
+ type = property.type
181
+ type_map = self.class.type_map
182
+
183
+ schema = (type_map[property.class] || type_map[primitive] || type_map[type]).merge(:name => property.field)
184
+
185
+ schema_primitive = schema[:primitive]
186
+
187
+ if primitive == String && schema_primitive != 'TEXT' && schema_primitive != 'CLOB' && schema_primitive != 'NVARCHAR'
188
+ schema[:length] = property.length
189
+ elsif primitive == BigDecimal || primitive == Float
190
+ schema[:precision] = property.precision
191
+ schema[:scale] = property.scale
192
+ end
193
+
194
+ schema[:allow_nil] = property.allow_nil?
195
+ schema[:serial] = property.serial?
196
+
197
+ default = property.default
198
+
199
+ if default.nil? || default.respond_to?(:call)
200
+ # remove the default if the property does not allow nil
201
+ schema.delete(:default) unless schema[:allow_nil]
202
+ else
203
+ schema[:default] = if type.respond_to?(:dump)
204
+ type.dump(default, property)
205
+ else
206
+ default
207
+ end
208
+ end
209
+
210
+ schema
211
+ end
212
+
213
+ # @api private
214
+ def property_schema_statement(connection, schema)
215
+ statement = quote_name(schema[:name])
216
+ statement << " #{schema[:primitive]}"
217
+
218
+ length = schema[:length]
219
+
220
+ if schema[:precision] && schema[:scale]
221
+ statement << "(#{[ :precision, :scale ].map { |key| connection.quote_value(schema[key]) }.join(', ')})"
222
+ elsif length == 'max'
223
+ statement << '(max)'
224
+ elsif length
225
+ statement << "(#{connection.quote_value(length)})"
226
+ end
227
+
228
+ statement << " DEFAULT #{connection.quote_value(schema[:default])}" if schema.key?(:default)
229
+ statement << ' NOT NULL' unless schema[:allow_nil]
230
+ statement
231
+ end
232
+
233
+ # @api private
234
+ def indexes(model)
235
+ model.properties(name).indexes
236
+ end
237
+
238
+ # @api private
239
+ def unique_indexes(model)
240
+ model.properties(name).unique_indexes
241
+ end
242
+ end # module SQL
243
+
244
+ include SQL
245
+
246
+ module ClassMethods
247
+ # Default types for all data object based adapters.
248
+ #
249
+ # @return [Hash] default types for data objects adapters.
250
+ #
251
+ # @api private
252
+ def type_map
253
+ length = Property::String::DEFAULT_LENGTH
254
+ precision = Property::Numeric::DEFAULT_PRECISION
255
+ scale = Property::Decimal::DEFAULT_SCALE
256
+
257
+ @type_map ||= {
258
+ Property::Binary => { :primitive => 'BLOB' },
259
+ Object => { :primitive => 'TEXT' },
260
+ Integer => { :primitive => 'INTEGER' },
261
+ String => { :primitive => 'VARCHAR', :length => length },
262
+ Class => { :primitive => 'VARCHAR', :length => length },
263
+ BigDecimal => { :primitive => 'DECIMAL', :precision => precision, :scale => scale },
264
+ Float => { :primitive => 'FLOAT', :precision => precision },
265
+ DateTime => { :primitive => 'TIMESTAMP' },
266
+ Date => { :primitive => 'DATE' },
267
+ Time => { :primitive => 'TIMESTAMP' },
268
+ TrueClass => { :primitive => 'BOOLEAN' },
269
+ Property::Text => { :primitive => 'TEXT' },
270
+ }.freeze
271
+ end
272
+ end
273
+ end
274
+
275
+ end
276
+ end