sequel 3.27.0 → 3.28.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 +96 -0
- data/README.rdoc +2 -2
- data/Rakefile +1 -1
- data/doc/association_basics.rdoc +48 -0
- data/doc/opening_databases.rdoc +29 -5
- data/doc/prepared_statements.rdoc +1 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/testing.rdoc +42 -0
- data/doc/transactions.rdoc +97 -0
- data/lib/sequel/adapters/db2.rb +95 -65
- data/lib/sequel/adapters/firebird.rb +25 -219
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/jdbc.rb +12 -0
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/mysql.rb +10 -15
- data/lib/sequel/adapters/odbc.rb +1 -2
- data/lib/sequel/adapters/odbc/db2.rb +5 -5
- data/lib/sequel/adapters/postgres.rb +71 -11
- data/lib/sequel/adapters/shared/db2.rb +290 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/mssql.rb +18 -75
- data/lib/sequel/adapters/shared/mysql.rb +13 -0
- data/lib/sequel/adapters/shared/postgres.rb +52 -36
- data/lib/sequel/adapters/shared/sqlite.rb +32 -36
- data/lib/sequel/adapters/sqlite.rb +4 -8
- data/lib/sequel/adapters/tinytds.rb +7 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +6 -5
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +2 -1
- data/lib/sequel/dataset/actions.rb +149 -33
- data/lib/sequel/dataset/features.rb +44 -7
- data/lib/sequel/dataset/misc.rb +9 -1
- data/lib/sequel/dataset/prepared_statements.rb +2 -2
- data/lib/sequel/dataset/query.rb +63 -10
- data/lib/sequel/dataset/sql.rb +22 -5
- data/lib/sequel/model.rb +3 -3
- data/lib/sequel/model/associations.rb +250 -27
- data/lib/sequel/model/base.rb +10 -16
- data/lib/sequel/plugins/many_through_many.rb +34 -2
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
- data/lib/sequel/sql.rb +94 -51
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/postgres_spec.rb +74 -6
- data/spec/adapters/spec_helper.rb +1 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/database_spec.rb +7 -0
- data/spec/core/dataset_spec.rb +180 -17
- data/spec/core/expression_filters_spec.rb +107 -41
- data/spec/core/spec_helper.rb +11 -0
- data/spec/extensions/many_through_many_spec.rb +115 -1
- data/spec/extensions/prepared_statements_with_pk_spec.rb +3 -3
- data/spec/integration/associations_test.rb +193 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +215 -19
- data/spec/integration/plugin_test.rb +8 -5
- data/spec/integration/prepared_statement_test.rb +91 -98
- data/spec/integration/schema_test.rb +27 -11
- data/spec/integration/spec_helper.rb +10 -0
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +13 -0
- data/spec/model/base_spec.rb +8 -21
- data/spec/model/eager_loading_spec.rb +243 -9
- data/spec/model/model_spec.rb +15 -2
- metadata +16 -4
@@ -8,10 +8,12 @@ describe Sequel::Database do
|
|
8
8
|
INTEGRATION_DB.pool.size.should == 0
|
9
9
|
end
|
10
10
|
|
11
|
-
specify "should provide disconnect functionality after preparing a
|
12
|
-
INTEGRATION_DB
|
11
|
+
specify "should provide disconnect functionality after preparing a statement" do
|
12
|
+
INTEGRATION_DB.create_table!(:items){Integer :i}
|
13
|
+
INTEGRATION_DB[:items].prepare(:first, :a).call
|
13
14
|
INTEGRATION_DB.disconnect
|
14
15
|
INTEGRATION_DB.pool.size.should == 0
|
16
|
+
INTEGRATION_DB.drop_table(:items) rescue nil
|
15
17
|
end
|
16
18
|
|
17
19
|
specify "should raise Sequel::DatabaseError on invalid SQL" do
|
@@ -2,16 +2,17 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
3
3
|
describe "Simple Dataset operations" do
|
4
4
|
before do
|
5
|
-
INTEGRATION_DB
|
5
|
+
@db = INTEGRATION_DB
|
6
|
+
@db.create_table!(:items) do
|
6
7
|
primary_key :id
|
7
8
|
Integer :number
|
8
9
|
end
|
9
|
-
@ds =
|
10
|
+
@ds = @db[:items]
|
10
11
|
@ds.insert(:number=>10)
|
11
12
|
clear_sqls
|
12
13
|
end
|
13
14
|
after do
|
14
|
-
|
15
|
+
@db.drop_table(:items)
|
15
16
|
end
|
16
17
|
|
17
18
|
specify "should support sequential primary keys" do
|
@@ -23,7 +24,7 @@ describe "Simple Dataset operations" do
|
|
23
24
|
{:id => 3, :number=>30} ]
|
24
25
|
end
|
25
26
|
|
26
|
-
cspecify "should insert with a primary key specified", :mssql do
|
27
|
+
cspecify "should insert with a primary key specified", :db2, :mssql do
|
27
28
|
@ds.insert(:id=>100, :number=>20)
|
28
29
|
@ds.count.should == 2
|
29
30
|
@ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
|
@@ -34,6 +35,15 @@ describe "Simple Dataset operations" do
|
|
34
35
|
@ds.filter(:id=>2).first[:number].should == 20
|
35
36
|
end
|
36
37
|
|
38
|
+
cspecify "should have insert work correctly when inserting a row with all NULL values", :db2 do
|
39
|
+
@db.create_table!(:items) do
|
40
|
+
String :name
|
41
|
+
Integer :number
|
42
|
+
end
|
43
|
+
proc{@ds.insert}.should_not raise_error
|
44
|
+
@ds.all.should == [{:name=>nil, :number=>nil}]
|
45
|
+
end
|
46
|
+
|
37
47
|
specify "should delete correctly" do
|
38
48
|
@ds.filter(1=>1).delete.should == 1
|
39
49
|
@ds.count.should == 0
|
@@ -79,10 +89,43 @@ describe "Simple Dataset operations" do
|
|
79
89
|
@ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
|
80
90
|
end
|
81
91
|
|
82
|
-
|
92
|
+
specify "should fetch correctly with a limit and offset for different combinations of from and join tables" do
|
93
|
+
@db.create_table!(:items2){primary_key :id2; Integer :number2}
|
94
|
+
@db[:items2].insert(:number2=>10)
|
95
|
+
@ds.from(:items, :items2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
96
|
+
@ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
97
|
+
@ds.cross_join(:items2).order(:id).limit(2, 0).all.should ==[{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
98
|
+
@ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
99
|
+
@ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10, :id3=>1, :number3=>10}]
|
100
|
+
|
101
|
+
@ds.from(:items, :items2).order(:id).limit(2, 1).all.should == []
|
102
|
+
@ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.should == []
|
103
|
+
@ds.cross_join(:items2).order(:id).limit(2, 1).all.should == []
|
104
|
+
@ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.should == []
|
105
|
+
@ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.should == []
|
106
|
+
@db.drop_table(:items2)
|
107
|
+
end
|
108
|
+
|
109
|
+
cspecify "should fetch correctly with a limit and offset without an order", :db2, :mssql do
|
83
110
|
@ds.limit(2, 1).all.should == []
|
84
111
|
end
|
85
112
|
|
113
|
+
specify "should fetch correctly with a limit in an IN subselect" do
|
114
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.should == [{:id=>1, :number=>10}]
|
115
|
+
@ds.insert(:number=>20)
|
116
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.should == [{:id=>1, :number=>10}]
|
117
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
|
118
|
+
end
|
119
|
+
|
120
|
+
specify "should fetch correctly with a limit and offset in an IN subselect" do
|
121
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.should == [{:id=>1, :number=>10}]
|
122
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == []
|
123
|
+
@ds.insert(:number=>20)
|
124
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.should == [{:id=>2, :number=>20}]
|
125
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
|
126
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == [{:id=>2, :number=>20}]
|
127
|
+
end
|
128
|
+
|
86
129
|
specify "should alias columns correctly" do
|
87
130
|
@ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
|
88
131
|
end
|
@@ -269,7 +312,7 @@ describe "Simple Dataset operations in transactions" do
|
|
269
312
|
INTEGRATION_DB.drop_table(:items_insert_in_transaction)
|
270
313
|
end
|
271
314
|
|
272
|
-
cspecify "should insert correctly with a primary key specified inside a transaction", :mssql do
|
315
|
+
cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
|
273
316
|
INTEGRATION_DB.transaction do
|
274
317
|
@ds.insert(:id=>100, :number=>20)
|
275
318
|
@ds.count.should == 1
|
@@ -385,7 +428,7 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
385
428
|
@db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
|
386
429
|
end
|
387
430
|
|
388
|
-
|
431
|
+
cspecify "should give correct results for recursive WITH", :db2 do
|
389
432
|
ds = @db[:t].select(:i___id, :pi___parent_id).with_recursive(:t, @ds.filter(:parent_id=>nil), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
390
433
|
ds.all.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>nil, :id=>2}, {:parent_id=>1, :id=>3}, {:parent_id=>1, :id=>4}, {:parent_id=>3, :id=>5}, {:parent_id=>5, :id=>6}]
|
391
434
|
ps = @db[:t].select(:i___id, :pi___parent_id).with_recursive(:t, @ds.filter(:parent_id=>:$n), @ds.join(:t, :i=>:parent_id).filter(:t__i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi]).prepare(:select, :cte_sel)
|
@@ -401,6 +444,92 @@ if INTEGRATION_DB.dataset.supports_cte?
|
|
401
444
|
end
|
402
445
|
end
|
403
446
|
|
447
|
+
if INTEGRATION_DB.dataset.supports_cte?(:update) # Assume INSERT and DELETE support as well
|
448
|
+
describe "Common Table Expressions in INSERT/UPDATE/DELETE" do
|
449
|
+
before do
|
450
|
+
@db = INTEGRATION_DB
|
451
|
+
@db.create_table!(:i1){Integer :id}
|
452
|
+
@ds = @db[:i1]
|
453
|
+
@ds2 = @ds.with(:t, @ds)
|
454
|
+
@ds.insert(:id=>1)
|
455
|
+
@ds.insert(:id=>2)
|
456
|
+
end
|
457
|
+
after do
|
458
|
+
@db.drop_table(:i1)
|
459
|
+
end
|
460
|
+
|
461
|
+
specify "should give correct results for WITH" do
|
462
|
+
@ds2.insert(@db[:t])
|
463
|
+
@ds.select_order_map(:id).should == [1, 1, 2, 2]
|
464
|
+
@ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>:id+1)
|
465
|
+
@ds.select_order_map(:id).should == [1, 1, 3, 3]
|
466
|
+
@ds2.filter(:id=>@db[:t].select{max(id)}).delete
|
467
|
+
@ds.select_order_map(:id).should == [1, 1]
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
if INTEGRATION_DB.dataset.supports_returning?(:insert)
|
473
|
+
describe "RETURNING clauses in INSERT" do
|
474
|
+
before do
|
475
|
+
@db = INTEGRATION_DB
|
476
|
+
@db.create_table!(:i1){Integer :id; Integer :foo}
|
477
|
+
@ds = @db[:i1]
|
478
|
+
end
|
479
|
+
after do
|
480
|
+
@db.drop_table(:i1)
|
481
|
+
end
|
482
|
+
|
483
|
+
specify "should give correct results" do
|
484
|
+
h = {}
|
485
|
+
@ds.returning(:foo).insert(1, 2){|r| h = r}
|
486
|
+
h.should == {:foo=>2}
|
487
|
+
@ds.returning(:id).insert(3, 4){|r| h = r}
|
488
|
+
h.should == {:id=>3}
|
489
|
+
@ds.returning.insert(5, 6){|r| h = r}
|
490
|
+
h.should == {:id=>5, :foo=>6}
|
491
|
+
@ds.returning(:id___foo, :foo___id).insert(7, 8){|r| h = r}
|
492
|
+
h.should == {:id=>8, :foo=>7}
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
if INTEGRATION_DB.dataset.supports_returning?(:update) # Assume DELETE support as well
|
498
|
+
describe "RETURNING clauses in UPDATE/DELETE" do
|
499
|
+
before do
|
500
|
+
@db = INTEGRATION_DB
|
501
|
+
@db.create_table!(:i1){Integer :id; Integer :foo}
|
502
|
+
@ds = @db[:i1]
|
503
|
+
@ds.insert(1, 2)
|
504
|
+
end
|
505
|
+
after do
|
506
|
+
@db.drop_table(:i1)
|
507
|
+
end
|
508
|
+
|
509
|
+
specify "should give correct results" do
|
510
|
+
h = []
|
511
|
+
@ds.returning(:foo).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
|
512
|
+
h.should == [{:foo=>4}]
|
513
|
+
h.clear
|
514
|
+
@ds.returning(:id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
|
515
|
+
h.should == [{:id=>3}]
|
516
|
+
h.clear
|
517
|
+
@ds.returning.update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
|
518
|
+
h.should == [{:id=>4, :foo=>16}]
|
519
|
+
h.clear
|
520
|
+
@ds.returning(:id___foo, :foo___id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
|
521
|
+
h.should == [{:id=>32, :foo=>5}]
|
522
|
+
h.clear
|
523
|
+
|
524
|
+
@ds.returning.delete{|r| h << r}
|
525
|
+
h.should == [{:id=>5, :foo=>32}]
|
526
|
+
h.clear
|
527
|
+
@ds.returning.delete{|r| h << r}
|
528
|
+
h.should == []
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
404
533
|
if INTEGRATION_DB.dataset.supports_window_functions?
|
405
534
|
describe "Window Functions" do
|
406
535
|
before do
|
@@ -442,21 +571,13 @@ if INTEGRATION_DB.dataset.supports_window_functions?
|
|
442
571
|
cspecify "should give correct results for aggregate window functions with frames", :mssql do
|
443
572
|
@ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
|
444
573
|
[{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
|
445
|
-
@ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:all){}.as(:sum)}.all.should ==
|
446
|
-
[{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
|
447
574
|
@ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
|
448
575
|
[{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
|
449
|
-
@ds.select(:id){sum(:over, :args=>amount, :frame=>:all){}.as(:sum)}.all.should ==
|
450
|
-
[{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
|
451
576
|
|
452
577
|
@ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
|
453
578
|
[{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
|
454
|
-
@ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:rows){}.as(:sum)}.all.should ==
|
455
|
-
[{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
|
456
579
|
@ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
|
457
580
|
[{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
|
458
|
-
@ds.select(:id){sum(:over, :args=>amount, :frame=>:rows){}.as(:sum)}.all.should ==
|
459
|
-
[{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
|
460
581
|
end
|
461
582
|
end
|
462
583
|
end
|
@@ -584,7 +705,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
584
705
|
@ds.group_and_count(:a___c).order(:count).all.each{|h| h[:count] = h[:count].to_i}.should == [{:c=>30, :count=>1}, {:c=>20, :count=>2}]
|
585
706
|
end
|
586
707
|
|
587
|
-
|
708
|
+
specify "#range should return the range between the maximum and minimum values" do
|
588
709
|
@ds = @ds.unordered
|
589
710
|
@ds.insert(20, 10)
|
590
711
|
@ds.insert(30, 10)
|
@@ -669,6 +790,77 @@ describe "Sequel::Dataset main SQL methods" do
|
|
669
790
|
end
|
670
791
|
end
|
671
792
|
|
793
|
+
describe "Sequel::Dataset convenience methods" do
|
794
|
+
before do
|
795
|
+
@db = INTEGRATION_DB
|
796
|
+
@db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
|
797
|
+
@ds = @db[:a].order(:a)
|
798
|
+
@ds.insert(1, 2, 3, 4)
|
799
|
+
@ds.insert(5, 6, 7, 8)
|
800
|
+
end
|
801
|
+
after do
|
802
|
+
@db.drop_table(:a)
|
803
|
+
end
|
804
|
+
|
805
|
+
specify "should have working #map" do
|
806
|
+
@ds.map(:a).should == [1, 5]
|
807
|
+
@ds.map(:b).should == [2, 6]
|
808
|
+
@ds.map([:a, :b]).should == [[1, 2], [5, 6]]
|
809
|
+
end
|
810
|
+
|
811
|
+
specify "should have working #to_hash" do
|
812
|
+
@ds.to_hash(:a).should == {1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8}}
|
813
|
+
@ds.to_hash(:b).should == {2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8}}
|
814
|
+
@ds.to_hash([:a, :b]).should == {[1, 2]=>{:a=>1, :b=>2, :c=>3, :d=>4}, [5, 6]=>{:a=>5, :b=>6, :c=>7, :d=>8}}
|
815
|
+
|
816
|
+
@ds.to_hash(:a, :b).should == {1=>2, 5=>6}
|
817
|
+
@ds.to_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
|
818
|
+
@ds.to_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
|
819
|
+
@ds.to_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
|
820
|
+
end
|
821
|
+
|
822
|
+
specify "should have working #select_map" do
|
823
|
+
@ds.select_map(:a).should == [1, 5]
|
824
|
+
@ds.select_map(:b).should == [2, 6]
|
825
|
+
@ds.select_map([:a, :b]).should == [[1, 2], [5, 6]]
|
826
|
+
|
827
|
+
@ds.select_map(:a___e).should == [1, 5]
|
828
|
+
@ds.select_map(:b___e).should == [2, 6]
|
829
|
+
@ds.select_map([:a___e, :b___f]).should == [[1, 2], [5, 6]]
|
830
|
+
@ds.select_map([:a__a___e, :a__b___f]).should == [[1, 2], [5, 6]]
|
831
|
+
@ds.select_map([:a__a.as(:e), :a__b.as(:f)]).should == [[1, 2], [5, 6]]
|
832
|
+
@ds.select_map([:a.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
|
833
|
+
@ds.select_map([:a.identifier.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
|
834
|
+
end
|
835
|
+
|
836
|
+
specify "should have working #select_order_map" do
|
837
|
+
@ds.select_order_map(:a).should == [1, 5]
|
838
|
+
@ds.select_order_map(:a__b.desc).should == [6, 2]
|
839
|
+
@ds.select_order_map(:a__b___e.desc).should == [6, 2]
|
840
|
+
@ds.select_order_map(:b.qualify(:a).as(:e)).should == [2, 6]
|
841
|
+
@ds.select_order_map([:a.desc, :b]).should == [[5, 6], [1, 2]]
|
842
|
+
|
843
|
+
@ds.select_order_map(:a___e).should == [1, 5]
|
844
|
+
@ds.select_order_map(:b___e).should == [2, 6]
|
845
|
+
@ds.select_order_map([:a___e.desc, :b___f]).should == [[5, 6], [1, 2]]
|
846
|
+
@ds.select_order_map([:a__a___e.desc, :a__b___f]).should == [[5, 6], [1, 2]]
|
847
|
+
@ds.select_order_map([:a__a.desc, :a__b.as(:f)]).should == [[5, 6], [1, 2]]
|
848
|
+
@ds.select_order_map([:a.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
|
849
|
+
@ds.select_order_map([:a.identifier.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
|
850
|
+
end
|
851
|
+
|
852
|
+
specify "should have working #select_hash" do
|
853
|
+
@ds.select_hash(:a, :b).should == {1=>2, 5=>6}
|
854
|
+
@ds.select_hash(:a__a___e, :b).should == {1=>2, 5=>6}
|
855
|
+
@ds.select_hash(:a__a.as(:e), :b).should == {1=>2, 5=>6}
|
856
|
+
@ds.select_hash(:a.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
|
857
|
+
@ds.select_hash(:a.identifier.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
|
858
|
+
@ds.select_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
|
859
|
+
@ds.select_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
|
860
|
+
@ds.select_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
|
861
|
+
end
|
862
|
+
end
|
863
|
+
|
672
864
|
describe "Sequel::Dataset DSL support" do
|
673
865
|
before do
|
674
866
|
@db = INTEGRATION_DB
|
@@ -709,7 +901,7 @@ describe "Sequel::Dataset DSL support" do
|
|
709
901
|
@ds.get{~b.sql_number}.to_i.should == -4
|
710
902
|
end
|
711
903
|
|
712
|
-
|
904
|
+
specify "should work with the bitwise xor operator" do
|
713
905
|
@ds.insert(3, 5)
|
714
906
|
@ds.get{a.sql_number ^ b}.to_i.should == 6
|
715
907
|
end
|
@@ -802,7 +994,7 @@ describe "Sequel::Dataset DSL support" do
|
|
802
994
|
@ds.filter({15=>20}.case(0, :a) > 0).all.should == []
|
803
995
|
end
|
804
996
|
|
805
|
-
|
997
|
+
specify "should work with multiple value arrays" do
|
806
998
|
@ds.insert(20, 10)
|
807
999
|
@ds.quote_identifiers = false
|
808
1000
|
@ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
|
@@ -871,12 +1063,16 @@ describe "SQL Extract Function" do
|
|
871
1063
|
@db.drop_table(:a)
|
872
1064
|
end
|
873
1065
|
|
874
|
-
|
1066
|
+
specify "should return the part of the datetime asked for" do
|
875
1067
|
t = Time.now
|
1068
|
+
def @ds.supports_timestamp_timezones?() false end
|
876
1069
|
@ds.insert(t)
|
877
1070
|
@ds.get{a.extract(:year)}.should == t.year
|
878
1071
|
@ds.get{a.extract(:month)}.should == t.month
|
879
1072
|
@ds.get{a.extract(:day)}.should == t.day
|
1073
|
+
@ds.get{a.extract(:hour)}.should == t.hour
|
1074
|
+
@ds.get{a.extract(:minute)}.should == t.min
|
1075
|
+
@ds.get{a.extract(:second)}.to_i.should == t.sec
|
880
1076
|
end
|
881
1077
|
end
|
882
1078
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
2
2
|
|
3
3
|
# H2 and MSSQL don't support USING joins
|
4
|
-
|
4
|
+
# DB2 does not seem to support USING joins in every version; it seems to be
|
5
|
+
# valid expression in DB2 iSeries UDB though.
|
6
|
+
unless [:h2, :mssql, :db2].include?(INTEGRATION_DB.database_type)
|
5
7
|
describe "Class Table Inheritance Plugin" do
|
6
8
|
before do
|
7
9
|
@db = INTEGRATION_DB
|
@@ -110,13 +112,13 @@ describe "Class Table Inheritance Plugin" do
|
|
110
112
|
@db[:executives][:id=>@i4].should == {:id=>@i4, :num_managers=>8}
|
111
113
|
end
|
112
114
|
|
113
|
-
|
115
|
+
specify "should handle many_to_one relationships" do
|
114
116
|
m = Staff.first.manager
|
115
117
|
m.should == Manager[@i4]
|
116
118
|
m.should be_a_kind_of(Executive)
|
117
119
|
end
|
118
120
|
|
119
|
-
|
121
|
+
specify "should handle eagerly loading many_to_one relationships" do
|
120
122
|
Staff.limit(1).eager(:manager).all.map{|x| x.manager}.should == [Manager[@i4]]
|
121
123
|
end
|
122
124
|
|
@@ -597,7 +599,7 @@ describe "Composition plugin" do
|
|
597
599
|
composition :date, :mapping=>[:year, :month, :day]
|
598
600
|
end
|
599
601
|
@e1 = Event.create(:year=>2010, :month=>2, :day=>15)
|
600
|
-
@e2 = Event.create(
|
602
|
+
@e2 = Event.create(:year=>nil)
|
601
603
|
end
|
602
604
|
after do
|
603
605
|
@db.drop_table(:events)
|
@@ -627,7 +629,8 @@ describe "Composition plugin" do
|
|
627
629
|
end
|
628
630
|
end
|
629
631
|
|
630
|
-
|
632
|
+
# DB2's implemention of CTE is too limited to use this plugin
|
633
|
+
if INTEGRATION_DB.dataset.supports_cte? and INTEGRATION_DB.database_type != :db2
|
631
634
|
describe "RcteTree Plugin" do
|
632
635
|
before do
|
633
636
|
@db = INTEGRATION_DB
|
@@ -2,86 +2,84 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
3
3
|
describe "Prepared Statements and Bound Arguments" do
|
4
4
|
before do
|
5
|
-
INTEGRATION_DB
|
5
|
+
@db = INTEGRATION_DB
|
6
|
+
@db.create_table!(:items) do
|
6
7
|
primary_key :id
|
7
8
|
integer :number
|
8
9
|
end
|
9
10
|
@c = Class.new(Sequel::Model(:items))
|
10
|
-
@ds =
|
11
|
+
@ds = @db[:items]
|
11
12
|
@ds.insert(:number=>10)
|
12
|
-
@ds.meta_def(:ba) do |sym|
|
13
|
-
prepared_arg_placeholder == '$' ? :"#{sym}__int" : sym
|
14
|
-
end
|
15
13
|
end
|
16
14
|
after do
|
17
|
-
|
15
|
+
@db.drop_table(:items)
|
18
16
|
end
|
19
17
|
|
20
18
|
specify "should support bound variables with select, all, and first" do
|
21
|
-
@ds.filter(:number
|
22
|
-
@ds.filter(:number
|
23
|
-
@ds.filter(:number
|
19
|
+
@ds.filter(:number=>:$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
20
|
+
@ds.filter(:number=>:$n).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
|
21
|
+
@ds.filter(:number=>:$n).call(:first, :n=>10).should == {:id=>1, :number=>10}
|
24
22
|
end
|
25
23
|
|
26
24
|
specify "should support blocks for select and all" do
|
27
|
-
@ds.filter(:number
|
28
|
-
@ds.filter(:number
|
25
|
+
@ds.filter(:number=>:$n).call(:select, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
|
26
|
+
@ds.filter(:number=>:$n).call(:all, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
|
29
27
|
end
|
30
28
|
|
31
29
|
specify "should support binding variables before the call with #bind" do
|
32
|
-
@ds.filter(:number
|
33
|
-
@ds.filter(:number
|
34
|
-
@ds.filter(:number
|
30
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
|
31
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
|
32
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
|
35
33
|
|
36
|
-
@ds.bind(:n=>10).filter(:number
|
37
|
-
@ds.bind(:n=>10).filter(:number
|
38
|
-
@ds.bind(:n=>10).filter(:number
|
34
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:select).should == [{:id=>1, :number=>10}]
|
35
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:all).should == [{:id=>1, :number=>10}]
|
36
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:first).should == {:id=>1, :number=>10}
|
39
37
|
end
|
40
38
|
|
41
39
|
specify "should allow overriding variables specified with #bind" do
|
42
|
-
@ds.filter(:number
|
43
|
-
@ds.filter(:number
|
44
|
-
@ds.filter(:number
|
40
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
41
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
|
42
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :number=>10}
|
45
43
|
|
46
|
-
@ds.filter(:number
|
47
|
-
@ds.filter(:number
|
48
|
-
@ds.filter(:number
|
44
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
|
45
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
|
46
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
|
49
47
|
end
|
50
48
|
|
51
49
|
specify "should support placeholder literal strings with call" do
|
52
|
-
@ds.filter("number = ?",
|
50
|
+
@ds.filter("number = ?", :$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
53
51
|
end
|
54
52
|
|
55
53
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
|
56
|
-
@ds.filter("number = :n", :n
|
54
|
+
@ds.filter("number = :n", :n=>:$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
57
55
|
@ds.insert(:number=>20)
|
58
56
|
@ds.insert(:number=>30)
|
59
|
-
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3
|
57
|
+
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
|
60
58
|
end
|
61
59
|
|
62
60
|
specify "should support datasets with static sql and placeholders with call" do
|
63
|
-
|
61
|
+
@db["SELECT * FROM items WHERE number = ?", :$n].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
64
62
|
end
|
65
63
|
|
66
64
|
specify "should support subselects with call" do
|
67
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number
|
65
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
68
66
|
end
|
69
67
|
|
70
68
|
specify "should support subselects with literal strings with call" do
|
71
|
-
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?",
|
69
|
+
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
72
70
|
end
|
73
71
|
|
74
72
|
specify "should support subselects with static sql and placeholders with call" do
|
75
|
-
@ds.filter(:id=>:$i, :number
|
73
|
+
@ds.filter(:id=>:$i, :number=>@db["SELECT number FROM items WHERE number = ?", :$n]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
76
74
|
end
|
77
75
|
|
78
76
|
specify "should support subselects of subselects with call" do
|
79
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number
|
77
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
80
78
|
end
|
81
79
|
|
82
|
-
|
80
|
+
cspecify "should support using a bound variable for a limit and offset", [:jdbc, :db2] do
|
83
81
|
@ds.insert(:number=>20)
|
84
|
-
ds = @ds.limit(
|
82
|
+
ds = @ds.limit(:$n, :$n2).order(:id)
|
85
83
|
ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
|
86
84
|
ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
|
87
85
|
ds.call(:select, :n=>1, :n2=>2).should == []
|
@@ -90,81 +88,83 @@ describe "Prepared Statements and Bound Arguments" do
|
|
90
88
|
end
|
91
89
|
|
92
90
|
specify "should support bound variables with insert" do
|
93
|
-
@ds.call(:insert, {:n=>20}, :number
|
91
|
+
@ds.call(:insert, {:n=>20}, :number=>:$n)
|
94
92
|
@ds.count.should == 2
|
95
93
|
@ds.order(:id).map(:number).should == [10, 20]
|
96
94
|
end
|
97
95
|
|
98
96
|
specify "should support bound variables with NULL values" do
|
99
97
|
@ds.delete
|
100
|
-
@ds.call(:insert, {:n=>nil}, :number
|
98
|
+
@ds.call(:insert, {:n=>nil}, :number=>:$n)
|
101
99
|
@ds.count.should == 1
|
102
100
|
@ds.map(:number).should == [nil]
|
103
101
|
end
|
104
102
|
|
105
103
|
specify "should have insert return primary key value when using bound arguments" do
|
106
|
-
@ds.call(:insert, {:n=>20}, :number
|
104
|
+
@ds.call(:insert, {:n=>20}, :number=>:$n).should == 2
|
107
105
|
@ds.filter(:id=>2).first[:number].should == 20
|
108
106
|
end
|
109
107
|
|
110
108
|
specify "should support bound variables with delete" do
|
111
|
-
@ds.filter(:number
|
109
|
+
@ds.filter(:number=>:$n).call(:delete, :n=>10).should == 1
|
112
110
|
@ds.count.should == 0
|
113
111
|
end
|
114
112
|
|
115
113
|
specify "should support bound variables with update" do
|
116
|
-
@ds.filter(:number
|
114
|
+
@ds.filter(:number=>:$n).call(:update, {:n=>10, :nn=>20}, :number=>:number+:$nn).should == 1
|
117
115
|
@ds.all.should == [{:id=>1, :number=>30}]
|
118
116
|
end
|
119
117
|
|
120
118
|
specify "should support prepared statements with select, first, and all" do
|
121
|
-
@ds.filter(:number
|
122
|
-
|
123
|
-
@ds.filter(:number
|
124
|
-
|
125
|
-
@ds.filter(:number
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
119
|
+
@ds.filter(:number=>:$n).prepare(:select, :select_n)
|
120
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
121
|
+
@ds.filter(:number=>:$n).prepare(:all, :select_n)
|
122
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
123
|
+
@ds.filter(:number=>:$n).prepare(:first, :select_n)
|
124
|
+
@db.call(:select_n, :n=>10).should == {:id=>1, :number=>10}
|
125
|
+
end
|
126
|
+
|
127
|
+
specify "should support prepared statements being call multiple times with different arguments" do
|
128
|
+
@ds.filter(:number=>:$n).prepare(:select, :select_n)
|
129
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
130
|
+
@db.call(:select_n, :n=>0).should == []
|
131
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
132
132
|
end
|
133
133
|
|
134
134
|
specify "should support placeholder literal strings with prepare" do
|
135
|
-
@ds.filter("number = ?",
|
135
|
+
@ds.filter("number = ?", :$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
136
136
|
end
|
137
137
|
|
138
138
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
|
139
|
-
@ds.filter("number = :n", :n
|
139
|
+
@ds.filter("number = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
140
140
|
@ds.insert(:number=>20)
|
141
141
|
@ds.insert(:number=>30)
|
142
|
-
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3
|
142
|
+
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
|
143
143
|
end
|
144
144
|
|
145
145
|
specify "should support datasets with static sql and placeholders with prepare" do
|
146
|
-
|
146
|
+
@db["SELECT * FROM items WHERE number = ?", :$n].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
147
147
|
end
|
148
148
|
|
149
149
|
specify "should support subselects with prepare" do
|
150
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number
|
150
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
151
151
|
end
|
152
152
|
|
153
153
|
specify "should support subselects with literal strings with prepare" do
|
154
|
-
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?",
|
154
|
+
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
155
155
|
end
|
156
156
|
|
157
157
|
specify "should support subselects with static sql and placeholders with prepare" do
|
158
|
-
@ds.filter(:id=>:$i, :number
|
158
|
+
@ds.filter(:id=>:$i, :number=>@db["SELECT number FROM items WHERE number = ?", :$n]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
159
159
|
end
|
160
160
|
|
161
161
|
specify "should support subselects of subselects with prepare" do
|
162
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number
|
162
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
163
163
|
end
|
164
164
|
|
165
|
-
|
165
|
+
cspecify "should support using a prepared_statement for a limit and offset", :db2 do
|
166
166
|
@ds.insert(:number=>20)
|
167
|
-
ps = @ds.limit(
|
167
|
+
ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
|
168
168
|
ps.call(:n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
|
169
169
|
ps.call(:n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
|
170
170
|
ps.call(:n=>1, :n2=>2).should == []
|
@@ -173,62 +173,58 @@ describe "Prepared Statements and Bound Arguments" do
|
|
173
173
|
end
|
174
174
|
|
175
175
|
specify "should support prepared statements with insert" do
|
176
|
-
@ds.prepare(:insert, :insert_n, :number
|
177
|
-
|
176
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
177
|
+
@db.call(:insert_n, :n=>20)
|
178
178
|
@ds.count.should == 2
|
179
179
|
@ds.order(:id).map(:number).should == [10, 20]
|
180
180
|
end
|
181
181
|
|
182
182
|
specify "should support prepared statements with NULL values" do
|
183
183
|
@ds.delete
|
184
|
-
@ds.prepare(:insert, :insert_n, :number
|
185
|
-
|
184
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
185
|
+
@db.call(:insert_n, :n=>nil)
|
186
186
|
@ds.count.should == 1
|
187
187
|
@ds.map(:number).should == [nil]
|
188
188
|
end
|
189
189
|
|
190
190
|
specify "should have insert return primary key value when using prepared statements" do
|
191
|
-
@ds.prepare(:insert, :insert_n, :number
|
192
|
-
|
191
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
192
|
+
@db.call(:insert_n, :n=>20).should == 2
|
193
193
|
@ds.filter(:id=>2).first[:number].should == 20
|
194
194
|
end
|
195
195
|
|
196
196
|
specify "should support prepared statements with delete" do
|
197
|
-
@ds.filter(:number
|
198
|
-
|
197
|
+
@ds.filter(:number=>:$n).prepare(:delete, :delete_n)
|
198
|
+
@db.call(:delete_n, :n=>10).should == 1
|
199
199
|
@ds.count.should == 0
|
200
200
|
end
|
201
201
|
|
202
202
|
specify "should support prepared statements with update" do
|
203
|
-
@ds.filter(:number
|
204
|
-
|
203
|
+
@ds.filter(:number=>:$n).prepare(:update, :update_n, :number=>:number+:$nn)
|
204
|
+
@db.call(:update_n, :n=>10, :nn=>20).should == 1
|
205
205
|
@ds.all.should == [{:id=>1, :number=>30}]
|
206
206
|
end
|
207
207
|
|
208
208
|
specify "model datasets should return model instances when using select, all, and first with bound variables" do
|
209
|
-
@c.filter(:number
|
210
|
-
@c.filter(:number
|
211
|
-
@c.filter(:number
|
209
|
+
@c.filter(:number=>:$n).call(:select, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
210
|
+
@c.filter(:number=>:$n).call(:all, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
211
|
+
@c.filter(:number=>:$n).call(:first, :n=>10).should == @c.load(:id=>1, :number=>10)
|
212
212
|
end
|
213
213
|
|
214
214
|
specify "model datasets should return model instances when using select, all, and first with prepared statements" do
|
215
|
-
@c.filter(:number
|
216
|
-
|
217
|
-
@c.filter(:number
|
218
|
-
|
219
|
-
@c.filter(:number
|
220
|
-
|
221
|
-
if INTEGRATION_DB.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
|
222
|
-
# Work around for open prepared statements on a table not allowing the
|
223
|
-
# dropping of a table when using SQLite over JDBC
|
224
|
-
INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
|
225
|
-
end
|
215
|
+
@c.filter(:number=>:$n).prepare(:select, :select_n)
|
216
|
+
@db.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
217
|
+
@c.filter(:number=>:$n).prepare(:all, :select_n)
|
218
|
+
@db.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
219
|
+
@c.filter(:number=>:$n).prepare(:first, :select_n)
|
220
|
+
@db.call(:select_n, :n=>10).should == @c.load(:id=>1, :number=>10)
|
226
221
|
end
|
227
222
|
end
|
228
223
|
|
229
224
|
describe "Bound Argument Types" do
|
230
225
|
before do
|
231
|
-
INTEGRATION_DB
|
226
|
+
@db = INTEGRATION_DB
|
227
|
+
@db.create_table!(:items) do
|
232
228
|
primary_key :id
|
233
229
|
Date :d
|
234
230
|
DateTime :dt
|
@@ -238,7 +234,7 @@ describe "Bound Argument Types" do
|
|
238
234
|
Float :f
|
239
235
|
TrueClass :b
|
240
236
|
end
|
241
|
-
@ds =
|
237
|
+
@ds = @db[:items]
|
242
238
|
@vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(20101010), :file=>Sequel::SQL::Blob.new('blob'), :b=>true}
|
243
239
|
@ds.insert(@vs)
|
244
240
|
@ds.meta_def(:ba) do |sym, type|
|
@@ -247,39 +243,36 @@ describe "Bound Argument Types" do
|
|
247
243
|
end
|
248
244
|
after do
|
249
245
|
Sequel.datetime_class = Time
|
250
|
-
|
251
|
-
INTEGRATION_DB.synchronize{|c| c.prepared_statements.each{|k, ps| ps[1].close}.clear}
|
252
|
-
end
|
253
|
-
INTEGRATION_DB.drop_table(:items)
|
246
|
+
@db.drop_table(:items)
|
254
247
|
end
|
255
248
|
|
256
249
|
cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite] do
|
257
|
-
@ds.filter(:d
|
250
|
+
@ds.filter(:d=>:$x).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
|
258
251
|
end
|
259
252
|
|
260
253
|
cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds] do
|
261
254
|
Sequel.datetime_class = DateTime
|
262
|
-
@ds.filter(:dt
|
255
|
+
@ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
|
263
256
|
end
|
264
257
|
|
265
258
|
cspecify "should handle time type", [:do], [:jdbc, :sqlite] do
|
266
|
-
@ds.filter(:t
|
259
|
+
@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
|
267
260
|
end
|
268
261
|
|
269
|
-
cspecify "should handle blob type", [:swift], [:odbc] do
|
270
|
-
@ds.filter(:file
|
262
|
+
cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2] do
|
263
|
+
@ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
|
271
264
|
end
|
272
265
|
|
273
266
|
cspecify "should handle float type", [:swift, :sqlite] do
|
274
|
-
@ds.filter(:f
|
267
|
+
@ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
|
275
268
|
end
|
276
269
|
|
277
270
|
specify "should handle string type" do
|
278
|
-
@ds.filter(:s
|
271
|
+
@ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
|
279
272
|
end
|
280
273
|
|
281
|
-
cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite] do
|
282
|
-
@ds.filter(:b
|
274
|
+
cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite], [:jdbc, :db2] do
|
275
|
+
@ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
|
283
276
|
end
|
284
277
|
end unless INTEGRATION_DB.adapter_scheme == :swift && INTEGRATION_DB.database_type == :postgres
|
285
278
|
|