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,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