sequel 3.21.0 → 3.31.0

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