sequel 3.21.0 → 3.31.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 (225) hide show
  1. data/CHANGELOG +485 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +37 -19
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +249 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/dataset_filtering.rdoc +8 -0
  8. data/doc/mass_assignment.rdoc +54 -0
  9. data/doc/migration.rdoc +15 -538
  10. data/doc/model_hooks.rdoc +72 -27
  11. data/doc/opening_databases.rdoc +89 -50
  12. data/doc/prepared_statements.rdoc +40 -13
  13. data/doc/reflection.rdoc +8 -2
  14. data/doc/release_notes/3.22.0.txt +39 -0
  15. data/doc/release_notes/3.23.0.txt +172 -0
  16. data/doc/release_notes/3.24.0.txt +420 -0
  17. data/doc/release_notes/3.25.0.txt +88 -0
  18. data/doc/release_notes/3.26.0.txt +88 -0
  19. data/doc/release_notes/3.27.0.txt +82 -0
  20. data/doc/release_notes/3.28.0.txt +304 -0
  21. data/doc/release_notes/3.29.0.txt +459 -0
  22. data/doc/release_notes/3.30.0.txt +135 -0
  23. data/doc/release_notes/3.31.0.txt +146 -0
  24. data/doc/schema_modification.rdoc +547 -0
  25. data/doc/sharding.rdoc +7 -1
  26. data/doc/testing.rdoc +129 -0
  27. data/doc/transactions.rdoc +137 -0
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  30. data/lib/sequel/adapters/ado.rb +40 -18
  31. data/lib/sequel/adapters/amalgalite.rb +17 -9
  32. data/lib/sequel/adapters/db2.rb +175 -86
  33. data/lib/sequel/adapters/dbi.rb +15 -15
  34. data/lib/sequel/adapters/do/mysql.rb +5 -7
  35. data/lib/sequel/adapters/do/postgres.rb +0 -5
  36. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/do.rb +17 -36
  38. data/lib/sequel/adapters/firebird.rb +27 -208
  39. data/lib/sequel/adapters/ibmdb.rb +448 -0
  40. data/lib/sequel/adapters/informix.rb +6 -23
  41. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  42. data/lib/sequel/adapters/jdbc/db2.rb +45 -0
  43. data/lib/sequel/adapters/jdbc/derby.rb +247 -0
  44. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  45. data/lib/sequel/adapters/jdbc/h2.rb +56 -29
  46. data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
  47. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  48. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  49. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  50. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  51. data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
  52. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  53. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  54. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  55. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  56. data/lib/sequel/adapters/jdbc.rb +231 -78
  57. data/lib/sequel/adapters/mock.rb +335 -0
  58. data/lib/sequel/adapters/mysql.rb +82 -184
  59. data/lib/sequel/adapters/mysql2.rb +26 -25
  60. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  61. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  62. data/lib/sequel/adapters/odbc.rb +28 -9
  63. data/lib/sequel/adapters/openbase.rb +3 -5
  64. data/lib/sequel/adapters/oracle.rb +351 -53
  65. data/lib/sequel/adapters/postgres.rb +194 -33
  66. data/lib/sequel/adapters/shared/access.rb +32 -9
  67. data/lib/sequel/adapters/shared/db2.rb +321 -0
  68. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  69. data/lib/sequel/adapters/shared/informix.rb +53 -0
  70. data/lib/sequel/adapters/shared/mssql.rb +231 -106
  71. data/lib/sequel/adapters/shared/mysql.rb +181 -63
  72. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +231 -41
  74. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  75. data/lib/sequel/adapters/shared/progress.rb +4 -7
  76. data/lib/sequel/adapters/shared/sqlite.rb +201 -57
  77. data/lib/sequel/adapters/sqlite.rb +29 -21
  78. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  79. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  80. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  81. data/lib/sequel/adapters/swift.rb +5 -5
  82. data/lib/sequel/adapters/tinytds.rb +160 -19
  83. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  84. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  85. data/lib/sequel/ast_transformer.rb +190 -0
  86. data/lib/sequel/connection_pool/threaded.rb +3 -2
  87. data/lib/sequel/connection_pool.rb +1 -1
  88. data/lib/sequel/core.rb +46 -5
  89. data/lib/sequel/database/connecting.rb +5 -6
  90. data/lib/sequel/database/dataset.rb +4 -4
  91. data/lib/sequel/database/dataset_defaults.rb +59 -1
  92. data/lib/sequel/database/logging.rb +1 -1
  93. data/lib/sequel/database/misc.rb +104 -19
  94. data/lib/sequel/database/query.rb +153 -58
  95. data/lib/sequel/database/schema_generator.rb +17 -7
  96. data/lib/sequel/database/schema_methods.rb +59 -29
  97. data/lib/sequel/dataset/actions.rb +231 -76
  98. data/lib/sequel/dataset/features.rb +91 -8
  99. data/lib/sequel/dataset/graph.rb +38 -11
  100. data/lib/sequel/dataset/misc.rb +50 -23
  101. data/lib/sequel/dataset/mutation.rb +5 -6
  102. data/lib/sequel/dataset/prepared_statements.rb +48 -27
  103. data/lib/sequel/dataset/query.rb +236 -43
  104. data/lib/sequel/dataset/sql.rb +665 -253
  105. data/lib/sequel/dataset.rb +8 -0
  106. data/lib/sequel/exceptions.rb +4 -0
  107. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  108. data/lib/sequel/extensions/migration.rb +6 -4
  109. data/lib/sequel/extensions/named_timezones.rb +5 -0
  110. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  111. data/lib/sequel/extensions/to_dot.rb +95 -83
  112. data/lib/sequel/model/associations.rb +1020 -337
  113. data/lib/sequel/model/base.rb +414 -132
  114. data/lib/sequel/model/errors.rb +1 -1
  115. data/lib/sequel/model/exceptions.rb +5 -1
  116. data/lib/sequel/model.rb +15 -8
  117. data/lib/sequel/plugins/association_pks.rb +22 -4
  118. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  119. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  120. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  121. data/lib/sequel/plugins/force_encoding.rb +6 -6
  122. data/lib/sequel/plugins/identity_map.rb +114 -7
  123. data/lib/sequel/plugins/many_through_many.rb +65 -7
  124. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  125. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  126. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  127. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  128. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  129. data/lib/sequel/plugins/serialization.rb +88 -44
  130. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  131. data/lib/sequel/plugins/sharding.rb +21 -54
  132. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  133. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  134. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  135. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  136. data/lib/sequel/sql.rb +109 -52
  137. data/lib/sequel/timezones.rb +57 -38
  138. data/lib/sequel/version.rb +1 -1
  139. data/spec/adapters/db2_spec.rb +146 -0
  140. data/spec/adapters/mssql_spec.rb +111 -29
  141. data/spec/adapters/mysql_spec.rb +135 -123
  142. data/spec/adapters/oracle_spec.rb +49 -77
  143. data/spec/adapters/postgres_spec.rb +267 -78
  144. data/spec/adapters/spec_helper.rb +6 -5
  145. data/spec/adapters/sqlite_spec.rb +35 -21
  146. data/spec/core/connection_pool_spec.rb +71 -92
  147. data/spec/core/core_sql_spec.rb +21 -30
  148. data/spec/core/database_spec.rb +788 -512
  149. data/spec/core/dataset_spec.rb +1073 -1053
  150. data/spec/core/expression_filters_spec.rb +159 -42
  151. data/spec/core/mock_adapter_spec.rb +419 -0
  152. data/spec/core/object_graph_spec.rb +86 -114
  153. data/spec/core/schema_generator_spec.rb +3 -3
  154. data/spec/core/schema_spec.rb +298 -38
  155. data/spec/core/spec_helper.rb +6 -48
  156. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  157. data/spec/extensions/association_dependencies_spec.rb +2 -12
  158. data/spec/extensions/association_pks_spec.rb +66 -32
  159. data/spec/extensions/caching_spec.rb +23 -50
  160. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  161. data/spec/extensions/columns_introspection_spec.rb +91 -0
  162. data/spec/extensions/composition_spec.rb +18 -13
  163. data/spec/extensions/dataset_associations_spec.rb +199 -0
  164. data/spec/extensions/defaults_setter_spec.rb +64 -0
  165. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  166. data/spec/extensions/identity_map_spec.rb +114 -22
  167. data/spec/extensions/instance_filters_spec.rb +11 -21
  168. data/spec/extensions/instance_hooks_spec.rb +53 -0
  169. data/spec/extensions/json_serializer_spec.rb +4 -5
  170. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  171. data/spec/extensions/list_spec.rb +17 -39
  172. data/spec/extensions/many_through_many_spec.rb +283 -250
  173. data/spec/extensions/migration_spec.rb +35 -32
  174. data/spec/extensions/named_timezones_spec.rb +23 -3
  175. data/spec/extensions/nested_attributes_spec.rb +97 -88
  176. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  177. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  178. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  179. data/spec/extensions/prepared_statements_spec.rb +53 -0
  180. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  181. data/spec/extensions/pretty_table_spec.rb +1 -6
  182. data/spec/extensions/rcte_tree_spec.rb +41 -43
  183. data/spec/extensions/schema_dumper_spec.rb +5 -8
  184. data/spec/extensions/schema_spec.rb +13 -21
  185. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  186. data/spec/extensions/serialization_spec.rb +72 -43
  187. data/spec/extensions/sharding_spec.rb +66 -140
  188. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  189. data/spec/extensions/spec_helper.rb +13 -61
  190. data/spec/extensions/sql_expr_spec.rb +20 -60
  191. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  192. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  193. data/spec/extensions/timestamps_spec.rb +6 -6
  194. data/spec/extensions/to_dot_spec.rb +4 -7
  195. data/spec/extensions/touch_spec.rb +13 -14
  196. data/spec/extensions/tree_spec.rb +11 -26
  197. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  198. data/spec/extensions/update_primary_key_spec.rb +30 -24
  199. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  200. data/spec/extensions/validation_helpers_spec.rb +16 -35
  201. data/spec/extensions/xml_serializer_spec.rb +16 -4
  202. data/spec/integration/associations_test.rb +537 -21
  203. data/spec/integration/database_test.rb +4 -2
  204. data/spec/integration/dataset_test.rb +461 -65
  205. data/spec/integration/eager_loader_test.rb +19 -21
  206. data/spec/integration/model_test.rb +80 -1
  207. data/spec/integration/plugin_test.rb +304 -116
  208. data/spec/integration/prepared_statement_test.rb +212 -122
  209. data/spec/integration/schema_test.rb +161 -30
  210. data/spec/integration/spec_helper.rb +39 -30
  211. data/spec/integration/timezone_test.rb +38 -12
  212. data/spec/integration/transaction_test.rb +172 -5
  213. data/spec/integration/type_test.rb +17 -3
  214. data/spec/model/association_reflection_spec.rb +201 -7
  215. data/spec/model/associations_spec.rb +865 -662
  216. data/spec/model/base_spec.rb +275 -95
  217. data/spec/model/dataset_methods_spec.rb +7 -27
  218. data/spec/model/eager_loading_spec.rb +677 -676
  219. data/spec/model/hooks_spec.rb +309 -67
  220. data/spec/model/model_spec.rb +222 -168
  221. data/spec/model/plugins_spec.rb +24 -13
  222. data/spec/model/record_spec.rb +381 -218
  223. data/spec/model/spec_helper.rb +13 -71
  224. data/spec/model/validations_spec.rb +11 -0
  225. metadata +115 -73
