sequel 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/CHANGELOG +40 -0
  2. data/Rakefile +1 -1
  3. data/doc/opening_databases.rdoc +7 -0
  4. data/doc/release_notes/3.3.0.txt +192 -0
  5. data/lib/sequel/adapters/ado.rb +34 -39
  6. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  7. data/lib/sequel/adapters/jdbc.rb +27 -4
  8. data/lib/sequel/adapters/jdbc/h2.rb +14 -3
  9. data/lib/sequel/adapters/jdbc/mssql.rb +51 -0
  10. data/lib/sequel/adapters/mysql.rb +28 -12
  11. data/lib/sequel/adapters/odbc.rb +36 -30
  12. data/lib/sequel/adapters/odbc/mssql.rb +44 -0
  13. data/lib/sequel/adapters/shared/mssql.rb +185 -10
  14. data/lib/sequel/adapters/shared/mysql.rb +9 -9
  15. data/lib/sequel/adapters/shared/sqlite.rb +45 -47
  16. data/lib/sequel/connection_pool.rb +8 -5
  17. data/lib/sequel/core.rb +2 -8
  18. data/lib/sequel/database.rb +9 -10
  19. data/lib/sequel/database/schema_sql.rb +3 -2
  20. data/lib/sequel/dataset.rb +1 -0
  21. data/lib/sequel/dataset/sql.rb +15 -6
  22. data/lib/sequel/extensions/schema_dumper.rb +7 -7
  23. data/lib/sequel/model/associations.rb +16 -14
  24. data/lib/sequel/model/base.rb +25 -7
  25. data/lib/sequel/plugins/association_proxies.rb +41 -0
  26. data/lib/sequel/plugins/many_through_many.rb +0 -1
  27. data/lib/sequel/sql.rb +8 -11
  28. data/lib/sequel/version.rb +1 -1
  29. data/spec/adapters/mysql_spec.rb +42 -38
  30. data/spec/adapters/sqlite_spec.rb +0 -4
  31. data/spec/core/database_spec.rb +22 -1
  32. data/spec/core/dataset_spec.rb +37 -12
  33. data/spec/core/expression_filters_spec.rb +5 -0
  34. data/spec/core/schema_spec.rb +15 -8
  35. data/spec/extensions/association_proxies_spec.rb +47 -0
  36. data/spec/extensions/caching_spec.rb +2 -2
  37. data/spec/extensions/hook_class_methods_spec.rb +6 -6
  38. data/spec/extensions/many_through_many_spec.rb +13 -0
  39. data/spec/extensions/schema_dumper_spec.rb +12 -4
  40. data/spec/extensions/validation_class_methods_spec.rb +3 -3
  41. data/spec/integration/dataset_test.rb +47 -17
  42. data/spec/integration/prepared_statement_test.rb +5 -5
  43. data/spec/integration/schema_test.rb +111 -34
  44. data/spec/model/associations_spec.rb +128 -11
  45. data/spec/model/hooks_spec.rb +7 -6
  46. data/spec/model/model_spec.rb +54 -4
  47. data/spec/model/record_spec.rb +2 -3
  48. data/spec/model/validations_spec.rb +4 -4
  49. metadata +109 -101
  50. data/spec/adapters/ado_spec.rb +0 -93
