sequel 3.2.0 → 3.3.0
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.
- data/CHANGELOG +40 -0
- data/Rakefile +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/lib/sequel/adapters/ado.rb +34 -39
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/jdbc.rb +27 -4
- data/lib/sequel/adapters/jdbc/h2.rb +14 -3
- data/lib/sequel/adapters/jdbc/mssql.rb +51 -0
- data/lib/sequel/adapters/mysql.rb +28 -12
- data/lib/sequel/adapters/odbc.rb +36 -30
- data/lib/sequel/adapters/odbc/mssql.rb +44 -0
- data/lib/sequel/adapters/shared/mssql.rb +185 -10
- data/lib/sequel/adapters/shared/mysql.rb +9 -9
- data/lib/sequel/adapters/shared/sqlite.rb +45 -47
- data/lib/sequel/connection_pool.rb +8 -5
- data/lib/sequel/core.rb +2 -8
- data/lib/sequel/database.rb +9 -10
- data/lib/sequel/database/schema_sql.rb +3 -2
- data/lib/sequel/dataset.rb +1 -0
- data/lib/sequel/dataset/sql.rb +15 -6
- data/lib/sequel/extensions/schema_dumper.rb +7 -7
- data/lib/sequel/model/associations.rb +16 -14
- data/lib/sequel/model/base.rb +25 -7
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/many_through_many.rb +0 -1
- data/lib/sequel/sql.rb +8 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +42 -38
- data/spec/adapters/sqlite_spec.rb +0 -4
- data/spec/core/database_spec.rb +22 -1
- data/spec/core/dataset_spec.rb +37 -12
- data/spec/core/expression_filters_spec.rb +5 -0
- data/spec/core/schema_spec.rb +15 -8
- data/spec/extensions/association_proxies_spec.rb +47 -0
- data/spec/extensions/caching_spec.rb +2 -2
- data/spec/extensions/hook_class_methods_spec.rb +6 -6
- data/spec/extensions/many_through_many_spec.rb +13 -0
- data/spec/extensions/schema_dumper_spec.rb +12 -4
- data/spec/extensions/validation_class_methods_spec.rb +3 -3
- data/spec/integration/dataset_test.rb +47 -17
- data/spec/integration/prepared_statement_test.rb +5 -5
- data/spec/integration/schema_test.rb +111 -34
- data/spec/model/associations_spec.rb +128 -11
- data/spec/model/hooks_spec.rb +7 -6
- data/spec/model/model_spec.rb +54 -4
- data/spec/model/record_spec.rb +2 -3
- data/spec/model/validations_spec.rb +4 -4
- metadata +109 -101
- 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'
|
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'
|
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
|
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
|
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
|
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(
|
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
|
-
|
278
|
-
|
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
|
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
|
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.
|
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
|
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
|
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
|
52
|
+
@ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n))
|
53
53
|
@ds.count.should == 2
|
54
|
-
@ds.order(:id).
|
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, :
|
88
|
-
INTEGRATION_DB.call(:insert_n, :n=>20
|
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).
|
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
|
-
@
|
149
|
+
@db = INTEGRATION_DB
|
150
|
+
@ds = @db[:items]
|
150
151
|
clear_sqls
|
151
152
|
end
|
152
153
|
after do
|
153
|
-
|
154
|
+
@db.drop_table(:items) if @db.table_exists?(:items)
|
154
155
|
end
|
155
156
|
|
156
157
|
specify "should create tables correctly" do
|
157
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
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
|
-
|
172
|
-
|
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
|
-
|
178
|
-
|
179
|
-
@
|
180
|
-
|
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
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
210
|
-
|
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
|
-
|
213
|
-
|
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
|
-
|
216
|
-
|
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
|