dm-migrations 0.10.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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