sequel 3.27.0 → 3.28.0

Sign up to get free protection for your applications and to get access to all the features.
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