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,218 +2,264 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Prepared Statements and Bound Arguments" do
4
4
  before do
5
- INTEGRATION_DB.create_table!(:items) do
5
+ @db = INTEGRATION_DB
6
+ @db.create_table!(:items) do
6
7
  primary_key :id
7
- integer :number
8
+ integer :numb
8
9
  end
9
10
  @c = Class.new(Sequel::Model(:items))
10
- @ds = INTEGRATION_DB[:items]
11
- @ds.insert(:number=>10)
12
- @ds.meta_def(:ba) do |sym|
13
- prepared_arg_placeholder == '$' ? :"#{sym}__int" : sym
14
- end
11
+ @ds = @db[:items]
12
+ @ds.insert(:numb=>10)
13
+ @pr = @ds.requires_placeholder_type_specifiers? ? proc{|i| :"#{i}__integer"} : proc{|i| i}
15
14
  end
16
15
  after do
17
- INTEGRATION_DB.drop_table(:items)
16
+ @db.drop_table?(:items)
18
17
  end
19
18
 
20
- specify "should support bound variables with select, all, and first" do
21
- @ds.filter(:number=>@ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
22
- @ds.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
23
- @ds.filter(:number=>@ds.ba(:$n)).call(:first, :n=>10).should == {:id=>1, :number=>10}
19
+ specify "should support bound variables when selecting" do
20
+ @ds.filter(:numb=>:$n).call(:each, :n=>10){|h| h.should == {:id=>1, :numb=>10}}
21
+ @ds.filter(:numb=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
22
+ @ds.filter(:numb=>:$n).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
23
+ @ds.filter(:numb=>:$n).call(:first, :n=>10).should == {:id=>1, :numb=>10}
24
+ @ds.filter(:numb=>:$n).call([:map, :numb], :n=>10).should == [10]
25
+ @ds.filter(:numb=>:$n).call([:to_hash, :id, :numb], :n=>10).should == {1=>10}
26
+ @ds.filter(:numb=>:$n).call([:to_hash_groups, :id, :numb], :n=>10).should == {1=>[10]}
24
27
  end
25
28
 
26
- specify "should support blocks for select and all" do
27
- @ds.filter(:number=>@ds.ba(:$n)).call(:select, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
28
- @ds.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
29
+ specify "should support blocks for each, select, all, and map when using bound variables" do
30
+ a = []
31
+ @ds.filter(:numb=>:$n).call(:each, :n=>10){|r| r[:numb] *= 2; a << r}; a.should == [{:id=>1, :numb=>20}]
32
+ @ds.filter(:numb=>:$n).call(:select, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
33
+ @ds.filter(:numb=>:$n).call(:all, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
34
+ @ds.filter(:numb=>:$n).call([:map], :n=>10){|r| r[:numb] * 2}.should == [20]
29
35
  end
30
36
 
31
37
  specify "should support binding variables before the call with #bind" do
32
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
33
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
34
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
38
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
39
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
40
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
35
41
 
36
- @ds.bind(:n=>10).filter(:number=>@ds.ba(:$n)).call(:select).should == [{:id=>1, :number=>10}]
37
- @ds.bind(:n=>10).filter(:number=>@ds.ba(:$n)).call(:all).should == [{:id=>1, :number=>10}]
38
- @ds.bind(:n=>10).filter(:number=>@ds.ba(:$n)).call(:first).should == {:id=>1, :number=>10}
42
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:select).should == [{:id=>1, :numb=>10}]
43
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:all).should == [{:id=>1, :numb=>10}]
44
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:first).should == {:id=>1, :numb=>10}
39
45
  end
40
46
 
41
47
  specify "should allow overriding variables specified with #bind" do
42
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
43
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
44
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :number=>10}
48
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
49
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
50
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :numb=>10}
45
51
 
46
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
47
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
48
- @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
52
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
53
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
54
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
49
55
  end
50
56
 
51
57
  specify "should support placeholder literal strings with call" do
