sequel 3.21.0 → 3.32.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 (234) hide show
  1. data/CHANGELOG +539 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -6
  4. data/Rakefile +37 -19
  5. data/bin/sequel +1 -5
  6. data/doc/advanced_associations.rdoc +17 -0
  7. data/doc/association_basics.rdoc +293 -43
  8. data/doc/dataset_basics.rdoc +4 -4
  9. data/doc/dataset_filtering.rdoc +8 -0
  10. data/doc/mass_assignment.rdoc +54 -0
  11. data/doc/migration.rdoc +15 -538
  12. data/doc/model_hooks.rdoc +72 -27
  13. data/doc/opening_databases.rdoc +89 -50
  14. data/doc/prepared_statements.rdoc +40 -13
  15. data/doc/reflection.rdoc +8 -2
  16. data/doc/release_notes/3.22.0.txt +39 -0
  17. data/doc/release_notes/3.23.0.txt +172 -0
  18. data/doc/release_notes/3.24.0.txt +420 -0
  19. data/doc/release_notes/3.25.0.txt +88 -0
  20. data/doc/release_notes/3.26.0.txt +88 -0
  21. data/doc/release_notes/3.27.0.txt +82 -0
  22. data/doc/release_notes/3.28.0.txt +304 -0
  23. data/doc/release_notes/3.29.0.txt +459 -0
  24. data/doc/release_notes/3.30.0.txt +135 -0
  25. data/doc/release_notes/3.31.0.txt +146 -0
  26. data/doc/release_notes/3.32.0.txt +202 -0
  27. data/doc/schema_modification.rdoc +547 -0
  28. data/doc/sharding.rdoc +7 -1
  29. data/doc/testing.rdoc +129 -0
  30. data/doc/transactions.rdoc +137 -0
  31. data/doc/virtual_rows.rdoc +2 -2
  32. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  33. data/lib/sequel/adapters/ado.rb +40 -18
  34. data/lib/sequel/adapters/amalgalite.rb +17 -9
  35. data/lib/sequel/adapters/db2.rb +175 -86
  36. data/lib/sequel/adapters/dbi.rb +15 -15
  37. data/lib/sequel/adapters/do/mysql.rb +5 -7
  38. data/lib/sequel/adapters/do/postgres.rb +0 -5
  39. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  40. data/lib/sequel/adapters/do.rb +17 -36
  41. data/lib/sequel/adapters/firebird.rb +27 -208
  42. data/lib/sequel/adapters/ibmdb.rb +448 -0
  43. data/lib/sequel/adapters/informix.rb +6 -23
  44. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  45. data/lib/sequel/adapters/jdbc/db2.rb +52 -0
  46. data/lib/sequel/adapters/jdbc/derby.rb +260 -0
  47. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  48. data/lib/sequel/adapters/jdbc/h2.rb +66 -30
  49. data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
  50. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  51. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  52. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  53. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  54. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  55. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  58. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  59. data/lib/sequel/adapters/jdbc.rb +231 -78
  60. data/lib/sequel/adapters/mock.rb +339 -0
  61. data/lib/sequel/adapters/mysql.rb +85 -184
  62. data/lib/sequel/adapters/mysql2.rb +26 -25
  63. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  64. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  65. data/lib/sequel/adapters/odbc.rb +28 -9
  66. data/lib/sequel/adapters/openbase.rb +3 -5
  67. data/lib/sequel/adapters/oracle.rb +355 -53
  68. data/lib/sequel/adapters/postgres.rb +194 -33
  69. data/lib/sequel/adapters/shared/access.rb +32 -9
  70. data/lib/sequel/adapters/shared/db2.rb +328 -0
  71. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  72. data/lib/sequel/adapters/shared/informix.rb +53 -0
  73. data/lib/sequel/adapters/shared/mssql.rb +278 -107
  74. data/lib/sequel/adapters/shared/mysql.rb +203 -65
  75. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  76. data/lib/sequel/adapters/shared/oracle.rb +237 -46
  77. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  78. data/lib/sequel/adapters/shared/progress.rb +5 -8
  79. data/lib/sequel/adapters/shared/sqlite.rb +200 -50
  80. data/lib/sequel/adapters/sqlite.rb +29 -21
  81. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  82. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  83. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  84. data/lib/sequel/adapters/swift.rb +5 -5
  85. data/lib/sequel/adapters/tinytds.rb +160 -19
  86. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  87. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  88. data/lib/sequel/ast_transformer.rb +190 -0
  89. data/lib/sequel/connection_pool/threaded.rb +3 -2
  90. data/lib/sequel/connection_pool.rb +1 -1
  91. data/lib/sequel/core.rb +68 -5
  92. data/lib/sequel/database/connecting.rb +5 -6
  93. data/lib/sequel/database/dataset.rb +4 -4
  94. data/lib/sequel/database/dataset_defaults.rb +59 -1
  95. data/lib/sequel/database/logging.rb +1 -1
  96. data/lib/sequel/database/misc.rb +104 -19
  97. data/lib/sequel/database/query.rb +163 -59
  98. data/lib/sequel/database/schema_generator.rb +17 -7
  99. data/lib/sequel/database/schema_methods.rb +59 -29
  100. data/lib/sequel/dataset/actions.rb +240 -76
  101. data/lib/sequel/dataset/features.rb +91 -8
  102. data/lib/sequel/dataset/graph.rb +38 -11
  103. data/lib/sequel/dataset/misc.rb +50 -23
  104. data/lib/sequel/dataset/mutation.rb +12 -7
  105. data/lib/sequel/dataset/prepared_statements.rb +59 -27
  106. data/lib/sequel/dataset/query.rb +236 -43
  107. data/lib/sequel/dataset/sql.rb +676 -267
  108. data/lib/sequel/dataset.rb +8 -0
  109. data/lib/sequel/exceptions.rb +4 -0
  110. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  111. data/lib/sequel/extensions/migration.rb +6 -4
  112. data/lib/sequel/extensions/named_timezones.rb +5 -0
  113. data/lib/sequel/extensions/query.rb +1 -1
  114. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  115. data/lib/sequel/extensions/to_dot.rb +95 -83
  116. data/lib/sequel/model/associations.rb +1081 -344
  117. data/lib/sequel/model/base.rb +420 -133
  118. data/lib/sequel/model/errors.rb +1 -1
  119. data/lib/sequel/model/exceptions.rb +5 -1
  120. data/lib/sequel/model.rb +20 -10
  121. data/lib/sequel/plugins/active_model.rb +13 -1
  122. data/lib/sequel/plugins/association_pks.rb +22 -4
  123. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  124. data/lib/sequel/plugins/composition.rb +43 -10
  125. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  126. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  127. data/lib/sequel/plugins/force_encoding.rb +6 -6
  128. data/lib/sequel/plugins/identity_map.rb +114 -7
  129. data/lib/sequel/plugins/many_through_many.rb +68 -7
  130. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  131. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  132. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  133. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  134. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  135. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  136. data/lib/sequel/plugins/serialization.rb +98 -49
  137. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  138. data/lib/sequel/plugins/sharding.rb +21 -54
  139. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  140. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  141. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  142. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  143. data/lib/sequel/sql.rb +109 -52
  144. data/lib/sequel/timezones.rb +57 -38
  145. data/lib/sequel/version.rb +1 -1
  146. data/spec/adapters/db2_spec.rb +146 -0
  147. data/spec/adapters/mssql_spec.rb +135 -30
  148. data/spec/adapters/mysql_spec.rb +244 -212
  149. data/spec/adapters/oracle_spec.rb +67 -77
  150. data/spec/adapters/postgres_spec.rb +267 -78
  151. data/spec/adapters/spec_helper.rb +6 -5
  152. data/spec/adapters/sqlite_spec.rb +35 -21
  153. data/spec/core/connection_pool_spec.rb +71 -92
  154. data/spec/core/core_sql_spec.rb +21 -30
  155. data/spec/core/database_spec.rb +789 -512
  156. data/spec/core/dataset_spec.rb +1176 -1061
  157. data/spec/core/expression_filters_spec.rb +159 -42
  158. data/spec/core/mock_adapter_spec.rb +419 -0
  159. data/spec/core/object_graph_spec.rb +86 -114
  160. data/spec/core/schema_generator_spec.rb +3 -3
  161. data/spec/core/schema_spec.rb +298 -38
  162. data/spec/core/spec_helper.rb +6 -48
  163. data/spec/extensions/active_model_spec.rb +13 -0
  164. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  165. data/spec/extensions/association_dependencies_spec.rb +2 -12
  166. data/spec/extensions/association_pks_spec.rb +66 -32
  167. data/spec/extensions/caching_spec.rb +23 -50
  168. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  169. data/spec/extensions/columns_introspection_spec.rb +91 -0
  170. data/spec/extensions/composition_spec.rb +18 -13
  171. data/spec/extensions/dataset_associations_spec.rb +199 -0
  172. data/spec/extensions/defaults_setter_spec.rb +64 -0
  173. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  174. data/spec/extensions/identity_map_spec.rb +114 -22
  175. data/spec/extensions/instance_filters_spec.rb +11 -21
  176. data/spec/extensions/instance_hooks_spec.rb +53 -0
  177. data/spec/extensions/json_serializer_spec.rb +4 -5
  178. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  179. data/spec/extensions/list_spec.rb +17 -39
  180. data/spec/extensions/many_through_many_spec.rb +283 -250
  181. data/spec/extensions/migration_spec.rb +35 -32
  182. data/spec/extensions/named_timezones_spec.rb +23 -3
  183. data/spec/extensions/nested_attributes_spec.rb +97 -88
  184. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  185. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  186. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  187. data/spec/extensions/prepared_statements_spec.rb +53 -0
  188. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  189. data/spec/extensions/pretty_table_spec.rb +1 -6
  190. data/spec/extensions/query_spec.rb +6 -0
  191. data/spec/extensions/rcte_tree_spec.rb +41 -43
  192. data/spec/extensions/schema_dumper_spec.rb +5 -8
  193. data/spec/extensions/schema_spec.rb +13 -21
  194. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  195. data/spec/extensions/serialization_spec.rb +81 -43
  196. data/spec/extensions/sharding_spec.rb +66 -140
  197. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  198. data/spec/extensions/spec_helper.rb +13 -61
  199. data/spec/extensions/sql_expr_spec.rb +20 -60
  200. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  201. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  202. data/spec/extensions/timestamps_spec.rb +6 -6
  203. data/spec/extensions/to_dot_spec.rb +4 -7
  204. data/spec/extensions/touch_spec.rb +13 -14
  205. data/spec/extensions/tree_spec.rb +11 -26
  206. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  207. data/spec/extensions/update_primary_key_spec.rb +30 -24
  208. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  209. data/spec/extensions/validation_helpers_spec.rb +16 -35
  210. data/spec/extensions/xml_serializer_spec.rb +16 -4
  211. data/spec/integration/associations_test.rb +661 -21
  212. data/spec/integration/database_test.rb +4 -2
  213. data/spec/integration/dataset_test.rb +500 -67
  214. data/spec/integration/eager_loader_test.rb +19 -21
  215. data/spec/integration/model_test.rb +80 -1
  216. data/spec/integration/plugin_test.rb +367 -119
  217. data/spec/integration/prepared_statement_test.rb +222 -125
  218. data/spec/integration/schema_test.rb +217 -39
  219. data/spec/integration/spec_helper.rb +39 -30
  220. data/spec/integration/timezone_test.rb +38 -12
  221. data/spec/integration/transaction_test.rb +182 -5
  222. data/spec/integration/type_test.rb +17 -3
  223. data/spec/model/association_reflection_spec.rb +201 -7
  224. data/spec/model/associations_spec.rb +955 -662
  225. data/spec/model/base_spec.rb +275 -95
  226. data/spec/model/dataset_methods_spec.rb +7 -27
  227. data/spec/model/eager_loading_spec.rb +677 -676
  228. data/spec/model/hooks_spec.rb +349 -67
  229. data/spec/model/model_spec.rb +222 -168
  230. data/spec/model/plugins_spec.rb +24 -13
  231. data/spec/model/record_spec.rb +381 -218
  232. data/spec/model/spec_helper.rb +13 -71
  233. data/spec/model/validations_spec.rb +11 -0
  234. metadata +117 -73
