sequel 3.21.0 → 3.36.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 (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -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,17 @@ 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
+ specify "should support sequential primary keys with a Bignum" do
27
+ @db.create_table!(:items) do
28
+ primary_key :id, :type=>Bignum
29
+ Integer :number
30
+ end
31
+ @ds << {:number=>20}
32
+ @ds << {:number=>30}
33
+ @ds.order(:number).all.should == [{:id => 1, :number=>20}, {:id => 2, :number=>30}]
34
+ end
35
+
36
+ cspecify "should insert with a primary key specified", :db2, :mssql do
27
37
  @ds.insert(:id=>100, :number=>20)
28
38
  @ds.count.should == 2
29
39
  @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
@@ -34,6 +44,43 @@ describe "Simple Dataset operations" do
34
44
  @ds.filter(:id=>2).first[:number].should == 20
35
45
  end
36
46
 
47
+ specify "should have insert work correctly with static SQL" do
48
+ @db["INSERT INTO #{@ds.literal(:items)} (#{@ds.literal(:number)}) VALUES (20)"].insert
49
+ @ds.filter(:id=>2).first[:number].should == 20
50
+ end
51
+
52
+ specify "should have insert_multiple return primary key values" do
53
+ @ds.insert_multiple([{:number=>20}, {:number=>30}]).should == [2, 3]
54
+ @ds.filter(:id=>2).get(:number).should == 20
55
+ @ds.filter(:id=>3).get(:number).should == 30
56
+ end
57
+
58
+ specify "should join correctly" do
59
+ @ds.join(:items___b, :id=>:id).select_all(:items).all.should == [{:id=>1, :number=>10}]
60
+ end
61
+
62
+ specify "should correctly deal with qualified columns and subselects" do
63
+ @ds.from_self(:alias=>:a).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
64
+ @ds.join(@ds.as(:a), :id=>:id).select(:a__id, :number.qualify(:a)).all.should == [{:id=>1, :number=>10}]
65
+ end
66
+
67
+ specify "should graph correctly" do
68
+ @ds.graph(:items, {:id=>:id}, :table_alias=>:b).all.should == [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
69
+ end
70
+
71
+ specify "should graph correctly with a subselect" do
72
+ @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}}]
73
+ end
74
+
75
+ cspecify "should have insert work correctly when inserting a row with all NULL values", :hsqldb do
76
+ @db.create_table!(:items) do
77
+ String :name
78
+ Integer :number
79
+ end
80
+ proc{@ds.insert}.should_not raise_error
81
+ @ds.all.should == [{:name=>nil, :number=>nil}]
82
+ end
83
+
37
84
  specify "should delete correctly" do
38
85
  @ds.filter(1=>1).delete.should == 1
39
86
  @ds.count.should == 0
@@ -44,7 +91,7 @@ describe "Simple Dataset operations" do
44
91
  @ds.all.should == [{:id=>1, :number=>11}]
45
92
  end
46
93
 
47
- cspecify "should have update return the number of matched rows", [:mysql, :mysql], [:do, :mysql], [:mysql2], [:ado] do
94
+ cspecify "should have update return the number of matched rows", [:do, :mysql], [:ado] do
48
95
  @ds.update(:number=>:number).should == 1
49
96
  @ds.filter(:id=>1).update(:number=>:number).should == 1
50
97
  @ds.filter(:id=>2).update(:number=>:number).should == 0
@@ -79,13 +126,87 @@ describe "Simple Dataset operations" do
79
126
  @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
80
127
  end
81
128
 
82
- cspecify "should fetch correctly with a limit and offset without an order", :mssql do
129
+ specify "should provide correct columns when using a limit and offset" do
130
+ ds = @ds.order(:id).limit(1, 1)
131
+ ds.all
132
+ ds.columns.should == [:id, :number]
133
+ @ds.order(:id).limit(1, 1).columns.should == [:id, :number]
134
+ end
135
+
136
+ specify "should fetch correctly with a limit and offset for different combinations of from and join tables" do
137
+ @db.create_table!(:items2){primary_key :id2; Integer :number2}
138
+ @db[:items2].insert(:number2=>10)
139
+ @ds.from(:items, :items2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
140
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
141
+ @ds.cross_join(:items2).order(:id).limit(2, 0).all.should ==[{:id=>1, :number=>10, :id2=>1, :number2=>10}]
142
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
143
+ @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}]
144
+
145
+ @ds.from(:items, :items2).order(:id).limit(2, 1).all.should == []
146
+ @ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.should == []
147
+ @ds.cross_join(:items2).order(:id).limit(2, 1).all.should == []
148
+ @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.should == []
149
+ @ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.should == []
150
+ @db.drop_table(:items2)
151
+ end
152
+
153
+ cspecify "should fetch correctly with a limit and offset without an order", :db2, :mssql, :oracle do
83
154
  @ds.limit(2, 1).all.should == []
84
155
  end
85
156
 
157
+ specify "should fetch correctly with a limit in an IN subselect" do
158
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.should == [{:id=>1, :number=>10}]
159
+ @ds.insert(:number=>20)
160
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.should == [{:id=>1, :number=>10}]
161
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
162
+ end
163
+
164
+ specify "should fetch correctly with a limit and offset in an IN subselect" do
165
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.should == [{:id=>1, :number=>10}]
166
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == []
167
+ @ds.insert(:number=>20)
168
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.should == [{:id=>2, :number=>20}]
169
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
170
+ @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.should == [{:id=>2, :number=>20}]
171
+ end
172
+
86
173
  specify "should alias columns correctly" do
87
174
  @ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
88
175
  end
