sequel 3.21.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 (158) hide show
  1. data/CHANGELOG +294 -0
  2. data/README.rdoc +20 -6
  3. data/Rakefile +20 -15
  4. data/doc/association_basics.rdoc +210 -43
  5. data/doc/dataset_basics.rdoc +4 -4
  6. data/doc/mass_assignment.rdoc +54 -0
  7. data/doc/migration.rdoc +15 -538
  8. data/doc/model_hooks.rdoc +64 -27
  9. data/doc/opening_databases.rdoc +37 -10
  10. data/doc/prepared_statements.rdoc +16 -10
  11. data/doc/reflection.rdoc +8 -2
  12. data/doc/release_notes/3.22.0.txt +39 -0
  13. data/doc/release_notes/3.23.0.txt +172 -0
  14. data/doc/release_notes/3.24.0.txt +420 -0
  15. data/doc/release_notes/3.25.0.txt +88 -0
  16. data/doc/release_notes/3.26.0.txt +88 -0
  17. data/doc/release_notes/3.27.0.txt +82 -0
  18. data/doc/release_notes/3.28.0.txt +304 -0
  19. data/doc/schema_modification.rdoc +547 -0
  20. data/doc/testing.rdoc +106 -0
  21. data/doc/transactions.rdoc +97 -0
  22. data/doc/virtual_rows.rdoc +2 -2
  23. data/lib/sequel/adapters/ado.rb +12 -1
  24. data/lib/sequel/adapters/amalgalite.rb +4 -0
  25. data/lib/sequel/adapters/db2.rb +95 -58
  26. data/lib/sequel/adapters/do.rb +12 -0
  27. data/lib/sequel/adapters/firebird.rb +25 -203
  28. data/lib/sequel/adapters/ibmdb.rb +440 -0
  29. data/lib/sequel/adapters/informix.rb +4 -19
  30. data/lib/sequel/adapters/jdbc/as400.rb +0 -7
  31. data/lib/sequel/adapters/jdbc/db2.rb +49 -0
  32. data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
  33. data/lib/sequel/adapters/jdbc/h2.rb +16 -5
  34. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  35. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  36. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  37. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  38. data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
  39. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
  40. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  41. data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
  42. data/lib/sequel/adapters/jdbc.rb +62 -29
  43. data/lib/sequel/adapters/mysql.rb +22 -139
  44. data/lib/sequel/adapters/mysql2.rb +9 -14
  45. data/lib/sequel/adapters/odbc/db2.rb +21 -0
  46. data/lib/sequel/adapters/odbc.rb +15 -3
  47. data/lib/sequel/adapters/oracle.rb +17 -1
  48. data/lib/sequel/adapters/postgres.rb +111 -16
  49. data/lib/sequel/adapters/shared/access.rb +21 -0
  50. data/lib/sequel/adapters/shared/db2.rb +290 -0
  51. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  52. data/lib/sequel/adapters/shared/informix.rb +45 -0
  53. data/lib/sequel/adapters/shared/mssql.rb +85 -47
  54. data/lib/sequel/adapters/shared/mysql.rb +50 -7
  55. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
  56. data/lib/sequel/adapters/shared/oracle.rb +0 -4
  57. data/lib/sequel/adapters/shared/postgres.rb +75 -43
  58. data/lib/sequel/adapters/shared/sqlite.rb +56 -8
  59. data/lib/sequel/adapters/sqlite.rb +12 -11
  60. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  61. data/lib/sequel/adapters/tinytds.rb +139 -7
  62. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
  63. data/lib/sequel/ast_transformer.rb +190 -0
  64. data/lib/sequel/connection_pool/threaded.rb +3 -2
  65. data/lib/sequel/connection_pool.rb +1 -1
  66. data/lib/sequel/core.rb +6 -5
  67. data/lib/sequel/database/connecting.rb +5 -5
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +1 -1
  70. data/lib/sequel/database/logging.rb +1 -1
  71. data/lib/sequel/database/misc.rb +38 -17
  72. data/lib/sequel/database/query.rb +50 -19
  73. data/lib/sequel/database/schema_generator.rb +8 -5
  74. data/lib/sequel/database/schema_methods.rb +52 -27
  75. data/lib/sequel/dataset/actions.rb +167 -48
  76. data/lib/sequel/dataset/features.rb +57 -8
  77. data/lib/sequel/dataset/graph.rb +1 -1
  78. data/lib/sequel/dataset/misc.rb +39 -20
  79. data/lib/sequel/dataset/mutation.rb +3 -3
  80. data/lib/sequel/dataset/prepared_statements.rb +29 -14
  81. data/lib/sequel/dataset/query.rb +182 -32
  82. data/lib/sequel/dataset/sql.rb +31 -58
  83. data/lib/sequel/dataset.rb +8 -0
  84. data/lib/sequel/exceptions.rb +4 -0
  85. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  86. data/lib/sequel/extensions/migration.rb +6 -4
  87. data/lib/sequel/extensions/to_dot.rb +95 -83
  88. data/lib/sequel/model/associations.rb +893 -309
  89. data/lib/sequel/model/base.rb +302 -105
  90. data/lib/sequel/model/errors.rb +1 -1
  91. data/lib/sequel/model/exceptions.rb +5 -1
  92. data/lib/sequel/model.rb +13 -7
  93. data/lib/sequel/plugins/association_pks.rb +22 -4
  94. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  95. data/lib/sequel/plugins/identity_map.rb +113 -6
  96. data/lib/sequel/plugins/many_through_many.rb +67 -5
  97. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  98. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  99. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  100. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  101. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  102. data/lib/sequel/plugins/sharding.rb +12 -20
  103. data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
  104. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  105. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  106. data/lib/sequel/sql.rb +107 -51
  107. data/lib/sequel/timezones.rb +12 -3
  108. data/lib/sequel/version.rb +1 -1
  109. data/spec/adapters/db2_spec.rb +146 -0
  110. data/spec/adapters/mssql_spec.rb +36 -0
  111. data/spec/adapters/mysql_spec.rb +36 -19
  112. data/spec/adapters/postgres_spec.rb +115 -28
  113. data/spec/adapters/spec_helper.rb +6 -0
  114. data/spec/adapters/sqlite_spec.rb +11 -0
  115. data/spec/core/connection_pool_spec.rb +62 -77
  116. data/spec/core/database_spec.rb +244 -287
  117. data/spec/core/dataset_spec.rb +383 -34
  118. data/spec/core/expression_filters_spec.rb +159 -41
  119. data/spec/core/schema_spec.rb +326 -3
  120. data/spec/core/spec_helper.rb +45 -0
  121. data/spec/extensions/association_pks_spec.rb +38 -0
  122. data/spec/extensions/columns_introspection_spec.rb +91 -0
  123. data/spec/extensions/defaults_setter_spec.rb +64 -0
  124. data/spec/extensions/identity_map_spec.rb +162 -0
  125. data/spec/extensions/many_through_many_spec.rb +195 -20
  126. data/spec/extensions/migration_spec.rb +17 -17
  127. data/spec/extensions/nested_attributes_spec.rb +1 -0
  128. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  129. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  130. data/spec/extensions/prepared_statements_spec.rb +72 -0
  131. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  132. data/spec/extensions/schema_dumper_spec.rb +2 -2
  133. data/spec/extensions/schema_spec.rb +12 -20
  134. data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
  135. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  136. data/spec/extensions/spec_helper.rb +3 -1
  137. data/spec/extensions/to_dot_spec.rb +3 -5
  138. data/spec/extensions/xml_serializer_spec.rb +16 -4
  139. data/spec/integration/associations_test.rb +405 -15
  140. data/spec/integration/database_test.rb +4 -2
  141. data/spec/integration/dataset_test.rb +240 -20
  142. data/spec/integration/plugin_test.rb +142 -5
  143. data/spec/integration/prepared_statement_test.rb +174 -95
  144. data/spec/integration/schema_test.rb +128 -16
  145. data/spec/integration/spec_helper.rb +15 -0
  146. data/spec/integration/transaction_test.rb +40 -0
  147. data/spec/integration/type_test.rb +16 -2
  148. data/spec/model/association_reflection_spec.rb +91 -0
  149. data/spec/model/associations_spec.rb +476 -5
  150. data/spec/model/base_spec.rb +91 -1
  151. data/spec/model/eager_loading_spec.rb +519 -31
  152. data/spec/model/hooks_spec.rb +161 -0
  153. data/spec/model/model_spec.rb +89 -2
  154. data/spec/model/plugins_spec.rb +17 -0
  155. data/spec/model/record_spec.rb +184 -12
  156. data/spec/model/spec_helper.rb +5 -0
  157. data/spec/model/validations_spec.rb +11 -0
  158. metadata +85 -34