@@ -2,218 +2,245 @@ 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(:select, :n=>10).should == [{:id=>1, :numb=>10}]
21
+ @ds.filter(:numb=>:$n).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
22
+ @ds.filter(:numb=>:$n).call(:first, :n=>10).should == {:id=>1, :numb=>10}
23
+ @ds.filter(:numb=>:$n).call([:map, :numb], :n=>10).should == [10]
24
+ @ds.filter(:numb=>:$n).call([:to_hash, :id, :numb], :n=>10).should == {1=>10}
24
25
  end
25
26
 
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}]
27
+ specify "should support blocks for select, all, and map " do
28
+ @ds.filter(:numb=>:$n).call(:select, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
29
+ @ds.filter(:numb=>:$n).call(:all, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
30
+ @ds.filter(:numb=>:$n).call([:map], :n=>10){|r| r[:numb] * 2}.should == [20]
29
31
  end
30
32
 
31
33
  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}
34
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
35
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
36
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
35
37
 
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}
38
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:select).should == [{:id=>1, :numb=>10}]
39
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:all).should == [{:id=>1, :numb=>10}]
40
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:first).should == {:id=>1, :numb=>10}
39
41
  end
40
42
 
41
43
  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}
44
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
45
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
46
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :numb=>10}
45
47
 
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}
48
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
49
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
50
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
49
51
  end