@@ -0,0 +1,47 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::AssociationProxies" do
4
+ before do
5
+ class ::Tag < Sequel::Model
6
+ end
7
+ class ::Item < Sequel::Model
8
+ plugin :association_proxies
9
+ many_to_many :tags
10
+ end
11
+ @i = Item.load(:id=>1)
12
+ @t = @i.tags
13
+ Item.db.reset
14
+ end
15
+ after do
16
+ Object.send(:remove_const, :Tag)
17
+ Object.send(:remove_const, :Item)
18
+ end
19
+
20
+ it "should send method calls to the associated object array if sent an array method" do
21
+ @i.associations.has_key?(:tags).should == false
22
+ @t.select{|x| false}.should == []
23
+ @i.associations.has_key?(:tags).should == true
24
+ end
25
+
26
+ it "should send method calls to the association dataset sent another method" do
27
+ @i.associations.has_key?(:tags).should == false
28
+ @t.filter(:a=>1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
29
+ @i.associations.has_key?(:tags).should == false
30
+ end
31
+
32
+ it "should reload the cached association if sent an array method and the reload flag was given" do
33
+ @t.select{|x| false}.should == []
34
+ Item.db.sqls.length == 1
35
+ @t.select{|x| false}.should == []
36
+ Item.db.sqls.length == 1
37
+ @i.tags(true).select{|x| false}.should == []
38
+ Item.db.sqls.length == 2
39
+ @t.filter(:a=>1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
40
+ Item.db.sqls.length == 2
41
+ end
42
+
43
+ it "should not return a proxy object for associations that do not return an array" do
44
+ Item.many_to_one :tag
45
+ proc{@i.tag.filter(:a=>1)}.should raise_error(NoMethodError)
46
+ end
47
+ end
@@ -155,14 +155,14 @@ describe Sequel::Model, "caching" do
155
155
  m.name = 'hey'
156
156
  m.save
157
157
  @cache.has_key?(m.cache_key).should be_false
158
- $sqls.last.should == "UPDATE items SET name = 'hey', id = 1 WHERE (id = 1)"
158
+ $sqls.last.should == "UPDATE items SET name = 'hey' WHERE (id = 1)"
159
159
 
160
160
  m = @c2[1]
161
161
  @cache[m.cache_key].should == m
162
162
  m.name = 'hey'
163
163
  m.save
164
164
  @cache.has_key?(m.cache_key).should be_false
165
- $sqls.last.should == "UPDATE items SET name = 'hey', id = 1 WHERE (id = 1)"
165
+ $sqls.last.should == "UPDATE items SET name = 'hey' WHERE (id = 1)"
166
166
  end
167
167
 
168
168
  it "should delete the cache when deleting the record" do
@@ -240,11 +240,11 @@ describe "Model#before_update && Model#after_update" do
240
240
 
241
241
  specify "should be called around record update" do
242
242
  @c.before_update {MODEL_DB << "BLAH before"}
243
- m = @c.load(:id => 2233)
243
+ m = @c.load(:id => 2233, :x=>123)
244
244
  m.save
245
245
  MODEL_DB.sqls.should == [
246
246
  'BLAH before',
247
- 'UPDATE items SET id = 2233 WHERE (id = 2233)',
247
+ 'UPDATE items SET x = 123 WHERE (id = 2233)',
248
248
  'BLAH after'
249
249
  ]
250
250
  end
@@ -277,11 +277,11 @@ describe "Model#before_save && Model#after_save" do
277
277
 
278
278
  specify "should be called around record update" do
279
279
  @c.before_save {MODEL_DB << "BLAH before"}
280
- m = @c.load(:id => 2233)
280
+ m = @c.load(:id => 2233, :x=>123)
281
281
  m.save
282
282
  MODEL_DB.sqls.should == [
283
283
  'BLAH before',
284
- 'UPDATE items SET id = 2233 WHERE (id = 2233)',
284
+ 'UPDATE items SET x = 123 WHERE (id = 2233)',
285
285
  'BLAH after'
286
286
  ]
287
287
  end
@@ -380,9 +380,9 @@ describe "Model#before_validation && Model#after_validation" do
380
380
 
381
381
  specify "should be called when calling save" do
382
382
  @c.before_validation{MODEL_DB << "BLAH before"}
383
- m = @c.load(:id => 2233)
383
+ m = @c.load(:id => 2233, :x=>123)
384
384
  m.save.should == m
385
- MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'UPDATE items SET id = 2233 WHERE (id = 2233)']
385
+ MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'UPDATE items SET x = 123 WHERE (id = 2233)']
386
386
 
387
387
  MODEL_DB.sqls.clear
388
388
  m = @c.load(:id => 22)
@@ -23,6 +23,19 @@ describe Sequel::Model, "many_through_many" do
23
23
  Object.send(:remove_const, :Tag)
24
24
  end
25
25
 
26
+ it "should default to associating to other models in the same scope" do
27
+ class ::AssociationModuleTest
28
+ class Artist < Sequel::Model
29
+ plugin :many_through_many
30
+ many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
31
+ end
32
+ class Tag < Sequel::Model
33
+ end
34
+ end
35
+
36
+ ::AssociationModuleTest::Artist.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag
37
+ end
38
+
26
39
  it "should raise an error if in invalid form of through is used" do
27
40
  proc{@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id]]}.should raise_error(Sequel::Error)