@@ -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,13 +89,53 @@ 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
132
+
133
+ specify "should handle true/false properly" do
134
+ @ds.filter(Sequel::TRUE).select_map(:number).should == [10]
135
+ @ds.filter(Sequel::FALSE).select_map(:number).should == []
136
+ @ds.filter(true).select_map(:number).should == [10]
137
+ @ds.filter(false).select_map(:number).should == []
138
+ end
89
139
  end
90
140
 
91
141
  describe Sequel::Dataset do
@@ -262,7 +312,7 @@ describe "Simple Dataset operations in transactions" do
262
312
  INTEGRATION_DB.drop_table(:items_insert_in_transaction)
263
313
  end
264
314
 
265
- 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
266
316
  INTEGRATION_DB.transaction do
267
317
  @ds.insert(:id=>100, :number=>20)
268
318
  @ds.count.should == 1
@@ -378,7 +428,7 @@ if INTEGRATION_DB.dataset.supports_cte?
378
428
  @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
379
429
  end
380
430
 
381
- specify "should give correct results for recursive WITH" do
431
+ cspecify "should give correct results for recursive WITH", :db2 do
382
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])
383
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}]
384
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)
@@ -394,6 +444,92 @@ if INTEGRATION_DB.dataset.supports_cte?
394
444
  end