50
52
 
51
53
  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}]
54
+ @ds.filter("numb = ?", :$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
53
55
  end
54
56
 
55
57
  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}]
58
+ @ds.filter("numb = :n", :n=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
59
+ @ds.insert(:numb=>20)
60
+ @ds.insert(:numb=>30)
61
+ @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
62
  end
61
63
 
62
64
  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}]
65
+ @db["SELECT * FROM items WHERE numb = ?", :$n].call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
64
66
  end
65
67
 
66
68
  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}]
69
+ @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}]
70
+ end
71
+
72
+ specify "should support subselects with exists with call" do
73
+ @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
74
  end
69
75
 
70
76
  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}]
77
+ @ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
72
78
  end
73
79
 
74
80
  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}]
81
+ @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
82
  end
77
83
 
78
84
  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}]
85
+ @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
86
  end
81
87
 
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}]
88
+ cspecify "should support using a bound variable for a limit and offset", [:jdbc, :db2] do
89
+ @ds.insert(:numb=>20)
90
+ ds = @ds.limit(:$n, :$n2).order(:id)
91
+ ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
92
+ ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
87
93
  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}]
94
+ ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
95
+ ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
90
96
  end
91
97
 
92
98
  specify "should support bound variables with insert" do
93
- @ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n))
99
+ @ds.call(:insert, {:n=>20}, :numb=>:$n)
94
100
  @ds.count.should == 2