176
+
177
+ specify "should handle true/false properly" do
178
+ @ds.filter(Sequel::TRUE).select_map(:number).should == [10]
179
+ @ds.filter(Sequel::FALSE).select_map(:number).should == []
180
+ @ds.filter(true).select_map(:number).should == [10]
181
+ @ds.filter(false).select_map(:number).should == []
182
+ end
183
+ end
184
+
185
+ describe "Simple dataset operations with nasty table names" do
186
+ before do
187
+ @db = INTEGRATION_DB
188
+ @table = :"i`t' [e]\"m\\s"
189
+ @qi = @db.quote_identifiers?
190
+ @db.quote_identifiers = true
191
+ end
192
+ after do
193
+ @db.quote_identifiers = @qi
194
+ end
195
+
196
+ cspecify "should work correctly", :mssql, :oracle do
197
+ @db.create_table!(@table) do
198
+ primary_key :id
199
+ Integer :number
200
+ end
201
+ @ds = @db[@table]
202
+ @ds.insert(:number=>10).should == 1
203
+ @ds.all.should == [{:id=>1, :number=>10}]
204
+ @ds.update(:number=>20).should == 1
205
+ @ds.all.should == [{:id=>1, :number=>20}]
206
+ @ds.delete.should == 1
207
+ @ds.count.should == 0
208
+ proc{@db.drop_table?(@table)}.should_not raise_error
209
+ end
89
210
  end
90
211
 
91
212
  describe Sequel::Dataset do
@@ -95,10 +216,9 @@ describe Sequel::Dataset do
95
216
  Integer :value
96
217
  end
97
218
  @d = INTEGRATION_DB[:test]
98
- clear_sqls
99
219
  end
100
220
  after do
101
- INTEGRATION_DB.drop_table(:test)
221
+ INTEGRATION_DB.drop_table?(:test)
102
222
  end
103
223
 
104
224
  specify "should return the correct record count" do
@@ -171,23 +291,38 @@ end
171
291
 
172
292
  describe Sequel::Database do
173
293
  specify "should correctly escape strings" do
174
- INTEGRATION_DB.get("\\dingo".as(:a)) == "\\dingo"
175
- end
176
-
177
- specify "should correctly escape strings with quotes" do
178
- INTEGRATION_DB.get("\\'dingo".as(:a)) == "\\'dingo"
294
+ ["\\\n",
295
+ "\\\\\n",
296
+ "\\\r\n",
297
+ "\\\\\r\n",
298
+ "\\\\\n\n",
299
+ "\\\\\r\n\r\n",
300
+ "\\dingo",
301
+ "\\'dingo",
302
+ "\\\\''dingo",
303
+ ].each do |str|
304
+ INTEGRATION_DB.get(str.as(:a)).should == str
305
+ str = "1#{str}1"
306
+ INTEGRATION_DB.get(str.as(:a)).should == str
307
+ str = "#{str}#{str}"
308
+ INTEGRATION_DB.get(str.as(:a)).should == str
309
+ end
179
310
  end
180
311
 
181
- specify "should properly escape binary data" do
182
- INTEGRATION_DB.get("\1\2\3".to_sequel_blob.as(:a)) == "\1\2\3"
312
+ cspecify "should properly escape binary data", [:odbc], [:jdbc, :hsqldb], [:swift], :oracle do
313
+ INTEGRATION_DB.get("\1\2\3".to_sequel_blob.cast(File).as(:a)).should == "\1\2\3"
183
314
  end
184
315
 
185
316
  specify "should have a working table_exists?" do
186
317
  t = :basdfdsafsaddsaf
187
- INTEGRATION_DB.drop_table(t) rescue nil
318
+ INTEGRATION_DB.drop_table?(t)
188
319
  INTEGRATION_DB.table_exists?(t).should == false
189
320
  INTEGRATION_DB.create_table(t){Integer :a}
190
- INTEGRATION_DB.table_exists?(t).should == true
321
+ begin
322
+ INTEGRATION_DB.table_exists?(t).should == true
323
+ ensure
324
+ INTEGRATION_DB.drop_table(t)
325
+ end
191
326
  end
192
327
  end
193
328
 
@@ -203,7 +338,7 @@ describe Sequel::Dataset do
203
338
  @d << {:value => 789}
204
339
  end
205
340
  after do
206
- INTEGRATION_DB.drop_table(:items)
341
+ INTEGRATION_DB.drop_table?(:items)
207
342
  end
208
343
 
209
344
  specify "should correctly return avg" do
@@ -232,7 +367,7 @@ describe "Simple Dataset operations" do
232
367
  @ds = INTEGRATION_DB[:items]
233
368
  end
234
369
  after do
235
- INTEGRATION_DB.drop_table(:items)
370
+ INTEGRATION_DB.drop_table?(:items)
236
371
  end
237
372
 
238
373
  specify "should deal with boolean conditions correctly" do
@@ -251,18 +386,17 @@ end
251
386
 
252
387
  describe "Simple Dataset operations in transactions" do
253
388
  before do
254
- INTEGRATION_DB.create_table!(:items_insert_in_transaction) do
389
+ INTEGRATION_DB.create_table!(:items) do
255
390
  primary_key :id
256
391
  integer :number
257
392
  end
258
- @ds = INTEGRATION_DB[:items_insert_in_transaction]
259
- clear_sqls
393
+ @ds = INTEGRATION_DB[:items]
260
394
  end
261
395
  after do
262
- INTEGRATION_DB.drop_table(:items_insert_in_transaction)
396
+ INTEGRATION_DB.drop_table?(:items)
263
397
  end
264
398
 
265
- cspecify "should insert correctly with a primary key specified inside a transaction", :mssql do
399
+ cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
266
400
  INTEGRATION_DB.transaction do
267
401
  @ds.insert(:id=>100, :number=>20)
268
402
  @ds.count.should == 1
@@ -293,7 +427,6 @@ describe "Dataset UNION, EXCEPT, and INTERSECT" do
293
427
  @ds2 = INTEGRATION_DB[:i2]
294
428
  @ds2.insert(:number=>10)
295
429
  @ds2.insert(:number=>30)
296
- clear_sqls
297
430
  end
298
431
 
299
432
  specify "should give the correct results for simple UNION, EXCEPT, and INTERSECT" do
@@ -359,7 +492,7 @@ end
359
492
 
360
493
  if INTEGRATION_DB.dataset.supports_cte?
361
494
  describe "Common Table Expressions" do
362
- before do
495
+ before(:all) do
363
496
  @db = INTEGRATION_DB
364
497
  @db.create_table!(:i1){Integer :id; Integer :parent_id}