395
445
  end
396
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
+
397
533
  if INTEGRATION_DB.dataset.supports_window_functions?
398
534
  describe "Window Functions" do
399
535
  before do
@@ -435,21 +571,13 @@ if INTEGRATION_DB.dataset.supports_window_functions?
435
571
  cspecify "should give correct results for aggregate window functions with frames", :mssql do
436
572
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
437
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}]
438
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:all){}.as(:sum)}.all.should ==
439
- [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
440
574
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
441
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}]
442
- @ds.select(:id){sum(:over, :args=>amount, :frame=>:all){}.as(:sum)}.all.should ==
443
- [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
444
576
 
445
577
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
446
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}]
447
- @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :frame=>:rows){}.as(:sum)}.all.should ==
448
- [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
449
579
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
450
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}]
451
- @ds.select(:id){sum(:over, :args=>amount, :frame=>:rows){}.as(:sum)}.all.should ==
452
- [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
453
581
  end
454
582
  end
455
583
  end
@@ -471,7 +599,7 @@ describe Sequel::SQL::Constants do
471
599
  @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
472
600
  end
473
601
  after do
474
- @db.drop_table(:constants)
602
+ @db.drop_table(:constants) if @db.table_exists?(:constants)
475
603
  end
476
604
 
477
605
  cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite] do
@@ -577,7 +705,7 @@ describe "Sequel::Dataset convenience methods" do
577
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}]
578
706
  end
579
707
 
580
- 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
581
709
  @ds = @ds.unordered
582
710
  @ds.insert(20, 10)
583
711
  @ds.insert(30, 10)
@@ -625,6 +753,23 @@ describe "Sequel::Dataset main SQL methods" do
625
753
  @ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
626
754
  @ds.filter(:a=>10).or(:b=>15).all.should == []
627
755
  end
756
+
757
+ it "#select_group should work correctly" do
758
+ @ds.unordered!
759
+ @ds.select_group(:a).all.should == []
760
+ @ds.insert(20, 30)
761
+ @ds.select_group(:a).all.should == [{:a=>20}]
762
+ @ds.select_group(:b).all.should == [{:b=>30}]
763
+ @ds.insert(20, 40)
764
+ @ds.select_group(:a).all.should == [{:a=>20}]
765
+ @ds.order(:b).select_group(:b).all.should == [{:b=>30}, {:b=>40}]
766
+ end
767
+
768
+ it "#select_group should work correctly when aliasing" do
769
+ @ds.unordered!
770
+ @ds.insert(20, 30)
771
+ @ds.select_group(:b___c).all.should == [{:c=>30}]
772
+ end
628
773
 
629
774
  it "#having should work correctly" do
630
775
  @ds.unordered!
@@ -645,6 +790,77 @@ describe "Sequel::Dataset main SQL methods" do
645
790
  end
646
791
  end
647
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
+
648
864
  describe "Sequel::Dataset DSL support" do
649
865
  before do
650
866
  @db = INTEGRATION_DB
@@ -685,7 +901,7 @@ describe "Sequel::Dataset DSL support" do
685
901
  @ds.get{~b.sql_number}.to_i.should == -4
686
902
  end
687
903
 
688
- cspecify "should work with the bitwise xor operator", :sqlite do
904
+ specify "should work with the bitwise xor operator" do
689
905
  @ds.insert(3, 5)