95
- @ds.order(:id).map(:number).should == [10, 20]
101
+ @ds.order(:id).map(:numb).should == [10, 20]
102
+ end
103
+
104
+ specify "should support bound variables with NULL values" do
105
+ @ds.delete
106
+ @ds.call(:insert, {:n=>nil}, :numb=>@pr[:$n])
107
+ @ds.count.should == 1
108
+ @ds.map(:numb).should == [nil]
96
109
  end
97
110
 
98
111
  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
112
+ @ds.call(:insert, {:n=>20}, :numb=>:$n).should == 2
113
+ @ds.filter(:id=>2).first[:numb].should == 20
101
114
  end
102
115
 
103
116
  specify "should support bound variables with delete" do
104
- @ds.filter(:number=>@ds.ba(:$n)).call(:delete, :n=>10).should == 1
117
+ @ds.filter(:numb=>:$n).call(:delete, :n=>10).should == 1
105
118
  @ds.count.should == 0
106
119
  end
107
120
 
108
121
  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}]
122
+ @ds.filter(:numb=>:$n).call(:update, {:n=>10, :nn=>20}, :numb=>:numb+:$nn).should == 1
123
+ @ds.all.should == [{:id=>1, :numb=>30}]
111
124
  end
112
125
 
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
126
+ specify "should support prepared statements when selecting" do
127
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
128
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
129
+ @ds.filter(:numb=>:$n).prepare(:all, :select_n)
130
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
131
+ @ds.filter(:numb=>:$n).prepare(:first, :select_n)
132
+ @db.call(:select_n, :n=>10).should == {:id=>1, :numb=>10}
133
+ @ds.filter(:numb=>:$n).prepare([:map, :numb], :select_n)
134
+ @db.call(:select_n, :n=>10).should == [10]
135
+ @ds.filter(:numb=>:$n).prepare([:to_hash, :id, :numb], :select_n)
136
+ @db.call(:select_n, :n=>10).should == {1=>10}
137
+ end
138
+
139
+ specify "should support prepared statements being call multiple times with different arguments" do
140
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
141
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
142
+ @db.call(:select_n, :n=>0).should == []
143
+ @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
125
144
  end
126
145
 
127
146
  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}]
