sequel 5.29.0 → 5.30.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 (323) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +8 -1922
  3. data/doc/release_notes/5.30.0.txt +20 -0
  4. data/lib/sequel/adapters/shared/sqlite.rb +7 -1
  5. data/lib/sequel/database/transactions.rb +5 -9
  6. data/lib/sequel/version.rb +1 -1
  7. metadata +4 -368
  8. data/Rakefile +0 -151
  9. data/doc/release_notes/4.0.0.txt +0 -262
  10. data/doc/release_notes/4.1.0.txt +0 -85
  11. data/doc/release_notes/4.10.0.txt +0 -226
  12. data/doc/release_notes/4.11.0.txt +0 -147
  13. data/doc/release_notes/4.12.0.txt +0 -105
  14. data/doc/release_notes/4.13.0.txt +0 -169
  15. data/doc/release_notes/4.14.0.txt +0 -68
  16. data/doc/release_notes/4.15.0.txt +0 -56
  17. data/doc/release_notes/4.16.0.txt +0 -36
  18. data/doc/release_notes/4.17.0.txt +0 -38
  19. data/doc/release_notes/4.18.0.txt +0 -36
  20. data/doc/release_notes/4.19.0.txt +0 -45
  21. data/doc/release_notes/4.2.0.txt +0 -129
  22. data/doc/release_notes/4.20.0.txt +0 -79
  23. data/doc/release_notes/4.21.0.txt +0 -94
  24. data/doc/release_notes/4.22.0.txt +0 -72
  25. data/doc/release_notes/4.23.0.txt +0 -65
  26. data/doc/release_notes/4.24.0.txt +0 -99
  27. data/doc/release_notes/4.25.0.txt +0 -181
  28. data/doc/release_notes/4.26.0.txt +0 -44
  29. data/doc/release_notes/4.27.0.txt +0 -78
  30. data/doc/release_notes/4.28.0.txt +0 -57
  31. data/doc/release_notes/4.29.0.txt +0 -41
  32. data/doc/release_notes/4.3.0.txt +0 -40
  33. data/doc/release_notes/4.30.0.txt +0 -37
  34. data/doc/release_notes/4.31.0.txt +0 -57
  35. data/doc/release_notes/4.32.0.txt +0 -132
  36. data/doc/release_notes/4.33.0.txt +0 -88
  37. data/doc/release_notes/4.34.0.txt +0 -86
  38. data/doc/release_notes/4.35.0.txt +0 -130
  39. data/doc/release_notes/4.36.0.txt +0 -116
  40. data/doc/release_notes/4.37.0.txt +0 -50
  41. data/doc/release_notes/4.38.0.txt +0 -67
  42. data/doc/release_notes/4.39.0.txt +0 -127
  43. data/doc/release_notes/4.4.0.txt +0 -92
  44. data/doc/release_notes/4.40.0.txt +0 -179
  45. data/doc/release_notes/4.41.0.txt +0 -77
  46. data/doc/release_notes/4.42.0.txt +0 -221
  47. data/doc/release_notes/4.43.0.txt +0 -87
  48. data/doc/release_notes/4.44.0.txt +0 -125
  49. data/doc/release_notes/4.45.0.txt +0 -370
  50. data/doc/release_notes/4.46.0.txt +0 -404
  51. data/doc/release_notes/4.47.0.txt +0 -56
  52. data/doc/release_notes/4.48.0.txt +0 -293
  53. data/doc/release_notes/4.49.0.txt +0 -222
  54. data/doc/release_notes/4.5.0.txt +0 -34
  55. data/doc/release_notes/4.6.0.txt +0 -30
  56. data/doc/release_notes/4.7.0.txt +0 -103
  57. data/doc/release_notes/4.8.0.txt +0 -175
  58. data/doc/release_notes/4.9.0.txt +0 -190
  59. data/spec/adapter_spec.rb +0 -4
  60. data/spec/adapters/db2_spec.rb +0 -170
  61. data/spec/adapters/mssql_spec.rb +0 -828
  62. data/spec/adapters/mysql_spec.rb +0 -1060
  63. data/spec/adapters/oracle_spec.rb +0 -371
  64. data/spec/adapters/postgres_spec.rb +0 -4476
  65. data/spec/adapters/spec_helper.rb +0 -44
  66. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  67. data/spec/adapters/sqlite_spec.rb +0 -652
  68. data/spec/bin_spec.rb +0 -278
  69. data/spec/core/connection_pool_spec.rb +0 -1250
  70. data/spec/core/database_spec.rb +0 -2915
  71. data/spec/core/dataset_spec.rb +0 -5544
  72. data/spec/core/deprecated_spec.rb +0 -70
  73. data/spec/core/expression_filters_spec.rb +0 -1498
  74. data/spec/core/mock_adapter_spec.rb +0 -722
  75. data/spec/core/object_graph_spec.rb +0 -336
  76. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  77. data/spec/core/schema_generator_spec.rb +0 -214
  78. data/spec/core/schema_spec.rb +0 -1844
  79. data/spec/core/spec_helper.rb +0 -24
  80. data/spec/core/version_spec.rb +0 -14
  81. data/spec/core_extensions_spec.rb +0 -763
  82. data/spec/core_model_spec.rb +0 -2
  83. data/spec/core_spec.rb +0 -1
  84. data/spec/deprecation_helper.rb +0 -30
  85. data/spec/extensions/accessed_columns_spec.rb +0 -51
  86. data/spec/extensions/active_model_spec.rb +0 -99
  87. data/spec/extensions/after_initialize_spec.rb +0 -28
  88. data/spec/extensions/any_not_empty_spec.rb +0 -23
  89. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  90. data/spec/extensions/association_dependencies_spec.rb +0 -125
  91. data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
  92. data/spec/extensions/association_pks_spec.rb +0 -423
  93. data/spec/extensions/association_proxies_spec.rb +0 -100
  94. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  95. data/spec/extensions/auto_validations_spec.rb +0 -229
  96. data/spec/extensions/blacklist_security_spec.rb +0 -95
  97. data/spec/extensions/blank_spec.rb +0 -69
  98. data/spec/extensions/boolean_readers_spec.rb +0 -93
  99. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  100. data/spec/extensions/caching_spec.rb +0 -273
  101. data/spec/extensions/caller_logging_spec.rb +0 -52
  102. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  103. data/spec/extensions/column_conflicts_spec.rb +0 -75
  104. data/spec/extensions/column_select_spec.rb +0 -129
  105. data/spec/extensions/columns_introspection_spec.rb +0 -90
  106. data/spec/extensions/columns_updated_spec.rb +0 -35
  107. data/spec/extensions/composition_spec.rb +0 -248
  108. data/spec/extensions/connection_expiration_spec.rb +0 -151
  109. data/spec/extensions/connection_validator_spec.rb +0 -144
  110. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  111. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  112. data/spec/extensions/constraint_validations_spec.rb +0 -439
  113. data/spec/extensions/core_refinements_spec.rb +0 -528
  114. data/spec/extensions/csv_serializer_spec.rb +0 -183
  115. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  116. data/spec/extensions/dataset_associations_spec.rb +0 -365
  117. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  118. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  119. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  120. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  121. data/spec/extensions/defaults_setter_spec.rb +0 -150
  122. data/spec/extensions/delay_add_association_spec.rb +0 -73
  123. data/spec/extensions/dirty_spec.rb +0 -222
  124. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  125. data/spec/extensions/eager_each_spec.rb +0 -62
  126. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  127. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  128. data/spec/extensions/empty_failure_backtraces_spec.rb +0 -60
  129. data/spec/extensions/error_splitter_spec.rb +0 -18
  130. data/spec/extensions/error_sql_spec.rb +0 -20
  131. data/spec/extensions/escaped_like_spec.rb +0 -40
  132. data/spec/extensions/eval_inspect_spec.rb +0 -81
  133. data/spec/extensions/exclude_or_null_spec.rb +0 -15
  134. data/spec/extensions/finder_spec.rb +0 -260
  135. data/spec/extensions/force_encoding_spec.rb +0 -126
  136. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  137. data/spec/extensions/graph_each_spec.rb +0 -113
  138. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  139. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  140. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  141. data/spec/extensions/index_caching_spec.rb +0 -66
  142. data/spec/extensions/inflector_spec.rb +0 -183
  143. data/spec/extensions/input_transformer_spec.rb +0 -69
  144. data/spec/extensions/insert_conflict_spec.rb +0 -103
  145. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  146. data/spec/extensions/instance_filters_spec.rb +0 -79
  147. data/spec/extensions/instance_hooks_spec.rb +0 -246
  148. data/spec/extensions/integer64_spec.rb +0 -22
  149. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  150. data/spec/extensions/json_serializer_spec.rb +0 -346
  151. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  152. data/spec/extensions/list_spec.rb +0 -291
  153. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  154. data/spec/extensions/many_through_many_spec.rb +0 -2177
  155. data/spec/extensions/migration_spec.rb +0 -864
  156. data/spec/extensions/modification_detection_spec.rb +0 -93
  157. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  158. data/spec/extensions/named_timezones_spec.rb +0 -218
  159. data/spec/extensions/nested_attributes_spec.rb +0 -815
  160. data/spec/extensions/null_dataset_spec.rb +0 -85
  161. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  162. data/spec/extensions/pagination_spec.rb +0 -116
  163. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  164. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  165. data/spec/extensions/pg_array_spec.rb +0 -398
  166. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
  167. data/spec/extensions/pg_enum_spec.rb +0 -118
  168. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  169. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  170. data/spec/extensions/pg_hstore_spec.rb +0 -219
  171. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  172. data/spec/extensions/pg_inet_spec.rb +0 -72
  173. data/spec/extensions/pg_interval_spec.rb +0 -103
  174. data/spec/extensions/pg_json_ops_spec.rb +0 -356
  175. data/spec/extensions/pg_json_spec.rb +0 -451
  176. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  177. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  178. data/spec/extensions/pg_range_spec.rb +0 -600
  179. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  180. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  181. data/spec/extensions/pg_row_spec.rb +0 -363
  182. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  183. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  184. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  185. data/spec/extensions/prepared_statements_spec.rb +0 -177
  186. data/spec/extensions/pretty_table_spec.rb +0 -123
  187. data/spec/extensions/query_spec.rb +0 -94
  188. data/spec/extensions/rcte_tree_spec.rb +0 -387
  189. data/spec/extensions/round_timestamps_spec.rb +0 -39
  190. data/spec/extensions/s_spec.rb +0 -60
  191. data/spec/extensions/schema_caching_spec.rb +0 -64
  192. data/spec/extensions/schema_dumper_spec.rb +0 -870
  193. data/spec/extensions/select_remove_spec.rb +0 -38
  194. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  195. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  196. data/spec/extensions/serialization_spec.rb +0 -365
  197. data/spec/extensions/server_block_spec.rb +0 -135
  198. data/spec/extensions/server_logging_spec.rb +0 -45
  199. data/spec/extensions/sharding_spec.rb +0 -197
  200. data/spec/extensions/shared_caching_spec.rb +0 -151
  201. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  202. data/spec/extensions/singular_table_names_spec.rb +0 -22
  203. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  204. data/spec/extensions/spec_helper.rb +0 -70
  205. data/spec/extensions/split_array_nil_spec.rb +0 -24
  206. data/spec/extensions/split_values_spec.rb +0 -57
  207. data/spec/extensions/sql_comments_spec.rb +0 -33
  208. data/spec/extensions/sql_expr_spec.rb +0 -59
  209. data/spec/extensions/static_cache_cache_spec.rb +0 -35
  210. data/spec/extensions/static_cache_spec.rb +0 -471
  211. data/spec/extensions/string_agg_spec.rb +0 -90
  212. data/spec/extensions/string_date_time_spec.rb +0 -95
  213. data/spec/extensions/string_stripper_spec.rb +0 -68
  214. data/spec/extensions/subclasses_spec.rb +0 -79
  215. data/spec/extensions/subset_conditions_spec.rb +0 -38
  216. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  217. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  218. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  219. data/spec/extensions/table_select_spec.rb +0 -83
  220. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  221. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  222. data/spec/extensions/throw_failures_spec.rb +0 -74
  223. data/spec/extensions/timestamps_spec.rb +0 -209
  224. data/spec/extensions/to_dot_spec.rb +0 -153
  225. data/spec/extensions/touch_spec.rb +0 -226
  226. data/spec/extensions/tree_spec.rb +0 -334
  227. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  228. data/spec/extensions/unlimited_update_spec.rb +0 -21
  229. data/spec/extensions/update_or_create_spec.rb +0 -83
  230. data/spec/extensions/update_primary_key_spec.rb +0 -105
  231. data/spec/extensions/update_refresh_spec.rb +0 -59
  232. data/spec/extensions/uuid_spec.rb +0 -101
  233. data/spec/extensions/validate_associated_spec.rb +0 -52
  234. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  235. data/spec/extensions/validation_contexts_spec.rb +0 -31
  236. data/spec/extensions/validation_helpers_spec.rb +0 -525
  237. data/spec/extensions/whitelist_security_spec.rb +0 -157
  238. data/spec/extensions/xml_serializer_spec.rb +0 -213
  239. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  240. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  241. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  242. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  243. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  244. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  245. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  246. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  247. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  248. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  249. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  250. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  251. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  252. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  253. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  254. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  255. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  256. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  257. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  258. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  259. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  260. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  261. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  262. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  263. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  264. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  265. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  266. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  267. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  268. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  269. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  270. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  271. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  272. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  273. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  274. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  275. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  276. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  277. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  278. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  279. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  280. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  281. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  282. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  283. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  284. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  285. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  286. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  287. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  288. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  289. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  290. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  291. data/spec/guards_helper.rb +0 -59
  292. data/spec/integration/associations_test.rb +0 -2597
  293. data/spec/integration/database_test.rb +0 -113
  294. data/spec/integration/dataset_test.rb +0 -2037
  295. data/spec/integration/eager_loader_test.rb +0 -687
  296. data/spec/integration/migrator_test.rb +0 -262
  297. data/spec/integration/model_test.rb +0 -203
  298. data/spec/integration/plugin_test.rb +0 -2423
  299. data/spec/integration/prepared_statement_test.rb +0 -405
  300. data/spec/integration/schema_test.rb +0 -903
  301. data/spec/integration/spec_helper.rb +0 -71
  302. data/spec/integration/timezone_test.rb +0 -86
  303. data/spec/integration/transaction_test.rb +0 -603
  304. data/spec/integration/type_test.rb +0 -127
  305. data/spec/model/association_reflection_spec.rb +0 -803
  306. data/spec/model/associations_spec.rb +0 -4738
  307. data/spec/model/base_spec.rb +0 -875
  308. data/spec/model/class_dataset_methods_spec.rb +0 -146
  309. data/spec/model/dataset_methods_spec.rb +0 -198
  310. data/spec/model/eager_loading_spec.rb +0 -2377
  311. data/spec/model/hooks_spec.rb +0 -370
  312. data/spec/model/inflector_spec.rb +0 -26
  313. data/spec/model/model_spec.rb +0 -956
  314. data/spec/model/plugins_spec.rb +0 -429
  315. data/spec/model/record_spec.rb +0 -2118
  316. data/spec/model/spec_helper.rb +0 -46
  317. data/spec/model/validations_spec.rb +0 -220
  318. data/spec/model_no_assoc_spec.rb +0 -1
  319. data/spec/model_spec.rb +0 -1
  320. data/spec/plugin_spec.rb +0 -1
  321. data/spec/sequel_coverage.rb +0 -15
  322. data/spec/sequel_warning.rb +0 -5
  323. data/spec/spec_config.rb +0 -12
