sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,12 +1,8 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
2
 
3
- Regexp.send(:include, Sequel::SQL::StringMethods)
4
- String.send(:include, Sequel::SQL::StringMethods)
5
-
6
3
  describe "Blockless Ruby Filters" do
7
4
  before do
8
5
  db = Sequel::Database.new
9
- db.quote_identifiers = false
10
6
  @d = db[:items]
11
7
  def @d.l(*args, &block)
12
8
  literal(filter_expr(*args, &block))
@@ -20,27 +16,22 @@ describe "Blockless Ruby Filters" do
20
16
  @d.l(:x).should == 'x'
21
17
  end
22
18
 
23
- it "should support NOT via Symbol#~" do
24
- @d.l(~:x).should == 'NOT x'
25
- end
26
-
27
19
  it "should support qualified columns" do
28
20
  @d.l(:x__y).should == 'x.y'
29
- @d.l(~:x__y).should == 'NOT x.y'
30
21
  end
31
22
 
32
23
  it "should support NOT with SQL functions" do
33
- @d.l(~:is_blah.sql_function).should == 'NOT is_blah()'
34
- @d.l(~:is_blah.sql_function(:x)).should == 'NOT is_blah(x)'
35
- @d.l(~:is_blah.sql_function(:x__y)).should == 'NOT is_blah(x.y)'
36
- @d.l(~:is_blah.sql_function(:x, :x__y)).should == 'NOT is_blah(x, x.y)'
24
+ @d.l(~Sequel.function(:is_blah)).should == 'NOT is_blah()'
25
+ @d.l(~Sequel.function(:is_blah, :x)).should == 'NOT is_blah(x)'
26
+ @d.l(~Sequel.function(:is_blah, :x__y)).should == 'NOT is_blah(x.y)'
27
+ @d.l(~Sequel.function(:is_blah, :x, :x__y)).should == 'NOT is_blah(x, x.y)'
37
28
  end
38
29
 
39
30
  it "should handle multiple ~" do
40
- @d.l(~~:x).should == 'x'
41
- @d.l(~~~:x).should == 'NOT x'
42
- @d.l(~~(:x & :y)).should == '(x AND y)'
43
- @d.l(~~(:x | :y)).should == '(x OR y)'
31
+ @d.l(~Sequel.~(:x)).should == 'x'
32
+ @d.l(~~Sequel.~(:x)).should == 'NOT x'
33
+ @d.l(~~Sequel.&(:x, :y)).should == '(x AND y)'
34
+ @d.l(~~Sequel.|(:x, :y)).should == '(x OR y)'
44
35
  end
45
36
 
46
37
  it "should support = via Hash" do
@@ -55,216 +46,109 @@ describe "Blockless Ruby Filters" do
55
46
  it "should use = 't' and != 't' OR IS NULL if IS TRUE is not supported" do
56
47
  @d.meta_def(:supports_is_true?){false}
57
48
  @d.l(:x => true).should == "(x = 't')"
58
- @d.l(~{:x => true}).should == "((x != 't') OR (x IS NULL))"
49
+ @d.l(~Sequel.expr(:x => true)).should == "((x != 't') OR (x IS NULL))"
59
50
  @d.l(:x => false).should == "(x = 'f')"
60
- @d.l(~{:x => false}).should == "((x != 'f') OR (x IS NULL))"
51
+ @d.l(~Sequel.expr(:x => false)).should == "((x != 'f') OR (x IS NULL))"
61
52
  end
62
53
 
63
- it "should support != via Hash#~" do
64
- @d.l(~{:x => 100}).should == '(x != 100)'
65
- @d.l(~{:x => 'a'}).should == '(x != \'a\')'
66
- @d.l(~{:x => true}).should == '(x IS NOT TRUE)'
67
- @d.l(~{:x => false}).should == '(x IS NOT FALSE)'
68
- @d.l(~{:x => nil}).should == '(x IS NOT NULL)'
54
+ it "should support != via inverted Hash" do
55
+ @d.l(~Sequel.expr(:x => 100)).should == '(x != 100)'
56
+ @d.l(~Sequel.expr(:x => 'a')).should == '(x != \'a\')'
57
+ @d.l(~Sequel.expr(:x => true)).should == '(x IS NOT TRUE)'
58
+ @d.l(~Sequel.expr(:x => false)).should == '(x IS NOT FALSE)'
59
+ @d.l(~Sequel.expr(:x => nil)).should == '(x IS NOT NULL)'
69
60
  end
70
61
 
71
62
  it "should support ~ via Hash and Regexp (if supported by database)" do
63
+ def @d.supports_regexp?; true end
72
64
  @d.l(:x => /blah/).should == '(x ~ \'blah\')'
73
65
  end
74
66
 
75
- it "should support !~ via Hash#~ and Regexp" do
76
- @d.l(~{:x => /blah/}).should == '(x !~ \'blah\')'
67
+ it "should support !~ via inverted Hash and Regexp" do
68
+ def @d.supports_regexp?; true end
69
+ @d.l(~Sequel.expr(:x => /blah/)).should == '(x !~ \'blah\')'
77
70
  end
78
71
 
