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.
Files changed (73) hide show
  1. data/CHANGELOG +96 -0
  2. data/README.rdoc +2 -2
  3. data/Rakefile +1 -1
  4. data/doc/association_basics.rdoc +48 -0
  5. data/doc/opening_databases.rdoc +29 -5
  6. data/doc/prepared_statements.rdoc +1 -0
  7. data/doc/release_notes/3.28.0.txt +304 -0
  8. data/doc/testing.rdoc +42 -0
  9. data/doc/transactions.rdoc +97 -0
  10. data/lib/sequel/adapters/db2.rb +95 -65
  11. data/lib/sequel/adapters/firebird.rb +25 -219
  12. data/lib/sequel/adapters/ibmdb.rb +440 -0
  13. data/lib/sequel/adapters/jdbc.rb +12 -0
  14. data/lib/sequel/adapters/jdbc/as400.rb +0 -7
  15. data/lib/sequel/adapters/jdbc/db2.rb +49 -0
  16. data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
  17. data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
  18. data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
  19. data/lib/sequel/adapters/mysql.rb +10 -15
  20. data/lib/sequel/adapters/odbc.rb +1 -2
  21. data/lib/sequel/adapters/odbc/db2.rb +5 -5
  22. data/lib/sequel/adapters/postgres.rb +71 -11
  23. data/lib/sequel/adapters/shared/db2.rb +290 -0
  24. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  25. data/lib/sequel/adapters/shared/mssql.rb +18 -75
  26. data/lib/sequel/adapters/shared/mysql.rb +13 -0
  27. data/lib/sequel/adapters/shared/postgres.rb +52 -36
  28. data/lib/sequel/adapters/shared/sqlite.rb +32 -36
  29. data/lib/sequel/adapters/sqlite.rb +4 -8
  30. data/lib/sequel/adapters/tinytds.rb +7 -3
  31. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
  32. data/lib/sequel/core.rb +1 -1
  33. data/lib/sequel/database/connecting.rb +1 -1
  34. data/lib/sequel/database/misc.rb +6 -5
  35. data/lib/sequel/database/query.rb +1 -1
  36. data/lib/sequel/database/schema_generator.rb +2 -1
  37. data/lib/sequel/dataset/actions.rb +149 -33
  38. data/lib/sequel/dataset/features.rb +44 -7
  39. data/lib/sequel/dataset/misc.rb +9 -1
  40. data/lib/sequel/dataset/prepared_statements.rb +2 -2
  41. data/lib/sequel/dataset/query.rb +63 -10
  42. data/lib/sequel/dataset/sql.rb +22 -5
  43. data/lib/sequel/model.rb +3 -3
  44. data/lib/sequel/model/associations.rb +250 -27
  45. data/lib/sequel/model/base.rb +10 -16
  46. data/lib/sequel/plugins/many_through_many.rb +34 -2
  47. data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
  48. data/lib/sequel/sql.rb +94 -51
  49. data/lib/sequel/version.rb +1 -1
  50. data/spec/adapters/db2_spec.rb +146 -0
  51. data/spec/adapters/postgres_spec.rb +74 -6
  52. data/spec/adapters/spec_helper.rb +1 -0
  53. data/spec/adapters/sqlite_spec.rb +11 -0
  54. data/spec/core/database_spec.rb +7 -0
  55. data/spec/core/dataset_spec.rb +180 -17
  56. data/spec/core/expression_filters_spec.rb +107 -41
  57. data/spec/core/spec_helper.rb +11 -0
  58. data/spec/extensions/many_through_many_spec.rb +115 -1
  59. data/spec/extensions/prepared_statements_with_pk_spec.rb +3 -3
  60. data/spec/integration/associations_test.rb +193 -15
  61. data/spec/integration/database_test.rb +4 -2
  62. data/spec/integration/dataset_test.rb +215 -19
  63. data/spec/integration/plugin_test.rb +8 -5
  64. data/spec/integration/prepared_statement_test.rb +91 -98
  65. data/spec/integration/schema_test.rb +27 -11
  66. data/spec/integration/spec_helper.rb +10 -0
  67. data/spec/integration/type_test.rb +2 -2
  68. data/spec/model/association_reflection_spec.rb +91 -0
  69. data/spec/model/associations_spec.rb +13 -0
  70. data/spec/model/base_spec.rb +8 -21
  71. data/spec/model/eager_loading_spec.rb +243 -9
  72. data/spec/model/model_spec.rb +15 -2
  73. 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 connection" do
12
- INTEGRATION_DB['SELECT 1'].prepare(:first, :a).call
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.create_table!(:items) do
5
+ @db = INTEGRATION_DB
6
+ @db.create_table!(:items) do
6
7
  primary_key :id
7
8
  Integer :number
8
9
  end
9
- @ds = INTEGRATION_DB[:items]
10
+ @ds = @db[:items]
10
11
  @ds.insert(:number=>10)
11
12
  clear_sqls
12
13
  end
13
14
  after do