365
498
  @ds = @db[:i1]
@@ -370,15 +503,15 @@ if INTEGRATION_DB.dataset.supports_cte?
370
503
  @ds.insert(:id=>5, :parent_id=>3)
371
504
  @ds.insert(:id=>6, :parent_id=>5)
372
505
  end
373
- after do
374
- @db.drop_table(:i1)
506
+ after(:all) do
507
+ @db.drop_table?(:i1)
375
508
  end
376
509
 
377
510
  specify "should give correct results for WITH" do
378
511
  @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).should == [1, 2]
379
512
  end
380
513
 
381
- specify "should give correct results for recursive WITH" do
514
+ cspecify "should give correct results for recursive WITH", :db2 do
382
515
  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
516
  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
517
  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 +524,116 @@ if INTEGRATION_DB.dataset.supports_cte?
391
524
  @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
525
  @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
526
  end
527
+
528
+ specify "should support a subselect in the FROM clause with a CTE" do
529
+ @ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
530
+ @db[:t].with(:t, @ds).from_self.select_order_map(:id).should == [1,2,3,4,5,6]
531
+ end
532
+
533
+ specify "should support using a CTE inside a CTE" do
534
+ @db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
535
+ @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]
536
+ end
537
+
538
+ specify "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
539
+ @ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
540
+ if @ds.supports_intersect_except?
541
+ @ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).should == [1,2,3,4,5,6]
542
+ @ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).should == []
543
+ end
544
+ end
545
+ end
546
+ end
547
+
548
+ if INTEGRATION_DB.dataset.supports_cte?(:update) # Assume INSERT and DELETE support as well
549
+ describe "Common Table Expressions in INSERT/UPDATE/DELETE" do
550
+ before do
551
+ @db = INTEGRATION_DB
552
+ @db.create_table!(:i1){Integer :id}
553
+ @ds = @db[:i1]
554
+ @ds2 = @ds.with(:t, @ds)
555
+ @ds.insert(:id=>1)
556
+ @ds.insert(:id=>2)
557
+ end
558
+ after do
559
+ @db.drop_table?(:i1)
560
+ end
561
+
562
+ specify "should give correct results for WITH" do
563
+ @ds2.insert(@db[:t])
564
+ @ds.select_order_map(:id).should == [1, 1, 2, 2]
565
+ @ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>:id+1)
566
+ @ds.select_order_map(:id).should == [1, 1, 3, 3]
567
+ @ds2.filter(:id=>@db[:t].select{max(id)}).delete
568
+ @ds.select_order_map(:id).should == [1, 1]
569
+ end
570
+ end
571
+ end
572
+
573
+ if INTEGRATION_DB.dataset.supports_returning?(:insert)
574
+ describe "RETURNING clauses in INSERT" do
575
+ before do
576
+ @db = INTEGRATION_DB
577
+ @db.create_table!(:i1){Integer :id; Integer :foo}
578
+ @ds = @db[:i1]
579
+ end
580
+ after do
581
+ @db.drop_table?(:i1)
582
+ end
583
+
584
+ specify "should give correct results" do
585
+ h = {}
586
+ @ds.returning(:foo).insert(1, 2){|r| h = r}
587
+ h.should == {:foo=>2}
588
+ @ds.returning(:id).insert(3, 4){|r| h = r}
589
+ h.should == {:id=>3}
590
+ @ds.returning.insert(5, 6){|r| h = r}
591
+ h.should == {:id=>5, :foo=>6}
592
+ @ds.returning(:id___foo, :foo___id).insert(7, 8){|r| h = r}
593
+ h.should == {:id=>8, :foo=>7}
594
+ end
595
+ end
596
+ end
597
+
598
+ if INTEGRATION_DB.dataset.supports_returning?(:update) # Assume DELETE support as well
599
+ describe "RETURNING clauses in UPDATE/DELETE" do
600
+ before do
601
+ @db = INTEGRATION_DB
602
+ @db.create_table!(:i1){Integer :id; Integer :foo}
603
+ @ds = @db[:i1]
604
+ @ds.insert(1, 2)
605
+ end
606
+ after do
607
+ @db.drop_table?(:i1)
608
+ end
609
+
610
+ specify "should give correct results" do
611
+ h = []
612
+ @ds.returning(:foo).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
613
+ h.should == [{:foo=>4}]
614
+ h.clear
615
+ @ds.returning(:id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
616
+ h.should == [{:id=>3}]
617
+ h.clear
618
+ @ds.returning.update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
619
+ h.should == [{:id=>4, :foo=>16}]
620
+ h.clear
621
+ @ds.returning(:id___foo, :foo___id).update(:id=>:id+1, :foo=>:foo*2){|r| h << r}
622
+ h.should == [{:id=>32, :foo=>5}]
623
+ h.clear
624
+
625
+ @ds.returning.delete{|r| h << r}
626
+ h.should == [{:id=>5, :foo=>32}]
627
+ h.clear
628
+ @ds.returning.delete{|r| h << r}
629
+ h.should == []
630
+ end
394
631
  end
395
632
  end
396
633
 
397
634
  if INTEGRATION_DB.dataset.supports_window_functions?
398
635
  describe "Window Functions" do
399
- before do
636
+ before(:all) do
400
637
  @db = INTEGRATION_DB
401
638
  @db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
402
639
  @ds = @db[:i1].order(:id)
@@ -407,8 +644,8 @@ if INTEGRATION_DB.dataset.supports_window_functions?
407
644
  @ds.insert(:id=>5, :group_id=>2, :amount=>10000)
408
645
  @ds.insert(:id=>6, :group_id=>2, :amount=>100000)
409
646
  end
410
- after do
411
- @db.drop_table(:i1)
647
+ after(:all) do
648
+ @db.drop_table?(:i1)
412
649
  end
413
650
 
414
651
  specify "should give correct results for aggregate window functions" do
@@ -435,21 +672,13 @@ if INTEGRATION_DB.dataset.supports_window_functions?
435
672
  cspecify "should give correct results for aggregate window functions with frames", :mssql do
436
673
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
437
674
  [{: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
675
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:all){}.as(:sum)}.all.should ==
441
676
  [{: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
677
 
445
678
  @ds.select(:id){sum(:over, :args=>amount, :partition=>group_id, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
446
679
  [{: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
680
  @ds.select(:id){sum(:over, :args=>amount, :order=>id, :frame=>:rows){}.as(:sum)}.all.should ==
450
681
  [{: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
682
  end
454
683
  end
455
684
  end
@@ -471,10 +700,10 @@ describe Sequel::SQL::Constants do
471
700
  @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
472
701
  end
473
702
  after do
474
- @db.drop_table(:constants)
703
+ @db.drop_table?(:constants)
475
704
  end
476
705
 
477
- cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite] do
706
+ cspecify "should have working CURRENT_DATE", [:odbc, :mssql], [:jdbc, :sqlite], :oracle do
478
707
  @db.create_table!(:constants){Date :d}
479
708
  @ds.insert(:d=>Sequel::CURRENT_DATE)
480
709
  d = @c2[@ds.get(:d)]
@@ -485,26 +714,33 @@ describe Sequel::SQL::Constants do
485
714
  cspecify "should have working CURRENT_TIME", [:do, :mysql], [:jdbc, :sqlite], [:mysql2] do
486
715
  @db.create_table!(:constants){Time :t, :only_time=>true}
487
716
  @ds.insert(:t=>Sequel::CURRENT_TIME)
488
- (Time.now - @c[@ds.get(:t)]).should be_within(1).of(0)
717
+ (Time.now - @c[@ds.get(:t)]).should be_within(2).of(0)
489
718
  end
490
719
 
491
- cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite] do
720
+ cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite], [:swift] do
492
721
  @db.create_table!(:constants){DateTime :ts}
493
722
  @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
494
- (Time.now - @c[@ds.get(:ts)]).should be_within(1).of(0)
723
+ (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
724
+ end
725
+
726
+ cspecify "should have working CURRENT_TIMESTAMP when used as a column default", [:jdbc, :sqlite], [:swift] do
727
+ @db.create_table!(:constants){DateTime :ts, :default=>Sequel::CURRENT_TIMESTAMP}
728
+ @ds.insert
729
+ (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
495
730
  end
496
731
  end
497
732
 
498
733
  describe "Sequel::Dataset#import and #multi_insert" do
499
- before do
734
+ before(:all) do
500
735
  @db = INTEGRATION_DB
501
736
  @db.create_table!(:imp){Integer :i}
502
- @db.create_table!(:exp2){Integer :i}
503
737
  @ids = @db[:imp].order(:i)
504
- @eds = @db[:exp2]
505
738
  end
506
- after do
507
- @db.drop_table(:imp, :exp2)
739
+ before do
740
+ @ids.delete
741
+ end
742
+ after(:all) do
743
+ @db.drop_table?(:imp)
508
744
  end
509
745
 
510
746
  it "should import with multi_insert and an array of hashes" do
@@ -518,9 +754,11 @@ describe "Sequel::Dataset#import and #multi_insert" do
518
754
  end
519
755
 
520
756
  it "should import with a dataset" do
521
- @eds.import([:i], [[10], [20]])
522
- @ids.import([:i], @eds)
757
+ @db.create_table!(:exp2){Integer :i}
758
+ @db[:exp2].import([:i], [[10], [20]])
759
+ @ids.import([:i], @db[:exp2])
523
760
  @ids.all.should == [{:i=>10}, {:i=>20}]
761
+ @db.drop_table(:exp2)
524
762
  end
525
763
 
526
764
  it "should have import work with the :slice_size option" do
@@ -535,14 +773,66 @@ describe "Sequel::Dataset#import and #multi_insert" do
535
773
  end
536
774
  end
537
775
 
538
- describe "Sequel::Dataset convenience methods" do
776
+ describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
539
777
  before do
778
+ @db = INTEGRATION_DB
779
+ @db.create_table!(:imp){primary_key :id; Integer :i}
780
+ @ds = @db[:imp]
781
+ end
782
+ after do
783
+ @db.drop_table?(:imp)
784
+ end
785
+
786
+ specify "should return primary key values " do
787
+ @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).should == [1, 2, 3]
788
+ @ds.import([:i], [[40], [50], [60]], :return=>:primary_key).should == [4, 5, 6]
789
+ @ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
790
+ end
791
+
792
+ specify "should return primary key values when :slice is used" do
793
+ @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).should == [1, 2, 3]
794
+ @ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).should == [4, 5, 6]
795
+ @ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
796
+ end
797
+ end
798
+
799
+ describe "Sequel::Dataset convenience methods" do
800
+ before(:all) do
801
+ @db = INTEGRATION_DB
802
+ @db.create_table!(:a){Integer :a; Integer :b; Integer :c}
803
+ @ds = @db[:a]
804
+ @ds.insert(1, 3, 5)
805
+ @ds.insert(1, 3, 6)
806
+ @ds.insert(1, 4, 5)
807
+ @ds.insert(2, 3, 5)
808
+ @ds.insert(2, 4, 6)
809
+ end
810
+ after(:all) do
811
+ @db.drop_table?(:a)
812
+ end
813
+
814
+ it "#group_rollup should include hierarchy of groupings" do
815
+ @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]]
816
+ @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]]
817
+ end if INTEGRATION_DB.dataset.supports_group_rollup?
818
+
819
+ it "#group_cube should include all combinations of groupings" do
820
+ @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]]
821
+ @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]]
822
+ end if INTEGRATION_DB.dataset.supports_group_cube?
823
+ end
824
+
825
+ describe "Sequel::Dataset convenience methods" do
826
+ before(:all) do
540
827
  @db = INTEGRATION_DB