@@ -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,43 @@ 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 have insert_multiple return primary key values" do
43
+ @ds.insert_multiple([{:number=>20}, {:number=>30}]).should == [2, 3]
44
+ @ds.filter(:id=>2).get(:number).should == 20
45
+ @ds.filter(:id=>3).get(:number).should == 30
46
+ end
47
+
48
+ specify "should join correctly" do
49
+ @ds.join(:items___b, :id=>:id).select_all(:items).all.should == [{:id=>1, :number=>10}]
50
+ end
51
+
52
+ specify "should correctly deal with qualified columns and subselects" do
53
+ @ds.from_self(:alias=>:a).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
54
+ @ds.join(@ds.as(:a), :id=>:id).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
55
+ end
56
+
57
+ specify "should graph correctly" do
58
+ @ds.graph(:items, {:id=>:id}, :table_alias=>:b).all.should == [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
59
+ end
60
+
61
+ specify "should graph correctly with a subselect" do
62
+ @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}}]
63
+ end
64
+
65
+ cspecify "should have insert work correctly when inserting a row with all NULL values", :hsqldb do
66
+ @db.create_table!(:items) do
67
+ String :name
68
+ Integer :number
69
+ end
70
+ proc{@ds.insert}.should_not raise_error
71
+ @ds.all.should == [{:name=>nil, :number=>nil}]
72
+ end
73
+
37
74
  specify "should delete correctly" do