52
- @ds.filter("number = ?", @ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
58
+ @ds.filter("numb = ?", :$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
53
59
  end
54
60
 
55
61
  specify "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
56
- @ds.filter("number = :n", :n=>@ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
57
- @ds.insert(:number=>20)
58
- @ds.insert(:number=>30)
59
- @ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
62
+ @ds.filter("numb = :n", :n=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
63
+ @ds.insert(:numb=>20)
64
+ @ds.insert(:numb=>30)
65
+ @ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :numb=>20}]
60
66
  end
61
67
 
62
68
  specify "should support datasets with static sql and placeholders with call" do
63
- INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
69
+ @db["SELECT * FROM items WHERE numb = ?", :$n].call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
64
70
  end
65
71
 
66
72
  specify "should support subselects with call" do
67
- @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
73
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
74
+ end
75
+
76
+ specify "should support subselects with exists with call" do
77
+ @ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
68
78
  end
69
79
 
70
80
  specify "should support subselects with literal strings with call" do
71
- @ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", @ds.ba(:$n))).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
81
+ @ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
72
82
  end
73
83
 
74
84
  specify "should support subselects with static sql and placeholders with call" do
75
- @ds.filter(:id=>:$i, :number=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
85
+ @ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
76
86
  end
77
87
 
78
88
  specify "should support subselects of subselects with call" do
79
- @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n)))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
89
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
80
90
  end
81
91
 
82
- specify "should support using a bound variable for a limit and offset" do
83
- @ds.insert(:number=>20)
84
- ds = @ds.limit(@ds.ba(:$n), @ds.ba(:$n2)).order(:id)
85
- ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
86
- ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
92
+ cspecify "should support using a bound variable for a limit and offset", [:jdbc, :db2] do
93
+ @ds.insert(:numb=>20)
94
+ ds = @ds.limit(:$n, :$n2).order(:id)
95
+ ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
96
+ ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
87
97
  ds.call(:select, :n=>1, :n2=>2).should == []
88
- ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
89
- ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :number=>20}]
98
+ ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
99
+ ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
90
100
  end
91
101
 
92
102
  specify "should support bound variables with insert" do
93
- @ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n))
103
+ @ds.call(:insert, {:n=>20}, :numb=>:$n)
94
104
  @ds.count.should == 2
95
- @ds.order(:id).map(:number).should == [10, 20]
105
+ @ds.order(:id).map(:numb).should == [10, 20]
106
+ end
107
+
108
+ specify "should support bound variables with NULL values" do
109
+ @ds.delete
110
+ @ds.call(:insert, {:n=>nil}, :numb=>@pr[:$n])
111
+ @ds.count.should == 1
112
+ @ds.map(:numb).should == [nil]
96
113
  end
97
114
 
98
115
  specify "should have insert return primary key value when using bound arguments" do
99
- @ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n)).should == 2
100
- @ds.filter(:id=>2).first[:number].should == 20
116
+ @ds.call(:insert, {:n=>20}, :numb=>:$n).should == 2
117
+ @ds.filter(:id=>2).first[:numb].should == 20
101
118
  end
102
119
 
103
120
  specify "should support bound variables with delete" do
104
- @ds.filter(:number=>@ds.ba(:$n)).call(:delete, :n=>10).should == 1
121
+ @ds.filter(:numb=>:$n).call(:delete, :n=>10).should == 1
105
122
  @ds.count.should == 0
106
123
  end
107
124
 
108
125
  specify "should support bound variables with update" do
109
- @ds.filter(:number=>@ds.ba(:$n)).call(:update, {:n=>10, :nn=>20}, :number=>:number+@ds.ba(:$nn)).should == 1
110
- @ds.all.should == [{:id=>1, :number=>30}]
126
+ @ds.filter(:numb=>:$n).call(:update, {:n=>10, :nn=>20}, :numb=>:numb+:$nn).should == 1
127
+ @ds.all.should == [{:id=>1, :numb=>30}]
111
128
  end
112
129
 