28
41
  proc{@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], {:table=>:album_tags, :left=>:album_id}]}.should raise_error(Sequel::Error)
@@ -253,13 +253,14 @@ END_MIG
253
253
 
254
254
  it "should convert many database types to ruby types" do
255
255
  types = %w"mediumint smallint int integer mediumint(6) smallint(7) int(8) integer(9)
256
- tinyint tinyint(1) bigint bigint(20) real float double boolean tinytext mediumtext
256
+ tinyint tinyint(2) bigint bigint(20) real float double boolean tinytext mediumtext
257
257
  longtext text clob date datetime timestamp time char character
258
258
  varchar varchar(255) varchar(30) bpchar string money
259
259
  decimal decimal(10,2) numeric numeric(15,3) number bytea tinyblob mediumblob longblob
260
260
  blob varbinary varbinary(10) binary binary(20) year" +
261
261
  ["double precision", "timestamp with time zone", "timestamp without time zone",
262
- "time with time zone", "time without time zone", "character varying(20)"]
262
+ "time with time zone", "time without time zone", "character varying(20)"] +
263
+ %w"nvarchar ntext smalldatetime smallmoney binary varbinary nchar"
263
264
  @d.meta_def(:schema) do |t, *o|
264
265
  i = 0
265
266
  types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
@@ -274,8 +275,8 @@ create_table(:x) do
274
275
  Integer :c6
275
276
  Integer :c7
276
277
  Integer :c8
277
- TrueClass :c9
278
- TrueClass :c10
278
+ Integer :c9
279
+ Integer :c10
279
280
  Bignum :c11
280
281
  Bignum :c12
281
282
  Float :c13
@@ -320,6 +321,13 @@ create_table(:x) do
320
321
  Time :c52, :only_time=>true
321
322
  Time :c53, :only_time=>true
322
323
  String :c54, :size=>20
324
+ String :c55
325
+ String :c56, :text=>true
326
+ DateTime :c57
327
+ BigDecimal :c58, :size=>[19, 2]
328
+ File :c59
329
+ File :c60
330
+ String :c61, :fixed=>true
323
331
  end
324
332
  END_MIG
325
333
  @d.dump_table_schema(:x).should == table.chomp
@@ -950,7 +950,7 @@ describe "Model#save" do
950
950
  o.errors[a] << 'blah' unless v == 5
951
951
  end
952
952
  end
953
- @m = @c.load(:id => 4)
953
+ @m = @c.load(:id => 4, :x=>6)
954
954
  MODEL_DB.reset
955
955
  end
956
956
 
@@ -963,14 +963,14 @@ describe "Model#save" do
963
963
  @m.id = 5
964
964
  @m.should be_valid
965
965
  @m.save.should_not be_false
966
- MODEL_DB.sqls.should == ['UPDATE people SET id = 5 WHERE (id = 5)']
966
+ MODEL_DB.sqls.should == ['UPDATE people SET x = 6 WHERE (id = 5)']
967
967
  end
968
968
 
969
969
  specify "should skip validations if the :validate=>false option is used" do
970
970
  @m.raise_on_save_failure = false
971
971
  @m.should_not be_valid
972
972
  @m.save(:validate=>false)
973
- MODEL_DB.sqls.should == ['UPDATE people SET id = 4 WHERE (id = 4)']
973
+ MODEL_DB.sqls.should == ['UPDATE people SET x = 6 WHERE (id = 4)']
974
974
  end
975
975
 
976
976
  specify "should raise error if validations fail and raise_on_save_faiure is true" do
@@ -57,6 +57,26 @@ describe "Simple Dataset operations" do
57
57
  @ds.first.should == {:id=>1, :number=>10}
58
58
  sqls_should_be('SELECT * FROM items LIMIT 1')
59
59
  end
60
+
61
+ specify "should fetch correctly with a limit" do
62
+ @ds.order(:id).limit(2).all.should == [{:id=>1, :number=>10}]
63
+ @ds.insert(:number=>20)
64
+ @ds.order(:id).limit(1).all.should == [{:id=>1, :number=>10}]
65
+ @ds.order(:id).limit(2).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
66
+ end
67
+
68
+ specify "should fetch correctly with a limit and offset" do
69
+ @ds.order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10}]
70
+ @ds.order(:id).limit(2, 1).all.should == []
71
+ @ds.insert(:number=>20)
72
+ @ds.order(:id).limit(1, 1).all.should == [{:id=>2, :number=>20}]
73
+ @ds.order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
74
+ @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
75
+ end
76
+
77
+ specify "should fetch correctly with a limit and offset without an order" do
78
+ @ds.limit(2, 1).all.should == []
79
+ end
60
80
 