38
75
  @ds.filter(1=>1).delete.should == 1
39
76
  @ds.count.should == 0
@@ -79,13 +116,60 @@ describe "Simple Dataset operations" do
79
116
  @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
80
117
  end
81
118
 
82
- cspecify "should fetch correctly with a limit and offset without an order", :mssql do
119
+ specify "should provide correct columns when using a limit and offset" do
120
+ ds = @ds.order(:id).limit(1, 1)
121
+ ds.all
122
+ ds.columns.should == [:id, :number]
123
+ @ds.order(:id).limit(1, 1).columns.should == [:id, :number]
124
+ end
125
+
126
+ specify "should fetch correctly with a limit and offset for different combinations of from and join tables" do
127
+ @db.create_table!(:items2){primary_key :id2; Integer :number2}
128
+ @db[:items2].insert(:number2=>10)
129
+ @ds.from(:items, :items2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
130
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
131
+ @ds.cross_join(:items2).order(:id).limit(2, 0).all.should ==[{:id=>1, :number=>10, :id2=>1, :number2=>10}]
132
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
133
+ @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}]
134
+
135
+ @ds.from(:items, :items2).order(:id).limit(2, 1).all.should == []
136
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.should == []
137
+ @ds.cross_join(:items2).order(:id).limit(2, 1).all.should == []
138
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.should == []
139
+ @ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.should == []
140
+ @db.drop_table(:items2)
141
+ end
142
+
143
+ cspecify "should fetch correctly with a limit and offset without an order", :db2, :mssql, :oracle do
83
144
  @ds.limit(2, 1).all.should == []
84
145
  end
85
146
 
147
+ specify "should fetch correctly with a limit in an IN subselect" do
148
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.should == [{:id=>1, :number=>10}]
149
+ @ds.insert(:number=>20)
150
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.should == [{:id=>1, :number=>10}]
151
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
152
+ end
153
+
154
+ specify "should fetch correctly with a limit and offset in an IN subselect" do
155
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.should == [{:id=>1, :number=>10}]
156
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == []
157
+ @ds.insert(:number=>20)
158
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.should == [{:id=>2, :number=>20}]
159
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
160
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == [{:id=>2, :number=>20}]
161
+ end
162
+
86
163
  specify "should alias columns correctly" do
87
164
  @ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
88
165
  end
166
+
167
+ specify "should handle true/false properly" do
168
+ @ds.filter(Sequel::TRUE).select_map(:number).should == [10]
169
+ @ds.filter(Sequel::FALSE).select_map(:number).should == []
170
+ @ds.filter(true).select_map(:number).should == [10]
171
+ @ds.filter(false).select_map(:number).should == []
172
+ end
89
173
  end
90
174
 
91
175
  describe Sequel::Dataset do
@@ -95,7 +179,6 @@ describe Sequel::Dataset do
95
179
  Integer :value
96
180
  end
97
181
  @d = INTEGRATION_DB[:test]
98
- clear_sqls
99
182
  end
100
183
  after do
101
184
  INTEGRATION_DB.drop_table(:test)
@@ -187,7 +270,11 @@ describe Sequel::Database do
187
270
  INTEGRATION_DB.drop_table(t) rescue nil
188
271
  INTEGRATION_DB.table_exists?(t).should == false
189
272
  INTEGRATION_DB.create_table(t){Integer :a}
190
- INTEGRATION_DB.table_exists?(t).should == true
273
+ begin
274
+ INTEGRATION_DB.table_exists?(t).should == true
275
+ ensure
276
+ INTEGRATION_DB.drop_table(t)
277
+ end
191
278
  end
192
279
  end
193
280
 
@@ -251,18 +338,17 @@ end
251
338
 
252
339
  describe "Simple Dataset operations in transactions" do
253
340
  before do
254
- INTEGRATION_DB.create_table!(:items_insert_in_transaction) do
341
+ INTEGRATION_DB.create_table!(:items) do
255
342
  primary_key :id
256
343
  integer :number
257
344
  end
258
- @ds = INTEGRATION_DB[:items_insert_in_transaction]
259
- clear_sqls
345
+ @ds = INTEGRATION_DB[:items]
260
346
  end
261
347
  after do
262
- INTEGRATION_DB.drop_table(:items_insert_in_transaction)
348
+ INTEGRATION_DB.drop_table(:items)
263
349
  end
264
350
 
265
- cspecify "should insert correctly with a primary key specified inside a transaction", :mssql do
351
+ cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
266
352
  INTEGRATION_DB.transaction do
267
353
  @ds.insert(:id=>100, :number=>20)
268
354
  @ds.count.should == 1
@@ -293,7 +379,6 @@ describe "Dataset UNION, EXCEPT, and INTERSECT" do
293
379
  @ds2 = INTEGRATION_DB[:i2]