113
- specify "should support prepared statements with select, first, and all" do
114
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:select, :select_n)
115
- INTEGRATION_DB.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
116
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:all, :select_n)
117
- INTEGRATION_DB.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
118
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
119
- INTEGRATION_DB.call(:select_n, :n=>10).should == {:id=>1, :number=>10}
120
- if INTEGRATION_DB.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
121
- # Work around for open prepared statements on a table not allowing the
122
- # dropping of a table when using SQLite over JDBC
123
- INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
124
- end
130
+ specify "should support prepared statements when selecting" do
131
+ @ds.filter(:numb=>:$n).prepare(:each, :select_n)
132
+ @db.call(:select_n, :n=>10){|h| h.should == {:id=>1, :numb=>10}}
133
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
134
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
135
+ @ds.filter(:numb=>:$n).prepare(:all, :select_n)
136
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
137
+ @ds.filter(:numb=>:$n).prepare(:first, :select_n)
138
+ @db.call(:select_n, :n=>10).should == {:id=>1, :numb=>10}
139
+ @ds.filter(:numb=>:$n).prepare([:map, :numb], :select_n)
140
+ @db.call(:select_n, :n=>10).should == [10]
141
+ @ds.filter(:numb=>:$n).prepare([:to_hash, :id, :numb], :select_n)
142
+ @db.call(:select_n, :n=>10).should == {1=>10}
143
+ end
144
+
145
+ specify "should support blocks for each, select, all, and map when using prepared statements" do
146
+ a = []
147
+ @ds.filter(:numb=>:$n).prepare(:each, :select_n).call(:n=>10){|r| r[:numb] *= 2; a << r}; a.should == [{:id=>1, :numb=>20}]
148
+ a = []
149
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2; a << r}; a.should == [{:id=>1, :numb=>20}]
150
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n).call(:n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
151
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
152
+ @ds.filter(:numb=>:$n).prepare(:all, :select_n).call(:n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
153
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
154
+ @ds.filter(:numb=>:$n).prepare([:map], :select_n).call(:n=>10){|r| r[:numb] *= 2}.should == [20]
155
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.should == [20]
156
+ end
157
+
158
+ specify "should support prepared statements being called multiple times with different arguments" do
159
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
160
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
161
+ @db.call(:select_n, :n=>0).should == []
162
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
125
163
  end
126
164
 
127
165
  specify "should support placeholder literal strings with prepare" do
128
- @ds.filter("number = ?", @ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
166
+ @ds.filter("numb = ?", :$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
129
167
  end
130
168
 
131
169
  specify "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
132
- @ds.filter("number = :n", :n=>@ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
133
- @ds.insert(:number=>20)
134
- @ds.insert(:number=>30)
135
- @ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
170
+ @ds.filter("numb = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
171
+ @ds.insert(:numb=>20)
172
+ @ds.insert(:numb=>30)
173
+ @ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :numb=>20}]
136
174
  end
137
175
 
138
176
  specify "should support datasets with static sql and placeholders with prepare" do
139
- INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
177
+ @db["SELECT * FROM items WHERE numb = ?", :$n].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
140
178
  end
141
179
 
142
180
  specify "should support subselects with prepare" do
143
- @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
181
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
182
+ end
183
+
184
+ specify "should support subselects with exists with prepare" do
185
+ @ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
144
186
  end
145
187
 
146
188
  specify "should support subselects with literal strings with prepare" do
147
- @ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", @ds.ba(:$n))).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
189
+ @ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
148
190
  end
149
191
 
150
192
  specify "should support subselects with static sql and placeholders with prepare" do
151
- @ds.filter(:id=>:$i, :number=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
193
+ @ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
152
194
  end
153
195
 
154
196
  specify "should support subselects of subselects with prepare" do
155
- @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n)))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
197
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
156
198
  end
157
199
 
158
- specify "should support using a prepared_statement for a limit and offset" do
159
- @ds.insert(:number=>20)
160
- ps = @ds.limit(@ds.ba(:$n), @ds.ba(:$n2)).order(:id).prepare(:select, :seq_select)
161
- ps.call(:n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
162
- ps.call(:n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
200
+ cspecify "should support using a prepared_statement for a limit and offset", :db2 do
201
+ @ds.insert(:numb=>20)
202
+ ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
203
+ ps.call(:n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
204
+ ps.call(:n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
163
205
  ps.call(:n=>1, :n2=>2).should == []
164
- ps.call(:n=>2, :n2=>0).should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
165
- ps.call(:n=>2, :n2=>1).should == [{:id=>2, :number=>20}]
206
+ ps.call(:n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
207
+ ps.call(:n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
166
208
  end
167
209
 
168
210
  specify "should support prepared statements with insert" do
169
- @ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
170
- INTEGRATION_DB.call(:insert_n, :n=>20)
211
+ @ds.prepare(:insert, :insert_n, :numb=>:$n)
212
+ @db.call(:insert_n, :n=>20)
171
213
  @ds.count.should == 2
172
- @ds.order(:id).map(:number).should == [10, 20]
214
+ @ds.order(:id).map(:numb).should == [10, 20]
215
+ end
216
+
217
+ specify "should support prepared statements with NULL values" do
218
+ @ds.delete
219
+ @ds.prepare(:insert, :insert_n, :numb=>@pr[:$n])
220
+ @db.call(:insert_n, :n=>nil)
221
+ @ds.count.should == 1
222
+ @ds.map(:numb).should == [nil]
173
223
  end
174
224
 
175
225
  specify "should have insert return primary key value when using prepared statements" do
176
- @ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
177
- INTEGRATION_DB.call(:insert_n, :n=>20).should == 2
178
- @ds.filter(:id=>2).first[:number].should == 20
226
+ @ds.prepare(:insert, :insert_n, :numb=>:$n)
227
+ @db.call(:insert_n, :n=>20).should == 2
228
+ @ds.filter(:id=>2).first[:numb].should == 20
179
229
  end
180
230
 
181
231
  specify "should support prepared statements with delete" do
182
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:delete, :delete_n)
183
- INTEGRATION_DB.call(:delete_n, :n=>10).should == 1
232
+ @ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
233
+ @db.call(:delete_n, :n=>10).should == 1
184
234
  @ds.count.should == 0
185
235
  end
186
236
 
187
237
  specify "should support prepared statements with update" do
188
- @ds.filter(:number=>@ds.ba(:$n)).prepare(:update, :update_n, :number=>:number+@ds.ba(:$nn))
189
- INTEGRATION_DB.call(:update_n, :n=>10, :nn=>20).should == 1
190
- @ds.all.should == [{:id=>1, :number=>30}]
238
+ @ds.filter(:numb=>:$n).prepare(:update, :update_n, :numb=>:numb+:$nn)
239
+ @db.call(:update_n, :n=>10, :nn=>20).should == 1
240
+ @ds.all.should == [{:id=>1, :numb=>30}]
191
241
  end
192
242
 
193
243
  specify "model datasets should return model instances when using select, all, and first with bound variables" do
194
- @c.filter(:number=>@ds.ba(:$n)).call(:select, :n=>10).should == [@c.load(:id=>1, :number=>10)]
195
- @c.filter(:number=>@ds.ba(:$n)).call(:all, :n=>10).should == [@c.load(:id=>1, :number=>10)]
196
- @c.filter(:number=>@ds.ba(:$n)).call(:first, :n=>10).should == @c.load(:id=>1, :number=>10)
244
+ @c.filter(:numb=>:$n).call(:select, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
245
+ @c.filter(:numb=>:$n).call(:all, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
246
+ @c.filter(:numb=>:$n).call(:first, :n=>10).should == @c.load(:id=>1, :numb=>10)
197
247
  end
198
248
 
199
249
  specify "model datasets should return model instances when using select, all, and first with prepared statements" do
200
- @c.filter(:number=>@ds.ba(:$n)).prepare(:select, :select_n)
201
- INTEGRATION_DB.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
202
- @c.filter(:number=>@ds.ba(:$n)).prepare(:all, :select_n)
203
- INTEGRATION_DB.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
204
- @c.filter(:number=>@ds.ba(:$n)).prepare(:first, :select_n)
205
- INTEGRATION_DB.call(:select_n, :n=>10).should == @c.load(:id=>1, :number=>10)
206
- if INTEGRATION_DB.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
207
- # Work around for open prepared statements on a table not allowing the
208
- # dropping of a table when using SQLite over JDBC
209
- INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
210
- end
250
+ @c.filter(:numb=>:$n).prepare(:select, :select_n1)
251
+ @db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
252
+ @c.filter(:numb=>:$n).prepare(:all, :select_n1)
253
+ @db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
254
+ @c.filter(:numb=>:$n).prepare(:first, :select_n1)
255
+ @db.call(:select_n1, :n=>10).should == @c.load(:id=>1, :numb=>10)
211
256
  end
212
257
  end
213
258
 
214
259
  describe "Bound Argument Types" do
215
- before do
216
- INTEGRATION_DB.create_table!(:items) do
260
+ before(:all) do
261
+ @db = INTEGRATION_DB
262
+ @db.create_table!(:items) do
217
263
  primary_key :id
218
264
  Date :d
219
265
  DateTime :dt
@@ -223,48 +269,137 @@ describe "Bound Argument Types" do
223
269
  Float :f
224
270
  TrueClass :b
225
271
  end
226
- @ds = INTEGRATION_DB[:items]
272
+ @ds = @db[:items]
227
273
  @vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(20101010), :file=>Sequel::SQL::Blob.new('blob'), :b=>true}
274
+ end
275
+ before do
276
+ @ds.delete
228
277
  @ds.insert(@vs)
229
- @ds.meta_def(:ba) do |sym, type|
230
- prepared_arg_placeholder == '$' ? :"#{sym}__#{type}" : sym
231
- end
232
278
  end
233
279
  after do
234
280
  Sequel.datetime_class = Time
235
- if INTEGRATION_DB.adapter_scheme == :jdbc && INTEGRATION_DB.database_type == :sqlite
236
- INTEGRATION_DB.synchronize{|c| c.prepared_statements.each{|k, ps| ps[1].close}.clear}
237
- end
238
- INTEGRATION_DB.drop_table(:items)
281
+ end
282
+ after(:all) do
283
+ @db.drop_table?(:items)
239
284
  end
240
285
 
241
- cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite] do
242
- @ds.filter(:d=>@ds.ba(:$x, :date)).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
286
+ cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite], :oracle do
287
+ @ds.filter(:d=>:$x).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
288
+ end
289
+
290
+ cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds], [:oracle] do
291
+ Sequel.datetime_class = DateTime
292
+ @ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
243
293
  end
244
294
 
245
- cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds] do
295
+ cspecify "should handle datetime type with fractional seconds", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds], [:oracle] do
246
296
  Sequel.datetime_class = DateTime
247
- @ds.filter(:dt=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
297
+ fract_time = DateTime.parse('2010-10-12 13:14:15.500000')
298
+ @ds.prepare(:update, :ps_datetime_up, :dt=>:$x).call(:x=>fract_time)
299
+ @ds.literal(@ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>fract_time)[:dt]).should == @ds.literal(fract_time)
248
300
  end
249
301
 
250
- cspecify "should handle time type", [:do], [:jdbc, :sqlite] do
251
- @ds.filter(:t=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
302
+ cspecify "should handle time type", [:do], [:jdbc, :sqlite], [:swift], [:oracle] do
303
+ @ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
252
304
  end
253
305
 
254
- cspecify "should handle blob type", [:swift] do
255
- @ds.filter(:file=>@ds.ba(:$x, :bytea)).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
306
+ cspecify "should handle time type with fractional seconds", [:do], [:jdbc, :sqlite], [:oracle] do
307
+ fract_time = @vs[:t] + 0.5
308
+ @ds.prepare(:update, :ps_time_up, :t=>:$x).call(:x=>fract_time)
309
+ @ds.literal(@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>fract_time)[:t]).should == @ds.literal(fract_time)
310
+ end
311
+
312
+ cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
313
+ @ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
314
+ end
315
+
316
+ cspecify "should handle blob type with embedded zeros", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
317
+ zero_blob = Sequel::SQL::Blob.new("a\0"*100)
318
+ @ds.prepare(:update, :ps_blob_up, :file=>:$x).call(:x=>zero_blob)
319
+ @ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>zero_blob)[:file].should == zero_blob
256
320
  end
257
321
 
258
322
  cspecify "should handle float type", [:swift, :sqlite] do
259
- @ds.filter(:f=>@ds.ba(:$x, :"double precision")).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
323
+ @ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
260
324
  end
261
325
 
262
326
  specify "should handle string type" do
263
- @ds.filter(:s=>@ds.ba(:$x, :text)).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
327
+ @ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
328
+ end
329
+
330
+ cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite], [:jdbc, :db2], :oracle do
331
+ @ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
332
+ end
333
+ end unless Sequel.guarded?([:swift, :postgres])
334
+
335
+ describe "Dataset#unbind" do
336
+ before do
337
+ @ds = ds = INTEGRATION_DB[:items]
338
+ @ct = proc do |t, v|
339
+ INTEGRATION_DB.create_table!(:items) do
340
+ column :c, t
341
+ end
342
+ ds.insert(:c=>v)
343
+ end
344
+ @u = proc{|ds| ds, bv = ds.unbind; ds.call(:first, bv)}
345
+ end
346
+ after do
347
+ INTEGRATION_DB.drop_table?(:items)
348
+ end
349
+
350
+ specify "should unbind values assigned to equality and inequality statements" do
351
+ @ct[Integer, 10]
352
+ @u[@ds.filter(:c=>10)].should == {:c=>10}
353
+ @u[@ds.exclude(:c=>10)].should == nil
354
+ @u[@ds.filter{c < 10}].should == nil
355
+ @u[@ds.filter{c <= 10}].should == {:c=>10}
356
+ @u[@ds.filter{c > 10}].should == nil
357
+ @u[@ds.filter{c >= 10}].should == {:c=>10}
358
+ end
359
+
360
+ cspecify "should handle numerics and strings", [:odbc], [:swift, :sqlite] do
361
+ @ct[Integer, 10]
362
+ @u[@ds.filter(:c=>10)].should == {:c=>10}
363
+ @ct[Float, 0.0]
364
+ @u[@ds.filter{c < 1}].should == {:c=>0.0}
365
+ @ct[String, 'foo']
366
+ @u[@ds.filter(:c=>'foo')].should == {:c=>'foo'}
367
+
368
+ INTEGRATION_DB.create_table!(:items) do
369
+ BigDecimal :c, :size=>[15,2]
370
+ end
371
+ @ds.insert(:c=>BigDecimal.new('1.1'))
372
+ @u[@ds.filter{c > 0}].should == {:c=>BigDecimal.new('1.1')}
373
+ end
374
+
375
+ cspecify "should handle dates and times", [:do], [:jdbc, :mssql], [:jdbc, :sqlite], [:swift], [:tinytds], :oracle do
376
+ @ct[Date, Date.today]
377
+ @u[@ds.filter(:c=>Date.today)].should == {:c=>Date.today}
378
+ t = Time.now
379
+ @ct[Time, t]
380
+ @u[@ds.filter{c < t + 1}][:c].to_i.should == t.to_i
381
+ end
382
+
383
+ specify "should handle QualifiedIdentifiers" do
384
+ @ct[Integer, 10]
385
+ @u[@ds.filter{items__c > 1}].should == {:c=>10}
264
386
  end
265
387
 
266
- cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite] do
267
- @ds.filter(:b=>@ds.ba(:$x, :boolean)).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
388
+ specify "should handle deep nesting" do
389
+ INTEGRATION_DB.create_table!(:items) do
390
+ Integer :a
391
+ Integer :b
392
+ Integer :c
393
+ Integer :d
394
+ end
395
+ @ds.insert(:a=>2, :b=>0, :c=>3, :d=>5)
396
+ @u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>4}=>1}.case(0) => 1)].should == {:a=>2, :b=>0, :c=>3, :d=>5}
397
+ @u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>5}=>1}.case(0) => 1)].should == nil
268
398
  end
269
- end unless INTEGRATION_DB.adapter_scheme == :swift && INTEGRATION_DB.database_type == :postgres
270
399
 
400
+ specify "should handle case where the same variable has the same value in multiple places " do
401
+ @ct[Integer, 1]
402
+ @u[@ds.filter{c > 1}.or{c < 1}.invert].should == {:c=>1}
403
+ @u[@ds.filter{c > 1}.or{c < 1}].should == nil
404
+ end
405
+ end