61
81
  specify "should alias columns correctly" do
62
82
  @ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
@@ -326,7 +346,7 @@ if INTEGRATION_DB.dataset.supports_cte?
326
346
  end
327
347
 
328
348
  specify "should give correct results for WITH" do
329
- @db[:t].with(:t, @ds.order(:id).filter(:parent_id=>nil).select(:id)).map(:id).should == [1, 2]
349
+ @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
330
350
  end
331
351
 
332
352
  specify "should give correct results for recursive WITH" do
@@ -357,34 +377,44 @@ if INTEGRATION_DB.dataset.supports_window_functions?
357
377
  @db.drop_table(:i1)
358
378
  end
359
379
 
360
- specify "should give correct results for window functions" do
361
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id){}}.all.should ==
362
- [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
363
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id){}}.all.should ==
380
+ specify "should give correct results for aggregate window functions" do
381
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id){}.as(:sum)}.all.should ==
364
382
  [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
365
- @ds.select(:id){sum(:over, :args=>amount, :order=>id){}}.all.should ==
366
- [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
367
- @ds.select(:id){sum(:over, :args=>amount){}}.all.should ==
383
+ @ds.select(:id){sum(:over, :args=>amount){}.as(:sum)}.all.should ==
368
384
  [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
369
385
  end
386
+
387
+ specify "should give correct results for ranking window functions with orders" do
388
+ @ds.select(:id){rank(:over, :partition=>group_id, :order=>id){}.as(:rank)}.all.should ==
389
+ [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>1, :id=>4}, {:rank=>2, :id=>5}, {:rank=>3, :id=>6}]
390
+ @ds.select(:id){rank(:over, :order=>id){}.as(:rank)}.all.should ==
391
+ [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>4, :id=>4}, {:rank=>5, :id=>5}, {:rank=>6, :id=>6}]
392
+ end
393
+
394
+ specify "should give correct results for aggregate window functions with orders" do
395
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id){}.as(:sum)}.all.should ==
396
+ [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
397
+ @ds.select(:id){sum(:over, :args=>amount, :order=>id){}.as(:sum)}.all.should ==
398
+ [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
399
+ end
370
400
 
371
- specify "should give correct results for window functions with frames" do
372
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}}.all.should ==
401
+ specify "should give correct results for aggregate window functions with frames" do
402
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
373
403
  [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
374
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:all){}}.all.should ==
404
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:all){}.as(:sum)}.all.should ==
375
405
  [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
376
- @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}}.all.should ==
406
+ @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
377
407
  [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
378
- @ds.select(:id){sum(:over, :args=>amount, :frame=>:all){}}.all.should ==
408
+ @ds.select(:id){sum(:over, :args=>amount, :frame=>:all){}.as(:sum)}.all.should ==
379
409
  [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
380
410
 
381
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}}.all.should ==
411
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
382
412
  [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
383
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:rows){}}.all.should ==
413
+ @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:rows){}.as(:sum)}.all.should ==
384
414
  [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
385
- @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}}.all.should ==
415
+ @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
386
416
  [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
387
- @ds.select(:id){sum(:over, :args=>amount, :frame=>:rows){}}.all.should ==
417
+ @ds.select(:id){sum(:over, :args=>amount, :frame=>:rows){}.as(:sum)}.all.should ==
388
418
  [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
389
419
  end
390
420
  end
@@ -49,9 +49,9 @@ describe "Prepared Statements and Bound Arguments" do
49
49
  end
50
50
 
51
51
  specify "should support bound variables with insert" do
52
- @ds.call(:insert, {:n=>20, :i=>100}, :id=>@ds.ba(:$i), :number=>@ds.ba(:$n))
52
+ @ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n))
53
53
  @ds.count.should == 2
54
- @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
54
+ @ds.order(:id).map(:number).should == [10, 20]
55
55
  end
56
56
 
57
57
  specify "should have insert return primary key value when using bound arguments" do
@@ -84,10 +84,10 @@ describe "Prepared Statements and Bound Arguments" do
84
84
  end