147
+ @ds.filter("numb = ?", :$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
129
148
  end
130
149
 
131
150
  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}]
151
+ @ds.filter("numb = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
152
+ @ds.insert(:numb=>20)
153
+ @ds.insert(:numb=>30)
154
+ @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
155
  end
137
156
 
138
157
  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}]
158
+ @db["SELECT * FROM items WHERE numb = ?", :$n].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
140
159
  end
141
160
 
142
161
  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}]
162
+ @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}]
163
+ end
164
+
165
+ specify "should support subselects with exists with prepare" do
166
+ @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
167
  end
145
168
 
146
169
  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}]
170
+ @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
171
  end
149
172
 
150
173
  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}]
174
+ @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
175
  end
153
176
 
154
177
  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}]
178
+ @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
179
  end
157
180
 
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}]
181
+ cspecify "should support using a prepared_statement for a limit and offset", :db2 do
182
+ @ds.insert(:numb=>20)
183
+ ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
184
+ ps.call(:n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
185
+ ps.call(:n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
163
186
  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}]
187
+ ps.call(:n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
188
+ ps.call(:n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
166
189
  end
167
190
 
168
191
  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)
192
+ @ds.prepare(:insert, :insert_n, :numb=>:$n)
193
+ @db.call(:insert_n, :n=>20)
171
194
  @ds.count.should == 2
172
- @ds.order(:id).map(:number).should == [10, 20]
195
+ @ds.order(:id).map(:numb).should == [10, 20]
196
+ end
197
+
198
+ specify "should support prepared statements with NULL values" do
199
+ @ds.delete
200
+ @ds.prepare(:insert, :insert_n, :numb=>@pr[:$n])
201
+ @db.call(:insert_n, :n=>nil)
202
+ @ds.count.should == 1
203
+ @ds.map(:numb).should == [nil]
173
204
  end
174
205
 
175
206
  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
207
+ @ds.prepare(:insert, :insert_n, :numb=>:$n)
208
+ @db.call(:insert_n, :n=>20).should == 2
209
+ @ds.filter(:id=>2).first[:numb].should == 20
179
210
  end
180
211
 
181
212
  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
213
+ @ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
214
+ @db.call(:delete_n, :n=>10).should == 1
184
215
  @ds.count.should == 0
185
216
  end
186
217
 
187
218
  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}]
219
+ @ds.filter(:numb=>:$n).prepare(:update, :update_n, :numb=>:numb+:$nn)
220
+ @db.call(:update_n, :n=>10, :nn=>20).should == 1
221
+ @ds.all.should == [{:id=>1, :numb=>30}]
191
222
  end
192
223
 
193
224
  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)
225
+ @c.filter(:numb=>:$n).call(:select, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
226
+ @c.filter(:numb=>:$n).call(:all, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
227
+ @c.filter(:numb=>:$n).call(:first, :n=>10).should == @c.load(:id=>1, :numb=>10)
197
228
  end
198
229
 
199
230
  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
231
+ @c.filter(:numb=>:$n).prepare(:select, :select_n1)
232
+ @db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
233
+ @c.filter(:numb=>:$n).prepare(:all, :select_n1)
234
+ @db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
235
+ @c.filter(:numb=>:$n).prepare(:first, :select_n1)
236
+ @db.call(:select_n1, :n=>10).should == @c.load(:id=>1, :numb=>10)
211
237
  end
212
238
  end
213
239
 
214
240
  describe "Bound Argument Types" do
215
- before do
216
- INTEGRATION_DB.create_table!(:items) do
241
+ before(:all) do
242
+ @db = INTEGRATION_DB
243
+ @db.create_table!(:items) do
217
244
  primary_key :id
218
245
  Date :d
219
246
  DateTime :dt
@@ -223,7 +250,7 @@ describe "Bound Argument Types" do
223
250
  Float :f
224
251
  TrueClass :b
225
252
  end
226
- @ds = INTEGRATION_DB[:items]
253
+ @ds = @db[:items]
227
254
  @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}
228
255
  @ds.insert(@vs)
229
256
  @ds.meta_def(:ba) do |sym, type|
@@ -232,39 +259,109 @@ describe "Bound Argument Types" do
232
259
  end
233
260
  after do
234
261
  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)
262
+ end
263
+ after(:all) do
264
+ @db.drop_table(:items)
239
265
  end
240
266
 
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]
267
+ cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite], :oracle do
268
+ @ds.filter(:d=>:$x).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
243
269
  end