541
828
  @db.create_table!(:a){Integer :a; Integer :b}
542
829
  @ds = @db[:a].order(:a)
543
830
  end
544
- after do
545
- @db.drop_table(:a)
831
+ before do
832
+ @ds.delete
833
+ end
834
+ after(:all) do
835
+ @db.drop_table?(:a)
546
836
  end
547
837
 
548
838
  it "#[]= should update matching rows" do
@@ -557,6 +847,22 @@ describe "Sequel::Dataset convenience methods" do
557
847
  @ds.empty?.should == false
558
848
  end
559
849
 
850
+ it "#empty? should work correctly for datasets with limits" do
851
+ ds = @ds.limit(1)
852
+ ds.empty?.should == true
853
+ ds.insert(20, 10)
854
+ ds.empty?.should == false
855
+ end
856
+
857
+ it "#empty? should work correctly for datasets with limits and offsets" do
858
+ ds = @ds.limit(1, 1)
859
+ ds.empty?.should == true
860
+ ds.insert(20, 10)
861
+ ds.empty?.should == true
862
+ ds.insert(20, 10)
863
+ ds.empty?.should == false
864
+ end
865
+
560
866
  it "#group_and_count should return a grouping by count" do
561
867
  @ds.group_and_count(:a).order(:count).all.should == []