14
- INTEGRATION_DB.drop_table(:items)
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
- cspecify "should fetch correctly with a limit and offset without an order", :mssql do
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
- specify "should give correct results for recursive WITH" do
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
- cspecify "#range should return the range between the maximum and minimum values", :sqlite do
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
- cspecify "should work with the bitwise xor operator", :sqlite do
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
- it "should work with multiple value arrays" do
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
- cspecify "should return the part of the datetime asked for", :sqlite, :mssql do
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
- unless [:h2, :mssql].include?(INTEGRATION_DB.database_type)
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
- cspecify "should handle many_to_one relationships", :sqlite do
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
- cspecify "should handle eagerly loading many_to_one relationships", :sqlite do
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
- if INTEGRATION_DB.dataset.supports_cte?
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.create_table!(:items) do
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 = INTEGRATION_DB[:items]
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
- INTEGRATION_DB.drop_table(:items)
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=>@ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
22
- @ds.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
23
- @ds.filter(:number=>@ds.ba(:$n)).call(:first, :n=>10).should == {:id=>1, :number=>10}
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=>@ds.ba(:$n)).call(:select, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
28
- @ds.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
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=>@ds.ba(:$n)).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
33
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
34
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
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=>@ds.ba(:$n)).call(:select).should == [{:id=>1, :number=>10}]
37
- @ds.bind(:n=>10).filter(:number=>@ds.ba(:$n)).call(:all).should == [{:id=>1, :number=>10}]
38
- @ds.bind(:n=>10).filter(:number=>@ds.ba(:$n)).call(:first).should == {:id=>1, :number=>10}
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=>@ds.ba(:$n)).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
43
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
44
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :number=>10}
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=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
47
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
48
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
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 = ?", @ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
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
- INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
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 = ?", @ds.ba(:$n))).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
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=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n)))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
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
- specify "should support using a bound variable for a limit and offset" do
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(@ds.ba(:$n), @ds.ba(:$n2)).order(:id)
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=>@ds.ba(:$n))
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=>@ds.ba(:$n))
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=>@ds.ba(:$n)).should == 2
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=>@ds.ba(:$n)).call(:delete, :n=>10).should == 1
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=>@ds.ba(:$n)).call(:update, {:n=>10, :nn=>20}, :number=>:number+@ds.ba(:$nn)).should == 1
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=>@ds.ba(:$n)).prepare(:select, :select_n)
122
- INTEGRATION_DB.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
123
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:all, :select_n)
124
- INTEGRATION_DB.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
125
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
126
- INTEGRATION_DB.call(:select_n, :n=>10).should == {:id=>1, :number=>10}
127
- if INTEGRATION_DB.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
128
- # Work around for open prepared statements on a table not allowing the
129
- # dropping of a table when using SQLite over JDBC
130
- INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
131
- end
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 = ?", @ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
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
- INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
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 = ?", @ds.ba(:$n))).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
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=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
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=>@ds.ba(:$n)))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
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
- specify "should support using a prepared_statement for a limit and offset" do
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(@ds.ba(:$n), @ds.ba(:$n2)).order(:id).prepare(:select, :seq_select)
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=>@ds.ba(:$n))
177
- INTEGRATION_DB.call(:insert_n, :n=>20)
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=>@ds.ba(:$n))
185
- INTEGRATION_DB.call(:insert_n, :n=>nil)
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=>@ds.ba(:$n))
192
- INTEGRATION_DB.call(:insert_n, :n=>20).should == 2
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=>@ds.ba(:$n)).prepare(:delete, :delete_n)
198
- INTEGRATION_DB.call(:delete_n, :n=>10).should == 1
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=>@ds.ba(:$n)).prepare(:update, :update_n, :number=>:number+@ds.ba(:$nn))
204
- INTEGRATION_DB.call(:update_n, :n=>10, :nn=>20).should == 1
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=>@ds.ba(:$n)).call(:select, :n=>10).should == [@c.load(:id=>1, :number=>10)]
210
- @c.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10).should == [@c.load(:id=>1, :number=>10)]
211
- @c.filter(:number=>@ds.ba(:$n)).call(:first, :n=>10).should == @c.load(:id=>1, :number=>10)
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=>@ds.ba(:$n)).prepare(:select, :select_n)
216
- INTEGRATION_DB.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
217
- @c.filter(:number=>@ds.ba(:$n)).prepare(:all, :select_n)
218
- INTEGRATION_DB.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
219
- @c.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
220
- INTEGRATION_DB.call(:select_n, :n=>10).should == @c.load(:id=>1, :number=>10)
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.create_table!(:items) do
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 = INTEGRATION_DB[:items]
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
- if INTEGRATION_DB.adapter_scheme == :jdbc && INTEGRATION_DB.database_type == :sqlite
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=>@ds.ba(:$x, :date)).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[: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=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[: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=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[: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=>@ds.ba(:$x, :bytea)).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[: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=>@ds.ba(:$x, :"double precision")).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[: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=>@ds.ba(:$x, :text)).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[: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=>@ds.ba(:$x, :boolean)).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[: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