85
85
 
86
86
  specify "should support prepared statements with insert" do
87
- @ds.prepare(:insert, :insert_n, :id=>@ds.ba(:$i), :number=>@ds.ba(:$n))
88
- INTEGRATION_DB.call(:insert_n, :n=>20, :i=>100)
87
+ @ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
88
+ INTEGRATION_DB.call(:insert_n, :n=>20)
89
89
  @ds.count.should == 2
90
- @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
90
+ @ds.order(:id).map(:number).should == [10, 20]
91
91
  end
92
92
 
93
93
  specify "should have insert return primary key value when using prepared statements" do
@@ -146,74 +146,151 @@ end
146
146
 
147
147
  describe "Database schema modifiers" do
148
148
  before do
149
- @ds = INTEGRATION_DB[:items]
149
+ @db = INTEGRATION_DB
150
+ @ds = @db[:items]
150
151
  clear_sqls
151
152
  end
152
153
  after do
153
- INTEGRATION_DB.drop_table(:items) if INTEGRATION_DB.table_exists?(:items)
154
+ @db.drop_table(:items) if @db.table_exists?(:items)
154
155
  end
155
156
 
156
157
  specify "should create tables correctly" do
157
- INTEGRATION_DB.create_table!(:items){Integer :number}
158
- INTEGRATION_DB.table_exists?(:items).should == true
159
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number]
158
+ @db.create_table!(:items){Integer :number}
159
+ @db.table_exists?(:items).should == true
160
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number]
160
161
  @ds.insert([10])
161
162
  @ds.columns!.should == [:number]
162
163
  end
163
164
 
164
165
  specify "should handle foreign keys correctly when creating tables" do
165
- INTEGRATION_DB.create_table!(:items) do
166
+ @db.create_table!(:items) do
166
167
  primary_key :id
167
168
  foreign_key :item_id, :items
168
169
  unique [:item_id, :id]
169
170
  foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
170
171
  end
171
- INTEGRATION_DB.table_exists?(:items).should == true
172
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
172
+ @db.table_exists?(:items).should == true
173
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
173
174
  @ds.columns!.should == [:id, :item_id]
174
175
  end
175
176
 
176
177
  specify "should add columns to tables correctly" do
177
- INTEGRATION_DB.create_table!(:items){Integer :number}
178
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number]
179
- @ds.columns!.should == [:number]
180
- INTEGRATION_DB.alter_table(:items){add_column :name, :text}
181
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
178
+ @db.create_table!(:items){Integer :number}
179
+ @ds.insert(:number=>10)
180
+ @db.alter_table(:items){add_column :name, :text}
181
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
182
182
  @ds.columns!.should == [:number, :name]