562
868
  @ds.insert(20, 10)
@@ -577,7 +883,7 @@ describe "Sequel::Dataset convenience methods" do
577
883
  @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
884
  end
579
885
 
580
- cspecify "#range should return the range between the maximum and minimum values", :sqlite do
886
+ specify "#range should return the range between the maximum and minimum values" do
581
887
  @ds = @ds.unordered
582
888
  @ds.insert(20, 10)
583
889
  @ds.insert(30, 10)
@@ -595,13 +901,16 @@ describe "Sequel::Dataset convenience methods" do
595
901
  end
596
902
 
597
903
  describe "Sequel::Dataset main SQL methods" do
598
- before do
904
+ before(:all) do
599
905
  @db = INTEGRATION_DB
600
906
  @db.create_table!(:a){Integer :a; Integer :b}
601
907
  @ds = @db[:a].order(:a)
602
908
  end
603
- after do
604
- @db.drop_table(:a)
909
+ before do
910
+ @ds.delete
911
+ end
912
+ after(:all) do
913
+ @db.drop_table?(:a)
605
914
  end
606
915
 
607
916
  it "#exists should return a usable exists clause" do
@@ -625,6 +934,23 @@ describe "Sequel::Dataset main SQL methods" do
625
934
  @ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
626
935
  @ds.filter(:a=>10).or(:b=>15).all.should == []
627
936
  end
937
+
938
+ it "#select_group should work correctly" do
939
+ @ds.unordered!
940
+ @ds.select_group(:a).all.should == []
941
+ @ds.insert(20, 30)
942
+ @ds.select_group(:a).all.should == [{:a=>20}]
943
+ @ds.select_group(:b).all.should == [{:b=>30}]
944
+ @ds.insert(20, 40)
945
+ @ds.select_group(:a).all.should == [{:a=>20}]
946
+ @ds.order(:b).select_group(:b).all.should == [{:b=>30}, {:b=>40}]
947
+ end
948
+
949
+ it "#select_group should work correctly when aliasing" do
950
+ @ds.unordered!
951
+ @ds.insert(20, 30)
952
+ @ds.select_group(:b___c).all.should == [{:c=>30}]
953
+ end
628
954
 
629
955
  it "#having should work correctly" do
630
956
  @ds.unordered!
@@ -645,14 +971,119 @@ describe "Sequel::Dataset main SQL methods" do
645
971
  end
646
972
  end
647
973
 
648
- describe "Sequel::Dataset DSL support" do
974
+ describe "Sequel::Dataset convenience methods" do
975
+ before(:all) do
976
+ @db = INTEGRATION_DB
977
+ @db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
978
+ @ds = @db[:a].order(:a)
979
+ end
649
980
  before do