294
380
  @ds2.insert(:number=>10)
295
381
  @ds2.insert(:number=>30)
296
- clear_sqls
297
382
  end
298
383
 
299
384
  specify "should give the correct results for simple UNION, EXCEPT, and INTERSECT" do
@@ -359,7 +444,7 @@ end
359
444
 
360
445
  if INTEGRATION_DB.dataset.supports_cte?
361
446
  describe "Common Table Expressions" do
362
- before do
447
+ before(:all) do
363
448
  @db = INTEGRATION_DB
364
449
  @db.create_table!(:i1){Integer :id; Integer :parent_id}
365
450
  @ds = @db[:i1]
@@ -370,7 +455,7 @@ if INTEGRATION_DB.dataset.supports_cte?
370
455
  @ds.insert(:id=>5, :parent_id=>3)
371
456
  @ds.insert(:id=>6, :parent_id=>5)
372
457
  end
373
- after do
458
+ after(:all) do
374
459
  @db.drop_table(:i1)
375
460
  end
376
461
 
@@ -378,7 +463,7 @@ if INTEGRATION_DB.dataset.supports_cte?
378
463
  @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
379
464
  end
380
465
 
381
- specify "should give correct results for recursive WITH" do
466
+ cspecify "should give correct results for recursive WITH", :db2 do
382
467
  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
468
  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
469
  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 +476,116 @@ if INTEGRATION_DB.dataset.supports_cte?
391
476
  @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
477
  @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
478
  end