79
- it "should support LIKE via Symbol#like" do
80
- @d.l(:x.like('a')).should == '(x LIKE \'a\')'
81
- @d.l(:x.like(/a/)).should == '(x ~ \'a\')'
82
- @d.l(:x.like('a', 'b')).should == '((x LIKE \'a\') OR (x LIKE \'b\'))'
83
- @d.l(:x.like(/a/, /b/i)).should == '((x ~ \'a\') OR (x ~* \'b\'))'
84
- @d.l(:x.like('a', /b/)).should == '((x LIKE \'a\') OR (x ~ \'b\'))'
85
-
86
- @d.l('a'.like(:x)).should == "('a' LIKE x)"
87
- @d.l('a'.like(:x, 'b')).should == "(('a' LIKE x) OR ('a' LIKE 'b'))"
88
- @d.l('a'.like(:x, /b/)).should == "(('a' LIKE x) OR ('a' ~ 'b'))"
89
- @d.l('a'.like(:x, /b/i)).should == "(('a' LIKE x) OR ('a' ~* 'b'))"
90
-
91
- @d.l(/a/.like(:x)).should == "('a' ~ x)"
92
- @d.l(/a/.like(:x, 'b')).should == "(('a' ~ x) OR ('a' ~ 'b'))"
93
- @d.l(/a/.like(:x, /b/)).should == "(('a' ~ x) OR ('a' ~ 'b'))"
94
- @d.l(/a/.like(:x, /b/i)).should == "(('a' ~ x) OR ('a' ~* 'b'))"
95
-
96
- @d.l(/a/i.like(:x)).should == "('a' ~* x)"
97
- @d.l(/a/i.like(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
98
- @d.l(/a/i.like(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
99
- @d.l(/a/i.like(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
100
- end
101
-
102
- it "should support NOT LIKE via Symbol#like and Symbol#~" do
103
- @d.l(~:x.like('a')).should == '(x NOT LIKE \'a\')'
104
- @d.l(~:x.like(/a/)).should == '(x !~ \'a\')'
105
- @d.l(~:x.like('a', 'b')).should == '((x NOT LIKE \'a\') AND (x NOT LIKE \'b\'))'
106
- @d.l(~:x.like(/a/, /b/i)).should == '((x !~ \'a\') AND (x !~* \'b\'))'
107
- @d.l(~:x.like('a', /b/)).should == '((x NOT LIKE \'a\') AND (x !~ \'b\'))'
108
-
109
- @d.l(~'a'.like(:x)).should == "('a' NOT LIKE x)"
110
- @d.l(~'a'.like(:x, 'b')).should == "(('a' NOT LIKE x) AND ('a' NOT LIKE 'b'))"
111
- @d.l(~'a'.like(:x, /b/)).should == "(('a' NOT LIKE x) AND ('a' !~ 'b'))"
112
- @d.l(~'a'.like(:x, /b/i)).should == "(('a' NOT LIKE x) AND ('a' !~* 'b'))"
113
-
114
- @d.l(~/a/.like(:x)).should == "('a' !~ x)"
115
- @d.l(~/a/.like(:x, 'b')).should == "(('a' !~ x) AND ('a' !~ 'b'))"
116
- @d.l(~/a/.like(:x, /b/)).should == "(('a' !~ x) AND ('a' !~ 'b'))"
117
- @d.l(~/a/.like(:x, /b/i)).should == "(('a' !~ x) AND ('a' !~* 'b'))"
118
-
119
- @d.l(~/a/i.like(:x)).should == "('a' !~* x)"
120
- @d.l(~/a/i.like(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
121
- @d.l(~/a/i.like(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
122
- @d.l(~/a/i.like(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
123
- end
124
-
125
- it "should support ILIKE via Symbol#ilike" do
126
- @d.l(:x.ilike('a')).should == '(x ILIKE \'a\')'
127
- @d.l(:x.ilike(/a/)).should == '(x ~* \'a\')'
128
- @d.l(:x.ilike('a', 'b')).should == '((x ILIKE \'a\') OR (x ILIKE \'b\'))'
129
- @d.l(:x.ilike(/a/, /b/i)).should == '((x ~* \'a\') OR (x ~* \'b\'))'
130
- @d.l(:x.ilike('a', /b/)).should == '((x ILIKE \'a\') OR (x ~* \'b\'))'
131
-
132
- @d.l('a'.ilike(:x)).should == "('a' ILIKE x)"
133
- @d.l('a'.ilike(:x, 'b')).should == "(('a' ILIKE x) OR ('a' ILIKE 'b'))"
134
- @d.l('a'.ilike(:x, /b/)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
135
- @d.l('a'.ilike(:x, /b/i)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
136
-
137
- @d.l(/a/.ilike(:x)).should == "('a' ~* x)"
138
- @d.l(/a/.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
139
- @d.l(/a/.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
140
- @d.l(/a/.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
141
-
142
- @d.l(/a/i.ilike(:x)).should == "('a' ~* x)"
143
- @d.l(/a/i.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
144
- @d.l(/a/i.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
145
- @d.l(/a/i.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
146
- end
147
-
148
- it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
149
- @d.l(~:x.ilike('a')).should == '(x NOT ILIKE \'a\')'
150
- @d.l(~:x.ilike(/a/)).should == '(x !~* \'a\')'
151
- @d.l(~:x.ilike('a', 'b')).should == '((x NOT ILIKE \'a\') AND (x NOT ILIKE \'b\'))'
152
- @d.l(~:x.ilike(/a/, /b/i)).should == '((x !~* \'a\') AND (x !~* \'b\'))'
153
- @d.l(~:x.ilike('a', /b/)).should == '((x NOT ILIKE \'a\') AND (x !~* \'b\'))'
154
-
155
- @d.l(~'a'.ilike(:x)).should == "('a' NOT ILIKE x)"
156
- @d.l(~'a'.ilike(:x, 'b')).should == "(('a' NOT ILIKE x) AND ('a' NOT ILIKE 'b'))"
157
- @d.l(~'a'.ilike(:x, /b/)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
158
- @d.l(~'a'.ilike(:x, /b/i)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
159
-
160
- @d.l(~/a/.ilike(:x)).should == "('a' !~* x)"
161
- @d.l(~/a/.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
162
- @d.l(~/a/.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
163
- @d.l(~/a/.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
164
-
165
- @d.l(~/a/i.ilike(:x)).should == "('a' !~* x)"
166
- @d.l(~/a/i.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
167
- @d.l(~/a/i.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
168
- @d.l(~/a/i.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
169
- end
170
-
171
- it "should support negating ranges via Hash#~ and Range" do
172
- @d.l(~{:x => 1..5}).should == '((x < 1) OR (x > 5))'
173
- @d.l(~{:x => 1...5}).should == '((x < 1) OR (x >= 5))'
72
+ it "should support negating ranges" do
73
+ @d.l(~Sequel.expr(:x => 1..5)).should == '((x < 1) OR (x > 5))'
74
+ @d.l(~Sequel.expr(:x => 1...5)).should == '((x < 1) OR (x >= 5))'
174
75
  end
175
76
 
176
- it "should support negating NOT IN via Hash#~ and Dataset or Array" do
177
- @d.l(~{:x => @d.select(:i)}).should == '(x NOT IN (SELECT i FROM items))'
178
- @d.l(~{:x => [1,2,3]}).should == '(x NOT IN (1, 2, 3))'
77
+ it "should support negating IN with Dataset or Array" do
78
+ @d.l(~Sequel.expr(:x => @d.select(:i))).should == '(x NOT IN (SELECT i FROM items))'
79
+ @d.l(~Sequel.expr(:x => [1,2,3])).should == '(x NOT IN (1, 2, 3))'
179
80
  end
180
81
 
181
- it "should support + - * / via Symbol#+,-,*,/" do
182
- @d.l(:x + 1 > 100).should == '((x + 1) > 100)'
183
- @d.l((:x * :y) < 100.01).should == '((x * y) < 100.01)'
184
- @d.l((:x - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
185
- @d.l((((:x - :y)/(:x + :y))*:z) <= 100).should == '((((x - y) / (x + y)) * z) <= 100)'
186
- @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
187
- end
188
-
189
- it "should not allow negation of string expressions" do
190
- proc{~:x.sql_string}.should raise_error
191
- proc{~([:x, :y].sql_string_join)}.should raise_error
82
+ it "should not add ~ method to string expressions" do
83
+ proc{~Sequel.expr(:x).sql_string}.should raise_error(NoMethodError)
192
84
  end
193
85
 
194
- it "should not allow mathematical or string operations on true, false, or nil" do
195
- proc{:x + 1}.should_not raise_error
196
- proc{:x - true}.should raise_error(Sequel::Error)
197
- proc{:x / false}.should raise_error(Sequel::Error)
198
- proc{:x * nil}.should raise_error(Sequel::Error)
199
- proc{[:x, nil].sql_string_join}.should raise_error(Sequel::Error)
86
+ it "should allow mathematical or string operations on true, false, or nil" do
87
+ @d.lit(Sequel.expr(:x) + 1).should == '(x + 1)'
88
+ @d.lit(Sequel.expr(:x) - true).should == "(x - 't')"
89
+ @d.lit(Sequel.expr(:x) / false).should == "(x / 'f')"
90
+ @d.lit(Sequel.expr(:x) * nil).should == '(x * NULL)'
91
+ @d.lit(Sequel.join([:x, nil])).should == '(x || NULL)'
200
92
  end
201
93
 
202
- it "should not allow mathematical or string operations on boolean complex expressions" do
203
- proc{:x + (:y + 1)}.should_not raise_error
204
- proc{:x - (~:y)}.should raise_error(Sequel::Error)
205
- proc{:x / (:y & :z)}.should raise_error(Sequel::Error)
206
- proc{:x * (:y | :z)}.should raise_error(Sequel::Error)
207
- proc{:x + :y.like('a')}.should raise_error(Sequel::Error)
208
- proc{:x - :y.like(/a/)}.should raise_error(Sequel::Error)
209
- proc{:x * :y.like(/a/i)}.should raise_error(Sequel::Error)
210
- proc{:x + ~:y.like('a')}.should raise_error(Sequel::Error)
211
- proc{:x - ~:y.like(/a/)}.should raise_error(Sequel::Error)
212
- proc{:x * ~:y.like(/a/i)}.should raise_error(Sequel::Error)
213
- proc{[:x, ~:y.like(/a/i)].sql_string_join}.should raise_error(Sequel::Error)
94
+ it "should allow mathematical or string operations on boolean complex expressions" do
95
+ @d.lit(Sequel.expr(:x) + (Sequel.expr(:y) + 1)).should == '(x + y + 1)'
96
+ @d.lit(Sequel.expr(:x) - ~Sequel.expr(:y)).should == '(x - NOT y)'
97
+ @d.lit(Sequel.expr(:x) / (Sequel.expr(:y) & :z)).should == '(x / (y AND z))'
98
+ @d.lit(Sequel.expr(:x) * (Sequel.expr(:y) | :z)).should == '(x * (y OR z))'
99
+ @d.lit(Sequel.expr(:x) + Sequel.expr(:y).like('a')).should == "(x + (y LIKE 'a'))"
100
+ @d.lit(Sequel.expr(:x) - ~Sequel.expr(:y).like('a')).should == "(x - (y NOT LIKE 'a'))"
101
+ @d.lit(Sequel.join([:x, ~Sequel.expr(:y).like('a')])).should == "(x || (y NOT LIKE 'a'))"
214
102
  end
215
103
 
216
104
  it "should support AND conditions via &" do
217
- @d.l(:x & :y).should == '(x AND y)'
218
- @d.l(:x.sql_boolean & :y).should == '(x AND y)'
219
- @d.l(:x & :y & :z).should == '(x AND y AND z)'
220
- @d.l(:x & {:y => :z}).should == '(x AND (y = z))'
221
- @d.l({:y => :z} & :x).should == '((y = z) AND x)'
222
- @d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
223
- @d.l((:x + 200 < 0) & (:y - 200 < 0)).should == '(((x + 200) < 0) AND ((y - 200) < 0))'
224
- @d.l(:x & ~:y).should == '(x AND NOT y)'
225
- @d.l(~:x & :y).should == '(NOT x AND y)'
226
- @d.l(~:x & ~:y).should == '(NOT x AND NOT y)'
105
+ @d.l(Sequel.expr(:x) & :y).should == '(x AND y)'
106
+ @d.l(Sequel.expr(:x).sql_boolean & :y).should == '(x AND y)'
107
+ @d.l(Sequel.expr(:x) & :y & :z).should == '(x AND y AND z)'
108
+ @d.l(Sequel.expr(:x) & {:y => :z}).should == '(x AND (y = z))'
109
+ @d.l((Sequel.expr(:x) + 200 < 0) & (Sequel.expr(:y) - 200 < 0)).should == '(((x + 200) < 0) AND ((y - 200) < 0))'
110
+ @d.l(Sequel.expr(:x) & ~Sequel.expr(:y)).should == '(x AND NOT y)'
111
+ @d.l(~Sequel.expr(:x) & :y).should == '(NOT x AND y)'
112
+ @d.l(~Sequel.expr(:x) & ~Sequel.expr(:y)).should == '(NOT x AND NOT y)'
227
113
  end
228
114
 
229
115
  it "should support OR conditions via |" do
230
- @d.l(:x | :y).should == '(x OR y)'
231
- @d.l(:x.sql_boolean | :y).should == '(x OR y)'
232
- @d.l(:x | :y | :z).should == '(x OR y OR z)'
233
- @d.l(:x | {:y => :z}).should == '(x OR (y = z))'
234
- @d.l({:y => :z} | :x).should == '((y = z) OR x)'
235
- @d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
236
- @d.l((:x.sql_number > 200) | (:y.sql_number < 200)).should == '((x > 200) OR (y < 200))'
116
+ @d.l(Sequel.expr(:x) | :y).should == '(x OR y)'
117
+ @d.l(Sequel.expr(:x).sql_boolean | :y).should == '(x OR y)'
118
+ @d.l(Sequel.expr(:x) | :y | :z).should == '(x OR y OR z)'
119
+ @d.l(Sequel.expr(:x) | {:y => :z}).should == '(x OR (y = z))'
120
+ @d.l((Sequel.expr(:x).sql_number > 200) | (Sequel.expr(:y).sql_number < 200)).should == '((x > 200) OR (y < 200))'
237
121
  end
238
122
 
239
123
  it "should support & | combinations" do
240
- @d.l((:x | :y) & :z).should == '((x OR y) AND z)'
241
- @d.l(:x | (:y & :z)).should == '(x OR (y AND z))'
242
- @d.l((:x & :w) | (:y & :z)).should == '((x AND w) OR (y AND z))'
124
+ @d.l((Sequel.expr(:x) | :y) & :z).should == '((x OR y) AND z)'
125
+ @d.l(Sequel.expr(:x) | (Sequel.expr(:y) & :z)).should == '(x OR (y AND z))'
126
+ @d.l((Sequel.expr(:x) & :w) | (Sequel.expr(:y) & :z)).should == '((x AND w) OR (y AND z))'
243
127
  end
244
128
 
245
129
  it "should support & | with ~" do
246
- @d.l(~((:x | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
247
- @d.l(~(:x | (:y & :z))).should == '(NOT x AND (NOT y OR NOT z))'
248
- @d.l(~((:x & :w) | (:y & :z))).should == '((NOT x OR NOT w) AND (NOT y OR NOT z))'
249
- @d.l(~((:x.sql_number > 200) | (:y & :z))).should == '((x <= 200) AND (NOT y OR NOT z))'
130
+ @d.l(~((Sequel.expr(:x) | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
131
+ @d.l(~(Sequel.expr(:x) | (Sequel.expr(:y) & :z))).should == '(NOT x AND (NOT y OR NOT z))'
132
+ @d.l(~((Sequel.expr(:x) & :w) | (Sequel.expr(:y) & :z))).should == '((NOT x OR NOT w) AND (NOT y OR NOT z))'
133
+ @d.l(~((Sequel.expr(:x).sql_number > 200) | (Sequel.expr(:y) & :z))).should == '((x <= 200) AND (NOT y OR NOT z))'
250
134
  end
251
135
 
252
136
  it "should support LiteralString" do
253
- @d.l('x'.lit).should == '(x)'
254
- @d.l(~'x'.lit).should == 'NOT x'
255
- @d.l(~~'x'.lit).should == 'x'
256
- @d.l(~(('x'.lit | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
257
- @d.l(~(:x | 'y'.lit)).should == '(NOT x AND NOT y)'
258
- @d.l(~('x'.lit & 'y'.lit)).should == '(NOT x OR NOT y)'
259
- @d.l({'y'.lit => 'z'.lit} & 'x'.lit).should == '((y = z) AND x)'
260
- @d.l(('x'.lit > 200) & ('y'.lit < 200)).should == '((x > 200) AND (y < 200))'
261
- @d.l(~('x'.lit + 1 > 100)).should == '((x + 1) <= 100)'
262
- @d.l('x'.lit.like(/a/)).should == '(x ~ \'a\')'
263
- @d.l('x'.lit + 1 > 100).should == '((x + 1) > 100)'
264
- @d.l(('x'.lit * :y) < 100.01).should == '((x * y) < 100.01)'
265
- @d.l(('x'.lit - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
266
- @d.l(('z'.lit * (('x'.lit / :y)/(:x + :y))) <= 100).should == '((z * (x / y / (x + y))) <= 100)'
267
- @d.l(~(((('x'.lit - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
137
+ @d.l(Sequel.lit('x')).should == '(x)'
138
+ @d.l(~Sequel.lit('x')).should == 'NOT x'
139
+ @d.l(~~Sequel.lit('x')).should == 'x'
140
+ @d.l(~((Sequel.lit('x') | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
141
+ @d.l(~(Sequel.expr(:x) | Sequel.lit('y'))).should == '(NOT x AND NOT y)'
142
+ @d.l(~(Sequel.lit('x') & Sequel.lit('y'))).should == '(NOT x OR NOT y)'
143
+ @d.l(Sequel.expr(Sequel.lit('y') => Sequel.lit('z')) & Sequel.lit('x')).should == '((y = z) AND x)'
144
+ @d.l((Sequel.lit('x') > 200) & (Sequel.lit('y') < 200)).should == '((x > 200) AND (y < 200))'
145
+ @d.l(~(Sequel.lit('x') + 1 > 100)).should == '((x + 1) <= 100)'
146
+ @d.l(Sequel.lit('x').like('a')).should == '(x LIKE \'a\')'
147
+ @d.l(Sequel.lit('x') + 1 > 100).should == '((x + 1) > 100)'
148
+ @d.l((Sequel.lit('x') * :y) < 100.01).should == '((x * y) < 100.01)'
149
+ @d.l((Sequel.lit('x') - Sequel.expr(:y)/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
150
+ @d.l((Sequel.lit('z') * ((Sequel.lit('x') / :y)/(Sequel.expr(:x) + :y))) <= 100).should == '((z * (x / y / (x + y))) <= 100)'
151
+ @d.l(~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
268
152
  end
269
153
 
270
154
  it "should support hashes by ANDing the conditions" do
@@ -273,134 +157,71 @@ describe "Blockless Ruby Filters" do
273
157
  @d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
274
158
  end
275
159
 
276
- it "should support sql_expr on hashes" do
277
- @d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
278
- @d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
279
- @d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
280
- end
281
-
282
- it "should support sql_negate on hashes" do
283
- @d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
284
- @d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
285
- @d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
286
- end
287
-
288
- it "should support ~ on hashes" do
289
- @d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
290
- @d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
291
- @d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
292
- end
293
-
294
- it "should support sql_or on hashes" do
295
- @d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
296
- @d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
297
- @d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
298
- end
299
-
300
160
  it "should support arrays with all two pairs the same as hashes" do
301
161
  @d.l([[:x, 100],[:y, 'a']]).should == '((x = 100) AND (y = \'a\'))'
302
162
  @d.l([[:x, true], [:y, false]]).should == '((x IS TRUE) AND (y IS FALSE))'
303
163
  @d.l([[:x, nil], [:y, [1,2,3]]]).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
304
164
  end
305
165
 
306
- it "should support sql_expr on arrays with all two pairs" do
307
- @d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
308
- @d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
309
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
310
- end
311
-
312
- it "should support sql_negate on arrays with all two pairs" do
313
- @d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
314
- @d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
315
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
316
- end
317
-
318
- it "should support ~ on arrays with all two pairs" do
319
- @d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
320
- @d.l(~[[:x, true], [:y, false]]).should == '((x IS NOT TRUE) OR (y IS NOT FALSE))'
321
- @d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
322
- end
323
-
324
- it "should support sql_or on arrays with all two pairs" do
325
- @d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
326
- @d.l([[:x, true], [:y, false]].sql_or).should == '((x IS TRUE) OR (y IS FALSE))'
327
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
328
- end
329
-
330
166
  it "should emulate columns for array values" do
331
- @d.l([:x, :y]=>[[1,2], [3,4]].sql_array).should == '((x, y) IN ((1, 2), (3, 4)))'
167
+ @d.l([:x, :y]=>Sequel.value_list([[1,2], [3,4]])).should == '((x, y) IN ((1, 2), (3, 4)))'
332
168
  @d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '((x, y, z) IN ((1, 2, 5), (3, 4, 6)))'
333
169
  end
334
170
 
335
171
  it "should emulate multiple column in if not supported" do
336
172
  @d.meta_def(:supports_multiple_column_in?){false}
337
- @d.l([:x, :y]=>[[1,2], [3,4]].sql_array).should == '(((x = 1) AND (y = 2)) OR ((x = 3) AND (y = 4)))'
173
+ @d.l([:x, :y]=>Sequel.value_list([[1,2], [3,4]])).should == '(((x = 1) AND (y = 2)) OR ((x = 3) AND (y = 4)))'
338
174
  @d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '(((x = 1) AND (y = 2) AND (z = 5)) OR ((x = 3) AND (y = 4) AND (z = 6)))'
339
175
  end
340
176
 
341
- it "should support Array#sql_string_join for concatenation of SQL strings" do
342
- @d.lit([:x].sql_string_join).should == '(x)'
343
- @d.lit([:x].sql_string_join(', ')).should == '(x)'
344
- @d.lit([:x, :y].sql_string_join).should == '(x || y)'
345
- @d.lit([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
346
- @d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).should == '(x(1) || y[1])'
347
- @d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
348
- @d.lit([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
349
- @d.lit([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
350
- @d.lit([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
351
- @d.lit([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
352
- @d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
353
- @d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "(x || y || a || b)"
354
- end
355
-
356
177
  it "should support StringExpression#+ for concatenation of SQL strings" do
357
- @d.lit(:x.sql_string + :y).should == '(x || y)'
358
- @d.lit([:x].sql_string_join + :y).should == '(x || y)'
359
- @d.lit([:x, :z].sql_string_join(' ') + :y).should == "(x || ' ' || z || y)"
178
+ @d.lit(Sequel.expr(:x).sql_string + :y).should == '(x || y)'
179
+ @d.lit(Sequel.join([:x]) + :y).should == '(x || y)'
180
+ @d.lit(Sequel.join([:x, :z], ' ') + :y).should == "(x || ' ' || z || y)"
360
181
  end
361
182
 
362
183
  it "should be supported inside blocks" do
363
- @d.l{[[:x, nil], [:y, [1,2,3]]].sql_or}.should == '((x IS NULL) OR (y IN (1, 2, 3)))'
364
- @d.l{~[[:x, nil], [:y, [1,2,3]]]}.should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
365
- @d.l{~(((('x'.lit - :y)/(:x + :y))*:z) <= 100)}.should == '((((x - y) / (x + y)) * z) > 100)'
366
- @d.l{{:x => :a} & {:y => :z}}.should == '((x = a) AND (y = z))'
184
+ @d.l{Sequel.or([[:x, nil], [:y, [1,2,3]]])}.should == '((x IS NULL) OR (y IN (1, 2, 3)))'
185
+ @d.l{Sequel.~([[:x, nil], [:y, [1,2,3]]])}.should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
186
+ @d.l{~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)}.should == '((((x - y) / (x + y)) * z) > 100)'
187
+ @d.l{Sequel.&({:x => :a}, {:y => :z})}.should == '((x = a) AND (y = z))'
367
188
  end
368
189
 
369
190
  it "should support &, |, ^, ~, <<, and >> for NumericExpressions" do
370
- @d.l(:x.sql_number & 1 > 100).should == '((x & 1) > 100)'
371
- @d.l(:x.sql_number | 1 > 100).should == '((x | 1) > 100)'
372
- @d.l(:x.sql_number ^ 1 > 100).should == '((x ^ 1) > 100)'
373
- @d.l(~:x.sql_number > 100).should == '(~x > 100)'
374
- @d.l(:x.sql_number << 1 > 100).should == '((x << 1) > 100)'
375
- @d.l(:x.sql_number >> 1 > 100).should == '((x >> 1) > 100)'
376
- @d.l((:x + 1) & 1 > 100).should == '(((x + 1) & 1) > 100)'
377
- @d.l((:x + 1) | 1 > 100).should == '(((x + 1) | 1) > 100)'
378
- @d.l((:x + 1) ^ 1 > 100).should == '(((x + 1) ^ 1) > 100)'
379
- @d.l(~(:x + 1) > 100).should == '(~(x + 1) > 100)'
380
- @d.l((:x + 1) << 1 > 100).should == '(((x + 1) << 1) > 100)'
381
- @d.l((:x + 1) >> 1 > 100).should == '(((x + 1) >> 1) > 100)'
382
- @d.l((:x + 1) & (:x + 2) > 100).should == '(((x + 1) & (x + 2)) > 100)'
191
+ @d.l(Sequel.expr(:x).sql_number & 1 > 100).should == '((x & 1) > 100)'
192
+ @d.l(Sequel.expr(:x).sql_number | 1 > 100).should == '((x | 1) > 100)'
193
+ @d.l(Sequel.expr(:x).sql_number ^ 1 > 100).should == '((x ^ 1) > 100)'
194
+ @d.l(~Sequel.expr(:x).sql_number > 100).should == '(~x > 100)'
195
+ @d.l(Sequel.expr(:x).sql_number << 1 > 100).should == '((x << 1) > 100)'
196
+ @d.l(Sequel.expr(:x).sql_number >> 1 > 100).should == '((x >> 1) > 100)'
197
+ @d.l((Sequel.expr(:x) + 1) & 1 > 100).should == '(((x + 1) & 1) > 100)'
198
+ @d.l((Sequel.expr(:x) + 1) | 1 > 100).should == '(((x + 1) | 1) > 100)'
199
+ @d.l((Sequel.expr(:x) + 1) ^ 1 > 100).should == '(((x + 1) ^ 1) > 100)'
200
+ @d.l(~(Sequel.expr(:x) + 1) > 100).should == '(~(x + 1) > 100)'
201
+ @d.l((Sequel.expr(:x) + 1) << 1 > 100).should == '(((x + 1) << 1) > 100)'
202
+ @d.l((Sequel.expr(:x) + 1) >> 1 > 100).should == '(((x + 1) >> 1) > 100)'
203
+ @d.l((Sequel.expr(:x) + 1) & (Sequel.expr(:x) + 2) > 100).should == '(((x + 1) & (x + 2)) > 100)'
383
204
  end
384
205
 
385
- it "should raise an error if use a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
386
- proc{(:x + 1) & (:x & 2)}.should raise_error(Sequel::Error)
206
+ it "should allow using a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
207
+ @d.lit((Sequel.expr(:x) + 1) & (Sequel.expr(:x) + '2')).should == "((x + 1) & (x || '2'))"
387
208
  end
388
209
 
389
- it "should raise an error if use a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
390
- proc{:x & (:x + 2)}.should raise_error(Sequel::Error)
210
+ it "should allow using a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
211
+ @d.l(Sequel.expr(:x) & (Sequel.expr(:x) + '2')).should == "(x AND (x || '2'))"
391
212
  end
392
213
 
393
214
  it "should raise an error if attempting to invert a ComplexExpression that isn't a BooleanExpression" do
394
- proc{Sequel::SQL::BooleanExpression.invert(:x + 2)}.should raise_error(Sequel::Error)
215
+ proc{Sequel::SQL::BooleanExpression.invert(Sequel.expr(:x) + 2)}.should raise_error(Sequel::Error)
395
216
  end
396
217
 
397
218
  it "should return self on .lit" do
398
- y = :x + 1
219
+ y = Sequel.expr(:x) + 1
399
220
  y.lit.should == y
400
221
  end
401
222
 
402
223
  it "should return have .sql_literal operate like .to_s" do
403
- y = :x + 1
224
+ y = Sequel.expr(:x) + 1
404
225
  y.sql_literal(@d).should == '(x + 1)'
405
226
  y.sql_literal(@d).should == y.to_s(@d)
406
227
  y.sql_literal(@d).should == @d.literal(y)
@@ -416,68 +237,159 @@ describe "Blockless Ruby Filters" do
416
237
  end
417
238
 
418
239
  it "should support negation of SQL::Constants" do
419
- @d.l(~{:x => Sequel::NULL}).should == '(x IS NOT NULL)'
420
- @d.l(~{:x => Sequel::NOTNULL}).should == '(x IS NULL)'
421
- @d.l(~{:x => Sequel::TRUE}).should == '(x IS NOT TRUE)'
422
- @d.l(~{:x => Sequel::FALSE}).should == '(x IS NOT FALSE)'
423
- @d.l(~{:x => Sequel::SQLTRUE}).should == '(x IS NOT TRUE)'
424
- @d.l(~{:x => Sequel::SQLFALSE}).should == '(x IS NOT FALSE)'
240
+ @d.l(Sequel.~(:x => Sequel::NULL)).should == '(x IS NOT NULL)'
241
+ @d.l(Sequel.~(:x => Sequel::NOTNULL)).should == '(x IS NULL)'
242
+ @d.l(Sequel.~(:x => Sequel::TRUE)).should == '(x IS NOT TRUE)'
243
+ @d.l(Sequel.~(:x => Sequel::FALSE)).should == '(x IS NOT FALSE)'
244
+ @d.l(Sequel.~(:x => Sequel::SQLTRUE)).should == '(x IS NOT TRUE)'
245
+ @d.l(Sequel.~(:x => Sequel::SQLFALSE)).should == '(x IS NOT FALSE)'
246
+ end
247
+
248
+ it "should support direct negation of SQL::Constants" do
249
+ @d.l({:x => ~Sequel::NULL}).should == '(x IS NOT NULL)'
250
+ @d.l({:x => ~Sequel::NOTNULL}).should == '(x IS NULL)'
251
+ @d.l({:x => ~Sequel::TRUE}).should == '(x IS FALSE)'
252
+ @d.l({:x => ~Sequel::FALSE}).should == '(x IS TRUE)'
253
+ @d.l({:x => ~Sequel::SQLTRUE}).should == '(x IS FALSE)'
254
+ @d.l({:x => ~Sequel::SQLFALSE}).should == '(x IS TRUE)'
425
255
  end
426
256
 
257
+ it "should raise an error if trying to invert an invalid SQL::Constant" do
258
+ proc{~Sequel::CURRENT_DATE}.should raise_error(Sequel::Error)
259
+ end
260
+
427
261
  it "should raise an error if trying to create an invalid complex expression" do
428
262
  proc{Sequel::SQL::ComplexExpression.new(:BANG, 1, 2)}.should raise_error(Sequel::Error)
429
263
  end
430
264
 
265
+ it "should use a string concatentation for + if given a string" do
266
+ @d.lit(Sequel.expr(:x) + '1').should == "(x || '1')"
267
+ @d.lit(Sequel.expr(:x) + '1' + '1').should == "(x || '1' || '1')"
268
+ end
269
+
270
+ it "should use an addition for + if given a literal string" do
271
+ @d.lit(Sequel.expr(:x) + Sequel.lit('1')).should == "(x + 1)"
272
+ @d.lit(Sequel.expr(:x) + Sequel.lit('1') + Sequel.lit('1')).should == "(x + 1 + 1)"
273
+ end
274
+
275
+ it "should use a bitwise operator for & and | if given an integer" do
276
+ @d.lit(Sequel.expr(:x) & 1).should == "(x & 1)"
277
+ @d.lit(Sequel.expr(:x) | 1).should == "(x | 1)"
278
+ @d.lit(Sequel.expr(:x) & 1 & 1).should == "(x & 1 & 1)"
279
+ @d.lit(Sequel.expr(:x) | 1 | 1).should == "(x | 1 | 1)"
280
+ end
281
+
282
+ it "should allow adding a string to an integer expression" do
283
+ @d.lit(Sequel.expr(:x) + 1 + 'a').should == "(x + 1 + 'a')"
284
+ end
285
+
286
+ it "should allow adding an integer to an string expression" do
287
+ @d.lit(Sequel.expr(:x) + 'a' + 1).should == "(x || 'a' || 1)"
288
+ end
289
+
290
+ it "should allow adding a boolean to an integer expression" do
291
+ @d.lit(Sequel.expr(:x) + 1 + true).should == "(x + 1 + 't')"
292
+ end
293
+
294
+ it "should allow adding a boolean to an string expression" do
295
+ @d.lit(Sequel.expr(:x) + 'a' + true).should == "(x || 'a' || 't')"
296
+ end
297
+
298
+ it "should allow using a boolean operation with an integer on an boolean expression" do
299
+ @d.lit(Sequel.expr(:x) & :a & 1).should == "(x AND a AND 1)"
300
+ end
301
+
302
+ it "should allow using a boolean operation with a string on an boolean expression" do
303
+ @d.lit(Sequel.expr(:x) & :a & 'a').should == "(x AND a AND 'a')"
304
+ end
305
+
306
+ it "should allowing AND of boolean expression and literal string" do
307
+ @d.lit(Sequel.expr(:x) & :a & Sequel.lit('a')).should == "(x AND a AND a)"
308
+ end
309
+
310
+ it "should allowing + of integer expression and literal string" do
311
+ @d.lit(Sequel.expr(:x) + :a + Sequel.lit('a')).should == "(x + a + a)"
312
+ end
313
+
314
+ it "should allowing + of string expression and literal string" do
315
+ @d.lit(Sequel.expr(:x) + 'a' + Sequel.lit('a')).should == "(x || 'a' || a)"
316
+ end
317
+
318
+ it "should allow sql_{string,boolean,number} methods on numeric expressions" do
319
+ @d.lit((Sequel.expr(:x) + 1).sql_string + 'a').should == "((x + 1) || 'a')"
320
+ @d.lit((Sequel.expr(:x) + 1).sql_boolean & 1).should == "((x + 1) AND 1)"
321
+ @d.lit((Sequel.expr(:x) + 1).sql_number + 'a').should == "(x + 1 + 'a')"
322
+ end
323
+
324
+ it "should allow sql_{string,boolean,number} methods on string expressions" do
325
+ @d.lit((Sequel.expr(:x) + 'a').sql_string + 'a').should == "(x || 'a' || 'a')"
326
+ @d.lit((Sequel.expr(:x) + 'a').sql_boolean & 1).should == "((x || 'a') AND 1)"
327
+ @d.lit((Sequel.expr(:x) + 'a').sql_number + 'a').should == "((x || 'a') + 'a')"
328
+ end
329
+
330
+ it "should allow sql_{string,boolean,number} methods on boolean expressions" do
331
+ @d.lit((Sequel.expr(:x) & :y).sql_string + 'a').should == "((x AND y) || 'a')"
332
+ @d.lit((Sequel.expr(:x) & :y).sql_boolean & 1).should == "(x AND y AND 1)"
333
+ @d.lit((Sequel.expr(:x) & :y).sql_number + 'a').should == "((x AND y) + 'a')"
334
+ end
335
+
431
336
  it "should raise an error if trying to literalize an invalid complex expression" do
432
- ce = :x + 1
337
+ ce = Sequel.+(:x, 1)
433
338
  ce.instance_variable_set(:@op, :BANG)
434
339
  proc{@d.lit(ce)}.should raise_error(Sequel::Error)
435
340
  end
436
341
 
437
342
  it "should support equality comparison of two expressions" do
438
- e1 = ~:comment.like('%:hidden:%')
439
- e2 = ~:comment.like('%:hidden:%')
343
+ e1 = ~Sequel.like(:comment, '%:hidden:%')
344
+ e2 = ~Sequel.like(:comment, '%:hidden:%')
440
345
  e1.should == e2
441
346
  end
442
-
443
- if RUBY_VERSION < '1.9.0'
444
- it "should not allow inequality operations on true, false, or nil" do
445
- proc{:x > 1}.should_not raise_error
446
- proc{:x < true}.should raise_error(Sequel::Error)
447
- proc{:x >= false}.should raise_error(Sequel::Error)
448
- proc{:x <= nil}.should raise_error(Sequel::Error)
449
- end
450
347
 
451
- it "should not allow inequality operations on boolean complex expressions" do
452
- proc{:x > (:y > 5)}.should raise_error(Sequel::Error)
453
- proc{:x < (:y < 5)}.should raise_error(Sequel::Error)
454
- proc{:x >= (:y >= 5)}.should raise_error(Sequel::Error)
455
- proc{:x <= (:y <= 5)}.should raise_error(Sequel::Error)
456
- proc{:x > {:y => nil}}.should raise_error(Sequel::Error)
457
- proc{:x < ~{:y => nil}}.should raise_error(Sequel::Error)
458
- proc{:x >= {:y => 5}}.should raise_error(Sequel::Error)
459
- proc{:x <= ~{:y => 5}}.should raise_error(Sequel::Error)
460
- proc{:x >= {:y => [1,2,3]}}.should raise_error(Sequel::Error)
461
- proc{:x <= ~{:y => [1,2,3]}}.should raise_error(Sequel::Error)
462
- end
463
-
464
- it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
465
- @d.l(:x > 100).should == '(x > 100)'
466
- @d.l(:x < 100.01).should == '(x < 100.01)'
467
- @d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
468
- @d.l(:x <= 100).should == '(x <= 100)'
469
- end
470
-
471
- it "should support negation of >, <, >=, and <= via Symbol#~" do
472
- @d.l(~(:x > 100)).should == '(x <= 100)'
473
- @d.l(~(:x < 100.01)).should == '(x >= 100.01)'
474
- @d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
475
- @d.l(~(:x <= 100)).should == '(x > 100)'
476
- end
477
-
478
- it "should support double negation via ~" do
479
- @d.l(~~(:x > 100)).should == '(x > 100)'
480
- end
348
+ it "should support expression filter methods on Datasets" do
349
+ d = @d.select(:a)
350
+
351
+ @d.lit(d + 1).should == '((SELECT a FROM items) + 1)'
352
+ @d.lit(d - 1).should == '((SELECT a FROM items) - 1)'
353
+ @d.lit(d * 1).should == '((SELECT a FROM items) * 1)'
354
+ @d.lit(d / 1).should == '((SELECT a FROM items) / 1)'
355
+
356
+ @d.lit(d => 1).should == '((SELECT a FROM items) = 1)'
357
+ @d.lit(Sequel.~(d => 1)).should == '((SELECT a FROM items) != 1)'
358
+ @d.lit(d > 1).should == '((SELECT a FROM items) > 1)'
359
+ @d.lit(d < 1).should == '((SELECT a FROM items) < 1)'
360
+ @d.lit(d >= 1).should == '((SELECT a FROM items) >= 1)'
361
+ @d.lit(d <= 1).should == '((SELECT a FROM items) <= 1)'
362
+
363
+ @d.lit(d.as(:b)).should == '(SELECT a FROM items) AS b'
364
+
365
+ @d.lit(d & :b).should == '((SELECT a FROM items) AND b)'
366
+ @d.lit(d | :b).should == '((SELECT a FROM items) OR b)'
367
+ @d.lit(~d).should == 'NOT (SELECT a FROM items)'
368
+
369
+ @d.lit(d.cast(Integer)).should == 'CAST((SELECT a FROM items) AS integer)'
370
+ @d.lit(d.cast_numeric).should == 'CAST((SELECT a FROM items) AS integer)'
371
+ @d.lit(d.cast_string).should == 'CAST((SELECT a FROM items) AS varchar(255))'
372
+ @d.lit(d.cast_numeric << :b).should == '(CAST((SELECT a FROM items) AS integer) << b)'
373
+ @d.lit(d.cast_string + :b).should == '(CAST((SELECT a FROM items) AS varchar(255)) || b)'
374
+
375
+ @d.lit(d.extract(:year)).should == 'extract(year FROM (SELECT a FROM items))'
376
+ @d.lit(d.sql_boolean & :b).should == '((SELECT a FROM items) AND b)'
377
+ @d.lit(d.sql_number << :b).should == '((SELECT a FROM items) << b)'
378
+ @d.lit(d.sql_string + :b).should == '((SELECT a FROM items) || b)'
379
+
380
+ @d.lit(d.asc).should == '(SELECT a FROM items) ASC'
381
+ @d.lit(d.desc).should == '(SELECT a FROM items) DESC'
382
+
383
+ @d.lit(d.like(:b)).should == '((SELECT a FROM items) LIKE b)'
384
+ @d.lit(d.ilike(:b)).should == '((SELECT a FROM items) ILIKE b)'
385
+ end
386
+
387
+ it "should handled emulated char_length function" do
388
+ @d.lit(Sequel.char_length(:a)).should == 'char_length(a)'
389
+ end
390
+
391
+ it "should handled emulated trim function" do
392
+ @d.lit(Sequel.trim(:a)).should == 'trim(a)'
481
393
  end
482
394
  end
483
395
 
@@ -553,7 +465,7 @@ describe Sequel::SQL::VirtualRow do
553
465
  end
554
466
 
555
467
  it "should support :frame=>:rows option for window function calls" do
556
- @d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
468
+ @d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
557
469
  end
558
470
 
559
471
  it "should support :frame=>'some string' option for window function calls" do
@@ -565,7 +477,7 @@ describe Sequel::SQL::VirtualRow do
565
477
  end
566
478
 
567
479
  it "should support all these options together" do
568
- @d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.should == 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS UNBOUNDED PRECEDING)'
480
+ @d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.should == 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
569
481
  end
570
482
 
571
483
  it "should raise an error if window functions are not supported" do
@@ -596,4 +508,448 @@ describe Sequel::SQL::VirtualRow do
596
508
  Sequel::BasicObject.remove_methods!
597
509
  @d.l{a > adsoiwemlsdaf2}.should == '("a" > "adsoiwemlsdaf2")'
598
510
  end
511
+
512
+ it "should have operator methods defined that produce Sequel expression objects" do
513
+ @d.l{|o| o.&({:a=>1}, :b)}.should == '(("a" = 1) AND "b")'
514
+ @d.l{|o| o.|({:a=>1}, :b)}.should == '(("a" = 1) OR "b")'
515
+ @d.l{|o| o.+(1, :b) > 2}.should == '((1 + "b") > 2)'
516
+ @d.l{|o| o.-(1, :b) < 2}.should == '((1 - "b") < 2)'
517
+ @d.l{|o| o.*(1, :b) >= 2}.should == '((1 * "b") >= 2)'
518
+ @d.l{|o| o./(1, :b) <= 2}.should == '((1 / "b") <= 2)'
519
+ @d.l{|o| o.~(:a=>1)}.should == '("a" != 1)'
520
+ @d.l{|o| o.~([[:a, 1], [:b, 2]])}.should == '(("a" != 1) OR ("b" != 2))'
521
+ @d.l{|o| o.<(1, :b)}.should == '(1 < "b")'
522
+ @d.l{|o| o.>(1, :b)}.should == '(1 > "b")'
523
+ @d.l{|o| o.<=(1, :b)}.should == '(1 <= "b")'
524
+ @d.l{|o| o.>=(1, :b)}.should == '(1 >= "b")'
525
+ end
526
+
527
+ it "should have have ` produce literal strings" do
528
+ @d.l{a > `some SQL`}.should == '("a" > some SQL)'
529
+ @d.l{|o| o.a > o.`('some SQL')}.should == '("a" > some SQL)' #`
530
+ end
531
+ end
532
+
533
+ describe "Sequel core extension replacements" do
534
+ before do
535
+ @db = Sequel::Database.new
536
+ @ds = @db.dataset
537
+ def @ds.supports_regexp?; true end
538
+ @o = Object.new
539
+ def @o.sql_literal(ds) 'foo' end
540
+ end
541
+
542
+ def l(arg, should)
543
+ @ds.literal(arg).should == should
544
+ end
545
+
546
+ it "Sequel.expr should return items wrapped in Sequel objects" do
547
+ Sequel.expr(1).should be_a_kind_of(Sequel::SQL::NumericExpression)
548
+ Sequel.expr('a').should be_a_kind_of(Sequel::SQL::StringExpression)
549
+ Sequel.expr(true).should be_a_kind_of(Sequel::SQL::BooleanExpression)
550
+ Sequel.expr(nil).should be_a_kind_of(Sequel::SQL::Wrapper)
551
+ Sequel.expr({1=>2}).should be_a_kind_of(Sequel::SQL::BooleanExpression)
552
+ Sequel.expr([[1, 2]]).should be_a_kind_of(Sequel::SQL::BooleanExpression)
553
+ Sequel.expr([1]).should be_a_kind_of(Sequel::SQL::Wrapper)
554
+ Sequel.expr{|o| o.should be_a_kind_of(Sequel::SQL::VirtualRow)}
555
+ Sequel.expr{self.should be_a_kind_of(Sequel::SQL::VirtualRow)}
556
+ Sequel.expr(:a).should be_a_kind_of(Sequel::SQL::Identifier)
557
+ Sequel.expr(:a__b).should be_a_kind_of(Sequel::SQL::QualifiedIdentifier)
558
+ Sequel.expr(:a___c).should be_a_kind_of(Sequel::SQL::AliasedExpression)
559
+ Sequel.expr(:a___c).expression.should be_a_kind_of(Sequel::SQL::Identifier)
560
+ Sequel.expr(:a__b___c).should be_a_kind_of(Sequel::SQL::AliasedExpression)
561
+ Sequel.expr(:a__b___c).expression.should be_a_kind_of(Sequel::SQL::QualifiedIdentifier)
562
+ end
563
+
564
+ it "Sequel.expr should return an appropriate wrapped object" do
565
+ l(Sequel.expr(1) + 1, "(1 + 1)")
566
+ l(Sequel.expr('a') + 'b', "('a' || 'b')")
567
+ l(Sequel.expr(:b) & nil, "(b AND NULL)")
568
+ l(Sequel.expr(nil) & true, "(NULL AND 't')")
569
+ l(Sequel.expr(false) & true, "('f' AND 't')")
570
+ l(Sequel.expr(true) | false, "('t' OR 'f')")
571
+ l(Sequel.expr(@o) + 1, "(foo + 1)")
572
+ end
573
+
574
+ it "Sequel.expr should handle condition specifiers" do
575
+ l(Sequel.expr(:a=>1) & nil, "((a = 1) AND NULL)")
576
+ l(Sequel.expr([[:a, 1]]) & nil, "((a = 1) AND NULL)")
577
+ l(Sequel.expr([[:a, 1], [:b, 2]]) & nil, "((a = 1) AND (b = 2) AND NULL)")
578
+ end
579
+
580
+ it "Sequel.expr should handle arrays that are not condition specifiers" do
581
+ l(Sequel.expr([1]), "(1)")
582
+ l(Sequel.expr([1, 2]), "(1, 2)")
583
+ end
584
+
585
+ it "Sequel.expr should treat blocks/procs as virtual rows and wrap the output" do
586
+ l(Sequel.expr{1} + 1, "(1 + 1)")
587
+ l(Sequel.expr{o__a} + 1, "(o.a + 1)")
588
+ l(Sequel.expr{[[:a, 1]]} & nil, "((a = 1) AND NULL)")
589
+ l(Sequel.expr{|v| @o} + 1, "(foo + 1)")
590
+
591
+ l(Sequel.expr(proc{1}) + 1, "(1 + 1)")
592
+ l(Sequel.expr(proc{o__a}) + 1, "(o.a + 1)")
593
+ l(Sequel.expr(proc{[[:a, 1]]}) & nil, "((a = 1) AND NULL)")
594
+ l(Sequel.expr(proc{|v| @o}) + 1, "(foo + 1)")
595
+ end
596
+
597
+ it "Sequel.expr should raise an error if given an argument and a block" do
598
+ proc{Sequel.expr(nil){}}.should raise_error(Sequel::Error)
599
+ end
600
+
601
+ it "Sequel.expr should raise an error if given neither an argument nor a block" do
602
+ proc{Sequel.expr}.should raise_error(Sequel::Error)
603
+ end
604
+
605
+ it "Sequel.expr should return existing Sequel expressions directly" do
606
+ o = Sequel.expr(1)
607
+ Sequel.expr(o).should equal(o)
608
+ o = Sequel.lit('1')
609
+ Sequel.expr(o).should equal(o)
610
+ end
611
+
612
+ it "Sequel.~ should invert the given object" do
613
+ l(Sequel.~(nil), 'NOT NULL')
614
+ l(Sequel.~(:a=>1), "(a != 1)")
615
+ l(Sequel.~([[:a, 1]]), "(a != 1)")
616
+ l(Sequel.~([[:a, 1], [:b, 2]]), "((a != 1) OR (b != 2))")
617
+ l(Sequel.~(Sequel.expr([[:a, 1], [:b, 2]]) & nil), "((a != 1) OR (b != 2) OR NOT NULL)")
618
+ end
619
+
620
+ it "Sequel.case should use a CASE expression" do
621
+ l(Sequel.case({:a=>1}, 2), "(CASE WHEN a THEN 1 ELSE 2 END)")
622
+ l(Sequel.case({:a=>1}, 2, :b), "(CASE b WHEN a THEN 1 ELSE 2 END)")
623
+ l(Sequel.case([[:a, 1]], 2), "(CASE WHEN a THEN 1 ELSE 2 END)")
624
+ l(Sequel.case([[:a, 1]], 2, :b), "(CASE b WHEN a THEN 1 ELSE 2 END)")
625
+ l(Sequel.case([[:a, 1], [:c, 3]], 2), "(CASE WHEN a THEN 1 WHEN c THEN 3 ELSE 2 END)")
626
+ l(Sequel.case([[:a, 1], [:c, 3]], 2, :b), "(CASE b WHEN a THEN 1 WHEN c THEN 3 ELSE 2 END)")
627
+ end
628
+
629
+ it "Sequel.case should raise an error if not given a condition specifier" do
630
+ proc{Sequel.case(1, 2)}.should raise_error(Sequel::Error)
631
+ end
632
+
633
+ it "Sequel.value_list should use an SQL value list" do
634
+ l(Sequel.value_list([[1, 2]]), "((1, 2))")
635
+ end
636
+
637
+ it "Sequel.value_list raise an error if not given an array" do
638
+ proc{Sequel.value_list(1)}.should raise_error(Sequel::Error)
639
+ end
640
+
641
+ it "Sequel.negate should negate all entries in conditions specifier and join with AND" do
642
+ l(Sequel.negate(:a=>1), "(a != 1)")
643
+ l(Sequel.negate([[:a, 1]]), "(a != 1)")
644
+ l(Sequel.negate([[:a, 1], [:b, 2]]), "((a != 1) AND (b != 2))")
645
+ end
646
+
647
+ it "Sequel.negate should raise an error if not given a conditions specifier" do
648
+ proc{Sequel.negate(1)}.should raise_error(Sequel::Error)
649
+ end
650
+
651
+ it "Sequel.or should join all entries in conditions specifier with OR" do
652
+ l(Sequel.or(:a=>1), "(a = 1)")
653
+ l(Sequel.or([[:a, 1]]), "(a = 1)")
654
+ l(Sequel.or([[:a, 1], [:b, 2]]), "((a = 1) OR (b = 2))")
655
+ end
656
+
657
+ it "Sequel.or should raise an error if not given a conditions specifier" do
658
+ proc{Sequel.or(1)}.should raise_error(Sequel::Error)
659
+ end
660
+
661
+ it "Sequel.join should should use SQL string concatenation to join array" do
662
+ l(Sequel.join([]), "''")
663
+ l(Sequel.join(['a']), "('a')")
664
+ l(Sequel.join(['a', 'b']), "('a' || 'b')")
665
+ l(Sequel.join(['a', 'b'], 'c'), "('a' || 'c' || 'b')")
666
+ l(Sequel.join([true, :b], :c), "('t' || c || b)")
667
+ l(Sequel.join([false, nil], Sequel.lit('c')), "('f' || c || NULL)")
668
+ l(Sequel.join([Sequel.expr('a'), Sequel.lit('d')], 'c'), "('a' || 'c' || d)")
669
+ end
670
+
671
+ it "Sequel.join should raise an error if not given an array" do
672
+ proc{Sequel.join(1)}.should raise_error(Sequel::Error)
673
+ end
674
+
675
+ it "Sequel.& should join all arguments given with AND" do
676
+ l(Sequel.&(:a), "(a)")
677
+ l(Sequel.&(:a, :b=>:c), "(a AND (b = c))")
678
+ l(Sequel.&(:a, {:b=>:c}, Sequel.lit('d')), "(a AND (b = c) AND d)")
679
+ end
680
+
681
+ it "Sequel.& should raise an error if given no arguments" do
682
+ proc{Sequel.&}.should raise_error(Sequel::Error)
683
+ end
684
+
685
+ it "Sequel.| should join all arguments given with OR" do
686
+ l(Sequel.|(:a), "(a)")
687
+ l(Sequel.|(:a, :b=>:c), "(a OR (b = c))")
688
+ l(Sequel.|(:a, {:b=>:c}, Sequel.lit('d')), "(a OR (b = c) OR d)")
689
+ end
690
+
691
+ it "Sequel.| should raise an error if given no arguments" do
692
+ proc{Sequel.|}.should raise_error(Sequel::Error)
693
+ end
694
+
695
+ it "Sequel.as should return an aliased expression" do
696
+ l(Sequel.as(:a, :b), "a AS b")
697
+ end
698
+
699
+ it "Sequel.cast should return a CAST expression" do
700
+ l(Sequel.cast(:a, :int), "CAST(a AS int)")
701
+ l(Sequel.cast(:a, Integer), "CAST(a AS integer)")
702
+ end
703
+
704
+ it "Sequel.cast_numeric should return a CAST expression treated as a number" do
705
+ l(Sequel.cast_numeric(:a), "CAST(a AS integer)")
706
+ l(Sequel.cast_numeric(:a, :int), "CAST(a AS int)")
707
+ l(Sequel.cast_numeric(:a) << 2, "(CAST(a AS integer) << 2)")
708
+ end
709
+
710
+ it "Sequel.cast_string should return a CAST expression treated as a string" do
711
+ l(Sequel.cast_string(:a), "CAST(a AS varchar(255))")
712
+ l(Sequel.cast_string(:a, :text), "CAST(a AS text)")
713
+ l(Sequel.cast_string(:a) + 'a', "(CAST(a AS varchar(255)) || 'a')")
714
+ end
715
+
716
+ it "Sequel.lit should return a literal string" do
717
+ l(Sequel.lit('a'), "a")
718
+ end
719
+
720
+ it "Sequel.lit should return the argument if given a single literal string" do
721
+ o = Sequel.lit('a')
722
+ Sequel.lit(o).should equal(o)
723
+ end
724
+
725
+ it "Sequel.lit should accept multiple arguments for a placeholder literal string" do
726
+ l(Sequel.lit('a = ?', 1), "a = 1")
727
+ l(Sequel.lit('? = ?', :a, 1), "a = 1")
728
+ l(Sequel.lit('a = :a', :a=>1), "a = 1")
729
+ end
730
+
731
+ it "Sequel.lit should work with an array for the placeholder string" do
732
+ l(Sequel.lit(['a = '], 1), "a = 1")
733
+ l(Sequel.lit(['', ' = '], :a, 1), "a = 1")
734
+ end
735
+
736
+ it "Sequel.blob should return an SQL::Blob" do
737
+ l(Sequel.blob('a'), "'a'")
738
+ Sequel.blob('a').should be_a_kind_of(Sequel::SQL::Blob)
739
+ end
740
+
741
+ it "Sequel.blob should return the given argument if given a blob" do
742
+ o = Sequel.blob('a')
743
+ Sequel.blob(o).should equal(o)
744
+ end
745
+
746
+ it "Sequel.qualify should return a qualified identifier" do
747
+ l(Sequel.qualify(:t, :c), "t.c")
748
+ end
749
+
750
+ it "Sequel.identifier should return an identifier" do
751
+ l(Sequel.identifier(:t__c), "t__c")
752
+ end
753
+
754
+ it "Sequel.asc should return an ASC ordered expression" do
755
+ l(Sequel.asc(:a), "a ASC")
756
+ l(Sequel.asc(:a, :nulls=>:first), "a ASC NULLS FIRST")
757
+ end
758
+
759
+ it "Sequel.desc should return a DESC ordered expression " do
760
+ l(Sequel.desc(:a), "a DESC")
761
+ l(Sequel.desc(:a, :nulls=>:last), "a DESC NULLS LAST")
762
+ end
763
+
764
+ it "Sequel.{+,-,*,/} should accept arguments and use the appropriate operator" do
765
+ %w'+ - * /'.each do |op|
766
+ l(Sequel.send(op, 1), '(1)')
767
+ l(Sequel.send(op, 1, 2), "(1 #{op} 2)")
768
+ l(Sequel.send(op, 1, 2, 3), "(1 #{op} 2 #{op} 3)")
769
+ end
770
+ end
771
+
772
+ it "Sequel.{+,-,*,/} should raise if given no arguments" do
773
+ %w'+ - * /'.each do |op|
774
+ proc{Sequel.send(op)}.should raise_error(Sequel::Error)
775
+ end
776
+ end
777
+
778
+ it "Sequel.like should use a LIKE expression" do
779
+ l(Sequel.like('a', 'b'), "('a' LIKE 'b')")
780
+ l(Sequel.like(:a, :b), "(a LIKE b)")
781
+ l(Sequel.like(:a, /b/), "(a ~ 'b')")
782
+ l(Sequel.like(:a, 'c', /b/), "((a LIKE 'c') OR (a ~ 'b'))")
783
+ end
784
+
785
+ it "Sequel.ilike should use an ILIKE expression" do
786
+ l(Sequel.ilike('a', 'b'), "('a' ILIKE 'b')")
787
+ l(Sequel.ilike(:a, :b), "(a ILIKE b)")
788
+ l(Sequel.ilike(:a, /b/), "(a ~* 'b')")
789
+ l(Sequel.ilike(:a, 'c', /b/), "((a ILIKE 'c') OR (a ~* 'b'))")
790
+ end
791
+
792
+ it "Sequel.subscript should use an SQL subscript" do
793
+ l(Sequel.subscript(:a, 1), 'a[1]')
794
+ l(Sequel.subscript(:a, 1, 2), 'a[1, 2]')
795
+ l(Sequel.subscript(:a, [1, 2]), 'a[1, 2]')
796
+ end
797
+
798
+ it "Sequel.function should return an SQL function" do
799
+ l(Sequel.function(:a), 'a()')
800
+ l(Sequel.function(:a, 1), 'a(1)')
801
+ l(Sequel.function(:a, :b, 2), 'a(b, 2)')
802
+ end
803
+
804
+ it "Sequel.extract should use a date/time extraction" do
805
+ l(Sequel.extract(:year, :a), 'extract(year FROM a)')
806
+ end
807
+
808
+ it "#* with no arguments should use a ColumnAll for Identifier and QualifiedIdentifier" do
809
+ l(Sequel.expr(:a).*, 'a.*')
810
+ l(Sequel.expr(:a__b).*, 'a.b.*')
811
+ end
812
+
813
+ it "SQL::Blob should be aliasable and castable by default" do
814
+ b = Sequel.blob('a')
815
+ l(b.as(:a), "'a' AS a")
816
+ l(b.cast(Integer), "CAST('a' AS integer)")
817
+ end
818
+
819
+ it "SQL::Blob should be convertable to a literal string by default" do
820
+ b = Sequel.blob('a ?')
821
+ l(b.lit, "a ?")
822
+ l(b.lit(1), "a 1")
823
+ end
824
+ end
825
+
826
+ describe "Sequel::SQL::Function#==" do
827
+ specify "should be true for functions with the same name and arguments, false otherwise" do
828
+ a = Sequel.function(:date, :t)
829
+ b = Sequel.function(:date, :t)
830
+ a.should == b
831
+ (a == b).should == true
832
+ c = Sequel.function(:date, :c)
833
+ a.should_not == c
834
+ (a == c).should == false
835
+ d = Sequel.function(:time, :c)
836
+ a.should_not == d
837
+ c.should_not == d
838
+ (a == d).should == false
839
+ (c == d).should == false
840
+ end
841
+ end
842
+
843
+ describe "Sequel::SQL::OrderedExpression" do
844
+ specify "should #desc" do
845
+ @oe = Sequel.asc(:column)
846
+ @oe.descending.should == false
847
+ @oe.desc.descending.should == true
848
+ end
849
+
850
+ specify "should #asc" do
851
+ @oe = Sequel.desc(:column)
852
+ @oe.descending.should == true
853
+ @oe.asc.descending.should == false
854
+ end
855
+
856
+ specify "should #invert" do
857
+ @oe = Sequel.desc(:column)
858
+ @oe.invert.descending.should == false
859
+ @oe.invert.invert.descending.should == true
860
+ end
861
+ end
862
+
863
+ describe "Expression" do
864
+ specify "should consider objects == only if they have the same attributes" do
865
+ Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.should == Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
866
+ Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.should_not == Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
867
+
868
+ Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.should eql(Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc)
869
+ Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.should_not eql(Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc)
870
+ end
871
+
872
+ specify "should use the same hash value for objects that have the same attributes" do
873
+ Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash.should == Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash
874
+ Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.hash.should_not == Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash
875
+
876
+ h = {}
877
+ a = Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
878
+ b = Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
879
+ h[a] = 1
880
+ h[b] = 2
881
+ h[a].should == 2
882
+ h[b].should == 2
883
+ end
884
+ end
885
+
886
+ describe "Sequel::SQLTime" do
887
+ before do
888
+ @db = Sequel.mock
889
+ end
890
+
891
+ specify ".create should create from hour, minutes, seconds and optional microseconds" do
892
+ @db.literal(Sequel::SQLTime.create(1, 2, 3)).should == "'01:02:03.000000'"
893
+ @db.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).should == "'01:02:03.500000'"
894
+ end
895
+ end
896
+
897
+ describe "Sequel::SQL::Wrapper" do
898
+ before do
899
+ @ds = Sequel.mock.dataset
900
+ end
901
+
902
+ specify "should wrap objects so they can be used by the Sequel DSL" do
903
+ o = Object.new
904
+ def o.sql_literal(ds) 'foo' end
905
+ s = Sequel::SQL::Wrapper.new(o)
906
+ @ds.literal(s).should == "foo"
907
+ @ds.literal(s+1).should == "(foo + 1)"
908
+ @ds.literal(s & true).should == "(foo AND 't')"
909
+ @ds.literal(s < 1).should == "(foo < 1)"
910
+ @ds.literal(s.sql_subscript(1)).should == "foo[1]"
911
+ @ds.literal(s.like('a')).should == "(foo LIKE 'a')"
912
+ @ds.literal(s.as(:a)).should == "foo AS a"
913
+ @ds.literal(s.cast(Integer)).should == "CAST(foo AS integer)"
914
+ @ds.literal(s.desc).should == "foo DESC"
915
+ @ds.literal(s.sql_string + '1').should == "(foo || '1')"
916
+ end
917
+ end
918
+
919
+ describe "Sequel::SQL::Blob#to_sequel_blob" do
920
+ specify "should return self" do
921
+ c = Sequel::SQL::Blob.new('a')
922
+ c.to_sequel_blob.should equal(c)
923
+ end
924
+ end
925
+
926
+ describe Sequel::SQL::Subscript do
927
+ before do
928
+ @s = Sequel::SQL::Subscript.new(:a, [1])
929
+ @ds = Sequel::Dataset.new(nil)
930
+ end
931
+
932
+ specify "should have | return a new non-nested subscript" do
933
+ s = (@s | 2)
934
+ s.should_not equal(@s)
935
+ @ds.literal(s).should == 'a[1, 2]'
936
+ end
937
+
938
+ specify "should have [] return a new nested subscript" do
939
+ s = @s[2]
940
+ s.should_not equal(@s)
941
+ @ds.literal(s).should == 'a[1][2]'
942
+ end
943
+ end
944
+
945
+ describe "Sequel.recursive_map" do
946
+ specify "should recursively convert an array using a callable" do
947
+ Sequel.recursive_map(['1'], proc{|s| s.to_i}).should == [1]
948
+ Sequel.recursive_map([['1']], proc{|s| s.to_i}).should == [[1]]
949
+ end
950
+
951
+ specify "should not call callable if value is nil" do
952
+ Sequel.recursive_map([nil], proc{|s| s.to_i}).should == [nil]
953
+ Sequel.recursive_map([[nil]], proc{|s| s.to_i}).should == [[nil]]
954
+ end
599
955
  end