sequel 3.21.0 → 3.29.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 (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -2,16 +2,16 @@ 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
- clear_sqls
12
12
  end
13
13
  after do
14
- INTEGRATION_DB.drop_table(:items)
14
+ @db.drop_table(:items)
15
15
  end
16
16
 
17
17
  specify "should support sequential primary keys" do
@@ -23,7 +23,7 @@ describe "Simple Dataset operations" do
23
23
  {:id => 3, :number=>30} ]
24
24
  end
25
25
 
26
- cspecify "should insert with a primary key specified", :mssql do
26
+ cspecify "should insert with a primary key specified", :db2, :mssql do
27
27
  @ds.insert(:id=>100, :number=>20)
28
28
  @ds.count.should == 2
29
29
  @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
@@ -34,6 +34,37 @@ describe "Simple Dataset operations" do
34
34
  @ds.filter(:id=>2).first[:number].should == 20
35
35
  end
36
36
 
37
+ specify "should have insert work correctly with static SQL" do
38
+ @db["INSERT INTO #{@ds.literal(:items)} (#{@ds.literal(:number)}) VALUES (20)"].insert
39
+ @ds.filter(:id=>2).first[:number].should == 20
40
+ end
41
+
42
+ specify "should join correctly" do
43
+ @ds.join(:items___b, :id=>:id).select_all(:items).all.should == [{:id=>1, :number=>10}]
44
+ end
45
+
46
+ specify "should correctly deal with qualified columns and subselects" do
47
+ @ds.from_self(:alias=>:a).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
48
+ @ds.join(@ds.as(:a), :id=>:id).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
49
+ end
50
+
51
+ specify "should graph correctly" do
52
+ @ds.graph(:items, {:id=>:id}, :table_alias=>:b).all.should == [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
53
+ end
54
+
55
+ specify "should graph correctly with a subselect" do
56
+ @ds.from_self(:alias=>:items).graph(@ds.from_self, {:id=>:id}, :table_alias=>:b).all.should == [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
57
+ end
58
+
59
+ cspecify "should have insert work correctly when inserting a row with all NULL values", :hsqldb do
60
+ @db.create_table!(:items) do
61
+ String :name
62
+ Integer :number
63
+ end
64
+ proc{@ds.insert}.should_not raise_error
65
+ @ds.all.should == [{:name=>nil, :number=>nil}]
66
+ end
67
+
37
68
  specify "should delete correctly" do
38
69
  @ds.filter(1=>1).delete.should == 1
39
70
  @ds.count.should == 0
@@ -79,13 +110,60 @@ describe "Simple Dataset operations" do
79
110
  @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
80
111
  end
81
112
 
82
- cspecify "should fetch correctly with a limit and offset without an order", :mssql do
113
+ specify "should provide correct columns when using a limit and offset" do
114
+ ds = @ds.order(:id).limit(1, 1)
115
+ ds.all
116
+ ds.columns.should == [:id, :number]
117
+ @ds.order(:id).limit(1, 1).columns.should == [:id, :number]
118
+ end
119
+
120
+ specify "should fetch correctly with a limit and offset for different combinations of from and join tables" do
121
+ @db.create_table!(:items2){primary_key :id2; Integer :number2}
122
+ @db[:items2].insert(:number2=>10)
123
+ @ds.from(:items, :items2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
124
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
125
+ @ds.cross_join(:items2).order(:id).limit(2, 0).all.should ==[{:id=>1, :number=>10, :id2=>1, :number2=>10}]
126
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
127
+ @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}]
128
+
129
+ @ds.from(:items, :items2).order(:id).limit(2, 1).all.should == []
130
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.should == []
131
+ @ds.cross_join(:items2).order(:id).limit(2, 1).all.should == []
132
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.should == []
133
+ @ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.should == []
134
+ @db.drop_table(:items2)
135
+ end
136
+
137
+ cspecify "should fetch correctly with a limit and offset without an order", :db2, :mssql, :oracle do
83
138
  @ds.limit(2, 1).all.should == []
84
139
  end
85
140
 
141
+ specify "should fetch correctly with a limit in an IN subselect" do
142
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.should == [{:id=>1, :number=>10}]
143
+ @ds.insert(:number=>20)
144
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.should == [{:id=>1, :number=>10}]
145
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
146
+ end
147
+
148
+ specify "should fetch correctly with a limit and offset in an IN subselect" do
149
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.should == [{:id=>1, :number=>10}]
150
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == []
151
+ @ds.insert(:number=>20)
152
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.should == [{:id=>2, :number=>20}]
153
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
154
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == [{:id=>2, :number=>20}]
155
+ end
156
+
86
157
  specify "should alias columns correctly" do
87
158
  @ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
88
159
  end
160
+
161
+ specify "should handle true/false properly" do
162
+ @ds.filter(Sequel::TRUE).select_map(:number).should == [10]
163
+ @ds.filter(Sequel::FALSE).select_map(:number).should == []
164
+ @ds.filter(true).select_map(:number).should == [10]
165
+ @ds.filter(false).select_map(:number).should == []
166
+ end
89
167
  end
90
168
 
91
169
  describe Sequel::Dataset do
@@ -95,7 +173,6 @@ describe Sequel::Dataset do
95
173
  Integer :value
96
174
  end
97
175
  @d = INTEGRATION_DB[:test]
98
- clear_sqls
99
176
  end
100
177
  after do
101
178
  INTEGRATION_DB.drop_table(:test)
@@ -187,7 +264,11 @@ describe Sequel::Database do
187
264
  INTEGRATION_DB.drop_table(t) rescue nil
188
265
  INTEGRATION_DB.table_exists?(t).should == false
189
266
  INTEGRATION_DB.create_table(t){Integer :a}
190
- INTEGRATION_DB.table_exists?(t).should == true
267
+ begin
268
+ INTEGRATION_DB.table_exists?(t).should == true
269
+ ensure
270
+ INTEGRATION_DB.drop_table(t)
271
+ end
191
272
  end
192
273
  end
193
274
 
@@ -251,18 +332,17 @@ end
251
332
 
252
333
  describe "Simple Dataset operations in transactions" do
253
334
  before do
254
- INTEGRATION_DB.create_table!(:items_insert_in_transaction) do
335
+ INTEGRATION_DB.create_table!(:items) do
255
336
  primary_key :id
256
337
  integer :number
257
338
  end
258
- @ds = INTEGRATION_DB[:items_insert_in_transaction]
259
- clear_sqls
339
+ @ds = INTEGRATION_DB[:items]
260
340
  end
261
341
  after do
262
- INTEGRATION_DB.drop_table(:items_insert_in_transaction)
342
+ INTEGRATION_DB.drop_table(:items)
263
343
  end
264
344
 
265
- cspecify "should insert correctly with a primary key specified inside a transaction", :mssql do
345
+ cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
266
346
  INTEGRATION_DB.transaction do
267
347
  @ds.insert(:id=>100, :number=>20)
268
348
  @ds.count.should == 1
@@ -293,7 +373,6 @@ describe "Dataset UNION, EXCEPT, and INTERSECT" do
293
373
  @ds2 = INTEGRATION_DB[:i2]
294
374
  @ds2.insert(:number=>10)
295
375
  @ds2.insert(:number=>30)
296
- clear_sqls
297
376
  end
298
377
 
299
378
  specify "should give the correct results for simple UNION, EXCEPT, and INTERSECT" do
@@ -359,7 +438,7 @@ end
359
438
 
360
439
  if INTEGRATION_DB.dataset.supports_cte?
361
440
  describe "Common Table Expressions" do
362
- before do
441
+ before(:all) do
363
442
  @db = INTEGRATION_DB
364
443
  @db.create_table!(:i1){Integer :id; Integer :parent_id}
365
444
  @ds = @db[:i1]
@@ -370,7 +449,7 @@ if INTEGRATION_DB.dataset.supports_cte?
370
449
  @ds.insert(:id=>5, :parent_id=>3)
371
450
  @ds.insert(:id=>6, :parent_id=>5)
372
451
  end
373
- after do
452
+ after(:all) do
374
453
  @db.drop_table(:i1)
375
454
  end
376
455
 
@@ -378,7 +457,7 @@ if INTEGRATION_DB.dataset.supports_cte?
378
457
  @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
379
458
  end
380
459
 
381
- specify "should give correct results for recursive WITH" do
460
+ cspecify "should give correct results for recursive WITH", :db2 do
382
461
  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
462
  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
463
  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)