690
906
  @ds.get{a.sql_number ^ b}.to_i.should == 6
691
907
  end
@@ -778,7 +994,7 @@ describe "Sequel::Dataset DSL support" do
778
994
  @ds.filter({15=>20}.case(0, :a) > 0).all.should == []
779
995
  end
780
996
 
781
- it "should work with multiple value arrays" do
997
+ specify "should work with multiple value arrays" do
782
998
  @ds.insert(20, 10)
783
999
  @ds.quote_identifiers = false
784
1000
  @ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
@@ -847,12 +1063,16 @@ describe "SQL Extract Function" do
847
1063
  @db.drop_table(:a)
848
1064
  end
849
1065
 
850
- 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
851
1067
  t = Time.now
1068
+ def @ds.supports_timestamp_timezones?() false end
852
1069
  @ds.insert(t)
853
1070
  @ds.get{a.extract(:year)}.should == t.year
854
1071
  @ds.get{a.extract(:month)}.should == t.month
855
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
856
1076
  end
857
1077
  end
858
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
 
@@ -196,6 +198,12 @@ describe "Many Through Many Plugin" do
196
198
  Artist[3].albums.map{|x| x.name}.sort.should == %w'B C'
197
199
  Artist[4].albums.map{|x| x.name}.sort.should == %w'B D'
198
200
 
201
+ Artist.plugin :prepared_statements_associations
202
+ Artist[1].albums.map{|x| x.name}.sort.should == %w'A D'
203
+ Artist[2].albums.map{|x| x.name}.sort.should == %w'A C'
204
+ Artist[3].albums.map{|x| x.name}.sort.should == %w'B C'
205
+ Artist[4].albums.map{|x| x.name}.sort.should == %w'B D'
206
+
199
207
  Artist.filter(:id=>1).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A D'
200
208
  Artist.filter(:id=>2).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
201
209
  Artist.filter(:id=>3).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
@@ -205,6 +213,25 @@ describe "Many Through Many Plugin" do
205
213
  Artist.filter(:artists__id=>2).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
206
214
  Artist.filter(:artists__id=>3).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
207
215
  Artist.filter(:artists__id=>4).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
216
+
217
+ Artist.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
218
+ Artist.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
219
+ Artist.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
220
+ Artist.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
221
+
222
+ Artist.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
223
+ Artist.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
224
+ Artist.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
225
+ Artist.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
226
+
227
+ Artist.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
228
+ Artist.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
229
+
230
+ Artist.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
231
+ Artist.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
232
+
233
+ Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
234
+ Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
208
235
  end
209
236
 
210
237
  specify "should handle typical case with 3 join tables" do
@@ -214,6 +241,12 @@ describe "Many Through Many Plugin" do
214
241
  Artist[3].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
215
242
  Artist[4].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
216
243
 
244
+ Artist.plugin :prepared_statements_associations
245
+ Artist[1].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
246
+ Artist[2].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
247
+ Artist[3].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
248
+ Artist[4].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
249
+
217
250
  Artist.filter(:id=>1).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
218
251
  Artist.filter(:id=>2).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
219
252
  Artist.filter(:id=>3).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
@@ -223,6 +256,22 @@ describe "Many Through Many Plugin" do
223
256
  Artist.filter(:artists__id=>2).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
224
257
  Artist.filter(:artists__id=>3).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
225
258
  Artist.filter(:artists__id=>4).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
259
+
260
+ Artist.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
261
+ Artist.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
262
+ Artist.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
263
+ Artist.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
264
+
265
+ Artist.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
266
+ Artist.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
267
+ Artist.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
268
+ Artist.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
269
+
270
+ Artist.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
271
+ Artist.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
272
+
273
+ Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
274
+ Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
226
275
  end
227
276
 
228
277
  specify "should handle extreme case with 5 join tables" do
@@ -241,6 +290,12 @@ describe "Many Through Many Plugin" do
241
290
  Artist[3].related_albums.map{|x| x.name}.sort.should == %w'A B D'
242
291
  Artist[4].related_albums.map{|x| x.name}.sort.should == %w'B D'
243
292
 
293
+ Artist.plugin :prepared_statements_associations
294
+ Artist[1].related_albums.map{|x| x.name}.sort.should == %w'A B C'
295
+ Artist[2].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
296
+ Artist[3].related_albums.map{|x| x.name}.sort.should == %w'A B D'
297
+ Artist[4].related_albums.map{|x| x.name}.sort.should == %w'B D'
298
+
244
299
  Artist.filter(:id=>1).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