981
+ @ds.delete
982
+ @ds.insert(1, 2, 3, 4)
983
+ @ds.insert(5, 6, 7, 8)
984
+ end
985
+ after(:all) do
986
+ @db.drop_table?(:a)
987
+ end
988
+
989
+ specify "should have working #map" do
990
+ @ds.map(:a).should == [1, 5]
991
+ @ds.map(:b).should == [2, 6]
992
+ @ds.map([:a, :b]).should == [[1, 2], [5, 6]]
993
+ end
994
+
995
+ specify "should have working #to_hash" do
996
+ @ds.to_hash(:a).should == {1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8}}
997
+ @ds.to_hash(:b).should == {2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8}}
998
+ @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}}
999
+
1000
+ @ds.to_hash(:a, :b).should == {1=>2, 5=>6}
1001
+ @ds.to_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
1002
+ @ds.to_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
1003
+ @ds.to_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
1004
+ end
1005
+
1006
+ specify "should have working #to_hash_groups" do
1007
+ ds = @ds.order(*@ds.columns)
1008
+ ds.insert(1, 2, 3, 9)
1009
+ ds.to_hash_groups(:a).should == {1=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 5=>[{:a=>5, :b=>6, :c=>7, :d=>8}]}
1010
+ ds.to_hash_groups(:b).should == {2=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 6=>[{:a=>5, :b=>6, :c=>7, :d=>8}]}
1011
+ ds.to_hash_groups([:a, :b]).should == {[1, 2]=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], [5, 6]=>[{:a=>5, :b=>6, :c=>7, :d=>8}]}
1012
+
1013
+ ds.to_hash_groups(:a, :d).should == {1=>[4, 9], 5=>[8]}
1014
+ ds.to_hash_groups([:a, :c], :d).should == {[1, 3]=>[4, 9], [5, 7]=>[8]}
1015
+ ds.to_hash_groups(:a, [:b, :d]).should == {1=>[[2, 4], [2, 9]], 5=>[[6, 8]]}
1016
+ ds.to_hash_groups([:a, :c], [:b, :d]).should == {[1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]]}
1017
+ end
1018
+
1019
+ specify "should have working #select_map" do
1020
+ @ds.select_map(:a).should == [1, 5]
1021
+ @ds.select_map(:b).should == [2, 6]
1022
+ @ds.select_map([:a]).should == [[1], [5]]
1023
+ @ds.select_map([:a, :b]).should == [[1, 2], [5, 6]]
1024
+
1025
+ @ds.select_map(:a___e).should == [1, 5]
1026
+ @ds.select_map(:b___e).should == [2, 6]
1027
+ @ds.select_map([:a___e, :b___f]).should == [[1, 2], [5, 6]]
1028
+ @ds.select_map([:a__a___e, :a__b___f]).should == [[1, 2], [5, 6]]
1029
+ @ds.select_map([:a__a.as(:e), :a__b.as(:f)]).should == [[1, 2], [5, 6]]
1030
+ @ds.select_map([:a.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
1031
+ @ds.select_map([:a.identifier.qualify(:a).as(:e), :b.qualify(:a).as(:f)]).should == [[1, 2], [5, 6]]
1032
+ end
1033
+
1034
+ specify "should have working #select_order_map" do
1035
+ @ds.select_order_map(:a).should == [1, 5]
1036
+ @ds.select_order_map(:a__b.desc).should == [6, 2]
1037
+ @ds.select_order_map(:a__b___e.desc).should == [6, 2]
1038
+ @ds.select_order_map(:b.qualify(:a).as(:e)).should == [2, 6]
1039
+ @ds.select_order_map([:a]).should == [[1], [5]]
1040
+ @ds.select_order_map([:a.desc, :b]).should == [[5, 6], [1, 2]]
1041
+
1042
+ @ds.select_order_map(:a___e).should == [1, 5]
1043
+ @ds.select_order_map(:b___e).should == [2, 6]
1044
+ @ds.select_order_map([:a___e.desc, :b___f]).should == [[5, 6], [1, 2]]
1045
+ @ds.select_order_map([:a__a___e.desc, :a__b___f]).should == [[5, 6], [1, 2]]
1046
+ @ds.select_order_map([:a__a.desc, :a__b.as(:f)]).should == [[5, 6], [1, 2]]
1047
+ @ds.select_order_map([:a.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
1048
+ @ds.select_order_map([:a.identifier.qualify(:a).desc, :b.qualify(:a).as(:f)]).should == [[5, 6], [1, 2]]
1049
+ end
1050
+
1051
+ specify "should have working #select_hash" do
1052
+ @ds.select_hash(:a, :b).should == {1=>2, 5=>6}
1053
+ @ds.select_hash(:a__a___e, :b).should == {1=>2, 5=>6}
1054
+ @ds.select_hash(:a__a.as(:e), :b).should == {1=>2, 5=>6}
1055
+ @ds.select_hash(:a.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
1056
+ @ds.select_hash(:a.identifier.qualify(:a).as(:e), :b).should == {1=>2, 5=>6}
1057
+ @ds.select_hash([:a, :c], :b).should == {[1, 3]=>2, [5, 7]=>6}
1058
+ @ds.select_hash(:a, [:b, :c]).should == {1=>[2, 3], 5=>[6, 7]}
1059
+ @ds.select_hash([:a, :c], [:b, :d]).should == {[1, 3]=>[2, 4], [5, 7]=>[6, 8]}
1060
+ end
1061
+
1062
+ specify "should have working #select_hash_groups" do
1063
+ ds = @ds.order(*@ds.columns)
1064
+ ds.insert(1, 2, 3, 9)
1065
+ ds.select_hash_groups(:a, :d).should == {1=>[4, 9], 5=>[8]}
1066
+ ds.select_hash_groups(:a__a___e, :d).should == {1=>[4, 9], 5=>[8]}
1067
+ ds.select_hash_groups(:a__a.as(:e), :d).should == {1=>[4, 9], 5=>[8]}
1068
+ ds.select_hash_groups(:a.qualify(:a).as(:e), :d).should == {1=>[4, 9], 5=>[8]}
1069
+ ds.select_hash_groups(:a.identifier.qualify(:a).as(:e), :d).should == {1=>[4, 9], 5=>[8]}
1070
+ ds.select_hash_groups([:a, :c], :d).should == {[1, 3]=>[4, 9], [5, 7]=>[8]}
1071
+ ds.select_hash_groups(:a, [:b, :d]).should == {1=>[[2, 4], [2, 9]], 5=>[[6, 8]]}
1072
+ ds.select_hash_groups([:a, :c], [:b, :d]).should == {[1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]]}
1073
+ end
1074
+ end
1075
+
1076
+ describe "Sequel::Dataset DSL support" do
1077
+ before(:all) do
650
1078
  @db = INTEGRATION_DB
651
1079
  @db.create_table!(:a){Integer :a; Integer :b}
652
1080
  @ds = @db[:a].order(:a)
653
1081
  end
654
- after do
655
- @db.drop_table(:a)
1082
+ before do
1083
+ @ds.delete
1084
+ end
1085
+ after(:all) do
1086
+ @db.drop_table?(:a)
656
1087
  end
657
1088
 
658
1089
  it "should work with standard mathematical operators" do
@@ -663,31 +1094,43 @@ describe "Sequel::Dataset DSL support" do
663
1094
  @ds.get{a / b}.to_i.should == 2
664
1095
  end
665
1096
 
666
- specify "should work with bitwise shift operators" do
1097
+ cspecify "should work with bitwise shift operators", :derby do
667
1098
  @ds.insert(3, 2)
668
1099
  @ds.get{a.sql_number << b}.to_i.should == 12
669
1100
  @ds.get{a.sql_number >> b}.to_i.should == 0
1101
+ @ds.get{a.sql_number << b << 1}.to_i.should == 24
670
1102
  @ds.delete
671
1103
  @ds.insert(3, 1)
672
1104
  @ds.get{a.sql_number << b}.to_i.should == 6
673
1105
  @ds.get{a.sql_number >> b}.to_i.should == 1
1106
+ @ds.get{a.sql_number >> b >> 1}.to_i.should == 0
674
1107
  end
675
1108
 
676
- specify "should work with bitwise AND and OR operators" do
1109
+ cspecify "should work with bitwise AND and OR operators", :derby do
677
1110
  @ds.insert(3, 5)
678
1111
  @ds.get{a.sql_number | b}.to_i.should == 7
679
1112
  @ds.get{a.sql_number & b}.to_i.should == 1
1113
+ @ds.get{a.sql_number | b | 8}.to_i.should == 15
1114
+ @ds.get{a.sql_number & b & 8}.to_i.should == 0
680
1115
  end
681
1116
 
682
- cspecify "should work with the bitwise compliment operator", :h2 do
1117
+ specify "should work with the bitwise compliment operator" do
683
1118
  @ds.insert(-3, 3)
684
1119
  @ds.get{~a.sql_number}.to_i.should == 2
685
1120
  @ds.get{~b.sql_number}.to_i.should == -4
686
1121
  end
687
1122
 
688
- cspecify "should work with the bitwise xor operator", :sqlite do
1123
+ cspecify "should work with the bitwise xor operator", :derby do
689
1124
  @ds.insert(3, 5)
690
1125
  @ds.get{a.sql_number ^ b}.to_i.should == 6
1126
+ @ds.get{a.sql_number ^ b ^ 1}.to_i.should == 7
1127
+ end
1128
+
1129
+ specify "should work with the modulus operator" do
1130
+ @ds.insert(3, 5)
1131
+ @ds.get{a.sql_number % 4}.to_i.should == 3
1132
+ @ds.get{b.sql_number % 4}.to_i.should == 1
1133
+ @ds.get{a.sql_number % 4 % 2}.to_i.should == 1
691
1134
  end
692
1135
 
693
1136
  specify "should work with inequality operators" do
@@ -778,7 +1221,7 @@ describe "Sequel::Dataset DSL support" do
778
1221
  @ds.filter({15=>20}.case(0, :a) > 0).all.should == []
779
1222
  end
780
1223
 
781
- it "should work with multiple value arrays" do
1224
+ specify "should work with multiple value arrays" do
782
1225
  @ds.insert(20, 10)
783
1226
  @ds.quote_identifiers = false
784
1227
  @ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
@@ -822,11 +1265,42 @@ describe "Sequel::Dataset DSL support" do
822
1265
  specify "should work empty arrays with nulls" do
823
1266
  @ds.insert(nil, nil)
824
1267
  @ds.filter(:a=>[]).all.should == []
825
- @ds.exclude(:a=>[]).all.should == [{:a=>nil, :b=>nil}]
1268
+ @ds.exclude(:a=>[]).all.should == []
826
1269
  @ds.filter([:a, :b]=>[]).all.should == []
827
- @ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
1270
+ @ds.exclude([:a, :b]=>[]).all.should == []
1271
+
1272
+ unless Sequel.guarded?(:mssql, :oracle, :db2)
1273
+ # MSSQL doesn't like boolean results in the select list
1274
+ pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1275
+ pr[@ds.get({:a=>[]}.sql_expr)].should == nil
1276
+ pr[@ds.get(~({:a=>[]}).sql_expr)].should == nil
1277
+ pr[@ds.get({[:a, :b]=>[]}.sql_expr)].should == nil
1278
+ pr[@ds.get(~({[:a, :b]=>[]}).sql_expr)].should == nil
1279
+ end
828
1280
  end
829
1281
 
1282
+ specify "should work empty arrays with nulls and Sequel.empty_array_null_handling = true" do
1283
+ begin
1284
+ Sequel.empty_array_handle_nulls = false
1285
+ @ds.insert(nil, nil)
1286
+ @ds.filter(:a=>[]).all.should == []
1287
+ @ds.exclude(:a=>[]).all.should == [{:a=>nil, :b=>nil}]
1288
+ @ds.filter([:a, :b]=>[]).all.should == []
1289
+ @ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
1290
+
1291
+ unless Sequel.guarded?(:mssql, :oracle, :db2)
1292
+ # MSSQL doesn't like boolean results in the select list
1293
+ pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1294
+ pr[@ds.get({:a=>[]}.sql_expr)].should == false
1295
+ pr[@ds.get(~({:a=>[]}).sql_expr)].should == true
1296
+ pr[@ds.get({[:a, :b]=>[]}.sql_expr)].should == false
1297
+ pr[@ds.get(~({[:a, :b]=>[]}).sql_expr)].should == true
1298
+ end
1299
+ ensure
1300
+ Sequel.empty_array_handle_nulls = true
1301
+ end
1302
+ end
1303
+
830
1304
  it "should work multiple conditions" do
831
1305
  @ds.insert(20, 10)
832
1306
  @ds.filter(:a=>20, :b=>10).all.should == [{:a=>20, :b=>10}]
@@ -844,26 +1318,40 @@ describe "SQL Extract Function" do
844
1318
  @ds = @db[:a].order(:a)
845
1319
  end
846
1320
  after do
847
- @db.drop_table(:a)
1321
+ @db.drop_table?(:a)
848
1322
  end
849
1323
 
850
- cspecify "should return the part of the datetime asked for", :sqlite, :mssql do
1324
+ specify "should return the part of the datetime asked for" do
851
1325
  t = Time.now
1326
+ def @ds.supports_timestamp_timezones?() false end
852
1327
  @ds.insert(t)
853
1328
  @ds.get{a.extract(:year)}.should == t.year
854
1329
  @ds.get{a.extract(:month)}.should == t.month
855
1330
  @ds.get{a.extract(:day)}.should == t.day
1331
+ @ds.get{a.extract(:hour)}.should == t.hour
1332
+ @ds.get{a.extract(:minute)}.should == t.min
1333
+ @ds.get{a.extract(:second)}.to_i.should == t.sec
856
1334
  end
857
1335
  end
858
1336
 
859
1337
  describe "Dataset string methods" do
860
- before do
1338
+ before(:all) do
861
1339
  @db = INTEGRATION_DB
862
- @db.create_table!(:a){String :a; String :b}
1340
+ csc = {}
1341
+ cic = {}
1342
+ csc[:collate] = @db.dataset_class::CASE_SENSITIVE_COLLATION if defined? @db.dataset_class::CASE_SENSITIVE_COLLATION
1343
+ cic[:collate] = @db.dataset_class::CASE_INSENSITIVE_COLLATION if defined? @db.dataset_class::CASE_INSENSITIVE_COLLATION
1344
+ @db.create_table!(:a) do
1345
+ String :a, csc
1346
+ String :b, cic
1347
+ end
863
1348
  @ds = @db[:a].order(:a)
864
1349
  end
865
- after do
866
- @db.drop_table(:a)
1350
+ before do
1351
+ @ds.delete
1352
+ end
1353
+ after(:all) do
1354
+ @db.drop_table?(:a)
867
1355
  end
868
1356
 
869
1357
  it "#grep should return matching rows" do
@@ -877,15 +1365,15 @@ describe "Dataset string methods" do
877
1365
  end
878
1366
 
879
1367
  it "#grep should work with :all_patterns and :all_columns options" do
880
- @ds.insert('foo bar', '')
1368
+ @ds.insert('foo bar', ' ')
881
1369
  @ds.insert('foo d', 'bar')
882
- @ds.insert('foo e', '')
883
- @ds.insert('', 'bar')
1370
+ @ds.insert('foo e', ' ')
1371
+ @ds.insert(' ', 'bar')
884
1372
  @ds.insert('foo f', 'baz')
885
1373
  @ds.insert('foo baz', 'bar baz')
886
1374
  @ds.insert('foo boo', 'boo foo')
887
1375
 
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'}]
1376
+ @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
1377
  @ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.should == []
890
1378
 
891
1379
  @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 +1388,19 @@ describe "Dataset string methods" do
900
1388
  @ds.filter(:a.like('foo')).all.should == [{:a=>'foo', :b=>'bar'}]
901
1389
  @ds.filter(:a.like('bar')).all.should == []
902
1390
  @ds.filter(:a.like('foo', 'bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1391
+ @ds.exclude(:a.like('foo')).all.should == []
1392
+ @ds.exclude(:a.like('bar')).all.should == [{:a=>'foo', :b=>'bar'}]
1393
+ @ds.exclude(:a.like('foo', 'bar')).all.should == []
1394
+ end
1395
+
1396
+ it "#like should be case sensitive" do
1397
+ @ds.insert('foo', 'bar')
1398
+ @ds.filter(:a.like('Foo')).all.should == []
1399
+ @ds.filter(:b.like('baR')).all.should == []
1400
+ @ds.filter(:a.like('FOO', 'BAR')).all.should == []
1401
+ @ds.exclude(:a.like('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
1402
+ @ds.exclude(:a.like('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1403
+ @ds.exclude(:a.like('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
903
1404
  end
904
1405
 
905
1406
  it "#ilike should return matching rows, in a case insensitive manner" do
@@ -907,17 +1408,20 @@ describe "Dataset string methods" do
907
1408
  @ds.filter(:a.ilike('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
908
1409
  @ds.filter(:a.ilike('baR')).all.should == []
909
1410
  @ds.filter(:a.ilike('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
1411
+ @ds.exclude(:a.ilike('Foo')).all.should == []
1412
+ @ds.exclude(:a.ilike('baR')).all.should == [{:a=>'foo', :b=>'bar'}]
1413
+ @ds.exclude(:a.ilike('FOO', 'BAR')).all.should == []
910
1414
  end
911
1415
 
912
1416
  it "should work with strings created with sql_string_join" do
913
1417
  @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'
1418
+ @ds.get([:a, "bar"].sql_string_join).should == 'foobar'
1419
+ @ds.get(["foo", :b].sql_string_join(' ')).should == 'foo bar'
916
1420
  end
917
1421
  end
918
1422
 
919
1423
  describe "Dataset identifier methods" do
920
- before do
1424
+ before(:all) do
921
1425
  class ::String
922
1426
  def uprev
923
1427
  upcase.reverse
@@ -925,20 +1429,27 @@ describe "Dataset identifier methods" do
925
1429
  end
926
1430
  @db = INTEGRATION_DB
927
1431
  @db.create_table!(:a){Integer :ab}
1432
+ @db[:a].insert(1)
1433
+ end
1434
+ before do
928
1435
  @ds = @db[:a].order(:ab)
929
- @ds.insert(1)
930
1436
  end
931
- after do
932
- @db.drop_table(:a)
1437
+ after(:all) do
1438
+ @db.drop_table?(:a)
933
1439
  end
934
1440
 
935
- cspecify "#identifier_output_method should change how identifiers are output", [:mysql2], [:swift] do
1441
+ cspecify "#identifier_output_method should change how identifiers are output", [:swift] do
936
1442
  @ds.identifier_output_method = :upcase
937
1443
  @ds.first.should == {:AB=>1}
938
1444
  @ds.identifier_output_method = :uprev
939
1445
  @ds.first.should == {:BA=>1}
940
1446
  end
941
1447
 
1448
+ it "should work with a nil identifier_output_method" do
1449
+ @ds.identifier_output_method = nil
1450
+ [{:ab=>1}, {:AB=>1}].should include(@ds.first)
1451
+ end
1452
+
942
1453
  it "should work when not quoting identifiers" do
943
1454
  @ds.quote_identifiers = false
944
1455
  @ds.first.should == {:ab=>1}
@@ -946,13 +1457,16 @@ describe "Dataset identifier methods" do
946
1457
  end
947
1458
 
948
1459
  describe "Dataset defaults and overrides" do
949
- before do
1460
+ before(:all) do
950
1461
  @db = INTEGRATION_DB
951
1462
  @db.create_table!(:a){Integer :a}
952
1463
  @ds = @db[:a].order(:a)
953
1464
  end
954
- after do
955
- @db.drop_table(:a)
1465
+ before do
1466
+ @ds.delete
1467
+ end
1468
+ after(:all) do
1469
+ @db.drop_table?(:a)
956
1470
  end
957
1471
 
958
1472
  it "#set_defaults should set defaults that can be overridden" do
@@ -986,7 +1500,7 @@ if INTEGRATION_DB.dataset.supports_modifying_joins?
986
1500
  @db[:c].insert(7, 8)
987
1501
  end
988
1502
  after do
989
- @db.drop_table(:a, :b, :c)
1503
+ @db.drop_table?(:a, :b, :c)
990
1504
  end
991
1505
 
992
1506
  it "#update should allow updating joined datasets" do