244
270
 
245
- cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds] do
271
+ cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds], [:oracle] do
246
272
  Sequel.datetime_class = DateTime
247
- @ds.filter(:dt=>@ds.ba(:$x, :timestamp)).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
273
+ @ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
248
274
  end
249
275
 
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]
276
+ cspecify "should handle time type", [:do], [:jdbc, :sqlite], [:oracle] do
277
+ @ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
252
278
  end
253
279
 
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]
280
+ cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
281
+ @ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
256
282
  end
257
283
 
258
284
  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]
285
+ @ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
260
286
  end
261
287
 
262
288
  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]
289
+ @ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
290
+ end
291
+
292
+ cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite], [:jdbc, :db2], :oracle do
293
+ @ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
264
294
  end
295
+ end unless Sequel.guarded?([:swift, :postgres])
265
296
 
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]
297
+ describe "Dataset#unbind" do
298
+ before do
299
+ @ds = ds = INTEGRATION_DB[:items]
300
+ @ct = proc do |t, v|
301
+ INTEGRATION_DB.create_table!(:items) do
302
+ column :c, t
303
+ end
304
+ ds.insert(:c=>v)
305
+ end
306
+ @u = proc{|ds| ds, bv = ds.unbind; ds.call(:first, bv)}
307
+ end
308
+ after do
309
+ INTEGRATION_DB.drop_table(:items) rescue nil
310
+ end
311
+
312
+ specify "should unbind values assigned to equality and inequality statements" do
313
+ @ct[Integer, 10]
314
+ @u[@ds.filter(:c=>10)].should == {:c=>10}
315
+ @u[@ds.exclude(:c=>10)].should == nil
316
+ @u[@ds.filter{c < 10}].should == nil
317
+ @u[@ds.filter{c <= 10}].should == {:c=>10}
318
+ @u[@ds.filter{c > 10}].should == nil
319
+ @u[@ds.filter{c >= 10}].should == {:c=>10}
320
+ end
321
+
322
+ cspecify "should handle numerics and strings", [:odbc], [:swift, :sqlite] do
323
+ @ct[Integer, 10]
324
+ @u[@ds.filter(:c=>10)].should == {:c=>10}
325
+ @ct[Float, 0.0]
326
+ @u[@ds.filter{c < 1}].should == {:c=>0.0}
327
+ @ct[String, 'foo']
328
+ @u[@ds.filter(:c=>'foo')].should == {:c=>'foo'}
329
+
330
+ INTEGRATION_DB.create_table!(:items) do
331
+ BigDecimal :c, :size=>[15,2]
332
+ end
333
+ @ds.insert(:c=>BigDecimal.new('1.1'))
334
+ @u[@ds.filter{c > 0}].should == {:c=>BigDecimal.new('1.1')}
268
335
  end
269
- end unless INTEGRATION_DB.adapter_scheme == :swift && INTEGRATION_DB.database_type == :postgres
270
336
 
337
+ cspecify "should handle dates and times", [:do], [:jdbc, :mssql], [:jdbc, :sqlite], [:tinytds], :oracle do
338
+ @ct[Date, Date.today]
339
+ @u[@ds.filter(:c=>Date.today)].should == {:c=>Date.today}
340
+ t = Time.now
341
+ @ct[Time, t]
342
+ @u[@ds.filter{c < t + 1}][:c].to_i.should == t.to_i
343
+ end
344
+
345
+ specify "should handle QualifiedIdentifiers" do
346
+ @ct[Integer, 10]
347
+ @u[@ds.filter{items__c > 1}].should == {:c=>10}
348
+ end
349
+
350
+ specify "should handle deep nesting" do
351
+ INTEGRATION_DB.create_table!(:items) do
352
+ Integer :a
353
+ Integer :b
354
+ Integer :c
355
+ Integer :d
356
+ end
357
+ @ds.insert(:a=>2, :b=>0, :c=>3, :d=>5)
358
+ @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}
359
+ @u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>5}=>1}.case(0) => 1)].should == nil
360
+ end
361
+
362
+ specify "should handle case where the same variable has the same value in multiple places " do
363
+ @ct[Integer, 1]
364
+ @u[@ds.filter{c > 1}.or{c < 1}.invert].should == {:c=>1}
365
+ @u[@ds.filter{c > 1}.or{c < 1}].should == nil
366
+ end
367
+ end