479
+
480
+ specify "should support a subselect in the FROM clause with a CTE" do
481
+ @ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
482
+ @db[:t].with(:t, @ds).from_self.select_order_map(:id).should == [1,2,3,4,5,6]
483
+ end
484
+
485
+ specify "should support using a CTE inside a CTE" do
486
+ @db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
487
+ @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]
488
+ end
489
+
490
+ specify "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
491
+ @ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
492
+ if @ds.supports_intersect_except?
493
+ @ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
494
+ @ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).should == []
495
+ end
496
+ end
497
+ end
498
+ end
499
+
500
+ if INTEGRATION_DB.dataset.supports_cte?(:update) # Assume INSERT and DELETE support as well
501
+ describe "Common Table Expressions in INSERT/UPDATE/DELETE" do
502
+ before do
503
+ @db = INTEGRATION_DB
504
+ @db.create_table!(:i1){Integer :id}
505
+ @ds = @db[:i1]
506
+ @ds2 = @ds.with(:t, @ds)
507
+ @ds.insert(:id=>1)
508
+ @ds.insert(:id=>2)
509
+ end
510
+ after do
511
+ @db.drop_table(:i1)
512
+ end
513
+
514
+ specify "should give correct results for WITH" do
515
+ @ds2.insert(@db[:t])
516
+ @ds.select_order_map(:id).should == [1, 1, 2, 2]
517
+ @ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>:id+1)
518
+ @ds.select_order_map(:id).should == [1, 1, 3, 3]
519
+ @ds2.filter(:id=>@db[:t].select{max(id)}).delete
520
+ @ds.select_order_map(:id).should == [1, 1]
521
+ end
522
+ end
523
+ end
524
+
525
+ if INTEGRATION_DB.dataset.supports_returning?(:insert)
526
+ describe "RETURNING clauses in INSERT" do
527
+ before do
528
+ @db = INTEGRATION_DB
529
+ @db.create_table!(:i1){Integer :id; Integer :foo}
530
+ @ds = @db[:i1]
531
+ end
532
+ after do
533
+ @db.drop_table(:i1)
534
+ end
535
+
536
+ specify "should give correct results" do
537
+ h = {}
538
+ @ds.returning(:foo).insert(1, 2){|r| h = r}
539
+ h.should == {:foo=>2}
540
+ @ds.returning(:id).insert(3, 4){|r| h = r}
541
+ h.should == {:id=>3}
542
+ @ds.returning.insert(5, 6){|r| h = r}
543
+ h.should == {:id=>5, :foo=>6}
544
+ @ds.returning(:id___foo, :foo___id).insert(7, 8){|r| h = r}
545
+ h.should == {:id=>8, :foo=>7}
546
+ end
547
+ end
548
+ end
549
+
550
+ if INTEGRATION_DB.dataset.supports_returning?(:update) # Assume DELETE support as well
551
+ describe "RETURNING clauses in UPDATE/DELETE" do
552
+ before do
553
+ @db = INTEGRATION_DB
554
+ @db.create_table!(:i1){Integer :id; Integer :foo}
555
+ @ds = @db[:i1]
556
+ @ds.insert(1, 2)
557
+ end
558
+ after do
559
+ @db.drop_table(:i1)
560
+ end
561
+
562
+ specify "should give correct results" do
563
+ h = []
564
+ @ds.returning(:foo).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
565
+ h.should == [{:foo=>4}]
566
+ h.clear
567
+ @ds.returning(:id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
568
+ h.should == [{:id=>3}]
569
+ h.clear
570
+ @ds.returning.update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
571
+ h.should == [{:id=>4, :foo=>16}]
572
+ h.clear
573
+ @ds.returning(:id___foo, :foo___id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
574
+ h.should == [{:id=>32, :foo=>5}]
575
+ h.clear
576
+
577
+ @ds.returning.delete{|r| h << r}
578
+ h.should == [{:id=>5, :foo=>32}]
579
+ h.clear
580
+ @ds.returning.delete{|r| h << r}
581
+ h.should == []
582
+ end
394
583
  end
395
584
  end
396
585
 
397
586
  if INTEGRATION_DB.dataset.supports_window_functions?
398
587
  describe "Window Functions" do
399
- before do
588
+ before(:all) do
400
589
  @db = INTEGRATION_DB
401
590
  @db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
402
591
  @ds = @db[:i1].order(:id)
@@ -407,7 +596,7 @@ if INTEGRATION_DB.dataset.supports_window_functions?
407
596
  @ds.insert(:id=>5, :group_id=>2, :amount=>10000)
408
597
  @ds.insert(:id=>6, :group_id=>2, :amount=>100000)
409
598
  end
410
- after do
599
+ after(:all) do
411
600
  @db.drop_table(:i1)
412
601
  end
413
602
 
@@ -435,21 +624,13 @@ if INTEGRATION_DB.dataset.supports_window_functions?
435
624
  cspecify "should give correct results for aggregate window functions with frames", :mssql do
436
625
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
437
626
  [{: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
627
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
441
628
  [{: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
629
 
445
630
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
446
631
  [{: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
632
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
450
633
  [{: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
634
  end
454
635
  end
455
636
  end
@@ -471,10 +652,10 @@ describe Sequel::SQL::Constants do
471
652
  @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
472
653
  end
473
654
  after do
474
- @db.drop_table(:constants)
655
+ @db.drop_table(:constants) if @db.table_exists?(:constants)
475
656
  end
476
657
 
477
- cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite] do
658
+ cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite], :oracle do
478
659
  @db.create_table!(:constants){Date :d}
479
660
  @ds.insert(:d=>Sequel::CURRENT_DATE)
480
661
  d = @c2[@ds.get(:d)]
@@ -485,26 +666,27 @@ describe Sequel::SQL::Constants do
485
666
  cspecify "should have working CURRENT_TIME", [:do, :mysql], [:jdbc, :sqlite], [:mysql2] do
486
667
  @db.create_table!(:constants){Time :t, :only_time=>true}
487
668
  @ds.insert(:t=>Sequel::CURRENT_TIME)
488
- (Time.now - @c[@ds.get(:t)]).should be_within(1).of(0)
669
+ (Time.now - @c[@ds.get(:t)]).should be_within(2).of(0)
489
670
  end
490
671
 
491
672
  cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite] do
492
673
  @db.create_table!(:constants){DateTime :ts}
493
674
  @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
494
- (Time.now - @c[@ds.get(:ts)]).should be_within(1).of(0)
675
+ (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
495
676
  end
496
677
  end
497
678
 
498
679
  describe "Sequel::Dataset#import and #multi_insert" do
499
- before do
680
+ before(:all) do
500
681
  @db = INTEGRATION_DB
501
682
  @db.create_table!(:imp){Integer :i}
502
- @db.create_table!(:exp2){Integer :i}
503
683
  @ids = @db[:imp].order(:i)
504
- @eds = @db[:exp2]
505
684
  end
506
- after do
507
- @db.drop_table(:imp, :exp2)
685
+ before do
686
+ @ids.delete
687
+ end
688
+ after(:all) do
689
+ @db.drop_table(:imp)
508
690
  end
509
691
 
510
692
  it "should import with multi_insert and an array of hashes" do
@@ -518,9 +700,11 @@ describe "Sequel::Dataset#import and #multi_insert" do
518
700
  end
519
701
 
520
702
  it "should import with a dataset" do
521
- @eds.import([:i], [[10], [20]])
522
- @ids.import([:i], @eds)
703
+ @db.create_table!(:exp2){Integer :i}
704
+ @db[:exp2].import([:i], [[10], [20]])
705
+ @ids.import([:i], @db[:exp2])
523
706
  @ids.all.should == [{:i=>10}, {:i=>20}]
707
+ @db.drop_table(:exp2)
524
708
  end
525
709
 
526
710
  it "should have import work with the :slice_size option" do
@@ -535,13 +719,65 @@ describe "Sequel::Dataset#import and #multi_insert" do
535
719
  end
536
720
  end
537
721
 
538
- describe "Sequel::Dataset convenience methods" do
722
+ describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
539
723
  before do
724
+ @db = INTEGRATION_DB
725
+ @db.create_table!(:imp){primary_key :id; Integer :i}
726
+ @ds = @db[:imp]
727
+ end
728
+ after do
729
+ @db.drop_table(:imp)
730
+ end
731
+
732
+ specify "should return primary key values " do
733
+ @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).should == [1, 2, 3]
734
+ @ds.import([:i], [[40], [50], [60]], :return=>:primary_key).should == [4, 5, 6]
735
+ @ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
736
+ end
737
+
738
+ specify "should return primary key values when :slice is used" do
739
+ @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).should == [1, 2, 3]
740
+ @ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).should == [4, 5, 6]
741
+ @ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
742
+ end
743
+ end
744
+
745
+ describe "Sequel::Dataset convenience methods" do
746
+ before(:all) do
747
+ @db = INTEGRATION_DB
748
+ @db.create_table!(:a){Integer :a; Integer :b; Integer :c}
749
+ @ds = @db[:a]
750
+ @ds.insert(1, 3, 5)
751
+ @ds.insert(1, 3, 6)
752
+ @ds.insert(1, 4, 5)
753
+ @ds.insert(2, 3, 5)
754
+ @ds.insert(2, 4, 6)
755
+ end
756
+ after(:all) do
757
+ @db.drop_table(:a)
758
+ end
759
+
760
+ it "#group_rollup should include hierarchy of groupings" do
761
+ @ds.group_by(:a).group_rollup.select_map([:a, :sum.sql_function(:b).cast(Integer).as(:b), :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 10, 16], [2, 7, 11], [nil, 17, 27]]
762
+ @ds.group_by(:a, :b).group_rollup.select_map([:a, :b, :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 3, 11], [1, 4, 5], [1, nil, 16], [2, 3, 5], [2, 4, 6], [2, nil, 11], [nil, nil, 27]]
763
+ end if INTEGRATION_DB.dataset.supports_group_rollup?
764
+
765
+ it "#group_cube should include all combinations of groupings" do
766
+ @ds.group_by(:a).group_cube.select_map([:a, :sum.sql_function(:b).cast(Integer).as(:b), :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 10, 16], [2, 7, 11], [nil, 17, 27]]
767
+ @ds.group_by(:a, :b).group_cube.select_map([:a, :b, :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 3, 11], [1, 4, 5], [1, nil, 16], [2, 3, 5], [2, 4, 6], [2, nil, 11], [nil, 3, 16], [nil, 4, 11], [nil, nil, 27]]
768
+ end if INTEGRATION_DB.dataset.supports_group_cube?
769
+ end
770
+
771
+ describe "Sequel::Dataset convenience methods" do
772
+ before(:all) do
540
773
  @db = INTEGRATION_DB
541
774
  @db.create_table!(:a){Integer :a; Integer :b}
542
775
  @ds = @db[:a].order(:a)
543
776
  end
544
- after do
777
+ before do
778
+ @ds.delete
779
+ end
780
+ after(:all) do
545
781
  @db.drop_table(:a)
546
782
  end
547
783
 
@@ -557,6 +793,22 @@ describe "Sequel::Dataset convenience methods" do
557
793
  @ds.empty?.should == false
558
794
  end
559
795
 
796
+ it "#empty? should work correctly for datasets with limits" do
797
+ ds = @ds.limit(1)
798
+ ds.empty?.should == true
799
+ ds.insert(20, 10)
800
+ ds.empty?.should == false
801
+ end
802
+
803
+ it "#empty? should work correctly for datasets with limits and offsets" do
804
+ ds = @ds.limit(1, 1)
805
+ ds.empty?.should == true
806
+ ds.insert(20, 10)
807
+ ds.empty?.should == true
808
+ ds.insert(20, 10)
809
+ ds.empty?.should == false
810
+ end
811
+
560
812
  it "#group_and_count should return a grouping by count" do
561
813
  @ds.group_and_count(:a).order(:count).all.should == []
562
814
  @ds.insert(20, 10)
@@ -577,7 +829,7 @@ describe "Sequel::Dataset convenience methods" do
577
829
  @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
830
  end
579
831
 
580
- cspecify "#range should return the range between the maximum and minimum values", :sqlite do
832
+ specify "#range should return the range between the maximum and minimum values" do
581
833
  @ds = @ds.unordered
582
834
  @ds.insert(20, 10)
583
835
  @ds.insert(30, 10)
@@ -595,12 +847,15 @@ describe "Sequel::Dataset convenience methods" do
595
847
  end
596
848
 
597
849
  describe "Sequel::Dataset main SQL methods" do
598
- before do
850
+ before(:all) do
599
851
  @db = INTEGRATION_DB
600
852
  @db.create_table!(:a){Integer :a; Integer :b}
601
853
  @ds = @db[:a].order(:a)
602
854
  end
603
- after do
855
+ before do
856
+ @ds.delete
857
+ end
858
+ after(:all) do
604
859
  @db.drop_table(:a)
605
860
  end
606
861
 
@@ -625,6 +880,23 @@ describe "Sequel::Dataset main SQL methods" do
625
880
  @ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
626
881
  @ds.filter(:a=>10).or(:b=>15).all.should == []
627
882
  end
883
+
884
+ it "#select_group should work correctly" do
885
+ @ds.unordered!
886
+ @ds.select_group(:a).all.should == []
887
+ @ds.insert(20, 30)
888
+ @ds.select_group(:a).all.should == [{:a=>20}]
889
+ @ds.select_group(:b).all.should == [{:b=>30}]
890
+ @ds.insert(20, 40)
891
+ @ds.select_group(:a).all.should == [{:a=>20}]
892
+ @ds.order(:b).select_group(:b).all.should == [{:b=>30}, {:b=>40}]
893
+ end
894
+
895
+ it "#select_group should work correctly when aliasing" do
896
+ @ds.unordered!
897
+ @ds.insert(20, 30)
898
+ @ds.select_group(:b___c).all.should == [{:c=>30}]
899
+ end
628
900
 
629
901
  it "#having should work correctly" do
630
902
  @ds.unordered!
@@ -645,13 +917,92 @@ describe "Sequel::Dataset main SQL methods" do
645
917
  end
646
918
  end
647
919
 
648
- describe "Sequel::Dataset DSL support" do
920
+ describe "Sequel::Dataset convenience methods" do
921
+ before(:all) do
922
+ @db = INTEGRATION_DB
923
+ @db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
924
+ @ds = @db[:a].order(:a)
925
+ end
649
926
  before do
927
+ @ds.delete
928
+ @ds.insert(1, 2, 3, 4)
929
+ @ds.insert(5, 6, 7, 8)
930
+ end
931
+ after(:all) do
932
+ @db.drop_table(:a)
933
+ end
934
+
935
+ specify "should have working #map" do
936
+ @ds.map(:a).should == [1, 5]
937
+ @ds.map(:b).should == [2, 6]
938
+ @ds.map([:a, :b]).should == [[1, 2], [5, 6]]
939
+ end
940
+
941
+ specify "should have working #to_hash" do
942
+ @ds.to_hash(:a).should == {1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8}}
943
+ @ds.to_hash(:b).should == {2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8}}
944
+ @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}}
945
+
946
+ @ds.to_hash(:a, :b).should == {1=>2, 5=>6}
947
+ @ds.to_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
948
+ @ds.to_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
949
+ @ds.to_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
950
+ end
951
+
952
+ specify "should have working #select_map" do
953
+ @ds.select_map(:a).should == [1, 5]
954
+ @ds.select_map(:b).should == [2, 6]
955
+ @ds.select_map([:a]).should == [[1], [5]]
956
+ @ds.select_map([:a, :b]).should == [[1, 2], [5, 6]]
957
+
958
+ @ds.select_map(:a___e).should == [1, 5]
959
+ @ds.select_map(:b___e).should == [2, 6]
960
+ @ds.select_map([:a___e, :b___f]).should == [[1, 2], [5, 6]]
961
+ @ds.select_map([:a__a___e, :a__b___f]).should == [[1, 2], [5, 6]]
962
+ @ds.select_map([:a__a.as(:e), :a__b.as(:f)]).should == [[1, 2], [5, 6]]
963
+ @ds.select_map([:a.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
964
+ @ds.select_map([:a.identifier.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
965
+ end
966
+
967
+ specify "should have working #select_order_map" do
968
+ @ds.select_order_map(:a).should == [1, 5]
969
+ @ds.select_order_map(:a__b.desc).should == [6, 2]
970
+ @ds.select_order_map(:a__b___e.desc).should == [6, 2]
971
+ @ds.select_order_map(:b.qualify(:a).as(:e)).should == [2, 6]
972
+ @ds.select_order_map([:a]).should == [[1], [5]]
973
+ @ds.select_order_map([:a.desc, :b]).should == [[5, 6], [1, 2]]
974
+
975
+ @ds.select_order_map(:a___e).should == [1, 5]
976
+ @ds.select_order_map(:b___e).should == [2, 6]
977
+ @ds.select_order_map([:a___e.desc, :b___f]).should == [[5, 6], [1, 2]]
978
+ @ds.select_order_map([:a__a___e.desc, :a__b___f]).should == [[5, 6], [1, 2]]
979
+ @ds.select_order_map([:a__a.desc, :a__b.as(:f)]).should == [[5, 6], [1, 2]]
980
+ @ds.select_order_map([:a.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
981
+ @ds.select_order_map([:a.identifier.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
982
+ end
983
+
984
+ specify "should have working #select_hash" do
985
+ @ds.select_hash(:a, :b).should == {1=>2, 5=>6}
986
+ @ds.select_hash(:a__a___e, :b).should == {1=>2, 5=>6}
987
+ @ds.select_hash(:a__a.as(:e), :b).should == {1=>2, 5=>6}
988
+ @ds.select_hash(:a.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
989
+ @ds.select_hash(:a.identifier.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
990
+ @ds.select_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
991
+ @ds.select_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
992
+ @ds.select_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
993
+ end
994
+ end
995
+
996
+ describe "Sequel::Dataset DSL support" do
997
+ before(:all) do
650
998
  @db = INTEGRATION_DB
651
999
  @db.create_table!(:a){Integer :a; Integer :b}
652
1000
  @ds = @db[:a].order(:a)
653
1001
  end
654
- after do
1002
+ before do
1003
+ @ds.delete
1004
+ end
1005
+ after(:all) do
655
1006
  @db.drop_table(:a)
656
1007
  end
657
1008
 
@@ -663,31 +1014,36 @@ describe "Sequel::Dataset DSL support" do
663
1014
  @ds.get{a / b}.to_i.should == 2
664
1015
  end
665
1016
 
666
- specify "should work with bitwise shift operators" do
1017
+ cspecify "should work with bitwise shift operators", :derby do
667
1018
  @ds.insert(3, 2)
668
1019
  @ds.get{a.sql_number << b}.to_i.should == 12
669
1020
  @ds.get{a.sql_number >> b}.to_i.should == 0
1021
+ @ds.get{a.sql_number << b << 1}.to_i.should == 24
670
1022
  @ds.delete
671
1023
  @ds.insert(3, 1)
672
1024
  @ds.get{a.sql_number << b}.to_i.should == 6
673
1025
  @ds.get{a.sql_number >> b}.to_i.should == 1
1026
+ @ds.get{a.sql_number >> b >> 1}.to_i.should == 0
674
1027
  end
675
1028
 
676
- specify "should work with bitwise AND and OR operators" do
1029
+ cspecify "should work with bitwise AND and OR operators", :derby do
677
1030
  @ds.insert(3, 5)
678
1031
  @ds.get{a.sql_number | b}.to_i.should == 7
679
1032
  @ds.get{a.sql_number & b}.to_i.should == 1
1033
+ @ds.get{a.sql_number | b | 8}.to_i.should == 15
1034
+ @ds.get{a.sql_number & b & 8}.to_i.should == 0
680
1035
  end
681
1036
 
682
- cspecify "should work with the bitwise compliment operator", :h2 do
1037
+ specify "should work with the bitwise compliment operator" do
683
1038
  @ds.insert(-3, 3)
684
1039
  @ds.get{~a.sql_number}.to_i.should == 2
685
1040
  @ds.get{~b.sql_number}.to_i.should == -4
686
1041
  end
687
1042
 
688
- cspecify "should work with the bitwise xor operator", :sqlite do
1043
+ cspecify "should work with the bitwise xor operator", :derby do
689
1044
  @ds.insert(3, 5)
690
1045
  @ds.get{a.sql_number ^ b}.to_i.should == 6
1046
+ @ds.get{a.sql_number ^ b ^ 1}.to_i.should == 7
691
1047
  end
692
1048
 
693
1049
  specify "should work with inequality operators" do
@@ -778,7 +1134,7 @@ describe "Sequel::Dataset DSL support" do
778
1134
  @ds.filter({15=>20}.case(0, :a) > 0).all.should == []
779
1135
  end
780
1136
 
781
- it "should work with multiple value arrays" do
1137
+ specify "should work with multiple value arrays" do
782
1138
  @ds.insert(20, 10)
783
1139
  @ds.quote_identifiers = false
784
1140
  @ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
@@ -847,22 +1203,36 @@ describe "SQL Extract Function" do
847
1203
  @db.drop_table(:a)
848
1204
  end
849
1205
 
850
- cspecify "should return the part of the datetime asked for", :sqlite, :mssql do
1206
+ specify "should return the part of the datetime asked for" do
851
1207
  t = Time.now
1208
+ def @ds.supports_timestamp_timezones?() false end
852
1209
  @ds.insert(t)
853
1210
  @ds.get{a.extract(:year)}.should == t.year
854
1211
  @ds.get{a.extract(:month)}.should == t.month
855
1212
  @ds.get{a.extract(:day)}.should == t.day
1213
+ @ds.get{a.extract(:hour)}.should == t.hour
1214
+ @ds.get{a.extract(:minute)}.should == t.min
1215
+ @ds.get{a.extract(:second)}.to_i.should == t.sec
856
1216
  end
857
1217
  end
858
1218
 
859
1219
  describe "Dataset string methods" do
860
- before do
1220
+ before(:all) do
861
1221
  @db = INTEGRATION_DB
862
- @db.create_table!(:a){String :a; String :b}
1222
+ csc = {}
1223
+ cic = {}
1224
+ csc[:collate] = @db.dataset_class::CASE_SENSITIVE_COLLATION if defined? @db.dataset_class::CASE_SENSITIVE_COLLATION
1225
+ cic[:collate] = @db.dataset_class::CASE_INSENSITIVE_COLLATION if defined? @db.dataset_class::CASE_INSENSITIVE_COLLATION
1226
+ @db.create_table!(:a) do
1227
+ String :a, csc
1228
+ String :b, cic
1229
+ end
863
1230
  @ds = @db[:a].order(:a)
864
1231
  end
865
- after do
1232
+ before do
1233
+ @ds.delete
1234
+ end
1235
+ after(:all) do
866
1236
  @db.drop_table(:a)
867
1237
  end
868
1238
 
@@ -877,15 +1247,15 @@ describe "Dataset string methods" do
877
1247
  end
878
1248
 
879
1249
  it "#grep should work with :all_patterns and :all_columns options" do
880
- @ds.insert('foo bar', '')
1250
+ @ds.insert('foo bar', ' ')
881
1251
  @ds.insert('foo d', 'bar')
882
- @ds.insert('foo e', '')
883
- @ds.insert('', 'bar')
1252
+ @ds.insert('foo e', ' ')
1253
+ @ds.insert(' ', 'bar')
884
1254
  @ds.insert('foo f', 'baz')
885
1255
  @ds.insert('foo baz', 'bar baz')
886
1256
  @ds.insert('foo boo', 'boo foo')
887
1257
 
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'}]
1258
+ @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
1259
  @ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.should == []
890
1260
 
891
1261
  @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 +1270,19 @@ describe "Dataset string methods" do
900
1270
  @ds.filter(:a.like('foo')).all.should == [{:a=>'foo', :b=>'bar'}]
901
1271
  @ds.filter(:a.like('bar')).all.should == []
902
1272
  @ds.filter(:a.like('foo', 'bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1273
+ @ds.exclude(:a.like('foo')).all.should == []
1274
+ @ds.exclude(:a.like('bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1275
+ @ds.exclude(:a.like('foo', 'bar')).all.should == []
1276
+ end
1277
+
1278
+ it "#like should be case sensitive" do
1279
+ @ds.insert('foo', 'bar')
1280
+ @ds.filter(:a.like('Foo')).all.should == []
1281
+ @ds.filter(:b.like('baR')).all.should == []
1282
+ @ds.filter(:a.like('FOO', 'BAR')).all.should == []
1283
+ @ds.exclude(:a.like('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
1284
+ @ds.exclude(:a.like('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1285
+ @ds.exclude(:a.like('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
903
1286
  end
904
1287
 
905
1288
  it "#ilike should return matching rows, in a case insensitive manner" do
@@ -907,17 +1290,20 @@ describe "Dataset string methods" do
907
1290
  @ds.filter(:a.ilike('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
908
1291
  @ds.filter(:a.ilike('baR')).all.should == []
909
1292
  @ds.filter(:a.ilike('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
1293
+ @ds.exclude(:a.ilike('Foo')).all.should == []
1294
+ @ds.exclude(:a.ilike('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1295
+ @ds.exclude(:a.ilike('FOO', 'BAR')).all.should == []
910
1296
  end
911
1297
 
912
1298
  it "should work with strings created with sql_string_join" do
913
1299
  @ds.insert('foo', 'bar')
914
- @ds.get([:a, :b].sql_string_join).should == 'foobar'
915
- @ds.get([:a, :b].sql_string_join(' ')).should == 'foo bar'
1300
+ @ds.get([:a, "bar"].sql_string_join).should == 'foobar'
1301
+ @ds.get(["foo", :b].sql_string_join(' ')).should == 'foo bar'
916
1302
  end
917
1303
  end
918
1304
 
919
1305
  describe "Dataset identifier methods" do
920
- before do
1306
+ before(:all) do
921
1307
  class ::String
922
1308
  def uprev
923
1309
  upcase.reverse
@@ -925,10 +1311,12 @@ describe "Dataset identifier methods" do
925
1311
  end
926
1312
  @db = INTEGRATION_DB
927
1313
  @db.create_table!(:a){Integer :ab}
1314
+ @db[:a].insert(1)
1315
+ end
1316
+ before do
928
1317
  @ds = @db[:a].order(:ab)
929
- @ds.insert(1)
930
1318
  end
931
- after do
1319
+ after(:all) do
932
1320
  @db.drop_table(:a)
933
1321
  end
934
1322
 
@@ -939,6 +1327,11 @@ describe "Dataset identifier methods" do
939
1327
  @ds.first.should == {:BA=>1}
940
1328
  end
941
1329
 
1330
+ it "should work with a nil identifier_output_method" do
1331
+ @ds.identifier_output_method = nil
1332
+ [{:ab=>1}, {:AB=>1}].should include(@ds.first)
1333
+ end
1334
+
942
1335
  it "should work when not quoting identifiers" do
943
1336
  @ds.quote_identifiers = false
944
1337
  @ds.first.should == {:ab=>1}
@@ -946,12 +1339,15 @@ describe "Dataset identifier methods" do
946
1339
  end
947
1340
 
948
1341
  describe "Dataset defaults and overrides" do
949
- before do
1342
+ before(:all) do
950
1343
  @db = INTEGRATION_DB
951
1344
  @db.create_table!(:a){Integer :a}
952
1345
  @ds = @db[:a].order(:a)
953
1346
  end
954
- after do
1347
+ before do
1348
+ @ds.delete
1349
+ end
1350
+ after(:all) do
955
1351
  @db.drop_table(:a)
956
1352
  end
957
1353