245
300
  Artist.filter(:id=>2).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
246
301
  Artist.filter(:id=>3).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
@@ -250,6 +305,25 @@ describe "Many Through Many Plugin" do
250
305
  Artist.filter(:artists__id=>2).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
251
306
  Artist.filter(:artists__id=>3).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
252
307
  Artist.filter(:artists__id=>4).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
308
+
309
+ Artist.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
310
+ Artist.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
311
+ Artist.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
312
+ Artist.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
313
+
314
+ Artist.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
315
+ Artist.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
316
+ Artist.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
317
+ Artist.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
318
+
319
+ Artist.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
320
+ Artist.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
321
+
322
+ Artist.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
323
+ Artist.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
324
+
325
+ Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
326
+ Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
253
327
  end
254
328
  end
255
329
 
@@ -525,7 +599,7 @@ describe "Composition plugin" do
525
599
  composition :date, :mapping=>[:year, :month, :day]
526
600
  end
527
601
  @e1 = Event.create(:year=>2010, :month=>2, :day=>15)
528
- @e2 = Event.create({})
602
+ @e2 = Event.create(:year=>nil)
529
603
  end
530
604
  after do
531
605
  @db.drop_table(:events)
@@ -555,7 +629,8 @@ describe "Composition plugin" do
555
629
  end
556
630
  end
557
631
 
558
- 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
559
634
  describe "RcteTree Plugin" do
560
635
  before do
561
636
  @db = INTEGRATION_DB
@@ -1306,3 +1381,65 @@ describe "Sequel::Plugins::Tree" do
1306
1381
  end
1307
1382
  end
1308
1383
  end
1384
+
1385
+ describe "Sequel::Plugins::PreparedStatements" do
1386
+ before do
1387
+ @db = INTEGRATION_DB
1388
+ @db.create_table!(:ps_test) do
1389
+ primary_key :id
1390
+ String :name
1391
+ Integer :i
1392
+ end
1393
+ @c = Class.new(Sequel::Model(@db[:ps_test]))
1394
+ @foo = @c.create(:name=>'foo', :i=>10)
1395
+ @bar = @c.create(:name=>'bar', :i=>20)
1396
+ @c.plugin :prepared_statements_with_pk
1397
+ end
1398
+ after do
1399
+ @db.drop_table(:ps_test)
1400
+ end
1401
+
1402
+ it "should work with looking up using Model.[]" do
1403
+ @c[@foo.id].should == @foo
1404
+ @c[@bar.id].should == @bar
1405
+ @c[0].should == nil
1406
+ end
1407
+
1408
+ it "should work with looking up using Dataset#with_pk" do
1409
+ @c.dataset.with_pk(@foo.id).should == @foo
1410
+ @c.dataset.with_pk(@bar.id).should == @bar
1411
+ @c.dataset.with_pk(0).should == nil
1412
+
1413
+ @c.dataset.filter(:i=>0).with_pk(@foo.id).should == nil
1414
+ @c.dataset.filter(:i=>10).with_pk(@foo.id).should == @foo
1415
+ @c.dataset.filter(:i=>20).with_pk(@bar.id).should == @bar
1416
+ @c.dataset.filter(:name=>'foo').with_pk(@foo.id).should == @foo
1417
+ @c.dataset.filter(:name=>'bar').with_pk(@bar.id).should == @bar
1418
+ @c.dataset.filter(:name=>'baz').with_pk(@bar.id).should == nil
1419
+ end
1420
+
1421
+ it "should work with Model#destroy" do
1422
+ @foo.destroy
1423
+ @bar.destroy
1424
+ @c[@foo.id].should == nil
1425
+ @c[@bar.id].should == nil
1426
+ end
1427
+
1428
+ it "should work with Model#update" do
1429
+ @foo.update(:name=>'foo2', :i=>30)
1430
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo2', :i=>30)
1431
+ @foo.update(:name=>'foo3')
1432
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>30)
1433
+ @foo.update(:i=>40)
1434
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>40)
1435
+ end
1436
+
1437
+ it "should work with Model#create" do
1438
+ o = @c.create(:name=>'foo2', :i=>30)
1439
+ @c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>30)
1440
+ o = @c.create(:name=>'foo2')
1441
+ @c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>nil)
1442
+ o = @c.create(:i=>30)
1443
+ @c[o.id].should == @c.load(:id=>o.id, :name=>nil, :i=>30)
1444
+ end
1445
+ end