@@ -1,70 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "Sequel::Deprecated" do
4
- before do
5
- @d = Sequel::Deprecation
6
- @prev_prefix = @d.prefix
7
- @prev_output = @d.output
8
- @prev_backtrace_filter = @d.backtrace_filter
9
- @output = []
10
- def @output.puts(s)
11
- self << s
12
- end
13
- @d.prefix = false
14
- @d.output = @output
15
- @d.backtrace_filter = false
16
- end
17
- after do
18
- @d.prefix = @prev_prefix
19
- @d.output = @prev_output
20
- @d.backtrace_filter = @prev_backtrace_filter
21
- end
22
-
23
- it "should output full messages to the given output" do
24
- @d.deprecate("foo")
25
- @output.must_equal ['foo']
26
- end
27
-
28
- it "should consider two arguments to be a method name and additional text" do
29
- @d.deprecate("foo", "Use bar instead")
30
- @output.must_equal ['foo is deprecated and will be removed in Sequel 5.1. Use bar instead.']
31
- end
32
-
33
- it "should include a prefix if set" do
34
- @d.prefix = "DEPWARN: "
35
- @d.deprecate("foo")
36
- @output.must_equal ['DEPWARN: foo']
37
- end
38
-
39
- it "should not output anything if output is false" do
40
- @d.output = false
41
- @d.deprecate("foo")
42
- end
43
-
44
- it "should include full backtrace if backtrace_filter is true" do
45
- @d.backtrace_filter = true
46
- @d.deprecate("foo")
47
- @output.first.must_equal 'foo'
48
- (4..100).must_include(@output.count)
49
- end
50
-
51
- it "should include given lines of backtrace if backtrace_filter is an integer" do
52
- @d.backtrace_filter = 1
53
- @d.deprecate("foo")
54
- @output.first.must_equal 'foo'
55
- @output.count.must_equal 2
56
-
57
- @output.clear
58
- @d.backtrace_filter = 3
59
- @d.deprecate("foo")
60
- @output.first.must_equal 'foo'
61
- @output.count.must_equal 4
62
- end
63
-
64
- it "should select backtrace lines if backtrace_filter is a proc" do
65
- @d.backtrace_filter = lambda{|line, line_no| line_no < 3 && line =~ /./}
66
- @d.deprecate("foo")
67
- @output.first.must_equal 'foo'
68
- @output.count.must_equal 4
69
- end
70
- end
@@ -1,1498 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "Blockless Ruby Filters" do
4
- before do
5
- db = Sequel.mock
6
- @d = db[:items].with_extend do
7
- def l(*args, &block)
8
- literal(filter_expr(*args, &block))
9
- end
10
- def lit(*args)
11
- literal(*args)
12
- end
13
- end
14
- end
15
-
16
- it "should support boolean columns directly" do
17
- x = Sequel[:x]
18
- x.dup.must_be_same_as x
19
- x.clone.must_be_same_as x
20
- end
21
-
22
- it "should support boolean columns directly" do
23
- @d.l(:x).must_equal 'x'
24
- end
25
-
26
- with_symbol_splitting "should support qualified columns and aliased columns using symbols" do
27
- @d.l(:x__y).must_equal 'x.y'
28
- @d.l(:x___y).must_equal 'x AS y'
29
- @d.l(:x__y___z).must_equal 'x.y AS z'
30
- end
31
-
32
- with_symbol_splitting "should support qualified columns using virtual rows" do
33
- @d.l(Sequel.expr{x__y}).must_equal 'x.y'
34
- end
35
-
36
- it "should not split symbols or virtual row methods if symbol splitting is disabled" do
37
- @d.l(:x__y).must_equal 'x__y'
38
- @d.l(:x___y).must_equal 'x___y'
39
- @d.l(:x__y___z).must_equal 'x__y___z'
40
- @d.l(Sequel.expr{x__y}).must_equal 'x__y'
41
- end
42
-
43
- it "should support NOT with SQL functions" do
44
- @d.l(~Sequel.function(:is_blah)).must_equal 'NOT is_blah()'
45
- @d.l(~Sequel.function(:is_blah, :x)).must_equal 'NOT is_blah(x)'
46
- @d.l(~Sequel.function(:is_blah, Sequel[:x][:y])).must_equal 'NOT is_blah(x.y)'
47
- @d.l(~Sequel.function(:is_blah, :x, Sequel[:x][:y])).must_equal 'NOT is_blah(x, x.y)'
48
- end
49
-
50
- it "should handle multiple ~" do
51
- @d.l(~Sequel.~(:x)).must_equal 'x'
52
- @d.l(~~Sequel.~(:x)).must_equal 'NOT x'
53
- @d.l(~~Sequel.&(:x, :y)).must_equal '(x AND y)'
54
- @d.l(~~Sequel.|(:x, :y)).must_equal '(x OR y)'
55
- end
56
-
57
- it "should not modifying boolean expression created from array if array is modified" do
58
- a = [1]
59
- expr = Sequel.expr(:b=>a)
60
- @d.l(expr).must_equal '(b IN (1))'
61
- a << 2
62
- @d.l(expr).must_equal '(b IN (1))'
63
- end
64
-
65
- it "should not modifying boolean expression created from string if string is modified" do
66
- a = '1'.dup
67
- expr = Sequel.expr(:b=>a)
68
- @d.l(expr).must_equal "(b = '1')"
69
- a << '2'
70
- @d.l(expr).must_equal "(b = '1')"
71
- end
72
-
73
- it "should support = via Hash" do
74
- @d.l(:x => 100).must_equal '(x = 100)'
75
- @d.l(:x => 'a').must_equal '(x = \'a\')'
76
- @d.l(:x => true).must_equal '(x IS TRUE)'
77
- @d.l(:x => false).must_equal '(x IS FALSE)'
78
- @d.l(:x => nil).must_equal '(x IS NULL)'
79
- @d.l(:x => [1,2,3]).must_equal '(x IN (1, 2, 3))'
80
- end
81
-
82
- it "should use = 't' and != 't' OR IS NULL if IS TRUE is not supported" do
83
- @d = @d.with_extend{def supports_is_true?; false end}
84
- @d.l(:x => true).must_equal "(x = 't')"
85
- @d.l(~Sequel.expr(:x => true)).must_equal "((x != 't') OR (x IS NULL))"
86
- @d.l(:x => false).must_equal "(x = 'f')"
87
- @d.l(~Sequel.expr(:x => false)).must_equal "((x != 'f') OR (x IS NULL))"
88
- end
89
-
90
- it "should support != via inverted Hash" do
91
- @d.l(~Sequel.expr(:x => 100)).must_equal '(x != 100)'
92
- @d.l(~Sequel.expr(:x => 'a')).must_equal '(x != \'a\')'
93
- @d.l(~Sequel.expr(:x => true)).must_equal '(x IS NOT TRUE)'
94
- @d.l(~Sequel.expr(:x => false)).must_equal '(x IS NOT FALSE)'
95
- @d.l(~Sequel.expr(:x => nil)).must_equal '(x IS NOT NULL)'
96
- end
97
-
98
- it "should use NOT for inverting boolean expressions where right hand side is function or literal strings" do
99
- @d.l(~Sequel.expr(:x => Sequel.function(:any))).must_equal 'NOT (x = any())'
100
- @d.l(~Sequel.expr(:x => Sequel.lit('any()'))).must_equal 'NOT (x = any())'
101
- @d.l(~Sequel.expr(:x => Sequel.lit('any(?)', 1))).must_equal 'NOT (x = any(1))'
102
- end
103
-
104
- it "should support = and similar operations via =~ method" do
105
- @d.l{x =~ 100}.must_equal '(x = 100)'
106
- @d.l{x =~ 'a'}.must_equal '(x = \'a\')'
107
- @d.l{x =~ true}.must_equal '(x IS TRUE)'
108
- @d.l{x =~ false}.must_equal '(x IS FALSE)'
109
- @d.l{x =~ nil}.must_equal '(x IS NULL)'
110
- @d.l{x =~ (1...5)}.must_equal '((x >= 1) AND (x < 5))'
111
- @d.l{x =~ [1,2,3]}.must_equal '(x IN (1, 2, 3))'
112
-
113
- @d.l{(x + y) =~ 100}.must_equal '((x + y) = 100)'
114
- @d.l{(x + y) =~ 'a'}.must_equal '((x + y) = \'a\')'
115
- @d.l{(x + y) =~ true}.must_equal '((x + y) IS TRUE)'
116
- @d.l{(x + y) =~ false}.must_equal '((x + y) IS FALSE)'
117
- @d.l{(x + y) =~ nil}.must_equal '((x + y) IS NULL)'
118
- @d.l{(x + y) =~ (1...5)}.must_equal '(((x + y) >= 1) AND ((x + y) < 5))'
119
- @d.l{(x + y) =~ [1,2,3]}.must_equal '((x + y) IN (1, 2, 3))'
120
-
121
- @d = @d.with_extend{def supports_regexp?; true end}
122
- @d.l{x =~ /blah/}.must_equal '(x ~ \'blah\')'
123
- @d.l{(x + y) =~ /blah/}.must_equal '((x + y) ~ \'blah\')'
124
- end
125
-
126
- it "should support != and similar inversions via !~ method" do
127
- @d.l{x !~ 100}.must_equal '(x != 100)'
128
- @d.l{x !~ 'a'}.must_equal '(x != \'a\')'
129
- @d.l{x !~ true}.must_equal '(x IS NOT TRUE)'
130
- @d.l{x !~ false}.must_equal '(x IS NOT FALSE)'
131
- @d.l{x !~ nil}.must_equal '(x IS NOT NULL)'
132
- @d.l{x !~ (1...5)}.must_equal '((x < 1) OR (x >= 5))'
133
- @d.l{x !~ [1,2,3]}.must_equal '(x NOT IN (1, 2, 3))'
134
-
135
- @d.l{(x + y) !~ 100}.must_equal '((x + y) != 100)'
136
- @d.l{(x + y) !~ 'a'}.must_equal '((x + y) != \'a\')'
137
- @d.l{(x + y) !~ true}.must_equal '((x + y) IS NOT TRUE)'
138
- @d.l{(x + y) !~ false}.must_equal '((x + y) IS NOT FALSE)'
139
- @d.l{(x + y) !~ nil}.must_equal '((x + y) IS NOT NULL)'
140
- @d.l{(x + y) !~ (1...5)}.must_equal '(((x + y) < 1) OR ((x + y) >= 5))'
141
- @d.l{(x + y) !~ [1,2,3]}.must_equal '((x + y) NOT IN (1, 2, 3))'
142
-
143
- @d = @d.with_extend{def supports_regexp?; true end}
144
- @d.l{x !~ /blah/}.must_equal '(x !~ \'blah\')'
145
- @d.l{(x + y) !~ /blah/}.must_equal '((x + y) !~ \'blah\')'
146
- end
147
-
148
- it "should support ~ via Hash and Regexp (if supported by database)" do
149
- @d = @d.with_extend{def supports_regexp?; true end}
150
- @d.l(:x => /blah/).must_equal '(x ~ \'blah\')'
151
- end
152
-
153
- it "should support !~ via inverted Hash and Regexp" do
154
- @d = @d.with_extend{def supports_regexp?; true end}
155
- @d.l(~Sequel.expr(:x => /blah/)).must_equal '(x !~ \'blah\')'
156
- end
157
-
158
- it "should support negating ranges" do
159
- @d.l(~Sequel.expr(:x => 1..5)).must_equal '((x < 1) OR (x > 5))'
160
- @d.l(~Sequel.expr(:x => 1...5)).must_equal '((x < 1) OR (x >= 5))'
161
- end
162
-
163
- it "should support negating IN with Dataset or Array" do
164
- @d.l(~Sequel.expr(:x => @d.select(:i))).must_equal '(x NOT IN (SELECT i FROM items))'
165
- @d.l(~Sequel.expr(:x => [1,2,3])).must_equal '(x NOT IN (1, 2, 3))'
166
- end
167
-
168
- it "should not add ~ method to string expressions" do
169
- proc{~Sequel.expr(:x).sql_string}.must_raise(NoMethodError)
170
- end
171
-
172
- it "should only allow combining associative operators" do
173
- @d.lit(Sequel.expr{a + b + c}).must_equal '(a + b + c)'
174
- @d.lit(Sequel.expr{a - b - c}).must_equal '((a - b) - c)'
175
- @d.lit(Sequel.expr{a * b * c}).must_equal '(a * b * c)'
176
- @d.lit(Sequel.expr{a / b / c}).must_equal '((a / b) / c)'
177
- @d.lit(Sequel.expr{a & b & c}).must_equal '(a AND b AND c)'
178
- @d.lit(Sequel.expr{a | b | c}).must_equal '(a OR b OR c)'
179
- @d.lit(Sequel.expr{a.sql_string + b + c}).must_equal '(a || b || c)'
180
- @d.lit(Sequel.expr{a.sql_number >> b >> c}).must_equal '((a >> b) >> c)'
181
- @d.lit(Sequel.expr{a.sql_number << b << c}).must_equal '((a << b) << c)'
182
- @d.lit(Sequel.expr{a.sql_number % b % c}).must_equal '((a % b) % c)'
183
- @d.lit(Sequel.expr{a.sql_number & b & c}).must_equal '(a & b & c)'
184
- @d.lit(Sequel.expr{a.sql_number | b | c}).must_equal '(a | b | c)'
185
- end
186
-
187
- it "should allow mathematical or string operations on true, false, or nil" do
188
- @d.lit(Sequel.expr(:x) + 1).must_equal '(x + 1)'
189
- @d.lit(Sequel.expr(:x) - true).must_equal "(x - 't')"
190
- @d.lit(Sequel.expr(:x) / false).must_equal "(x / 'f')"
191
- @d.lit(Sequel.expr(:x) * nil).must_equal '(x * NULL)'
192
- @d.lit(Sequel.expr(:x) ** 1).must_equal 'power(x, 1)'
193
- @d.lit(Sequel.join([:x, nil])).must_equal '(x || NULL)'
194
- end
195
-
196
- it "should allow mathematical or string operations on boolean complex expressions" do
197
- @d.lit(Sequel.expr(:x) + (Sequel.expr(:y) + 1)).must_equal '(x + y + 1)'
198
- @d.lit(Sequel.expr(:x) - ~Sequel.expr(:y)).must_equal '(x - NOT y)'
199
- @d.lit(Sequel.expr(:x) / (Sequel.expr(:y) & :z)).must_equal '(x / (y AND z))'
200
- @d.lit(Sequel.expr(:x) * (Sequel.expr(:y) | :z)).must_equal '(x * (y OR z))'
201
- @d.lit(Sequel.expr(:x) + Sequel.expr(:y).like('a')).must_equal "(x + (y LIKE 'a' ESCAPE '\\'))"
202
- @d.lit(Sequel.expr(:x) - ~Sequel.expr(:y).like('a')).must_equal "(x - (y NOT LIKE 'a' ESCAPE '\\'))"
203
- @d.lit(Sequel.join([:x, ~Sequel.expr(:y).like('a')])).must_equal "(x || (y NOT LIKE 'a' ESCAPE '\\'))"
204
- @d.lit(Sequel.expr(:x) ** (Sequel.expr(:y) + 1)).must_equal 'power(x, (y + 1))'
205
- end
206
-
207
- it "should allow mathematical or string operations on numerics when argument is a generic or numeric expressions" do
208
- @d.lit(1 + Sequel.expr(:x)).must_equal '(1 + x)'
209
- @d.lit(2**65 - Sequel.+(:x, 1)).must_equal "(#{2**65} - (x + 1))"
210
- @d.lit(1.0 / Sequel.function(:x)).must_equal '(1.0 / x())'
211
- @d.lit(BigDecimal('1.0') * Sequel[:a][:y]).must_equal '(1.0 * a.y)'
212
- @d.lit(2 ** Sequel.cast(:x, Integer)).must_equal 'power(2, CAST(x AS integer))'
213
- @d.lit(1 + Sequel.lit('x')).must_equal '(1 + x)'
214
- @d.lit(1 + Sequel.lit('?', :x)).must_equal '(1 + x)'
215
- end
216
-
217
- it "should not break Date/DateTime equality" do
218
- (Date.today == Sequel.expr(:x)).must_equal false
219
- (DateTime.now == Sequel.expr(:x)).must_equal false
220
- end
221
-
222
- it "should have coerce return array if called on a non-numeric" do
223
- Sequel.expr(:x).coerce(:a).must_equal [Sequel.expr(:x), :a]
224
- end
225
-
226
- it "should support AND conditions via &" do
227
- @d.l(Sequel.expr(:x) & :y).must_equal '(x AND y)'
228
- @d.l(Sequel.expr(:x).sql_boolean & :y).must_equal '(x AND y)'
229
- @d.l(Sequel.expr(:x) & :y & :z).must_equal '(x AND y AND z)'
230
- @d.l(Sequel.expr(:x) & {:y => :z}).must_equal '(x AND (y = z))'
231
- @d.l((Sequel.expr(:x) + 200 < 0) & (Sequel.expr(:y) - 200 < 0)).must_equal '(((x + 200) < 0) AND ((y - 200) < 0))'
232
- @d.l(Sequel.expr(:x) & ~Sequel.expr(:y)).must_equal '(x AND NOT y)'
233
- @d.l(~Sequel.expr(:x) & :y).must_equal '(NOT x AND y)'
234
- @d.l(~Sequel.expr(:x) & ~Sequel.expr(:y)).must_equal '(NOT x AND NOT y)'
235
- end
236
-
237
- it "should support OR conditions via |" do
238
- @d.l(Sequel.expr(:x) | :y).must_equal '(x OR y)'
239
- @d.l(Sequel.expr(:x).sql_boolean | :y).must_equal '(x OR y)'
240
- @d.l(Sequel.expr(:x) | :y | :z).must_equal '(x OR y OR z)'
241
- @d.l(Sequel.expr(:x) | {:y => :z}).must_equal '(x OR (y = z))'
242
- @d.l((Sequel.expr(:x).sql_number > 200) | (Sequel.expr(:y).sql_number < 200)).must_equal '((x > 200) OR (y < 200))'
243
- end
244
-
245
- it "should support & | combinations" do
246
- @d.l((Sequel.expr(:x) | :y) & :z).must_equal '((x OR y) AND z)'
247
- @d.l(Sequel.expr(:x) | (Sequel.expr(:y) & :z)).must_equal '(x OR (y AND z))'
248
- @d.l((Sequel.expr(:x) & :w) | (Sequel.expr(:y) & :z)).must_equal '((x AND w) OR (y AND z))'
249
- end
250
-
251
- it "should support & | with ~" do
252
- @d.l(~((Sequel.expr(:x) | :y) & :z)).must_equal '((NOT x AND NOT y) OR NOT z)'
253
- @d.l(~(Sequel.expr(:x) | (Sequel.expr(:y) & :z))).must_equal '(NOT x AND (NOT y OR NOT z))'
254
- @d.l(~((Sequel.expr(:x) & :w) | (Sequel.expr(:y) & :z))).must_equal '((NOT x OR NOT w) AND (NOT y OR NOT z))'
255
- @d.l(~((Sequel.expr(:x).sql_number > 200) | (Sequel.expr(:y) & :z))).must_equal '((x <= 200) AND (NOT y OR NOT z))'
256
- end
257
-
258
- it "should support LiteralString" do
259
- @d.l(Sequel.lit('x')).must_equal '(x)'
260
- @d.l(~Sequel.lit('x')).must_equal 'NOT x'
261
- @d.l(~~Sequel.lit('x')).must_equal 'x'
262
- @d.l(~((Sequel.lit('x') | :y) & :z)).must_equal '((NOT x AND NOT y) OR NOT z)'
263
- @d.l(~(Sequel.expr(:x) | Sequel.lit('y'))).must_equal '(NOT x AND NOT y)'
264
- @d.l(~(Sequel.lit('x') & Sequel.lit('y'))).must_equal '(NOT x OR NOT y)'
265
- @d.l(Sequel.expr(Sequel.lit('y') => Sequel.lit('z')) & Sequel.lit('x')).must_equal '((y = z) AND x)'
266
- @d.l((Sequel.lit('x') > 200) & (Sequel.lit('y') < 200)).must_equal '((x > 200) AND (y < 200))'
267
- @d.l(~(Sequel.lit('x') + 1 > 100)).must_equal '((x + 1) <= 100)'
268
- @d.l(Sequel.lit('x').like('a')).must_equal '(x LIKE \'a\' ESCAPE \'\\\')'
269
- @d.l(Sequel.lit('x') + 1 > 100).must_equal '((x + 1) > 100)'
270
- @d.l((Sequel.lit('x') * :y) < 100.01).must_equal '((x * y) < 100.01)'
271
- @d.l((Sequel.lit('x') ** :y) < 100.01).must_equal '(power(x, y) < 100.01)'
272
- @d.l((Sequel.lit('x') - Sequel.expr(:y)/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
273
- @d.l((Sequel.lit('z') * ((Sequel.lit('x') / :y)/(Sequel.expr(:x) + :y))) <= 100).must_equal '((z * ((x / y) / (x + y))) <= 100)'
274
- @d.l(~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
275
- end
276
-
277
- it "should have LiteralString#inspect show it is a literal string" do
278
- Sequel.lit('x').inspect.must_equal "#<Sequel::LiteralString \"x\">"
279
- end
280
-
281
- it "should support hashes by ANDing the conditions" do
282
- @d.l(:x => 100, :y => 'a')[1...-1].split(' AND ').sort.must_equal ['(x = 100)', '(y = \'a\')']
283
- @d.l(:x => true, :y => false)[1...-1].split(' AND ').sort.must_equal ['(x IS TRUE)', '(y IS FALSE)']
284
- @d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.must_equal ['(x IS NULL)', '(y IN (1, 2, 3))']
285
- end
286
-
287
- it "should support arrays with all two pairs the same as hashes" do
288
- @d.l([[:x, 100],[:y, 'a']]).must_equal '((x = 100) AND (y = \'a\'))'
289
- @d.l([[:x, true], [:y, false]]).must_equal '((x IS TRUE) AND (y IS FALSE))'
290
- @d.l([[:x, nil], [:y, [1,2,3]]]).must_equal '((x IS NULL) AND (y IN (1, 2, 3)))'
291
- end
292
-
293
- it "should emulate columns for array values" do
294
- @d.l([:x, :y]=>Sequel.value_list([[1,2], [3,4]])).must_equal '((x, y) IN ((1, 2), (3, 4)))'
295
- @d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).must_equal '((x, y, z) IN ((1, 2, 5), (3, 4, 6)))'
296
- end
297
-
298
- it "should emulate multiple column in if not supported" do
299
- @d = @d.with_extend{def supports_multiple_column_in?; false end}
300
- @d.l([:x, :y]=>Sequel.value_list([[1,2], [3,4]])).must_equal '(((x = 1) AND (y = 2)) OR ((x = 3) AND (y = 4)))'
301
- @d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).must_equal '(((x = 1) AND (y = 2) AND (z = 5)) OR ((x = 3) AND (y = 4) AND (z = 6)))'
302
- end
303
-
304
- it "should have SQL::ValueList#inspect show it is a value list" do
305
- Sequel.value_list([[1,2], [3,4]]).inspect.must_equal "#<Sequel::SQL::ValueList [[1, 2], [3, 4]]>"
306
- end
307
-
308
- it "should support StringExpression#+ for concatenation of SQL strings" do
309
- @d.lit(Sequel.expr(:x).sql_string + :y).must_equal '(x || y)'
310
- @d.lit(Sequel.join([:x]) + :y).must_equal '(x || y)'
311
- @d.lit(Sequel.join([:x, :z], ' ') + :y).must_equal "(x || ' ' || z || y)"
312
- end
313
-
314
- it "should be supported inside blocks" do
315
- @d.l{Sequel.or([[:x, nil], [:y, [1,2,3]]])}.must_equal '((x IS NULL) OR (y IN (1, 2, 3)))'
316
- @d.l{Sequel.~([[:x, nil], [:y, [1,2,3]]])}.must_equal '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
317
- @d.l{~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)}.must_equal '((((x - y) / (x + y)) * z) > 100)'
318
- @d.l{Sequel.&({:x => :a}, {:y => :z})}.must_equal '((x = a) AND (y = z))'
319
- end
320
-
321
- it "should support &, |, ^, ~, <<, and >> for NumericExpressions" do
322
- @d.l(Sequel.expr(:x).sql_number & 1 > 100).must_equal '((x & 1) > 100)'
323
- @d.l(Sequel.expr(:x).sql_number | 1 > 100).must_equal '((x | 1) > 100)'
324
- @d.l(Sequel.expr(:x).sql_number ^ 1 > 100).must_equal '((x ^ 1) > 100)'
325
- @d.l(~Sequel.expr(:x).sql_number > 100).must_equal '(~x > 100)'
326
- @d.l(Sequel.expr(:x).sql_number << 1 > 100).must_equal '((x << 1) > 100)'
327
- @d.l(Sequel.expr(:x).sql_number >> 1 > 100).must_equal '((x >> 1) > 100)'
328
- @d.l((Sequel.expr(:x) + 1) & 1 > 100).must_equal '(((x + 1) & 1) > 100)'
329
- @d.l((Sequel.expr(:x) + 1) | 1 > 100).must_equal '(((x + 1) | 1) > 100)'
330
- @d.l((Sequel.expr(:x) + 1) ^ 1 > 100).must_equal '(((x + 1) ^ 1) > 100)'
331
- @d.l(~(Sequel.expr(:x) + 1) > 100).must_equal '(~(x + 1) > 100)'
332
- @d.l((Sequel.expr(:x) + 1) << 1 > 100).must_equal '(((x + 1) << 1) > 100)'
333
- @d.l((Sequel.expr(:x) + 1) >> 1 > 100).must_equal '(((x + 1) >> 1) > 100)'
334
- @d.l((Sequel.expr(:x) + 1) & (Sequel.expr(:x) + 2) > 100).must_equal '(((x + 1) & (x + 2)) > 100)'
335
- end
336
-
337
- it "should allow using a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
338
- @d.lit((Sequel.expr(:x) + 1) & (Sequel.expr(:x) + '2')).must_equal "((x + 1) & (x || '2'))"
339
- end
340
-
341
- it "should allow using a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
342
- @d.l(Sequel.expr(:x) & (Sequel.expr(:x) + '2')).must_equal "(x AND (x || '2'))"
343
- end
344
-
345
- it "should raise an error if attempting to invert a ComplexExpression that isn't a BooleanExpression" do
346
- proc{Sequel::SQL::BooleanExpression.invert(Sequel.expr(:x) + 2)}.must_raise(Sequel::Error)
347
- end
348
-
349
- it "should support SQL::Constants" do
350
- @d.l({:x => Sequel::NULL}).must_equal '(x IS NULL)'
351
- @d.l({:x => Sequel::NOTNULL}).must_equal '(x IS NOT NULL)'
352
- @d.l({:x => Sequel::TRUE}).must_equal '(x IS TRUE)'
353
- @d.l({:x => Sequel::FALSE}).must_equal '(x IS FALSE)'
354
- @d.l({:x => Sequel::SQLTRUE}).must_equal '(x IS TRUE)'
355
- @d.l({:x => Sequel::SQLFALSE}).must_equal '(x IS FALSE)'
356
-
357
- @d.l({:x => Sequel::CURRENT_DATE}).must_equal '(x = CURRENT_DATE)'
358
- @d.l({:x => Sequel::CURRENT_TIME}).must_equal '(x = CURRENT_TIME)'
359
- @d.l({:x => Sequel::CURRENT_TIMESTAMP}).must_equal '(x = CURRENT_TIMESTAMP)'
360
- @d.l({:x => Sequel::DEFAULT}).must_equal '(x = DEFAULT)'
361
- end
362
-
363
- it "should support negation of SQL::Constants" do
364
- @d.l(Sequel.~(:x => Sequel::NULL)).must_equal '(x IS NOT NULL)'
365
- @d.l(Sequel.~(:x => Sequel::NOTNULL)).must_equal '(x IS NULL)'
366
- @d.l(Sequel.~(:x => Sequel::TRUE)).must_equal '(x IS NOT TRUE)'
367
- @d.l(Sequel.~(:x => Sequel::FALSE)).must_equal '(x IS NOT FALSE)'
368
- @d.l(Sequel.~(:x => Sequel::SQLTRUE)).must_equal '(x IS NOT TRUE)'
369
- @d.l(Sequel.~(:x => Sequel::SQLFALSE)).must_equal '(x IS NOT FALSE)'
370
- end
371
-
372
- it "should support direct negation of SQL::Constants" do
373
- @d.l({:x => ~Sequel::NULL}).must_equal '(x IS NOT NULL)'
374
- @d.l({:x => ~Sequel::NOTNULL}).must_equal '(x IS NULL)'
375
- @d.l({:x => ~Sequel::TRUE}).must_equal '(x IS FALSE)'
376
- @d.l({:x => ~Sequel::FALSE}).must_equal '(x IS TRUE)'
377
- @d.l({:x => ~Sequel::SQLTRUE}).must_equal '(x IS FALSE)'
378
- @d.l({:x => ~Sequel::SQLFALSE}).must_equal '(x IS TRUE)'
379
- end
380
-
381
- it "should raise an error if trying to invert an invalid SQL::Constant" do
382
- proc{~Sequel::CURRENT_DATE}.must_raise(Sequel::Error)
383
- end
384
-
385
- it "should raise an error if trying to create an invalid complex expression" do
386
- proc{Sequel::SQL::ComplexExpression.new(:BANG, 1, 2)}.must_raise(Sequel::Error)
387
- end
388
-
389
- it "should use a string concatentation for + if given a string" do
390
- @d.lit(Sequel.expr(:x) + '1').must_equal "(x || '1')"
391
- @d.lit(Sequel.expr(:x) + '1' + '1').must_equal "(x || '1' || '1')"
392
- end
393
-
394
- it "should use an addition for + if given a literal string" do
395
- @d.lit(Sequel.expr(:x) + Sequel.lit('1')).must_equal "(x + 1)"
396
- @d.lit(Sequel.expr(:x) + Sequel.lit('1') + Sequel.lit('1')).must_equal "(x + 1 + 1)"
397
- end
398
-
399
- it "should use a bitwise operator for & and | if given an integer" do
400
- @d.lit(Sequel.expr(:x) & 1).must_equal "(x & 1)"
401
- @d.lit(Sequel.expr(:x) | 1).must_equal "(x | 1)"
402
- @d.lit(Sequel.expr(:x) & 1 & 1).must_equal "(x & 1 & 1)"
403
- @d.lit(Sequel.expr(:x) | 1 | 1).must_equal "(x | 1 | 1)"
404
- end
405
-
406
- it "should allow adding a string to an integer expression" do
407
- @d.lit(Sequel.expr(:x) + 1 + 'a').must_equal "(x + 1 + 'a')"
408
- end
409
-
410
- it "should allow adding an integer to an string expression" do
411
- @d.lit(Sequel.expr(:x) + 'a' + 1).must_equal "(x || 'a' || 1)"
412
- end
413
-
414
- it "should allow adding a boolean to an integer expression" do
415
- @d.lit(Sequel.expr(:x) + 1 + true).must_equal "(x + 1 + 't')"
416
- end
417
-
418
- it "should allow adding a boolean to an string expression" do
419
- @d.lit(Sequel.expr(:x) + 'a' + true).must_equal "(x || 'a' || 't')"
420
- end
421
-
422
- it "should allow using a boolean operation with an integer on an boolean expression" do
423
- @d.lit(Sequel.expr(:x) & :a & 1).must_equal "(x AND a AND 1)"
424
- end
425
-
426
- it "should allow using a boolean operation with a string on an boolean expression" do
427
- @d.lit(Sequel.expr(:x) & :a & 'a').must_equal "(x AND a AND 'a')"
428
- end
429
-
430
- it "should allowing AND of boolean expression and literal string" do
431
- @d.lit(Sequel.expr(:x) & :a & Sequel.lit('a')).must_equal "(x AND a AND a)"
432
- end
433
-
434
- it "should allowing + of integer expression and literal string" do
435
- @d.lit(Sequel.expr(:x) + :a + Sequel.lit('a')).must_equal "(x + a + a)"
436
- end
437
-
438
- it "should allowing + of string expression and literal string" do
439
- @d.lit(Sequel.expr(:x) + 'a' + Sequel.lit('a')).must_equal "(x || 'a' || a)"
440
- end
441
-
442
- it "should allow sql_{string,boolean,number} methods on numeric expressions" do
443
- @d.lit((Sequel.expr(:x) + 1).sql_string + 'a').must_equal "((x + 1) || 'a')"
444
- @d.lit((Sequel.expr(:x) + 1).sql_boolean & 1).must_equal "((x + 1) AND 1)"
445
- @d.lit((Sequel.expr(:x) + 1).sql_number + 'a').must_equal "(x + 1 + 'a')"
446
- end
447
-
448
- it "should allow sql_{string,boolean,number} methods on string expressions" do
449
- @d.lit((Sequel.expr(:x) + 'a').sql_string + 'a').must_equal "(x || 'a' || 'a')"
450
- @d.lit((Sequel.expr(:x) + 'a').sql_boolean & 1).must_equal "((x || 'a') AND 1)"
451
- @d.lit((Sequel.expr(:x) + 'a').sql_number + 'a').must_equal "((x || 'a') + 'a')"
452
- end
453
-
454
- it "should allow sql_{string,boolean,number} methods on boolean expressions" do
455
- @d.lit((Sequel.expr(:x) & :y).sql_string + 'a').must_equal "((x AND y) || 'a')"
456
- @d.lit((Sequel.expr(:x) & :y).sql_boolean & 1).must_equal "(x AND y AND 1)"
457
- @d.lit((Sequel.expr(:x) & :y).sql_number + 'a').must_equal "((x AND y) + 'a')"
458
- end
459
-
460
- it "should raise an error if trying to literalize an invalid complex expression" do
461
- ce = Sequel::SQL::ComplexExpression.allocate
462
- ce.instance_eval do
463
- @op = :BANG
464
- @args = [:x, 1]
465
- end
466
- proc{@d.lit(ce)}.must_raise(Sequel::InvalidOperation)
467
- end
468
-
469
- it "should support equality comparison of two expressions" do
470
- e1 = ~Sequel.like(:comment, '%:hidden:%')
471
- e2 = ~Sequel.like(:comment, '%:hidden:%')
472
- e1.must_equal e2
473
- end
474
-
475
- it "should support expression filter methods on Datasets" do
476
- d = @d.select(:a)
477
-
478
- @d.lit(d + 1).must_equal '((SELECT a FROM items) + 1)'
479
- @d.lit(d - 1).must_equal '((SELECT a FROM items) - 1)'
480
- @d.lit(d * 1).must_equal '((SELECT a FROM items) * 1)'
481
- @d.lit(d / 1).must_equal '((SELECT a FROM items) / 1)'
482
- @d.lit(d ** 1).must_equal 'power((SELECT a FROM items), 1)'
483
-
484
- @d.lit(d => 1).must_equal '((SELECT a FROM items) = 1)'
485
- @d.lit(Sequel.~(d => 1)).must_equal '((SELECT a FROM items) != 1)'
486
- @d.lit(d > 1).must_equal '((SELECT a FROM items) > 1)'
487
- @d.lit(d < 1).must_equal '((SELECT a FROM items) < 1)'
488
- @d.lit(d >= 1).must_equal '((SELECT a FROM items) >= 1)'
489
- @d.lit(d <= 1).must_equal '((SELECT a FROM items) <= 1)'
490
-
491
- @d.lit(d.as(:b)).must_equal '(SELECT a FROM items) AS b'
492
-
493
- @d.lit(d & :b).must_equal '((SELECT a FROM items) AND b)'
494
- @d.lit(d | :b).must_equal '((SELECT a FROM items) OR b)'
495
- @d.lit(~d).must_equal 'NOT (SELECT a FROM items)'
496
-
497
- @d.lit(d.cast(Integer)).must_equal 'CAST((SELECT a FROM items) AS integer)'
498
- @d.lit(d.cast_numeric).must_equal 'CAST((SELECT a FROM items) AS integer)'
499
- @d.lit(d.cast_string).must_equal 'CAST((SELECT a FROM items) AS varchar(255))'
500
- @d.lit(d.cast_numeric << :b).must_equal '(CAST((SELECT a FROM items) AS integer) << b)'
501
- @d.lit(d.cast_string + :b).must_equal '(CAST((SELECT a FROM items) AS varchar(255)) || b)'
502
-
503
- @d.lit(d.extract(:year)).must_equal 'extract(year FROM (SELECT a FROM items))'
504
- @d.lit(d.sql_boolean & :b).must_equal '((SELECT a FROM items) AND b)'
505
- @d.lit(d.sql_number << :b).must_equal '((SELECT a FROM items) << b)'
506
- @d.lit(d.sql_string + :b).must_equal '((SELECT a FROM items) || b)'
507
-
508
- @d.lit(d.asc).must_equal '(SELECT a FROM items) ASC'
509
- @d.lit(d.desc).must_equal '(SELECT a FROM items) DESC'
510
-
511
- @d.lit(d.like(:b)).must_equal '((SELECT a FROM items) LIKE b ESCAPE \'\\\')'
512
- @d.lit(d.ilike(:b)).must_equal '(UPPER((SELECT a FROM items)) LIKE UPPER(b) ESCAPE \'\\\')'
513
- end
514
-
515
- it "should handled emulated char_length function" do
516
- @d.lit(Sequel.char_length(:a)).must_equal 'char_length(a)'
517
- end
518
-
519
- it "should handled emulated trim function" do
520
- @d.lit(Sequel.trim(:a)).must_equal 'trim(a)'
521
- end
522
-
523
- it "should handled emulated function where only name is emulated" do
524
- ds = Sequel.mock[:a]
525
- ds.literal(Sequel.trim(:a)).must_equal 'trim(a)'
526
- ds.with_extend{def native_function_name(f) 'foo' end}.literal(Sequel.trim(:a)).must_equal 'foo(a)'
527
- end
528
-
529
- it "should handled emulated function needing full emulation" do
530
- dsc = Class.new(Sequel::Dataset) do
531
- def emulate_function?(n) n == :trim end
532
- def emulate_function_sql_append(sql, f)
533
- sql << "#{f.name}FOO(lower(#{f.args.first}))"
534
- end
535
- end
536
- dsc.new(@d.db).literal(Sequel.trim(:a)).must_equal 'trimFOO(lower(a))'
537
- end
538
-
539
- it "should handle endless ranges" do
540
- endless = eval('(1..)')
541
- @d.l{x =~ endless}.must_equal '(x >= 1)'
542
- @d.l(:x => endless).must_equal '(x >= 1)'
543
-
544
- endless = eval('(1...)')
545
- @d.l{x =~ endless}.must_equal '(x >= 1)'
546
- @d.l(:x => endless).must_equal '(x >= 1)'
547
- end if RUBY_VERSION >= '2.6'
548
-
549
- it "should handle startless ranges" do
550
- endless = eval('(..1)')
551
- @d.l{x =~ endless}.must_equal '(x <= 1)'
552
- @d.l(:x => endless).must_equal '(x <= 1)'
553
-
554
- endless = eval('(...1)')
555
- @d.l{x =~ endless}.must_equal '(x < 1)'
556
- @d.l(:x => endless).must_equal '(x < 1)'
557
- end if RUBY_VERSION >= '2.7'
558
-
559
- it "should handle startless, endless ranges" do
560
- endless = eval('nil..nil')
561
- @d.l{x =~ endless}.must_equal '(1 = 1)'
562
- @d.l(:x => endless).must_equal '(1 = 1)'
563
-
564
- endless = eval('nil...nil')
565
- @d.l{x =~ endless}.must_equal '(1 = 1)'
566
- @d.l(:x => endless).must_equal '(1 = 1)'
567
- end if RUBY_VERSION >= '2.7'
568
- end
569
-
570
- describe Sequel::SQL::VirtualRow do
571
- before do
572
- @d = Sequel.mock[:items].with_quote_identifiers(true).with_extend do
573
- def supports_window_functions?; true end
574
- def l(*args, &block)
575
- literal(filter_expr(*args, &block))
576
- end
577
- end
578
- end
579
-
580
- it "should treat methods without arguments as identifiers" do
581
- @d.l{column}.must_equal '"column"'
582
- end
583
-
584
- with_symbol_splitting "should treat methods without arguments that have embedded double underscores as qualified identifiers" do
585
- @d.l{table__column}.must_equal '"table"."column"'
586
- end
587
-
588
- it "should treat methods with arguments as functions with the arguments" do
589
- @d.l{function(arg1, 10, 'arg3')}.must_equal 'function("arg1", 10, \'arg3\')'
590
- end
591
-
592
-
593
- it "should treat methods followed by function as a function call with no arguments" do
594
- @d.l{version.function}.must_equal 'version()'
595
- end
596
-
597
- it "should treat methods followed by function.* as a function call with * argument" do
598
- @d.l{count.function.*}.must_equal 'count(*)'
599
- end
600
-
601
- it "should support * method on functions to raise error if function already has an argument" do
602
- proc{@d.l{count(1).*}}.must_raise(Sequel::Error)
603
- end
604
-
605
- it "should support * method on functions to use * as the argument" do
606
- @d.l{count.function.*}.must_equal 'count(*)'
607
- @d.literal(Sequel.expr{sum(1) * 2}).must_equal '(sum(1) * 2)'
608
- end
609
-
610
- it "should support distinct methods on functions to use DISTINCT before the arguments" do
611
- @d.l{count(column1).distinct}.must_equal 'count(DISTINCT "column1")'
612
- @d.l{count(column1, column2).distinct}.must_equal 'count(DISTINCT "column1", "column2")'
613
- end
614
-
615
- it "should handle method.function.over as a window function call" do
616
- @d.l{rank.function.over}.must_equal 'rank() OVER ()'
617
- end
618
-
619
- it "should handle method.function.over(:partition) as a window function call" do
620
- @d.l{rank.function.over(:partition=>column1)}.must_equal 'rank() OVER (PARTITION BY "column1")'
621
- @d.l{rank.function.over(:partition=>[column1, column2])}.must_equal 'rank() OVER (PARTITION BY "column1", "column2")'
622
- end
623
-
624
- it "should handle method(arg).over options as a window function call" do
625
- @d.l{avg(column1).over}.must_equal 'avg("column1") OVER ()'
626
- @d.l{avg(column1, column2).over}.must_equal 'avg("column1", "column2") OVER ()'
627
- end
628
-
629
- it "should handle method.function.over(:order) as a window function call" do
630
- @d.l{rank.function.over(:order=>column1)}.must_equal 'rank() OVER (ORDER BY "column1")'
631
- @d.l{rank.function.over(:order=>[column1, column2])}.must_equal 'rank() OVER (ORDER BY "column1", "column2")'
632
- end
633
-
634
- it "should handle method.function.over(:window) as a window function call" do
635
- @d.l{rank.function.over(:window=>:win)}.must_equal 'rank() OVER ("win")'
636
- end
637
-
638
- it "should handle method.function.*.over as a window function call" do
639
- @d.l{count.function.*.over}.must_equal 'count(*) OVER ()'
640
- end
641
-
642
- it "should handle method.function.over(:frame=>:all) as a window function call with frame for all rows" do
643
- @d.l{rank.function.over(:frame=>:all)}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
644
- end
645
-
646
- it "should handle method.function.over(:frame=>:rows) as a window function call with frame for all rows before current row" do
647
- @d.l{rank.function.over(:frame=>:rows)}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
648
- end
649
-
650
- it "should handle method.function.over(:frame=>:groups) as a window function call with frame for all groups before current row" do
651
- @d.l{rank.function.over(:frame=>:groups)}.must_equal 'rank() OVER (GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
652
- end
653
-
654
- it "should handle method.function.over(:frame=>:range) as a window function call with frame for all groups before current row" do
655
- @d.l{rank.function.over(:frame=>:range)}.must_equal 'rank() OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
656
- end
657
-
658
- it "should handle window function with :frame hash argument with :type option" do
659
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
660
- @d.l{rank.function.over(:frame=>{:type=>:range, :start=>:preceding})}.must_equal 'rank() OVER (RANGE UNBOUNDED PRECEDING)'
661
- @d.l{rank.function.over(:frame=>{:type=>:groups, :start=>:preceding})}.must_equal 'rank() OVER (GROUPS UNBOUNDED PRECEDING)'
662
- end
663
-
664
- it "should handle window function with :frame hash argument with :start option" do
665
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
666
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:following})}.must_equal 'rank() OVER (ROWS UNBOUNDED FOLLOWING)'
667
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:current})}.must_equal 'rank() OVER (ROWS CURRENT ROW)'
668
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>1})}.must_equal 'rank() OVER (ROWS 1 PRECEDING)'
669
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>[1, :following]})}.must_equal 'rank() OVER (ROWS 1 FOLLOWING)'
670
- end
671
-
672
- it "should handle window function with :frame hash argument with :end option" do
673
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>:preceding})}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED PRECEDING)'
674
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>:following})}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
675
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>:current})}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
676
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>1})}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING)'
677
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>[1, :preceding]})}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)'
678
- end
679
-
680
- it "should handle window function with :frame hash argument with :exclude option" do
681
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding,:exclude=>:current})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING EXCLUDE CURRENT ROW)'
682
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :exclude=>:group})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING EXCLUDE GROUP)'
683
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :exclude=>:ties})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING EXCLUDE TIES)'
684
- @d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :exclude=>:no_others})}.must_equal 'rank() OVER (ROWS UNBOUNDED PRECEDING EXCLUDE NO OTHERS)'
685
- end
686
-
687
- it "should handle window function with :frame hash argument with invalid options" do
688
- proc{@d.l{rank.function.over(:frame=>{:type=>:blah, :start=>:preceding})}}.must_raise Sequel::Error
689
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows})}}.must_raise Sequel::Error
690
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:blah})}}.must_raise Sequel::Error
691
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>[1, :blah]})}}.must_raise Sequel::Error
692
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>[1, :preceding, 3]})}}.must_raise Sequel::Error
693
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>:blah})}}.must_raise Sequel::Error
694
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>[1, :blah]})}}.must_raise Sequel::Error
695
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :end=>[1, :following, 3]})}}.must_raise Sequel::Error
696
- proc{@d.l{rank.function.over(:frame=>{:type=>:rows, :start=>:preceding, :exclude=>:blah})}}.must_raise Sequel::Error
697
- end
698
-
699
- it "should handle method.function.over(:frame=>'some string') as a window function call with explicit frame" do
700
- @d.l{rank.function.over(:frame=>'RANGE BETWEEN 3 PRECEDING AND CURRENT ROW')}.must_equal 'rank() OVER (RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)'
701
- end
702
-
703
- it "should support window functions options" do
704
- @d.supports_window_function_frame_option?(:rows).must_equal true
705
- @d.supports_window_function_frame_option?(:range).must_equal true
706
- @d.supports_window_function_frame_option?(:groups).must_equal false
707
- @d.supports_window_function_frame_option?(:offset).must_equal true
708
- @d.supports_window_function_frame_option?(:exclude).must_equal false
709
- end
710
-
711
- it "should raise an error if an invalid :frame option is used" do
712
- proc{@d.l{rank.function.over(:frame=>:blah)}}.must_raise(Sequel::Error)
713
- end
714
-
715
- it "should support all over options together" do
716
- @d.l{count.function.*.over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}.must_equal 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
717
- end
718
-
719
- it "should support order method on functions to specify orders for aggregate functions" do
720
- @d.l{rank(:c).order(:a, :b)}.must_equal 'rank("c" ORDER BY "a", "b")'
721
- end
722
-
723
- it "should support over method on functions to create window functions" do
724
- @d.l{sum(c).over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}.must_equal 'sum("c") OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
725
- end
726
-
727
- it "should support over method with a Window argument" do
728
- @d.l{sum(c).over(Sequel::SQL::Window.new(:partition=>a, :order=>b, :window=>:win, :frame=>:rows))}.must_equal 'sum("c") OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
729
- end
730
-
731
- it "should raise error if over is called on a function that already has a window " do
732
- proc{@d.l{rank.function.over.over}}.must_raise(Sequel::Error)
733
- end
734
-
735
- it "should raise an error if window functions are not supported" do
736
- proc{@d.with_extend{def supports_window_functions?; false end}.l{count.function.*.over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}}.must_raise(Sequel::Error)
737
- proc{Sequel.mock.dataset.filter{count.function.*.over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}.sql}.must_raise(Sequel::Error)
738
- end
739
-
740
- it "should handle lateral function calls" do
741
- @d.l{rank.function.lateral}.must_equal 'LATERAL rank()'
742
- end
743
-
744
- it "should handle ordered-set and hypothetical-set function calls" do
745
- @d.l{mode.function.within_group(:a)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a")'
746
- @d.l{mode.function.within_group(:a, :b)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a", "b")'
747
- end
748
-
749
- it "should handle emualted filtered aggregate function calls" do
750
- @d.l{count.function.*.filter(Sequel.&(:a, :b))}.must_equal 'count((CASE WHEN ("a" AND "b") THEN 1 ELSE NULL END))'
751
- @d.l{count.function.*.filter(:a=>1)}.must_equal 'count((CASE WHEN ("a" = 1) THEN 1 ELSE NULL END))'
752
- @d.l{count(:a).filter{b > 1}}.must_equal 'count((CASE WHEN ("b" > 1) THEN "a" ELSE NULL END))'
753
- @d.l{count(:a).filter(:a=>1){b > 1}}.must_equal 'count((CASE WHEN (("a" = 1) AND ("b" > 1)) THEN "a" ELSE NULL END))'
754
- end
755
-
756
- it "should handle filtered aggregate function calls" do
757
- @d = @d.with_extend{def supports_filtered_aggregates?; true end}
758
- @d.l{count.function.*.filter(Sequel.&(:a, :b))}.must_equal 'count(*) FILTER (WHERE ("a" AND "b"))'
759
- @d.l{count.function.*.filter(:a=>1)}.must_equal 'count(*) FILTER (WHERE ("a" = 1))'
760
- @d.l{count.function.*.filter{b > 1}}.must_equal 'count(*) FILTER (WHERE ("b" > 1))'
761
- @d.l{count.function.*.filter(:a=>1){b > 1}}.must_equal 'count(*) FILTER (WHERE (("a" = 1) AND ("b" > 1)))'
762
- end
763
-
764
- it "should handle filtered ordered-set and hypothetical-set function calls" do
765
- @d = @d.with_extend{def supports_filtered_aggregates?; true end}
766
- @d.l{mode.function.within_group(:a).filter(:a=>1)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a") FILTER (WHERE ("a" = 1))'
767
- end
768
-
769
- it "should handle function calls with ordinality" do
770
- @d.l{foo.function.with_ordinality}.must_equal 'foo() WITH ORDINALITY'
771
- end
772
-
773
- it "should support function method on identifiers to create functions" do
774
- @d.l{rank.function}.must_equal 'rank()'
775
- @d.l{sum.function(c)}.must_equal 'sum("c")'
776
- @d.l{sum.function(c, 1)}.must_equal 'sum("c", 1)'
777
- end
778
-
779
- with_symbol_splitting "should support function method on foo__bar methods to create functions" do
780
- @d.l{sch__rank.function}.must_equal 'sch.rank()'
781
- @d.l{sch__sum.function(c)}.must_equal 'sch.sum("c")'
782
- @d.l{sch__sum.function(c, 1)}.must_equal 'sch.sum("c", 1)'
783
- @d.l{Sequel.qualify(sch[:sum], x[:y]).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
784
- end
785
-
786
- it "should support function method on qualified identifiers to create functions" do
787
- @d.l{sch[rank].function}.must_equal 'sch.rank()'
788
- @d.l{sch[sum].function(c)}.must_equal 'sch.sum("c")'
789
- @d.l{sch[sum].function(c, 1)}.must_equal 'sch.sum("c", 1)'
790
- @d.l{Sequel.qualify(sch[:sum], x[:y]).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
791
- end
792
-
793
- with_symbol_splitting "should support function method on qualified identifiers to create functions" do
794
- @d.l{Sequel.qualify(sch__sum, :x__y).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
795
- end
796
-
797
- it "should not quote function names created from identifiers by default" do
798
- @d = @d.with_extend{def supports_quoted_function_names?; true end}
799
- @d.l{rank.function}.must_equal 'rank()'
800
- end
801
-
802
- with_symbol_splitting "should handle quoted function names when using double underscores" do
803
- @d = @d.with_extend{def supports_quoted_function_names?; true end}
804
- @d.l{sch__rank.function}.must_equal '"sch"."rank"()'
805
- end
806
-
807
- it "should quote function names if a quoted function is used and database supports quoted function names" do
808
- @d = @d.with_extend{def supports_quoted_function_names?; true end}
809
- @d.l{rank(1).quoted}.must_equal '"rank"(1)'
810
- @d.l{rank.function.quoted}.must_equal '"rank"()'
811
- @d.l{sch__rank(1).quoted}.must_equal '"sch__rank"(1)'
812
- end
813
-
814
- it "should not quote function names created from qualified identifiers if an unquoted function is used" do
815
- @d = @d.with_extend{def supports_quoted_function_names?; true end}
816
- @d.l{sch[rank].function.unquoted}.must_equal 'sch.rank()'
817
- end
818
-
819
- it "should deal with classes without requiring :: prefix" do
820
- @d.l{date < Date.today}.must_equal "(\"date\" < '#{Date.today}')"
821
- @d.l{date < Sequel::CURRENT_DATE}.must_equal "(\"date\" < CURRENT_DATE)"
822
- @d.l{num < Math::PI.to_i}.must_equal "(\"num\" < 3)"
823
- end
824
-
825
- it "should have operator methods defined that produce Sequel expression objects" do
826
- @d.l{|o| o.&({:a=>1}, :b)}.must_equal '(("a" = 1) AND "b")'
827
- @d.l{|o| o.|({:a=>1}, :b)}.must_equal '(("a" = 1) OR "b")'
828
- @d.l{|o| o.+(1, :b) > 2}.must_equal '((1 + "b") > 2)'
829
- @d.l{|o| o.-(1, :b) < 2}.must_equal '((1 - "b") < 2)'
830
- @d.l{|o| o.*(1, :b) >= 2}.must_equal '((1 * "b") >= 2)'
831
- @d.l{|o| o.**(1, :b) >= 2}.must_equal '(power(1, "b") >= 2)'
832
- @d.l{|o| o./(1, :b) <= 2}.must_equal '((1 / "b") <= 2)'
833
- @d.l{|o| o.~(:a=>1)}.must_equal '("a" != 1)'
834
- @d.l{|o| o.~([[:a, 1], [:b, 2]])}.must_equal '(("a" != 1) OR ("b" != 2))'
835
- @d.l{|o| o.<(1, :b)}.must_equal '(1 < "b")'
836
- @d.l{|o| o.>(1, :b)}.must_equal '(1 > "b")'
837
- @d.l{|o| o.<=(1, :b)}.must_equal '(1 <= "b")'
838
- @d.l{|o| o.>=(1, :b)}.must_equal '(1 >= "b")'
839
- end
840
- end
841
-
842
- describe "Sequel core extension replacements" do
843
- before do
844
- @db = Sequel.mock
845
- @ds = @db.dataset.with_extend{def supports_regexp?; true end}
846
- @o = Object.new
847
- def @o.sql_literal(ds) 'foo' end
848
- end
849
-
850
- def l(arg, should)
851
- @ds.literal(arg).must_equal should
852
- end
853
-
854
- it "Sequel.expr should return items wrapped in Sequel objects" do
855
- Sequel.expr(1).must_be_kind_of(Sequel::SQL::NumericExpression)
856
- Sequel.expr('a').must_be_kind_of(Sequel::SQL::StringExpression)
857
- Sequel.expr(true).must_be_kind_of(Sequel::SQL::BooleanExpression)
858
- Sequel.expr(nil).must_be_kind_of(Sequel::SQL::Wrapper)
859
- Sequel.expr({1=>2}).must_be_kind_of(Sequel::SQL::BooleanExpression)
860
- Sequel.expr([[1, 2]]).must_be_kind_of(Sequel::SQL::BooleanExpression)
861
- Sequel.expr([1]).must_be_kind_of(Sequel::SQL::Wrapper)
862
- Sequel.expr{|o| o.a}.must_be_kind_of(Sequel::SQL::Identifier)
863
- Sequel.expr{a}.must_be_kind_of(Sequel::SQL::Identifier)
864
- Sequel.expr(:a).must_be_kind_of(Sequel::SQL::Identifier)
865
- end
866
-
867
- with_symbol_splitting "Sequel.expr should return items wrapped in Sequel objects for splittable symbols" do
868
- Sequel.expr(:a__b).must_be_kind_of(Sequel::SQL::QualifiedIdentifier)
869
- Sequel.expr(:a___c).must_be_kind_of(Sequel::SQL::AliasedExpression)
870
- Sequel.expr(:a___c).expression.must_be_kind_of(Sequel::SQL::Identifier)
871
- Sequel.expr(:a__b___c).must_be_kind_of(Sequel::SQL::AliasedExpression)
872
- Sequel.expr(:a__b___c).expression.must_be_kind_of(Sequel::SQL::QualifiedIdentifier)
873
- end
874
-
875
- it "Sequel.expr should return an appropriate wrapped object" do
876
- l(Sequel.expr(1) + 1, "(1 + 1)")
877
- l(Sequel.expr('a') + 'b', "('a' || 'b')")
878
- l(Sequel.expr(:b) & nil, "(b AND NULL)")
879
- l(Sequel.expr(nil) & true, "(NULL AND 't')")
880
- l(Sequel.expr(false) & true, "('f' AND 't')")
881
- l(Sequel.expr(true) | false, "('t' OR 'f')")
882
- l(Sequel.expr(@o) + 1, "(foo + 1)")
883
- end
884
-
885
- it "Sequel.expr should handle condition specifiers" do
886
- l(Sequel.expr(:a=>1) & nil, "((a = 1) AND NULL)")
887
- l(Sequel.expr([[:a, 1]]) & nil, "((a = 1) AND NULL)")
888
- l(Sequel.expr([[:a, 1], [:b, 2]]) & nil, "((a = 1) AND (b = 2) AND NULL)")
889
- end
890
-
891
- it "Sequel.expr should handle arrays that are not condition specifiers" do
892
- l(Sequel.expr([1]), "(1)")
893
- l(Sequel.expr([1, 2]), "(1, 2)")
894
- end
895
-
896
- it "Sequel.expr should treat blocks/procs as virtual rows and wrap the output" do
897
- l(Sequel.expr{1} + 1, "(1 + 1)")
898
- l(Sequel.expr{o[a]} + 1, "(o.a + 1)")
899
- l(Sequel.expr{[[:a, 1]]} & nil, "((a = 1) AND NULL)")
900
- l(Sequel.expr{|v| @o} + 1, "(foo + 1)")
901
-
902
- l(Sequel.expr(proc{1}) + 1, "(1 + 1)")
903
- l(Sequel.expr(proc{o[a]}) + 1, "(o.a + 1)")
904
- l(Sequel.expr(proc{[[:a, 1]]}) & nil, "((a = 1) AND NULL)")
905
- l(Sequel.expr(proc{|v| @o}) + 1, "(foo + 1)")
906
- end
907
-
908
- it "Sequel.expr should handle lambda proc virtual rows" do
909
- l(Sequel.expr(&lambda{1}), "1")
910
- l(Sequel.expr(&lambda{|| 1}), "1")
911
- end
912
-
913
- it "Sequel.expr should raise an error if given an argument and a block" do
914
- proc{Sequel.expr(nil){}}.must_raise(Sequel::Error)
915
- end
916
-
917
- it "Sequel.expr should raise an error if given neither an argument nor a block" do
918
- proc{Sequel.expr}.must_raise(Sequel::Error)
919
- end
920
-
921
- it "Sequel.expr should return existing Sequel expressions directly" do
922
- o = Sequel.expr(1)
923
- Sequel.expr(o).must_be_same_as(o)
924
- o = Sequel.lit('1')
925
- Sequel.expr(o).must_be_same_as(o)
926
- end
927
-
928
- it "Sequel.~ should invert the given object" do
929
- l(Sequel.~(nil), 'NOT NULL')
930
- l(Sequel.~(:a=>1), "(a != 1)")
931
- l(Sequel.~([[:a, 1]]), "(a != 1)")
932
- l(Sequel.~([[:a, 1], [:b, 2]]), "((a != 1) OR (b != 2))")
933
- l(Sequel.~(Sequel.expr([[:a, 1], [:b, 2]]) & nil), "((a != 1) OR (b != 2) OR NOT NULL)")
934
- end
935
-
936
- it "Sequel.case should use a CASE expression" do
937
- l(Sequel.case({:a=>1}, 2), "(CASE WHEN a THEN 1 ELSE 2 END)")
938
- l(Sequel.case({:a=>1}, 2, :b), "(CASE b WHEN a THEN 1 ELSE 2 END)")
939
- l(Sequel.case([[:a, 1]], 2), "(CASE WHEN a THEN 1 ELSE 2 END)")
940
- l(Sequel.case([[:a, 1]], 2, :b), "(CASE b WHEN a THEN 1 ELSE 2 END)")
941
- l(Sequel.case([[:a, 1], [:c, 3]], 2), "(CASE WHEN a THEN 1 WHEN c THEN 3 ELSE 2 END)")
942
- l(Sequel.case([[:a, 1], [:c, 3]], 2, :b), "(CASE b WHEN a THEN 1 WHEN c THEN 3 ELSE 2 END)")
943
- end
944
-
945
- it "Sequel.case should raise an error if not given a condition specifier" do
946
- proc{Sequel.case(1, 2)}.must_raise(Sequel::Error)
947
- end
948
-
949
- it "Sequel.value_list should use an SQL value list" do
950
- l(Sequel.value_list([[1, 2]]), "((1, 2))")
951
- end
952
-
953
- it "Sequel.value_list raise an error if not given an array" do
954
- proc{Sequel.value_list(1)}.must_raise(Sequel::Error)
955
- end
956
-
957
- it "Sequel.negate should negate all entries in conditions specifier and join with AND" do
958
- l(Sequel.negate(:a=>1), "(a != 1)")
959
- l(Sequel.negate([[:a, 1]]), "(a != 1)")
960
- l(Sequel.negate([[:a, 1], [:b, 2]]), "((a != 1) AND (b != 2))")
961
- end
962
-
963
- it "Sequel.negate should raise an error if not given a conditions specifier" do
964
- proc{Sequel.negate(1)}.must_raise(Sequel::Error)
965
- end
966
-
967
- it "Sequel.or should join all entries in conditions specifier with OR" do
968
- l(Sequel.or(:a=>1), "(a = 1)")
969
- l(Sequel.or([[:a, 1]]), "(a = 1)")
970
- l(Sequel.or([[:a, 1], [:b, 2]]), "((a = 1) OR (b = 2))")
971
- end
972
-
973
- it "Sequel.or should raise an error if not given a conditions specifier" do
974
- proc{Sequel.or(1)}.must_raise(Sequel::Error)
975
- end
976
-
977
- it "Sequel.join should should use SQL string concatenation to join array" do
978
- l(Sequel.join([]), "''")
979
- l(Sequel.join(['a']), "('a')")
980
- l(Sequel.join(['a', 'b']), "('a' || 'b')")
981
- l(Sequel.join(['a', 'b'], 'c'), "('a' || 'c' || 'b')")
982
- l(Sequel.join([true, :b], :c), "('t' || c || b)")
983
- l(Sequel.join([false, nil], Sequel.lit('c')), "('f' || c || NULL)")
984
- l(Sequel.join([Sequel.expr('a'), Sequel.lit('d')], 'c'), "('a' || 'c' || d)")
985
- end
986
-
987
- it "Sequel.join should raise an error if not given an array" do
988
- proc{Sequel.join(1)}.must_raise(Sequel::Error)
989
- end
990
-
991
- it "Sequel.& should join all arguments given with AND" do
992
- l(Sequel.&(:a), "a")
993
- l(Sequel.&(:a, :b=>:c), "(a AND (b = c))")
994
- l(Sequel.&(:a, {:b=>:c}, Sequel.lit('d')), "(a AND (b = c) AND d)")
995
- end
996
-
997
- it "Sequel.& should raise an error if given no arguments" do
998
- proc{Sequel.&}.must_raise(Sequel::Error)
999
- end
1000
-
1001
- it "Sequel.| should join all arguments given with OR" do
1002
- l(Sequel.|(:a), "a")
1003
- l(Sequel.|(:a, :b=>:c), "(a OR (b = c))")
1004
- l(Sequel.|(:a, {:b=>:c}, Sequel.lit('d')), "(a OR (b = c) OR d)")
1005
- end
1006
-
1007
- it "Sequel.| should raise an error if given no arguments" do
1008
- proc{Sequel.|}.must_raise(Sequel::Error)
1009
- end
1010
-
1011
- it "Sequel.as should return an aliased expression" do
1012
- l(Sequel.as(:a, :b), "a AS b")
1013
- end
1014
-
1015
- it "Sequel.cast should return a CAST expression" do
1016
- l(Sequel.cast(:a, :int), "CAST(a AS int)")
1017
- l(Sequel.cast(:a, Integer), "CAST(a AS integer)")
1018
- end
1019
-
1020
- it "Sequel.cast_numeric should return a CAST expression treated as a number" do
1021
- l(Sequel.cast_numeric(:a), "CAST(a AS integer)")
1022
- l(Sequel.cast_numeric(:a, :int), "CAST(a AS int)")
1023
- l(Sequel.cast_numeric(:a) << 2, "(CAST(a AS integer) << 2)")
1024
- end
1025
-
1026
- it "Sequel.cast_string should return a CAST expression treated as a string" do
1027
- l(Sequel.cast_string(:a), "CAST(a AS varchar(255))")
1028
- l(Sequel.cast_string(:a, :text), "CAST(a AS text)")
1029
- l(Sequel.cast_string(:a) + 'a', "(CAST(a AS varchar(255)) || 'a')")
1030
- end
1031
-
1032
- it "Sequel.lit should return a literal string" do
1033
- l(Sequel.lit('a'), "a")
1034
- end
1035
-
1036
- it "Sequel.lit should return the argument if given a single literal string" do
1037
- o = Sequel.lit('a')
1038
- Sequel.lit(o).must_be_same_as(o)
1039
- end
1040
-
1041
- it "Sequel.lit should accept multiple arguments for a placeholder literal string" do
1042
- l(Sequel.lit('a = ?', 1), "a = 1")
1043
- l(Sequel.lit('? = ?', :a, 1), "a = 1")
1044
- l(Sequel.lit('a = :a', :a=>1), "a = 1")
1045
- end
1046
-
1047
- it "Sequel.lit should work with an array for the placeholder string" do
1048
- l(Sequel.lit(['a = '], 1), "a = 1")
1049
- l(Sequel.lit(['', ' = '], :a, 1), "a = 1")
1050
- end
1051
-
1052
- it "Sequel.blob should return an SQL::Blob" do
1053
- l(Sequel.blob('a'), "'a'")
1054
- Sequel.blob('a').must_be_kind_of(Sequel::SQL::Blob)
1055
- end
1056
-
1057
- it "Sequel.blob should return the given argument if given a blob" do
1058
- o = Sequel.blob('a')
1059
- Sequel.blob(o).must_be_same_as(o)
1060
- end
1061
-
1062
- it "Sequel.blob#inspect output should indicate it is a blob and the size" do
1063
- o = Sequel.blob('a')
1064
- o.inspect.must_equal "#<Sequel::SQL::Blob:0x#{'%x' % o.object_id} bytes=1 content=\"a\">"
1065
- o = Sequel.blob(('a'..'z').to_a.join)
1066
- o.inspect.must_equal "#<Sequel::SQL::Blob:0x#{'%x' % o.object_id} bytes=26 start=\"abcdefghij\" end=\"qrstuvwxyz\">"
1067
- o = Sequel.blob(255.chr)
1068
- o.inspect.must_equal "#<Sequel::SQL::Blob:0x#{'%x' % o.object_id} bytes=1 content=\"\\xFF\">"
1069
- o = Sequel.blob((230..255).map(&:chr).join)
1070
- o.inspect.must_equal "#<Sequel::SQL::Blob:0x#{'%x' % o.object_id} bytes=26 start=\"\\xE6\\xE7\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF\" end=\"\\xF6\\xF7\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF\">"
1071
- end
1072
-
1073
- it "Sequel.deep_qualify should do a deep qualification into nested structors" do
1074
- l(Sequel.deep_qualify(:t, Sequel.+(:c, 1)), "(t.c + 1)")
1075
- end
1076
-
1077
- it "Sequel.qualify should return a qualified identifier" do
1078
- l(Sequel.qualify(:t, :c), "t.c")
1079
- end
1080
-
1081
- it "Sequel::SQL::Identifier#[] should return a qualified identifier" do
1082
- l(Sequel[:t][:c], "t.c")
1083
- end
1084
-
1085
- it "Sequel::SQL::QualifiedIdentifier#[] should return a nested qualified identifier" do
1086
- l(Sequel[:s][:t][:c], "s.t.c")
1087
- end
1088
-
1089
- it "Sequel.identifier should return an identifier" do
1090
- l(Sequel.identifier(:t__c), "t__c")
1091
- end
1092
-
1093
- it "Sequel.asc should return an ASC ordered expression" do
1094
- l(Sequel.asc(:a), "a ASC")
1095
- l(Sequel.asc(:a, :nulls=>:first), "a ASC NULLS FIRST")
1096
- end
1097
-
1098
- it "Sequel.desc should return a DESC ordered expression " do
1099
- l(Sequel.desc(:a), "a DESC")
1100
- l(Sequel.desc(:a, :nulls=>:last), "a DESC NULLS LAST")
1101
- end
1102
-
1103
- it "Sequel.{+,-,*,/} should accept arguments and use the appropriate operator" do
1104
- %w'+ - * /'.each do |op|
1105
- l(Sequel.send(op, 1), '1')
1106
- l(Sequel.send(op, 1, 2), "(1 #{op} 2)")
1107
- l(Sequel.send(op, 1, 2, 3), "(1 #{op} 2 #{op} 3)")
1108
- end
1109
- end
1110
-
1111
- it "Sequel.{+,-,*,/} should raise if given no arguments" do
1112
- %w'+ - * /'.each do |op|
1113
- proc{Sequel.send(op)}.must_raise(Sequel::Error)
1114
- end
1115
- end
1116
-
1117
- it "Sequel.** should use power function if given 2 arguments" do
1118
- l(Sequel.**(1, 2), 'power(1, 2)')
1119
- end
1120
-
1121
- it "Sequel.** should raise if not given 2 arguments" do
1122
- proc{Sequel.**}.must_raise(ArgumentError)
1123
- proc{Sequel.**(1)}.must_raise(ArgumentError)
1124
- proc{Sequel.**(1, 2, 3)}.must_raise(ArgumentError)
1125
- end
1126
-
1127
- it "Sequel.like should use a LIKE expression" do
1128
- l(Sequel.like('a', 'b'), "('a' LIKE 'b' ESCAPE '\\')")
1129
- l(Sequel.like(:a, :b), "(a LIKE b ESCAPE '\\')")
1130
- l(Sequel.like(:a, /b/), "(a ~ 'b')")
1131
- l(Sequel.like(:a, 'c', /b/), "((a LIKE 'c' ESCAPE '\\') OR (a ~ 'b'))")
1132
- end
1133
-
1134
- it "Sequel.ilike should use an ILIKE expression" do
1135
- l(Sequel.ilike('a', 'b'), "(UPPER('a') LIKE UPPER('b') ESCAPE '\\')")
1136
- l(Sequel.ilike(:a, :b), "(UPPER(a) LIKE UPPER(b) ESCAPE '\\')")
1137
- l(Sequel.ilike(:a, /b/), "(a ~* 'b')")
1138
- l(Sequel.ilike(:a, 'c', /b/), "((UPPER(a) LIKE UPPER('c') ESCAPE '\\') OR (a ~* 'b'))")
1139
- end
1140
-
1141
- it "Sequel.subscript should use an SQL subscript" do
1142
- l(Sequel.subscript(:a, 1), 'a[1]')
1143
- l(Sequel.subscript(:a, 1, 2), 'a[1, 2]')
1144
- l(Sequel.subscript(:a, [1, 2]), 'a[1, 2]')
1145
- l(Sequel.subscript(:a, 1..2), 'a[1:2]')
1146
- l(Sequel.subscript(:a, 1...3), 'a[1:2]')
1147
- end
1148
-
1149
- it "Sequel.subscript.f should be subscript expression for backwards compatibility" do
1150
- Sequel.subscript(:a, 1).f.must_equal :a
1151
- end
1152
-
1153
- it "Sequel.function should return an SQL function" do
1154
- l(Sequel.function(:a), 'a()')
1155
- l(Sequel.function(:a, 1), 'a(1)')
1156
- l(Sequel.function(:a, :b, 2), 'a(b, 2)')
1157
- end
1158
-
1159
- it "Sequel.extract should use a date/time extraction" do
1160
- l(Sequel.extract(:year, :a), 'extract(year FROM a)')
1161
- end
1162
-
1163
- it "#* with no arguments should use a ColumnAll for Identifier and QualifiedIdentifier" do
1164
- l(Sequel.expr(:a).*, 'a.*')
1165
- l(Sequel[:a][:b].*, 'a.b.*')
1166
- end
1167
-
1168
- it "SQL::Blob should be aliasable and castable by default" do
1169
- b = Sequel.blob('a')
1170
- l(b.as(:a), "'a' AS a")
1171
- l(b.cast(Integer), "CAST('a' AS integer)")
1172
- end
1173
-
1174
- it "SQL::Blob should be convertable to a literal string by default" do
1175
- b = Sequel.blob('a ?')
1176
- l(b.lit, "a ?")
1177
- l(b.lit(1), "a 1")
1178
- end
1179
- end
1180
-
1181
- describe "Sequel::SQL::Function#==" do
1182
- it "should be true for functions with the same name and arguments, false otherwise" do
1183
- a = Sequel.function(:date, :t)
1184
- b = Sequel.function(:date, :t)
1185
- a.must_equal b
1186
- (a == b).must_equal true
1187
- c = Sequel.function(:date, :c)
1188
- a.wont_equal c
1189
- (a == c).must_equal false
1190
- d = Sequel.function(:time, :c)
1191
- a.wont_equal d
1192
- c.wont_equal d
1193
- (a == d).must_equal false
1194
- (c == d).must_equal false
1195
- end
1196
- end
1197
-
1198
- describe "Sequel::SQL::OrderedExpression" do
1199
- it "should #desc" do
1200
- @oe = Sequel.asc(:column)
1201
- @oe.descending.must_equal false
1202
- @oe.desc.descending.must_equal true
1203
- end
1204
-
1205
- it "should #asc" do
1206
- @oe = Sequel.desc(:column)
1207
- @oe.descending.must_equal true
1208
- @oe.asc.descending.must_equal false
1209
- end
1210
-
1211
- it "should #invert" do
1212
- @oe = Sequel.desc(:column)
1213
- @oe.invert.descending.must_equal false
1214
- @oe.invert.invert.descending.must_equal true
1215
- end
1216
- end
1217
-
1218
- describe "Expression" do
1219
- it "should consider objects == only if they have the same attributes" do
1220
- Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.must_equal Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
1221
- Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.wont_equal Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
1222
-
1223
- Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.must_equal(Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc)
1224
- Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.wont_equal(Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc)
1225
- end
1226
-
1227
- it "should use the same hash value for objects that have the same attributes" do
1228
- Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash.must_equal Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash
1229
- Sequel.qualify(:table, :other_column).cast(:type).*(:numeric_column).asc.hash.wont_equal Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc.hash
1230
-
1231
- h = {}
1232
- a = Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
1233
- b = Sequel.qualify(:table, :column).cast(:type).*(:numeric_column).asc
1234
- h[a] = 1
1235
- h[b] = 2
1236
- h[a].must_equal 2
1237
- h[b].must_equal 2
1238
- end
1239
- end
1240
-
1241
- describe "Sequel::SQLTime" do
1242
- before do
1243
- @db = Sequel.mock
1244
- end
1245
- after do
1246
- Sequel::application_timezone = Sequel::SQLTime.date = nil
1247
- end
1248
-
1249
- it ".create should create from hour, minutes, seconds and optional microseconds" do
1250
- @db.literal(Sequel::SQLTime.create(1, 2, 3)).must_equal "'01:02:03.000000'"
1251
- @db.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).must_equal "'01:02:03.500000'"
1252
- end
1253
-
1254
- it ".create should use utc is that is the application_timezone setting" do
1255
- Sequel::SQLTime.create(1, 2, 3).utc?.must_equal false
1256
- Sequel::application_timezone = :local
1257
- Sequel::SQLTime.create(1, 2, 3).utc?.must_equal false
1258
- Sequel::application_timezone = :utc
1259
- Sequel::SQLTime.create(1, 2, 3).utc?.must_equal true
1260
- end
1261
-
1262
- it ".create should use today's date by default" do
1263
- Sequel::SQLTime.create(1, 2, 3).strftime('%Y-%m-%d').must_equal Date.today.strftime('%Y-%m-%d')
1264
- end
1265
-
1266
- it ".create should use specific date if set" do
1267
- Sequel::SQLTime.date = Date.new(2000)
1268
- Sequel::SQLTime.create(1, 2, 3).strftime('%Y-%m-%d').must_equal Date.new(2000).strftime('%Y-%m-%d')
1269
- end
1270
-
1271
- it ".parse should respect SQLTime.date setting" do
1272
- Sequel::SQLTime.date = Date.new(2000, 2, 3)
1273
- Sequel::SQLTime.parse('10:11:12').strftime('%F').must_equal "2000-02-03"
1274
- end
1275
-
1276
- it ".parse should respect application_timezone setting" do
1277
- Sequel::application_timezone = :utc
1278
- Sequel::SQLTime.parse('10:11:12').utc_offset.must_equal 0
1279
- end
1280
-
1281
- it "#inspect should show class and time by default" do
1282
- Sequel::SQLTime.create(1, 2, 3).inspect.must_equal "#<Sequel::SQLTime 01:02:03>"
1283
- Sequel::SQLTime.create(13, 24, 35).inspect.must_equal "#<Sequel::SQLTime 13:24:35>"
1284
- end
1285
-
1286
- it "#to_s should include hour, minute, and second by default" do
1287
- Sequel::SQLTime.create(1, 2, 3).to_s.must_equal "01:02:03"
1288
- Sequel::SQLTime.create(1, 2, 3, 500000).to_s.must_equal "01:02:03"
1289
- end
1290
-
1291
- it "#to_s should handle arguments with super" do
1292
- t = Sequel::SQLTime.create(1, 2, 3)
1293
- begin
1294
- Time.now.to_s('%F')
1295
- rescue
1296
- proc{t.to_s('%F')}.must_raise ArgumentError
1297
- else
1298
- t.to_s('%F')
1299
- end
1300
- end
1301
- end
1302
-
1303
- describe "Sequel::SQL::Wrapper" do
1304
- before do
1305
- @ds = Sequel.mock.dataset
1306
- end
1307
-
1308
- it "should wrap objects so they can be used by the Sequel DSL" do
1309
- o = Object.new
1310
- def o.sql_literal(ds) 'foo' end
1311
- s = Sequel::SQL::Wrapper.new(o)
1312
- @ds.literal(s).must_equal "foo"
1313
- @ds.literal(s+1).must_equal "(foo + 1)"
1314
- @ds.literal(s**1).must_equal "power(foo, 1)"
1315
- @ds.literal(s & true).must_equal "(foo AND 't')"
1316
- @ds.literal(s < 1).must_equal "(foo < 1)"
1317
- @ds.literal(s.sql_subscript(1)).must_equal "(foo)[1]"
1318
- @ds.literal(s.like('a')).must_equal "(foo LIKE 'a' ESCAPE '\\')"
1319
- @ds.literal(s.as(:a)).must_equal "foo AS a"
1320
- @ds.literal(s.cast(Integer)).must_equal "CAST(foo AS integer)"
1321
- @ds.literal(s.desc).must_equal "foo DESC"
1322
- @ds.literal(s.sql_string + '1').must_equal "(foo || '1')"
1323
- end
1324
- end
1325
-
1326
- describe "Sequel::SQL::Blob" do
1327
- it ".call should be an alias for .new" do
1328
- Sequel::SQL::Blob.call('a').must_equal Sequel::SQL::Blob.new('a')
1329
- end
1330
-
1331
- it "#to_sequel_blob should return self" do
1332
- c = Sequel::SQL::Blob.new('a')
1333
- c.to_sequel_blob.must_be_same_as(c)
1334
- end
1335
- end
1336
-
1337
- describe Sequel::SQL::Subscript do
1338
- before do
1339
- @s = Sequel::SQL::Subscript.new(:a, [1])
1340
- @ds = Sequel.mock.dataset
1341
- end
1342
-
1343
- it "should have | return a new non-nested subscript" do
1344
- s = (@s | 2)
1345
- @ds.literal(s).must_equal 'a[1, 2]'
1346
- end
1347
-
1348
- it "should have [] return a new nested subscript" do
1349
- s = @s[2]
1350
- @ds.literal(s).must_equal 'a[1][2]'
1351
- end
1352
-
1353
- it "should not wrap identifiers in parentheses" do
1354
- @ds.literal(Sequel::SQL::Subscript.new(:a, [1])).must_equal 'a[1]'
1355
- @ds.literal(Sequel::SQL::Subscript.new(Sequel[:a], [1])).must_equal 'a[1]'
1356
- @ds.literal(Sequel::SQL::Subscript.new(Sequel[:a][:b], [1])).must_equal 'a.b[1]'
1357
- end
1358
-
1359
- it "should wrap other expression types in parentheses" do
1360
- @ds.literal(Sequel::SQL::Subscript.new(Sequel.function('a'), [1])).must_equal '(a())[1]'
1361
- @ds.literal(Sequel::SQL::Subscript.new(Sequel.lit('a'), [1])).must_equal '(a)[1]'
1362
- @ds.literal(Sequel::SQL::Subscript.new(Sequel.lit('a(?)', 2), [1])).must_equal '(a(2))[1]'
1363
- end
1364
- end
1365
-
1366
- describe Sequel::SQL::CaseExpression, "#with_merged_expression" do
1367
- it "should return self if it has no expression" do
1368
- c = Sequel.case({1=>0}, 3)
1369
- c.with_merged_expression.must_be_same_as(c)
1370
- end
1371
-
1372
- it "should merge expression into conditions if it has an expression" do
1373
- db = Sequel::Database.new
1374
- c = Sequel.case({1=>0}, 3, 4)
1375
- db.literal(c.with_merged_expression).must_equal db.literal(Sequel.case({{4=>1}=>0}, 3))
1376
- end
1377
- end
1378
-
1379
- describe "Sequel.recursive_map" do
1380
- it "should recursively convert an array using a callable" do
1381
- Sequel.recursive_map(['1'], proc{|s| s.to_i}).must_equal [1]
1382
- Sequel.recursive_map([['1']], proc{|s| s.to_i}).must_equal [[1]]
1383
- end
1384
-
1385
- it "should not call callable if value is nil" do
1386
- Sequel.recursive_map([nil], proc{|s| s.to_i}).must_equal [nil]
1387
- Sequel.recursive_map([[nil]], proc{|s| s.to_i}).must_equal [[nil]]
1388
- end
1389
-
1390
- it "should call callable for falsey value" do
1391
- Sequel.recursive_map([false], proc{|s| s.to_s}).must_equal ['false']
1392
- Sequel.recursive_map([[false]], proc{|s| s.to_s}).must_equal [['false']]
1393
- end
1394
- end
1395
-
1396
- describe "Sequel.delay" do
1397
- before do
1398
- @o = Class.new do
1399
- def a
1400
- @a ||= 0
1401
- @a += 1
1402
- end
1403
- def _a
1404
- @a if defined?(@a)
1405
- end
1406
-
1407
- attr_accessor :b
1408
- end.new
1409
- end
1410
-
1411
- it "should delay calling the block until literalization" do
1412
- ds = Sequel.mock[:b].where(:a=>Sequel.delay{@o.a})
1413
- @o._a.must_be_nil
1414
- ds.sql.must_equal "SELECT * FROM b WHERE (a = 1)"
1415
- @o._a.must_equal 1
1416
- ds.sql.must_equal "SELECT * FROM b WHERE (a = 2)"
1417
- @o._a.must_equal 2
1418
- end
1419
-
1420
- it "should call the block with the current dataset if it accepts one argument" do
1421
- ds = Sequel.mock[:b].where(Sequel.delay{|x| x.first_source})
1422
- ds.sql.must_equal "SELECT * FROM b WHERE b"
1423
- ds.from(:c).sql.must_equal "SELECT * FROM c WHERE c"
1424
- end
1425
-
1426
- it "should have the condition specifier handling respect delayed evaluations" do
1427
- ds = Sequel.mock[:b].where(:a=>Sequel.delay{@o.b})
1428
- ds.sql.must_equal "SELECT * FROM b WHERE (a IS NULL)"
1429
- @o.b = 1
1430
- ds.sql.must_equal "SELECT * FROM b WHERE (a = 1)"
1431
- @o.b = [1, 2]
1432
- ds.sql.must_equal "SELECT * FROM b WHERE (a IN (1, 2))"
1433
- end
1434
-
1435
- it "should have the condition specifier handling call block with the current dataset if it accepts one argument" do
1436
- ds = Sequel.mock[:b].where(:a=>Sequel.delay{|x| x.first_source})
1437
- ds.sql.must_equal "SELECT * FROM b WHERE (a = b)"
1438
- ds.from(:c).sql.must_equal "SELECT * FROM c WHERE (a = c)"
1439
- end
1440
-
1441
- it "should raise if called without a block" do
1442
- proc{Sequel.delay}.must_raise(Sequel::Error)
1443
- end
1444
- end
1445
-
1446
- describe Sequel do
1447
- before do
1448
- Sequel::JSON = Class.new do
1449
- self::ParserError = Sequel
1450
- def self.parse(json, opts={})
1451
- [json, opts]
1452
- end
1453
- end
1454
- end
1455
- after do
1456
- Sequel.send(:remove_const, :JSON)
1457
- end
1458
-
1459
- it ".parse_json should parse json correctly" do
1460
- Sequel.parse_json('[]').must_equal ['[]', {:create_additions=>false}]
1461
- end
1462
-
1463
- it ".json_parser_error_class should return the related parser error class" do
1464
- Sequel.json_parser_error_class.must_equal Sequel
1465
- end
1466
-
1467
- it ".object_to_json should return a json version of the object" do
1468
- o = Object.new
1469
- def o.to_json(*args); [1, args]; end
1470
- Sequel.object_to_json(o, :foo).must_equal [1, [:foo]]
1471
- end
1472
- end
1473
-
1474
- describe "Sequel::LiteralString" do
1475
- before do
1476
- @s = Sequel::LiteralString.new("? = ?")
1477
- end
1478
-
1479
- it "should have lit return self if no arguments" do
1480
- @s.lit.must_be_same_as(@s)
1481
- end
1482
-
1483
- it "should have lit return self if return a placeholder literal string if arguments" do
1484
- @s.lit(1, 2).must_be_kind_of(Sequel::SQL::PlaceholderLiteralString)
1485
- Sequel.mock.literal(@s.lit(1, :a)).must_equal '1 = a'
1486
- end
1487
-
1488
- it "should have to_sequel_blob convert to blob" do
1489
- @s.to_sequel_blob.must_equal @s
1490
- @s.to_sequel_blob.must_be_kind_of(Sequel::SQL::Blob)
1491
- end
1492
- end
1493
-
1494
- describe "Sequel core extensions" do
1495
- it "should have Sequel.core_extensions? be false by default" do
1496
- Sequel.core_extensions?.must_equal false
1497
- end
1498
- end