183
- unless INTEGRATION_DB.database_type == :sqlite
184
- INTEGRATION_DB.alter_table(:items){add_primary_key :id}
185
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name, :id]
186
- @ds.columns!.should == [:number, :name, :id]
187
- INTEGRATION_DB.alter_table(:items){add_foreign_key :item_id, :items}
188
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name, :id, :item_id]
189
- @ds.columns!.should == [:number, :name, :id, :item_id]
190
- INTEGRATION_DB.alter_table(:items) do
191
- add_unique_constraint [:item_id, :id]
192
- add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
193
- end
194
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name, :id, :item_id]
195
- @ds.columns!.should == [:number, :name, :id, :item_id]
183
+ @ds.all.should == [{:number=>10, :name=>nil}]
184
+ end
185
+
186
+ specify "should add primary key columns to tables correctly" do
187
+ @db.create_table!(:items){Integer :number}
188
+ @ds.insert(:number=>10)
189
+ @db.alter_table(:items){add_primary_key :id}
190
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :id]
191
+ @ds.columns!.should == [:number, :id]
192
+ @ds.map(:number).should == [10]
193
+ end
194
+
195
+ specify "should add foreign key columns to tables correctly" do
196
+ @db.create_table!(:items){primary_key :id}
197
+ i = @ds.insert
198
+ @db.alter_table(:items){add_foreign_key :item_id, :items}
199
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
200
+ @ds.columns!.should == [:id, :item_id]
201
+ @ds.all.should == [{:id=>i, :item_id=>nil}]
202
+ end
203
+
204
+ specify "should rename columns correctly" do
205
+ @db.create_table!(:items){Integer :id}
206
+ @ds.insert(:id=>10)
207
+ @db.alter_table(:items){rename_column :id, :id2}
208
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id2]
209
+ @ds.columns!.should == [:id2]
210
+ @ds.all.should == [{:id2=>10}]
211
+ end
212
+
213
+ specify "should rename columns with defaults correctly" do
214
+ @db.create_table!(:items){String :n, :default=>'blah'}
215
+ @ds.insert
216
+ @db.alter_table(:items){rename_column :n, :n2}
217
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:n2]
218
+ @ds.columns!.should == [:n2]
219
+ @ds.insert
220
+ @ds.all.should == [{:n2=>'blah'}, {:n2=>'blah'}]
221
+ end
222
+
223
+ specify "should rename columns with not null constraints" do
224
+ @db.create_table!(:items){String :n, :null=>false}
225
+ @ds.insert(:n=>'blah')
226
+ @db.alter_table(:items){rename_column :n, :n2}
227
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:n2]
228
+ @ds.columns!.should == [:n2]
229
+ @ds.insert(:n2=>'blah')
230
+ @ds.all.should == [{:n2=>'blah'}, {:n2=>'blah'}]
231
+ proc{@ds.insert}.should raise_error(Sequel::DatabaseError)
232
+ end
233
+
234
+ specify "should set column NULL/NOT NULL correctly" do
235
+ @db.create_table!(:items){Integer :id}
236
+ @ds.insert(:id=>10)
237
+ @db.alter_table(:items){set_column_allow_null :id, false}
238
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
239
+ @ds.columns!.should == [:id]
240
+ proc{@ds.insert}.should raise_error(Sequel::DatabaseError)
241
+ @db.alter_table(:items){set_column_allow_null :id, true}
242
+ @ds.insert
243
+ @ds.all.should == [{:id=>10}, {:id=>nil}]
244
+ end
245
+
246
+ specify "should set column defaults correctly" do
247
+ @db.create_table!(:items){Integer :id}
248
+ @ds.insert(:id=>10)
249
+ @db.alter_table(:items){set_column_default :id, 20}
250
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
251
+ @ds.columns!.should == [:id]
252
+ @ds.insert
253
+ @ds.all.should == [{:id=>10}, {:id=>20}]
254
+ end
255
+
256
+ specify "should set column types correctly" do
257
+ @db.create_table!(:items){Integer :id}
258
+ @ds.insert(:id=>10)
259
+ @db.alter_table(:items){set_column_type :id, String}
260
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
261
+ @ds.columns!.should == [:id]
262
+ @ds.insert(:id=>20)
263
+ @ds.all.should == [{:id=>"10"}, {:id=>"20"}]
264
+ end
265
+
266
+ specify "should add unique constraints and foreign key table constraints correctly" do
267
+ @db.create_table!(:items){Integer :id; Integer :item_id}
268
+ @db.alter_table(:items) do
269
+ add_unique_constraint [:item_id, :id]
270
+ add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
196
271
  end
272
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
273
+ @ds.columns!.should == [:id, :item_id]
197
274
  end
198
275
 
199
276
  specify "should remove columns from tables correctly" do
200
- INTEGRATION_DB.create_table!(:items) do
277
+ @db.create_table!(:items) do
201
278
  primary_key :id
202
279
  String :name
203
280
  Integer :number
204
281
  foreign_key :item_id, :items
205
282
  end
206
283
  @ds.insert(:number=>10)
207
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :name, :number, :item_id]
284
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :name, :number, :item_id]
208
285
  @ds.columns!.should == [:id, :name, :number, :item_id]
209
- INTEGRATION_DB.drop_column(:items, :number)
210
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :name, :item_id]
286
+ @db.drop_column(:items, :number)
287
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :name, :item_id]
211
288
  @ds.columns!.should == [:id, :name, :item_id]
212
- INTEGRATION_DB.drop_column(:items, :name)
213
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
289
+ @db.drop_column(:items, :name)
290
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
214
291
  @ds.columns!.should == [:id, :item_id]
215
- INTEGRATION_DB.drop_column(:items, :item_id)
216
- INTEGRATION_DB.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
292
+ @db.drop_column(:items, :item_id)
293
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
217
294
  @ds.columns!.should == [:id]
218
295
  end
219
296
  end