@@ -391,12 +470,116 @@ if INTEGRATION_DB.dataset.supports_cte?
391
470
  @ds.inner_join(@db[:t].with(:t, @ds.filter(:parent_id=>nil)), :id => :id).select(:i1__id).order(:i1__id).map(:id).should == [1,2]
392
471
  @db[:t].with(:t, @ds).inner_join(@db[:s].with(:s, @ds.filter(:parent_id=>nil)), :id => :id).select(:t__id).order(:t__id).map(:id).should == [1,2]
393
472
  end
473
+
474
+ specify "should support a subselect in the FROM clause with a CTE" do
475
+ @ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
476
+ @db[:t].with(:t, @ds).from_self.select_order_map(:id).should == [1,2,3,4,5,6]
477
+ end
478
+
479
+ specify "should support using a CTE inside a CTE" do
480
+ @db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
481
+ @db[:s].with_recursive(:s, @db[:t].with(:t, @ds), @db[:t2].with(:t2, @ds)).select_order_map(:id).should == [1,1,2,2,3,3,4,4,5,5,6,6]
482
+ end
483
+
484
+ specify "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
485
+ @ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
486
+ if @ds.supports_intersect_except?
487
+ @ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
488
+ @ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).should == []
489
+ end
490
+ end
491
+ end
492
+ end
493
+
494
+ if INTEGRATION_DB.dataset.supports_cte?(:update) # Assume INSERT and DELETE support as well
495
+ describe "Common Table Expressions in INSERT/UPDATE/DELETE" do
496
+ before do
497
+ @db = INTEGRATION_DB
498
+ @db.create_table!(:i1){Integer :id}
499
+ @ds = @db[:i1]
500
+ @ds2 = @ds.with(:t, @ds)
501
+ @ds.insert(:id=>1)
502
+ @ds.insert(:id=>2)
503
+ end
504
+ after do
505
+ @db.drop_table(:i1)
506
+ end
507
+
508
+ specify "should give correct results for WITH" do
509
+ @ds2.insert(@db[:t])
510
+ @ds.select_order_map(:id).should == [1, 1, 2, 2]
511
+ @ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>:id+1)
512
+ @ds.select_order_map(:id).should == [1, 1, 3, 3]
513
+ @ds2.filter(:id=>@db[:t].select{max(id)}).delete
514
+ @ds.select_order_map(:id).should == [1, 1]
515
+ end
516
+ end
517
+ end
518
+
519
+ if INTEGRATION_DB.dataset.supports_returning?(:insert)
520
+ describe "RETURNING clauses in INSERT" do
521
+ before do
522
+ @db = INTEGRATION_DB
523
+ @db.create_table!(:i1){Integer :id; Integer :foo}
524
+ @ds = @db[:i1]
525
+ end
526
+ after do
527
+ @db.drop_table(:i1)
528
+ end
529
+
530
+ specify "should give correct results" do
531
+ h = {}
532
+ @ds.returning(:foo).insert(1, 2){|r| h = r}
533
+ h.should == {:foo=>2}
534
+ @ds.returning(:id).insert(3, 4){|r| h = r}
535
+ h.should == {:id=>3}
536
+ @ds.returning.insert(5, 6){|r| h = r}
537
+ h.should == {:id=>5, :foo=>6}
538
+ @ds.returning(:id___foo, :foo___id).insert(7, 8){|r| h = r}
539
+ h.should == {:id=>8, :foo=>7}
540
+ end
541
+ end
542
+ end
543
+
544
+ if INTEGRATION_DB.dataset.supports_returning?(:update) # Assume DELETE support as well
545
+ describe "RETURNING clauses in UPDATE/DELETE" do
546
+ before do
547
+ @db = INTEGRATION_DB
548
+ @db.create_table!(:i1){Integer :id; Integer :foo}
549
+ @ds = @db[:i1]
550
+ @ds.insert(1, 2)
551
+ end
552
+ after do
553
+ @db.drop_table(:i1)
554
+ end
555
+
556
+ specify "should give correct results" do
557
+ h = []
558
+ @ds.returning(:foo).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
559
+ h.should == [{:foo=>4}]
560
+ h.clear
561
+ @ds.returning(:id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
562
+ h.should == [{:id=>3}]
563
+ h.clear
564
+ @ds.returning.update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
565
+ h.should == [{:id=>4, :foo=>16}]
566
+ h.clear
567
+ @ds.returning(:id___foo, :foo___id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
568
+ h.should == [{:id=>32, :foo=>5}]
569
+ h.clear
570
+
571
+ @ds.returning.delete{|r| h << r}
572
+ h.should == [{:id=>5, :foo=>32}]
573
+ h.clear
574
+ @ds.returning.delete{|r| h << r}
575
+ h.should == []
576
+ end
394
577
  end
395
578
  end
396
579
 
397
580
  if INTEGRATION_DB.dataset.supports_window_functions?
398
581
  describe "Window Functions" do
399
- before do
582
+ before(:all) do
400
583
  @db = INTEGRATION_DB
401
584
  @db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
402
585
  @ds = @db[:i1].order(:id)
@@ -407,7 +590,7 @@ if INTEGRATION_DB.dataset.supports_window_functions?
407
590
  @ds.insert(:id=>5, :group_id=>2, :amount=>10000)
408
591
  @ds.insert(:id=>6, :group_id=>2, :amount=>100000)
409
592
  end
410
- after do
593
+ after(:all) do
411
594
  @db.drop_table(:i1)
412
595
  end
413
596
 
@@ -435,21 +618,13 @@ if INTEGRATION_DB.dataset.supports_window_functions?
435
618
  cspecify "should give correct results for aggregate window functions with frames", :mssql do
436
619
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
437
620
  [{: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
621
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
441
622
  [{: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
623
 
445
624
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
446
625
  [{: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
626
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
450
627
  [{: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
628
  end
454
629
  end
455
630
  end
@@ -471,10 +646,10 @@ describe Sequel::SQL::Constants do
471
646
  @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
472
647
  end
473
648
  after do
474
- @db.drop_table(:constants)
649
+ @db.drop_table(:constants) if @db.table_exists?(:constants)
475
650
  end
476
651
 
477
- cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite] do
652
+ cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite], :oracle do
478
653
  @db.create_table!(:constants){Date :d}
479
654
  @ds.insert(:d=>Sequel::CURRENT_DATE)
480
655
  d = @c2[@ds.get(:d)]
@@ -485,26 +660,27 @@ describe Sequel::SQL::Constants do
485
660
  cspecify "should have working CURRENT_TIME", [:do, :mysql], [:jdbc, :sqlite], [:mysql2] do
486
661
  @db.create_table!(:constants){Time :t, :only_time=>true}
487
662
  @ds.insert(:t=>Sequel::CURRENT_TIME)
488
- (Time.now - @c[@ds.get(:t)]).should be_within(1).of(0)
663
+ (Time.now - @c[@ds.get(:t)]).should be_within(2).of(0)
489
664
  end
490
665
 
491
666
  cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite] do
492
667
  @db.create_table!(:constants){DateTime :ts}
493
668
  @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
494
- (Time.now - @c[@ds.get(:ts)]).should be_within(1).of(0)
669
+ (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
495
670
  end
496
671
  end
497
672
 
498
673
  describe "Sequel::Dataset#import and #multi_insert" do
499
- before do
674
+ before(:all) do
500
675
  @db = INTEGRATION_DB
501
676
  @db.create_table!(:imp){Integer :i}
502
- @db.create_table!(:exp2){Integer :i}
503
677
  @ids = @db[:imp].order(:i)
504
- @eds = @db[:exp2]
505
678
  end
506
- after do
507
- @db.drop_table(:imp, :exp2)
679
+ before do
680
+ @ids.delete
681
+ end
682
+ after(:all) do
683
+ @db.drop_table(:imp)
508
684
  end
509
685
 
510
686
  it "should import with multi_insert and an array of hashes" do
@@ -518,9 +694,11 @@ describe "Sequel::Dataset#import and #multi_insert" do
518
694
  end
519
695
 
520
696
  it "should import with a dataset" do
521
- @eds.import([:i], [[10], [20]])
522
- @ids.import([:i], @eds)
697
+ @db.create_table!(:exp2){Integer :i}
698
+ @db[:exp2].import([:i], [[10], [20]])
699
+ @ids.import([:i], @db[:exp2])
523
700
  @ids.all.should == [{:i=>10}, {:i=>20}]
701
+ @db.drop_table(:exp2)
524
702
  end
525
703
 
526
704
  it "should have import work with the :slice_size option" do
@@ -536,12 +714,15 @@ describe "Sequel::Dataset#import and #multi_insert" do
536
714
  end
537
715
 
538
716
  describe "Sequel::Dataset convenience methods" do
539
- before do
717
+ before(:all) do
540
718
  @db = INTEGRATION_DB
541
719
  @db.create_table!(:a){Integer :a; Integer :b}
542
720
  @ds = @db[:a].order(:a)
543
721
  end
544
- after do
722
+ before do
723
+ @ds.delete
724
+ end
725
+ after(:all) do
545
726
  @db.drop_table(:a)
546
727
  end
547
728
 
@@ -577,7 +758,7 @@ describe "Sequel::Dataset convenience methods" do
577
758
  @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
759
  end
579
760
 
580
- cspecify "#range should return the range between the maximum and minimum values", :sqlite do
761
+ specify "#range should return the range between the maximum and minimum values" do
581
762
  @ds = @ds.unordered
582
763
  @ds.insert(20, 10)
583
764
  @ds.insert(30, 10)
@@ -595,12 +776,15 @@ describe "Sequel::Dataset convenience methods" do
595
776
  end
596
777
 
597
778
  describe "Sequel::Dataset main SQL methods" do
598
- before do
779
+ before(:all) do
599
780
  @db = INTEGRATION_DB
600
781
  @db.create_table!(:a){Integer :a; Integer :b}
601
782
  @ds = @db[:a].order(:a)
602
783
  end
603
- after do
784
+ before do
785
+ @ds.delete
786
+ end
787
+ after(:all) do
604
788
  @db.drop_table(:a)
605
789
  end
606
790
 
@@ -625,6 +809,23 @@ describe "Sequel::Dataset main SQL methods" do
625
809
  @ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
626
810
  @ds.filter(:a=>10).or(:b=>15).all.should == []
627
811
  end
812
+
813
+ it "#select_group should work correctly" do
814
+ @ds.unordered!
815
+ @ds.select_group(:a).all.should == []
816
+ @ds.insert(20, 30)
817
+ @ds.select_group(:a).all.should == [{:a=>20}]
818
+ @ds.select_group(:b).all.should == [{:b=>30}]
819
+ @ds.insert(20, 40)
820
+ @ds.select_group(:a).all.should == [{:a=>20}]
821
+ @ds.order(:b).select_group(:b).all.should == [{:b=>30}, {:b=>40}]
822
+ end
823
+
824
+ it "#select_group should work correctly when aliasing" do
825
+ @ds.unordered!
826
+ @ds.insert(20, 30)
827
+ @ds.select_group(:b___c).all.should == [{:c=>30}]
828
+ end
628
829
 
629
830
  it "#having should work correctly" do
630
831
  @ds.unordered!
@@ -645,13 +846,92 @@ describe "Sequel::Dataset main SQL methods" do
645
846
  end
646
847
  end
647
848
 
648
- describe "Sequel::Dataset DSL support" do
849
+ describe "Sequel::Dataset convenience methods" do
850
+ before(:all) do
851
+ @db = INTEGRATION_DB
852
+ @db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
853
+ @ds = @db[:a].order(:a)
854
+ end
649
855
  before do
856
+ @ds.delete
857
+ @ds.insert(1, 2, 3, 4)
858
+ @ds.insert(5, 6, 7, 8)
859
+ end
860
+ after(:all) do
861
+ @db.drop_table(:a)
862
+ end
863
+
864
+ specify "should have working #map" do
865
+ @ds.map(:a).should == [1, 5]
866
+ @ds.map(:b).should == [2, 6]
867
+ @ds.map([:a, :b]).should == [[1, 2], [5, 6]]
868
+ end
869
+
870
+ specify "should have working #to_hash" do
871
+ @ds.to_hash(:a).should == {1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8}}
872
+ @ds.to_hash(:b).should == {2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8}}
873
+ @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}}
874
+
875
+ @ds.to_hash(:a, :b).should == {1=>2, 5=>6}
876
+ @ds.to_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
877
+ @ds.to_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
878
+ @ds.to_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
879
+ end
880
+
881
+ specify "should have working #select_map" do
882
+ @ds.select_map(:a).should == [1, 5]
883
+ @ds.select_map(:b).should == [2, 6]
884
+ @ds.select_map([:a]).should == [[1], [5]]
885
+ @ds.select_map([:a, :b]).should == [[1, 2], [5, 6]]
886
+
887
+ @ds.select_map(:a___e).should == [1, 5]
888
+ @ds.select_map(:b___e).should == [2, 6]
889
+ @ds.select_map([:a___e, :b___f]).should == [[1, 2], [5, 6]]
890
+ @ds.select_map([:a__a___e, :a__b___f]).should == [[1, 2], [5, 6]]
891
+ @ds.select_map([:a__a.as(:e), :a__b.as(:f)]).should == [[1, 2], [5, 6]]
892
+ @ds.select_map([:a.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
893
+ @ds.select_map([:a.identifier.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
894
+ end
895
+
896
+ specify "should have working #select_order_map" do
897
+ @ds.select_order_map(:a).should == [1, 5]
898
+ @ds.select_order_map(:a__b.desc).should == [6, 2]
899
+ @ds.select_order_map(:a__b___e.desc).should == [6, 2]
900
+ @ds.select_order_map(:b.qualify(:a).as(:e)).should == [2, 6]
901
+ @ds.select_order_map([:a]).should == [[1], [5]]
902
+ @ds.select_order_map([:a.desc, :b]).should == [[5, 6], [1, 2]]
903
+
904
+ @ds.select_order_map(:a___e).should == [1, 5]
905
+ @ds.select_order_map(:b___e).should == [2, 6]
906
+ @ds.select_order_map([:a___e.desc, :b___f]).should == [[5, 6], [1, 2]]
907
+ @ds.select_order_map([:a__a___e.desc, :a__b___f]).should == [[5, 6], [1, 2]]
908
+ @ds.select_order_map([:a__a.desc, :a__b.as(:f)]).should == [[5, 6], [1, 2]]
909
+ @ds.select_order_map([:a.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
910
+ @ds.select_order_map([:a.identifier.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
911
+ end
912
+
913
+ specify "should have working #select_hash" do
914
+ @ds.select_hash(:a, :b).should == {1=>2, 5=>6}
915
+ @ds.select_hash(:a__a___e, :b).should == {1=>2, 5=>6}
916
+ @ds.select_hash(:a__a.as(:e), :b).should == {1=>2, 5=>6}
917
+ @ds.select_hash(:a.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
918
+ @ds.select_hash(:a.identifier.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
919
+ @ds.select_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
920
+ @ds.select_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
921
+ @ds.select_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
922
+ end
923
+ end
924
+
925
+ describe "Sequel::Dataset DSL support" do
926
+ before(:all) do
650
927
  @db = INTEGRATION_DB
651
928
  @db.create_table!(:a){Integer :a; Integer :b}
652
929
  @ds = @db[:a].order(:a)
653
930
  end
654
- after do
931
+ before do
932
+ @ds.delete
933
+ end
934
+ after(:all) do
655
935
  @db.drop_table(:a)
656
936
  end
657
937
 
@@ -663,31 +943,36 @@ describe "Sequel::Dataset DSL support" do
663
943
  @ds.get{a / b}.to_i.should == 2
664
944
  end
665
945
 
666
- specify "should work with bitwise shift operators" do
946
+ cspecify "should work with bitwise shift operators", :derby do
667
947
  @ds.insert(3, 2)
668
948
  @ds.get{a.sql_number << b}.to_i.should == 12
669
949
  @ds.get{a.sql_number >> b}.to_i.should == 0
950
+ @ds.get{a.sql_number << b << 1}.to_i.should == 24
670
951
  @ds.delete
671
952
  @ds.insert(3, 1)
672
953
  @ds.get{a.sql_number << b}.to_i.should == 6
673
954
  @ds.get{a.sql_number >> b}.to_i.should == 1
955
+ @ds.get{a.sql_number >> b >> 1}.to_i.should == 0
674
956
  end
675
957
 
676
- specify "should work with bitwise AND and OR operators" do
958
+ cspecify "should work with bitwise AND and OR operators", :derby do
677
959
  @ds.insert(3, 5)
678
960
  @ds.get{a.sql_number | b}.to_i.should == 7
679
961
  @ds.get{a.sql_number & b}.to_i.should == 1
962
+ @ds.get{a.sql_number | b | 8}.to_i.should == 15
963
+ @ds.get{a.sql_number & b & 8}.to_i.should == 0
680
964
  end
681
965
 
682
- cspecify "should work with the bitwise compliment operator", :h2 do
966
+ specify "should work with the bitwise compliment operator" do
683
967
  @ds.insert(-3, 3)
684
968
  @ds.get{~a.sql_number}.to_i.should == 2
685
969
  @ds.get{~b.sql_number}.to_i.should == -4
686
970
  end
687
971
 
688
- cspecify "should work with the bitwise xor operator", :sqlite do
972
+ cspecify "should work with the bitwise xor operator", :derby do
689
973
  @ds.insert(3, 5)
690
974
  @ds.get{a.sql_number ^ b}.to_i.should == 6
975
+ @ds.get{a.sql_number ^ b ^ 1}.to_i.should == 7
691
976
  end
692
977
 
693
978
  specify "should work with inequality operators" do
@@ -778,7 +1063,7 @@ describe "Sequel::Dataset DSL support" do
778
1063
  @ds.filter({15=>20}.case(0, :a) > 0).all.should == []
779
1064
  end
780
1065
 
781
- it "should work with multiple value arrays" do
1066
+ specify "should work with multiple value arrays" do
782
1067
  @ds.insert(20, 10)
783
1068
  @ds.quote_identifiers = false
784
1069
  @ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
@@ -847,22 +1132,29 @@ describe "SQL Extract Function" do
847
1132
  @db.drop_table(:a)
848
1133
  end
849
1134
 
850
- cspecify "should return the part of the datetime asked for", :sqlite, :mssql do
1135
+ specify "should return the part of the datetime asked for" do
851
1136
  t = Time.now
1137
+ def @ds.supports_timestamp_timezones?() false end
852
1138
  @ds.insert(t)
853
1139
  @ds.get{a.extract(:year)}.should == t.year
854
1140
  @ds.get{a.extract(:month)}.should == t.month
855
1141
  @ds.get{a.extract(:day)}.should == t.day
1142
+ @ds.get{a.extract(:hour)}.should == t.hour
1143
+ @ds.get{a.extract(:minute)}.should == t.min
1144
+ @ds.get{a.extract(:second)}.to_i.should == t.sec
856
1145
  end
857
1146
  end
858
1147
 
859
1148
  describe "Dataset string methods" do
860
- before do
1149
+ before(:all) do
861
1150
  @db = INTEGRATION_DB
862
1151
  @db.create_table!(:a){String :a; String :b}
863
1152
  @ds = @db[:a].order(:a)
864
1153
  end
865
- after do
1154
+ before do
1155
+ @ds.delete
1156
+ end
1157
+ after(:all) do
866
1158
  @db.drop_table(:a)
867
1159
  end
868
1160
 
@@ -877,15 +1169,15 @@ describe "Dataset string methods" do
877
1169
  end
878
1170
 
879
1171
  it "#grep should work with :all_patterns and :all_columns options" do
880
- @ds.insert('foo bar', '')
1172
+ @ds.insert('foo bar', ' ')
881
1173
  @ds.insert('foo d', 'bar')
882
- @ds.insert('foo e', '')
883
- @ds.insert('', 'bar')
1174
+ @ds.insert('foo e', ' ')
1175
+ @ds.insert(' ', 'bar')
884
1176
  @ds.insert('foo f', 'baz')
885
1177
  @ds.insert('foo baz', 'bar baz')
886
1178
  @ds.insert('foo boo', 'boo foo')
887
1179
 
888
- @ds.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true).all.should == [{:a=>'foo bar', :b=>''}, {:a=>'foo baz', :b=>'bar baz'}, {:a=>'foo d', :b=>'bar'}]
1180
+ @ds.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true).all.should == [{:a=>'foo bar', :b=>' '}, {:a=>'foo baz', :b=>'bar baz'}, {:a=>'foo d', :b=>'bar'}]
889
1181
  @ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.should == []
890
1182
 
891
1183
  @ds.grep([:a, :b], %w'%bar% %foo%', :all_columns=>true).all.should == [{:a=>"foo baz", :b=>"bar baz"}, {:a=>"foo boo", :b=>"boo foo"}, {:a=>"foo d", :b=>"bar"}]
@@ -900,6 +1192,19 @@ describe "Dataset string methods" do
900
1192
  @ds.filter(:a.like('foo')).all.should == [{:a=>'foo', :b=>'bar'}]
901
1193
  @ds.filter(:a.like('bar')).all.should == []
902
1194
  @ds.filter(:a.like('foo', 'bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1195
+ @ds.exclude(:a.like('foo')).all.should == []
1196
+ @ds.exclude(:a.like('bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1197
+ @ds.exclude(:a.like('foo', 'bar')).all.should == []
1198
+ end
1199
+
1200
+ it "#like should be case sensitive" do
1201
+ @ds.insert('foo', 'bar')
1202
+ @ds.filter(:a.like('Foo')).all.should == []
1203
+ @ds.filter(:a.like('baR')).all.should == []
1204
+ @ds.filter(:a.like('FOO', 'BAR')).all.should == []
1205
+ @ds.exclude(:a.like('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
1206
+ @ds.exclude(:a.like('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1207
+ @ds.exclude(:a.like('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
903
1208
  end
904
1209
 
905
1210
  it "#ilike should return matching rows, in a case insensitive manner" do
@@ -907,6 +1212,9 @@ describe "Dataset string methods" do
907
1212
  @ds.filter(:a.ilike('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
908
1213
  @ds.filter(:a.ilike('baR')).all.should == []
909
1214
  @ds.filter(:a.ilike('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
1215
+ @ds.exclude(:a.ilike('Foo')).all.should == []
1216
+ @ds.exclude(:a.ilike('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1217
+ @ds.exclude(:a.ilike('FOO', 'BAR')).all.should == []
910
1218
  end
911
1219
 
912
1220
  it "should work with strings created with sql_string_join" do
@@ -917,7 +1225,7 @@ describe "Dataset string methods" do
917
1225
  end
918
1226
 
919
1227
  describe "Dataset identifier methods" do
920
- before do
1228
+ before(:all) do
921
1229
  class ::String
922
1230
  def uprev
923
1231
  upcase.reverse
@@ -925,10 +1233,12 @@ describe "Dataset identifier methods" do
925
1233
  end
926
1234
  @db = INTEGRATION_DB
927
1235
  @db.create_table!(:a){Integer :ab}
1236
+ @db[:a].insert(1)
1237
+ end
1238
+ before do
928
1239
  @ds = @db[:a].order(:ab)
929
- @ds.insert(1)
930
1240
  end
931
- after do
1241
+ after(:all) do
932
1242
  @db.drop_table(:a)
933
1243
  end
934
1244
 
@@ -946,12 +1256,15 @@ describe "Dataset identifier methods" do
946
1256
  end
947
1257
 
948
1258
  describe "Dataset defaults and overrides" do
949
- before do
1259
+ before(:all) do
950
1260
  @db = INTEGRATION_DB
951
1261
  @db.create_table!(:a){Integer :a}
952
1262
  @ds = @db[:a].order(:a)
953
1263
  end
954
- after do
1264
+ before do
1265
+ @ds.delete
1266
+ end
1267
+ after(:all) do
955
1268
  @db.drop_table(:a)
956
1269
  end
957
1270