sbf-dm-migrations 1.3.0.beta

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 (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,590 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'dm-migrations/auto_migration'
4
+
5
+ module DataMapper
6
+ class Property
7
+ class NumericString < DataMapper::Property::String
8
+ default 0
9
+
10
+ def dump(value)
11
+ return if value.nil?
12
+
13
+ value.to_s
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ module ::Blog
20
+ class Article
21
+ include DataMapper::Resource
22
+ end
23
+ end
24
+
25
+ describe DataMapper::Migrations do
26
+ def capture_log(mod)
27
+ original = mod.logger
28
+ mod.logger = DataObjects::Logger.new(@log = StringIO.new, :debug)
29
+ yield
30
+ ensure
31
+ @log.rewind
32
+ @output = @log.readlines.map do |line|
33
+ line.chomp.gsub(/\A.+?~ \(\d+\.?\d*\)\s+/, '')
34
+ end
35
+
36
+ mod.logger = original
37
+ end
38
+
39
+ supported_by :mysql do
40
+ before :all do
41
+ @model = Blog::Article
42
+ end
43
+
44
+ describe '#auto_migrate' do
45
+ describe 'Integer property' do
46
+ [
47
+ [0, 1, 'TINYINT(1) UNSIGNED'],
48
+ [0, 9, 'TINYINT(1) UNSIGNED'],
49
+ [0, 10, 'TINYINT(2) UNSIGNED'],
50
+ [0, 99, 'TINYINT(2) UNSIGNED'],
51
+ [0, 100, 'TINYINT(3) UNSIGNED'],
52
+ [0, 255, 'TINYINT(3) UNSIGNED'],
53
+ [0, 256, 'SMALLINT(3) UNSIGNED'],
54
+ [0, 999, 'SMALLINT(3) UNSIGNED'],
55
+ [0, 1000, 'SMALLINT(4) UNSIGNED'],
56
+ [0, 9999, 'SMALLINT(4) UNSIGNED'],
57
+ [0, 10_000, 'SMALLINT(5) UNSIGNED'],
58
+ [0, 65_535, 'SMALLINT(5) UNSIGNED'],
59
+ [0, 65_536, 'MEDIUMINT(5) UNSIGNED'],
60
+ [0, 99_999, 'MEDIUMINT(5) UNSIGNED'],
61
+ [0, 100_000, 'MEDIUMINT(6) UNSIGNED'],
62
+ [0, 999_999, 'MEDIUMINT(6) UNSIGNED'],
63
+ [0, 1_000_000, 'MEDIUMINT(7) UNSIGNED'],
64
+ [0, 9_999_999, 'MEDIUMINT(7) UNSIGNED'],
65
+ [0, 10_000_000, 'MEDIUMINT(8) UNSIGNED'],
66
+ [0, 16_777_215, 'MEDIUMINT(8) UNSIGNED'],
67
+ [0, 16_777_216, 'INT(8) UNSIGNED'],
68
+ [0, 99_999_999, 'INT(8) UNSIGNED'],
69
+ [0, 100_000_000, 'INT(9) UNSIGNED'],
70
+ [0, 999_999_999, 'INT(9) UNSIGNED'],
71
+ [0, 1_000_000_000, 'INT(10) UNSIGNED'],
72
+ [0, 4_294_967_295, 'INT(10) UNSIGNED'],
73
+ [0, 4_294_967_296, 'BIGINT(10) UNSIGNED'],
74
+ [0, 9_999_999_999, 'BIGINT(10) UNSIGNED'],
75
+ [0, 10_000_000_000, 'BIGINT(11) UNSIGNED'],
76
+ [0, 99_999_999_999, 'BIGINT(11) UNSIGNED'],
77
+ [0, 100_000_000_000, 'BIGINT(12) UNSIGNED'],
78
+ [0, 999_999_999_999, 'BIGINT(12) UNSIGNED'],
79
+ [0, 1_000_000_000_000, 'BIGINT(13) UNSIGNED'],
80
+ [0, 9_999_999_999_999, 'BIGINT(13) UNSIGNED'],
81
+ [0, 10_000_000_000_000, 'BIGINT(14) UNSIGNED'],
82
+ [0, 99_999_999_999_999, 'BIGINT(14) UNSIGNED'],
83
+ [0, 100_000_000_000_000, 'BIGINT(15) UNSIGNED'],
84
+ [0, 999_999_999_999_999, 'BIGINT(15) UNSIGNED'],
85
+ [0, 1_000_000_000_000_000, 'BIGINT(16) UNSIGNED'],
86
+ [0, 9_999_999_999_999_999, 'BIGINT(16) UNSIGNED'],
87
+ [0, 10_000_000_000_000_000, 'BIGINT(17) UNSIGNED'],
88
+ [0, 99_999_999_999_999_999, 'BIGINT(17) UNSIGNED'],
89
+ [0, 100_000_000_000_000_000, 'BIGINT(18) UNSIGNED'],
90
+ [0, 999_999_999_999_999_999, 'BIGINT(18) UNSIGNED'],
91
+ [0, 1_000_000_000_000_000_000, 'BIGINT(19) UNSIGNED'],
92
+ [0, 9_999_999_999_999_999_999, 'BIGINT(19) UNSIGNED'],
93
+ [0, 10_000_000_000_000_000_000, 'BIGINT(20) UNSIGNED'],
94
+ [0, 18_446_744_073_709_551_615, 'BIGINT(20) UNSIGNED'],
95
+
96
+ [-1, 0, 'TINYINT(2)'],
97
+ [-1, 9, 'TINYINT(2)'],
98
+ [-1, 10, 'TINYINT(2)'],
99
+ [-1, 99, 'TINYINT(2)'],
100
+ [-1, 100, 'TINYINT(3)'],
101
+ [-1, 127, 'TINYINT(3)'],
102
+ [-1, 128, 'SMALLINT(3)'],
103
+ [-1, 999, 'SMALLINT(3)'],
104
+ [-1, 1000, 'SMALLINT(4)'],
105
+ [-1, 9999, 'SMALLINT(4)'],
106
+ [-1, 10_000, 'SMALLINT(5)'],
107
+ [-1, 32_767, 'SMALLINT(5)'],
108
+ [-1, 32_768, 'MEDIUMINT(5)'],
109
+ [-1, 99_999, 'MEDIUMINT(5)'],
110
+ [-1, 100_000, 'MEDIUMINT(6)'],
111
+ [-1, 999_999, 'MEDIUMINT(6)'],
112
+ [-1, 1_000_000, 'MEDIUMINT(7)'],
113
+ [-1, 8_388_607, 'MEDIUMINT(7)'],
114
+ [-1, 8_388_608, 'INT(7)'],
115
+ [-1, 9_999_999, 'INT(7)'],
116
+ [-1, 10_000_000, 'INT(8)'],
117
+ [-1, 99_999_999, 'INT(8)'],
118
+ [-1, 100_000_000, 'INT(9)'],
119
+ [-1, 999_999_999, 'INT(9)'],
120
+ [-1, 1_000_000_000, 'INT(10)'],
121
+ [-1, 2_147_483_647, 'INT(10)'],
122
+ [-1, 2_147_483_648, 'BIGINT(10)'],
123
+ [-1, 9_999_999_999, 'BIGINT(10)'],
124
+ [-1, 10_000_000_000, 'BIGINT(11)'],
125
+ [-1, 99_999_999_999, 'BIGINT(11)'],
126
+ [-1, 100_000_000_000, 'BIGINT(12)'],
127
+ [-1, 999_999_999_999, 'BIGINT(12)'],
128
+ [-1, 1_000_000_000_000, 'BIGINT(13)'],
129
+ [-1, 9_999_999_999_999, 'BIGINT(13)'],
130
+ [-1, 10_000_000_000_000, 'BIGINT(14)'],
131
+ [-1, 99_999_999_999_999, 'BIGINT(14)'],
132
+ [-1, 100_000_000_000_000, 'BIGINT(15)'],
133
+ [-1, 999_999_999_999_999, 'BIGINT(15)'],
134
+ [-1, 1_000_000_000_000_000, 'BIGINT(16)'],
135
+ [-1, 9_999_999_999_999_999, 'BIGINT(16)'],
136
+ [-1, 10_000_000_000_000_000, 'BIGINT(17)'],
137
+ [-1, 99_999_999_999_999_999, 'BIGINT(17)'],
138
+ [-1, 100_000_000_000_000_000, 'BIGINT(18)'],
139
+ [-1, 999_999_999_999_999_999, 'BIGINT(18)'],
140
+ [-1, 1_000_000_000_000_000_000, 'BIGINT(19)'],
141
+ [-1, 9_223_372_036_854_775_807, 'BIGINT(19)'],
142
+
143
+ [-1, 0, 'TINYINT(2)'],
144
+ [-9, 0, 'TINYINT(2)'],
145
+ [-10, 0, 'TINYINT(3)'],
146
+ [-99, 0, 'TINYINT(3)'],
147
+ [-100, 0, 'TINYINT(4)'],
148
+ [-128, 0, 'TINYINT(4)'],
149
+ [-129, 0, 'SMALLINT(4)'],
150
+ [-999, 0, 'SMALLINT(4)'],
151
+ [-1000, 0, 'SMALLINT(5)'],
152
+ [-9999, 0, 'SMALLINT(5)'],
153
+ [-10_000, 0, 'SMALLINT(6)'],
154
+ [-32_768, 0, 'SMALLINT(6)'],
155
+ [-32_769, 0, 'MEDIUMINT(6)'],
156
+ [-99_999, 0, 'MEDIUMINT(6)'],
157
+ [-100_000, 0, 'MEDIUMINT(7)'],
158
+ [-999_999, 0, 'MEDIUMINT(7)'],
159
+ [-1_000_000, 0, 'MEDIUMINT(8)'],
160
+ [-8_388_608, 0, 'MEDIUMINT(8)'],
161
+ [-8_388_609, 0, 'INT(8)'],
162
+ [-9_999_999, 0, 'INT(8)'],
163
+ [-10_000_000, 0, 'INT(9)'],
164
+ [-99_999_999, 0, 'INT(9)'],
165
+ [-100_000_000, 0, 'INT(10)'],
166
+ [-999_999_999, 0, 'INT(10)'],
167
+ [-1_000_000_000, 0, 'INT(11)'],
168
+ [-2_147_483_648, 0, 'INT(11)'],
169
+ [-2_147_483_649, 0, 'BIGINT(11)'],
170
+ [-9_999_999_999, 0, 'BIGINT(11)'],
171
+ [-10_000_000_000, 0, 'BIGINT(12)'],
172
+ [-99_999_999_999, 0, 'BIGINT(12)'],
173
+ [-100_000_000_000, 0, 'BIGINT(13)'],
174
+ [-999_999_999_999, 0, 'BIGINT(13)'],
175
+ [-1_000_000_000_000, 0, 'BIGINT(14)'],
176
+ [-9_999_999_999_999, 0, 'BIGINT(14)'],
177
+ [-10_000_000_000_000, 0, 'BIGINT(15)'],
178
+ [-99_999_999_999_999, 0, 'BIGINT(15)'],
179
+ [-100_000_000_000_000, 0, 'BIGINT(16)'],
180
+ [-999_999_999_999_999, 0, 'BIGINT(16)'],
181
+ [-1_000_000_000_000_000, 0, 'BIGINT(17)'],
182
+ [-9_999_999_999_999_999, 0, 'BIGINT(17)'],
183
+ [-10_000_000_000_000_000, 0, 'BIGINT(18)'],
184
+ [-99_999_999_999_999_999, 0, 'BIGINT(18)'],
185
+ [-100_000_000_000_000_000, 0, 'BIGINT(19)'],
186
+ [-999_999_999_999_999_999, 0, 'BIGINT(19)'],
187
+ [-1_000_000_000_000_000_000, 0, 'BIGINT(20)'],
188
+ [-9_223_372_036_854_775_808, 0, 'BIGINT(20)'],
189
+
190
+ [nil, 2_147_483_647, 'INT(10) UNSIGNED'],
191
+ [0, nil, 'INT(10) UNSIGNED'],
192
+ [nil, nil, 'INTEGER']
193
+ ].each do |min, max, statement|
194
+ options = {key: true}
195
+ options[:min] = min if min
196
+ options[:max] = max if max
197
+
198
+ describe "with a min of #{min} and a max of #{max}" do
199
+ before :all do
200
+ @property = @model.property(:id, Integer, options)
201
+
202
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
203
+ end
204
+
205
+ it 'returns true' do
206
+ expect(@response).to be(true)
207
+ end
208
+
209
+ it "creates a #{statement} column" do
210
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` #{Regexp.escape(statement)} NOT NULL, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z/
211
+ end
212
+
213
+ %i(min max).each do |key|
214
+ next unless (value = options[key])
215
+
216
+ it "allows the #{key} value #{value} to be stored" do
217
+ if RUBY_PLATFORM[/java/] && JRUBY_VERSION < '1.5.6' && value == -9_223_372_036_854_775_808
218
+ pending "#{value} causes problem with JRuby 1.5.2 parser"
219
+ end
220
+
221
+ expect {
222
+ resource = @model.create(@property => value)
223
+ expect(@model.first(@property => value)).to eq resource
224
+ }.not_to raise_error
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ describe 'with a property that dumps as integer but has no min or max' do
231
+ before :all do
232
+ klass = Class.new(DataMapper::Property::Object) do
233
+ load_as Integer
234
+ dump_as Integer
235
+ end
236
+
237
+ @model.property(:id, DataMapper::Property::Serial)
238
+ @model.property(:number, klass)
239
+
240
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
241
+ end
242
+
243
+ it 'creates an INTEGER column' do
244
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `number` INTEGER, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE [a-z\d](?:_?[a-z\d]+)*\z/
245
+ end
246
+ end
247
+ end
248
+
249
+ describe 'Text property' do
250
+ before :all do
251
+ @model.property(:id, DataMapper::Property::Serial)
252
+ end
253
+
254
+ [
255
+ [0, 'TINYTEXT'],
256
+ [1, 'TINYTEXT'],
257
+ [255, 'TINYTEXT'],
258
+ [256, 'TEXT'],
259
+ [65_535, 'TEXT'],
260
+ [65_536, 'MEDIUMTEXT'],
261
+ [16_777_215, 'MEDIUMTEXT'],
262
+ [16_777_216, 'LONGTEXT'],
263
+ [4_294_967_295, 'LONGTEXT'],
264
+
265
+ [nil, 'TEXT']
266
+ ].each do |length, statement|
267
+ options = {}
268
+ options[:length] = length if length
269
+
270
+ describe "with a length of #{length}" do
271
+ before :all do
272
+ @property = @model.property(:body, DataMapper::Property::Text, options)
273
+
274
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
275
+ end
276
+
277
+ it 'returns true' do
278
+ expect(@response).to be(true)
279
+ end
280
+
281
+ it "creates a #{statement} column" do
282
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `body` #{Regexp.escape(statement)}, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z/
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ describe 'String property' do
289
+ before :all do
290
+ @model.property(:id, DataMapper::Property::Serial)
291
+ end
292
+
293
+ [
294
+ [1, 'VARCHAR(1)'],
295
+ [50, 'VARCHAR(50)'],
296
+ [255, 'VARCHAR(255)'],
297
+ [nil, 'VARCHAR(50)']
298
+ ].each do |length, statement|
299
+ options = {}
300
+ options[:length] = length if length
301
+
302
+ describe "with a length of #{length}" do
303
+ before :all do
304
+ @property = @model.property(:title, String, options)
305
+
306
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
307
+ end
308
+
309
+ it 'returns true' do
310
+ expect(@response).to be(true)
311
+ end
312
+
313
+ it "creates a #{statement} column" do
314
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `title` #{Regexp.escape(statement)}, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z/
315
+ end
316
+ end
317
+ end
318
+ end
319
+
320
+ describe 'NumericString property' do
321
+ before :all do
322
+ @model.property(:id, DataMapper::Property::Serial)
323
+ @model.property(:number, DataMapper::Property::NumericString)
324
+
325
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
326
+ end
327
+
328
+ it "creates a VARCHAR(50) column with a default of '0'" do
329
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `number` VARCHAR\(50\) DEFAULT '0', PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE [a-z\d](?:_?[a-z\d]+)*\z/
330
+ end
331
+ end
332
+
333
+ describe 'IntegerDumpedAsString property' do
334
+ before :all do
335
+ klass = Class.new(DataMapper::Property::Object) do
336
+ load_as Integer
337
+ dump_as String
338
+
339
+ attr_reader :length
340
+ end
341
+
342
+ @model.property(:id, DataMapper::Property::Serial)
343
+ @model.property(:number, klass)
344
+
345
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
346
+ end
347
+
348
+ it 'creates a large VARCHAR column' do
349
+ expect(@output.last).to match /\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `number` VARCHAR\(16383\), PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE [a-z\d](?:_?[a-z\d]+)*\z/
350
+ end
351
+ end
352
+ end
353
+ end
354
+
355
+ supported_by :postgres do
356
+ before :all do
357
+ @model = Blog::Article
358
+ end
359
+
360
+ describe '#auto_migrate' do
361
+ describe 'Integer property' do
362
+ [
363
+ [0, 1, 'SMALLINT'],
364
+ [0, 32_767, 'SMALLINT'],
365
+ [0, 32_768, 'INTEGER'],
366
+ [0, 2_147_483_647, 'INTEGER'],
367
+ [0, 2_147_483_648, 'BIGINT'],
368
+ [0, 9_223_372_036_854_775_807, 'BIGINT'],
369
+
370
+ [-1, 1, 'SMALLINT'],
371
+ [-1, 32_767, 'SMALLINT'],
372
+ [-1, 32_768, 'INTEGER'],
373
+ [-1, 2_147_483_647, 'INTEGER'],
374
+ [-1, 2_147_483_648, 'BIGINT'],
375
+ [-1, 9_223_372_036_854_775_807, 'BIGINT'],
376
+
377
+ [-1, 0, 'SMALLINT'],
378
+ [-32_768, 0, 'SMALLINT'],
379
+ [-32_769, 0, 'INTEGER'],
380
+ [-2_147_483_648, 0, 'INTEGER'],
381
+ [-2_147_483_649, 0, 'BIGINT'],
382
+ [-9_223_372_036_854_775_808, 0, 'BIGINT'],
383
+
384
+ [nil, 2_147_483_647, 'INTEGER'],
385
+ [0, nil, 'INTEGER'],
386
+ [nil, nil, 'INTEGER']
387
+ ].each do |min, max, statement|
388
+ options = {key: true}
389
+ options[:min] = min if min
390
+ options[:max] = max if max
391
+
392
+ describe "with a min of #{min} and a max of #{max}" do
393
+ before :all do
394
+ @property = @model.property(:id, Integer, options)
395
+
396
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
397
+ end
398
+
399
+ it 'returns true' do
400
+ expect(@response).to be(true)
401
+ end
402
+
403
+ it "creates a #{statement} column" do
404
+ expect(@output[-2]).to eq "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
405
+ end
406
+
407
+ %i(min max).each do |key|
408
+ next unless (value = options[key])
409
+
410
+ it "allows the #{key} value #{value} to be stored" do
411
+ if RUBY_PLATFORM =~ /java/ && JRUBY_VERSION < '1.6' && value == -9_223_372_036_854_775_808
412
+ pending "#{value} causes problem with the JRuby < 1.6 parser"
413
+ end
414
+
415
+ expect {
416
+ resource = @model.create(@property => value)
417
+ expect(@model.first(@property => value)).to eql(resource)
418
+ }.not_to raise_error
419
+ end
420
+ end
421
+ end
422
+ end
423
+ end
424
+
425
+ describe 'Serial property' do
426
+ [
427
+ [1, 'SERIAL'],
428
+ [2_147_483_647, 'SERIAL'],
429
+ [2_147_483_648, 'BIGSERIAL'],
430
+ [9_223_372_036_854_775_807, 'BIGSERIAL'],
431
+
432
+ [nil, 'SERIAL']
433
+ ].each do |max, statement|
434
+ options = {}
435
+ options[:max] = max if max
436
+
437
+ describe "with a max of #{max}" do
438
+ before :all do
439
+ @property = @model.property(:id, DataMapper::Property::Serial, options)
440
+
441
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
442
+ end
443
+
444
+ it 'returns true' do
445
+ expect(@response).to be(true)
446
+ end
447
+
448
+ it "creates a #{statement} column" do
449
+ expect(@output[-2]).to eq "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
450
+ end
451
+
452
+ %i(min max).each do |key|
453
+ next unless (value = options[key])
454
+
455
+ it "allows the #{key} value #{value} to be stored" do
456
+ expect {
457
+ resource = @model.create(@property => value)
458
+ expect(@model.first(@property => value)).to eql(resource)
459
+ }.not_to raise_error
460
+ end
461
+ end
462
+ end
463
+ end
464
+ end
465
+
466
+ describe 'String property' do
467
+ before :all do
468
+ @model.property(:id, DataMapper::Property::Serial)
469
+ end
470
+
471
+ [
472
+ [1, 'VARCHAR(1)'],
473
+ [50, 'VARCHAR(50)'],
474
+ [255, 'VARCHAR(255)'],
475
+ [nil, 'VARCHAR(50)']
476
+ ].each do |length, statement|
477
+ options = {}
478
+ options[:length] = length if length
479
+
480
+ describe "with a length of #{length}" do
481
+ before :all do
482
+ @property = @model.property(:title, String, options)
483
+
484
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
485
+ end
486
+
487
+ it 'returns true' do
488
+ expect(@response).to be(true)
489
+ end
490
+
491
+ it "creates a #{statement} column" do
492
+ expect(@output[-2]).to eq "CREATE TABLE \"blog_articles\" (\"id\" SERIAL NOT NULL, \"title\" #{statement}, PRIMARY KEY(\"id\"))"
493
+ end
494
+ end
495
+ end
496
+ end
497
+
498
+ describe 'NumericString property' do
499
+ before :all do
500
+ @model.property(:id, DataMapper::Property::Serial)
501
+ @model.property(:number, DataMapper::Property::NumericString)
502
+
503
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
504
+ end
505
+
506
+ it "creates a VARCHAR(50) column with a default of '0'" do
507
+ expect(@output[-2]).to eq "CREATE TABLE \"blog_articles\" (\"id\" SERIAL NOT NULL, \"number\" VARCHAR(50) DEFAULT '0', PRIMARY KEY(\"id\"))"
508
+ end
509
+ end
510
+ end
511
+ end
512
+
513
+ supported_by :sqlserver do
514
+ before :all do
515
+ @model = Blog::Article
516
+ end
517
+
518
+ describe '#auto_migrate' do
519
+ describe 'Integer property' do
520
+ [
521
+ [0, 1, 'TINYINT'],
522
+ [0, 255, 'TINYINT'],
523
+ [0, 256, 'SMALLINT'],
524
+ [0, 32_767, 'SMALLINT'],
525
+ [0, 32_768, 'INT'],
526
+ [0, 2_147_483_647, 'INT'],
527
+ [0, 2_147_483_648, 'BIGINT'],
528
+ [0, 9_223_372_036_854_775_807, 'BIGINT'],
529
+
530
+ [-1, 1, 'SMALLINT'],
531
+ [-1, 255, 'SMALLINT'],
532
+ [-1, 256, 'SMALLINT'],
533
+ [-1, 32_767, 'SMALLINT'],
534
+ [-1, 32_768, 'INT'],
535
+ [-1, 2_147_483_647, 'INT'],
536
+ [-1, 2_147_483_648, 'BIGINT'],
537
+ [-1, 9_223_372_036_854_775_807, 'BIGINT'],
538
+
539
+ [-1, 0, 'SMALLINT'],
540
+ [-32_768, 0, 'SMALLINT'],
541
+ [-32_769, 0, 'INT'],
542
+ [-2_147_483_648, 0, 'INT'],
543
+ [-2_147_483_649, 0, 'BIGINT'],
544
+ [-9_223_372_036_854_775_808, 0, 'BIGINT'],
545
+
546
+ [nil, 2_147_483_647, 'INT'],
547
+ [0, nil, 'INT'],
548
+ [nil, nil, 'INTEGER']
549
+ ].each do |min, max, statement|
550
+ options = {key: true}
551
+ options[:min] = min if min
552
+ options[:max] = max if max
553
+
554
+ describe "with a min of #{min} and a max of #{max}" do
555
+ before :all do
556
+ @property = @model.property(:id, Integer, options)
557
+
558
+ @response = capture_log(DataObjects::Sqlserver) { @model.auto_migrate! }
559
+ end
560
+
561
+ it 'returns true' do
562
+ expect(@response).to be(true)
563
+ end
564
+
565
+ it "creates a #{statement} column" do
566
+ expect(@output.last).to eq "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
567
+ end
568
+
569
+ %i(min max).each do |key|
570
+ next unless (value = options[key])
571
+
572
+ it "allows the #{key} value #{value} to be stored" do
573
+ pending "#{value} causes problem with JRuby 1.5.2 parser" if RUBY_PLATFORM =~ /java/ && value == -9_223_372_036_854_775_808
574
+
575
+ expect {
576
+ resource = @model.create(@property => value)
577
+ expect(@model.first(@property => value)).to eql(resource)
578
+ }.not_to raise_error
579
+ end
580
+ end
581
+ end
582
+ end
583
+ end
584
+
585
+ describe 'String property' do
586
+ it 'needs specs'
587
+ end
588
+ end
589
+ end
590
+ end
@@ -0,0 +1,41 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'dm-migrations/auto_migration'
4
+
5
+ module ::Blog
6
+ class Article
7
+ include DataMapper::Resource
8
+
9
+ property :id, Serial
10
+ end
11
+ end
12
+
13
+ describe DataMapper::Migrations do
14
+ def capture_log(mod)
15
+ original = mod.logger
16
+ mod.logger = DataObjects::Logger.new(@log = StringIO.new, :debug)
17
+ yield
18
+ ensure
19
+ @log.rewind
20
+ @output = @log.readlines.map do |line|
21
+ line.chomp.gsub(/\A.+?~ \(\d+\.?\d*\)\s+/, '')
22
+ end
23
+
24
+ mod.logger = original
25
+ end
26
+
27
+ supported_by :postgres do
28
+ before :all do
29
+ @model = Blog::Article
30
+ end
31
+
32
+ describe '#auto_upgrade' do
33
+ it 'creates an index' do
34
+ @model.auto_migrate!
35
+ @property = @model.property(:name, String, index: true)
36
+ @response = capture_log(DataObjects::Postgres) { @model.auto_upgrade! }
37
+ expect(@output[-2]).to eq 'CREATE INDEX "index_blog_articles_name" ON "blog_articles" ("name")'
38
+ end
39
+ end
40
+ end
41
+ end