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,439 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "constraint_validations extension" do
4
- def parse_insert(s)
5
- m = /\AINSERT INTO "?sequel_constraint_validations"? \("?(.*)"?\) VALUES \((.*)\)\z/.match(s)
6
- Hash[*m[1].split(/"?, "?/).map{|v| v.to_sym}.zip(m[2].split(/"?, "?/).map{|v| parse_insert_value(v)}).reject{|k, v| v.nil?}.flatten]
7
- end
8
-
9
- def parse_insert_value(s)
10
- case s
11
- when 'NULL'
12
- nil
13
- when /\A'(.*)'\z/
14
- $1
15
- else
16
- raise Sequel::Error, "unhandled insert value: #{s.inspect}"
17
- end
18
- end
19
-
20
- before do
21
- @db = Sequel.mock
22
- @db.extend(Module.new{attr_writer :schema; def schema(table, *) execute("parse schema for #{table}"); @schema; end})
23
- def @db.table_exists?(_) true; end
24
- @db.extension(:constraint_validations)
25
- end
26
-
27
- it "should allow creating the sequel_constraint_validations table" do
28
- @db.create_constraint_validations_table
29
- @db.sqls.must_equal ["CREATE TABLE sequel_constraint_validations (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
30
- end
31
-
32
- it "should allow creating the sequel_constraint_validations table with a non-default table name" do
33
- @db.constraint_validations_table = :foo
34
- @db.create_constraint_validations_table
35
- @db.sqls.must_equal ["CREATE TABLE foo (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
36
- end
37
-
38
- it "should allow dropping the sequel_constraint_validations table" do
39
- @db.drop_constraint_validations_table
40
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'sequel_constraint_validations')", "DROP TABLE sequel_constraint_validations"]
41
- end
42
-
43
- it "should allow dropping the sequel_constraint_validations table with a non-default table name" do
44
- @db.constraint_validations_table = :foo
45
- @db.drop_constraint_validations_table
46
- @db.sqls.must_equal ["DELETE FROM foo WHERE (table = 'foo')", "DROP TABLE foo"]
47
- end
48
-
49
- it "should allow dropping validations for a given table" do
50
- @db.drop_constraint_validations_for(:table=>:foo)
51
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')"]
52
- end
53
-
54
- it "should drop validations for a given table when dropping the table" do
55
- @db.drop_table(:foo)
56
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
57
-
58
- @db.drop_table(:foo, :if_exists => true)
59
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE IF EXISTS foo"]
60
-
61
- @db.drop_table?(:foo)
62
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
63
- end
64
-
65
- it "should not drop validations for a given table if the constraint validations table does not exist" do
66
- def @db.table_exists?(_) false; end
67
- @db.drop_table(:foo)
68
- @db.sqls.must_equal ["DROP TABLE foo"]
69
- end
70
-
71
- it "should allow dropping validations for a given table and column" do
72
- @db.drop_constraint_validations_for(:table=>:foo, :column=>:bar)
73
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (column = 'bar'))"]
74
- end
75
-
76
- it "should allow dropping validations for a given table and constraint" do
77
- @db.drop_constraint_validations_for(:table=>:foo, :constraint=>:bar)
78
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (constraint_name = 'bar'))"]
79
- end
80
-
81
- it "should allow dropping validations for a non-default constraint_validations table" do
82
- @db.constraint_validations_table = :cv
83
- @db.drop_constraint_validations_for(:table=>:foo)
84
- @db.sqls.must_equal ["DELETE FROM cv WHERE (table = 'foo')"]
85
- end
86
-
87
- it "should raise an error without deleting if attempting to drop validations without table, column, or constraint" do
88
- proc{@db.drop_constraint_validations_for({})}.must_raise(Sequel::Error)
89
- @db.sqls.must_equal []
90
- end
91
-
92
- it "should allow adding constraint validations via create_table validate" do
93
- @db.create_table(:foo){String :name; validate{presence :name}}
94
- sqls = @db.sqls
95
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
96
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
97
- end
98
-
99
- it "should allow adding constraint validations via alter_table validate" do
100
- @db.schema = [[:name, {:type=>:string}]]
101
- @db.alter_table(:foo){validate{presence :name}}
102
- sqls = @db.sqls
103
- parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
104
- sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK ((name IS NOT NULL) AND (trim(name) != ''))"]
105
- end
106
-
107
- it "should handle :message option when adding validations" do
108
- @db.create_table(:foo){String :name; validate{presence :name, :message=>'not there'}}
109
- sqls = @db.sqls
110
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :message=>'not there')
111
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
112
- end
113
-
114
- it "should handle :allow_nil option when adding validations" do
115
- @db.create_table(:foo){String :name; validate{presence :name, :allow_nil=>true}}
116
- sqls = @db.sqls
117
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
118
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NULL) OR (trim(name) != '')))"]
119
- end
120
-
121
- it "should handle :name option when adding validations" do
122
- @db.create_table(:foo){String :name; validate{presence :name, :name=>'cons'}}
123
- sqls = @db.sqls
124
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :constraint_name=>'cons')
125
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CONSTRAINT cons CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
126
- end
127
-
128
- it "should handle multiple string columns when adding presence validations" do
129
- @db.create_table(:foo){String :name; String :bar; validate{presence [:name, :bar]}}
130
- sqls = @db.sqls
131
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
132
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
133
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), bar varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '') AND (bar IS NOT NULL) AND (trim(bar) != '')))"]
134
- end
135
-
136
- it "should handle multiple string columns when adding presence validations with :allow_nil" do
137
- @db.create_table(:foo){String :name; String :bar; validate{presence [:name, :bar], :allow_nil=>true}}
138
- sqls = @db.sqls
139
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
140
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo", :allow_nil=>'t')
141
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), bar varchar(255), CHECK (((name IS NULL) OR (trim(name) != '')) AND ((bar IS NULL) OR (trim(bar) != ''))))"]
142
- end
143
-
144
- it "should handle multiple string columns when adding presence validations" do
145
- @db.create_table(:foo){String :name; Integer :x; String :bar; validate{presence [:name, :x, :bar]}}
146
- sqls = @db.sqls
147
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
148
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"x", :table=>"foo")
149
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
150
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), x integer, bar varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '') AND (bar IS NOT NULL) AND (trim(bar) != '') AND (x IS NOT NULL)))"]
151
- end
152
-
153
- it "should handle multiple string columns when adding presence validations with :allow_nil" do
154
- @db.create_table(:foo){String :name; Integer :x; String :bar; validate{presence [:name, :x, :bar], :allow_nil=>true}}
155
- sqls = @db.sqls
156
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
157
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"x", :table=>"foo", :allow_nil=>'t')
158
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo", :allow_nil=>'t')
159
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), x integer, bar varchar(255), CHECK (((name IS NULL) OR (trim(name) != '')) AND ((bar IS NULL) OR (trim(bar) != ''))))"]
160
- end
161
-
162
- it "should handle presence validation on non-String columns" do
163
- @db.create_table(:foo){Integer :name; validate{presence :name}}
164
- sqls = @db.sqls
165
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
166
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (name IS NOT NULL))"]
167
-
168
- @db.schema = [[:name, {:type=>:integer}]]
169
- @db.alter_table(:foo){validate{presence :name}}
170
- sqls = @db.sqls
171
- parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
172
- sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (name IS NOT NULL)"]
173
- end
174
-
175
- it "should handle presence validation on Oracle with IS NOT NULL instead of != ''" do
176
- @db = Sequel.mock(:host=>'oracle')
177
- @db.extend_datasets do
178
- def quote_identifiers?; false end
179
- def input_identifier(v) v.to_s end
180
- end
181
- @db.extension(:constraint_validations)
182
- @db.create_table(:foo){String :name; validate{presence :name}}
183
- sqls = @db.sqls
184
- s = sqls.slice!(1).upcase
185
- m = /\AINSERT INTO sequel_constraint_validations \((.*)\) SELECT (.*) FROM DUAL\z/i.match(s)
186
- Hash[*m[1].split(', ').map{|v| v.downcase.to_sym}.zip(m[2].split(', ').map{|v| parse_insert_value(v.downcase.gsub('null', 'NULL'))}).reject{|k, v| v.nil?}.flatten].must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
187
- sqls.must_equal ["BEGIN", "COMMIT", 'CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) IS NOT NULL)))']
188
- end
189
-
190
- it "should assume column is not a String if it can't determine the type" do
191
- @db.create_table(:foo){Integer :name; validate{presence :bar}}
192
- sqls = @db.sqls
193
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
194
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (bar IS NOT NULL))"]
195
-
196
- @db.schema = [[:name, {:type=>:integer}]]
197
- @db.alter_table(:foo){validate{presence :bar}}
198
- sqls = @db.sqls
199
- parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
200
- sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (bar IS NOT NULL)"]
201
- end
202
-
203
- it "should handle presence validation on non-String columns with :allow_nil option" do
204
- @db.create_table(:foo){Integer :name; validate{presence :name, :allow_nil=>true}}
205
- sqls = @db.sqls
206
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
207
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer)"]
208
- end
209
-
210
- it "should support :exact_length constraint validation" do
211
- @db.create_table(:foo){String :name; validate{exact_length 5, :name}}
212
- sqls = @db.sqls
213
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"exact_length", :column=>"name", :table=>"foo", :argument=>'5')
214
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) = 5)))"]
215
- end
216
-
217
- it "should support :min_length constraint validation" do
218
- @db.create_table(:foo){String :name; validate{min_length 5, :name}}
219
- sqls = @db.sqls
220
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"min_length", :column=>"name", :table=>"foo", :argument=>'5')
221
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 5)))"]
222
- end
223
-
224
- it "should support :max_length constraint validation" do
225
- @db.create_table(:foo){String :name; validate{max_length 5, :name}}
226
- sqls = @db.sqls
227
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"max_length", :column=>"name", :table=>"foo", :argument=>'5')
228
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) <= 5)))"]
229
- end
230
-
231
- it "should support :length_range constraint validation" do
232
- @db.create_table(:foo){String :name; validate{length_range 3..5, :name}}
233
- sqls = @db.sqls
234
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3..5')
235
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) <= 5)))"]
236
-
237
- @db.create_table(:foo){String :name; validate{length_range 3...5, :name}}
238
- sqls = @db.sqls
239
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3...5')
240
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) < 5)))"]
241
- end
242
-
243
- it "should support :format constraint validation" do
244
- @db = Sequel.mock(:host=>'postgres')
245
- @db.extend_datasets{def quote_identifiers?; false end}
246
- @db.extension(:constraint_validations)
247
- @db.create_table(:foo){String :name; validate{format(/^foo.*/, :name)}}
248
- sqls = @db.sqls
249
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"format", :column=>"name", :table=>"foo", :argument=>'^foo.*')
250
- sqls.must_equal ["BEGIN", "COMMIT", %[CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~ '^foo.*')))]]
251
- end
252
-
253
- it "should support :format constraint validation with case insensitive format" do
254
- @db = Sequel.mock(:host=>'postgres')
255
- @db.extend_datasets{def quote_identifiers?; false end}
256
- @db.extension(:constraint_validations)
257
- @db.create_table(:foo){String :name; validate{format(/^foo.*/i, :name)}}
258
- sqls = @db.sqls
259
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"iformat", :column=>"name", :table=>"foo", :argument=>'^foo.*')
260
- sqls.must_equal ["BEGIN", "COMMIT", %[CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~* '^foo.*')))]]
261
- end
262
-
263
- it "should support :includes constraint validation with an array of strings" do
264
- @db.create_table(:foo){String :name; validate{includes %w'a b c', :name}}
265
- sqls = @db.sqls
266
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_str_array", :column=>"name", :table=>"foo", :argument=>'a,b,c')
267
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN ('a', 'b', 'c'))))"]
268
- end
269
-
270
- it "should support :includes constraint validation with an array of integers" do
271
- @db.create_table(:foo){String :name; validate{includes [1, 2, 3], :name}}
272
- sqls = @db.sqls
273
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_array", :column=>"name", :table=>"foo", :argument=>'1,2,3')
274
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN (1, 2, 3))))"]
275
- end
276
-
277
- it "should support :includes constraint validation with a inclusive range of integers" do
278
- @db.create_table(:foo){String :name; validate{includes 3..5, :name}}
279
- sqls = @db.sqls
280
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3..5')
281
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name <= 5)))"]
282
- end
283
-
284
- it "should support :includes constraint validation with a exclusive range of integers" do
285
- @db.create_table(:foo){String :name; validate{includes 3...5, :name}}
286
- sqls = @db.sqls
287
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3...5')
288
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name < 5)))"]
289
- end
290
-
291
- it "should support :like constraint validation" do
292
- @db.create_table(:foo){String :name; validate{like 'foo%', :name}}
293
- sqls = @db.sqls
294
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"like", :column=>"name", :table=>"foo", :argument=>'foo%')
295
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name LIKE 'foo%' ESCAPE '\\')))"]
296
- end
297
-
298
- it "should support :ilike constraint validation" do
299
- @db.create_table(:foo){String :name; validate{ilike 'foo%', :name}}
300
- sqls = @db.sqls
301
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"ilike", :column=>"name", :table=>"foo", :argument=>'foo%')
302
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (UPPER(name) LIKE UPPER('foo%') ESCAPE '\\')))"]
303
- end
304
-
305
- it "should support :operator :< constraint validation with string" do
306
- @db.create_table(:foo){String :name; validate{operator :<, 'a', :name}}
307
- sqls = @db.sqls
308
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_lt", :column=>"name", :table=>"foo", :argument=>'a')
309
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name < 'a')))"]
310
- end
311
-
312
- it "should support :operator :<= constraint validation with string" do
313
- @db.create_table(:foo){String :name; validate{operator :<=, 'a', :name}}
314
- sqls = @db.sqls
315
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_lte", :column=>"name", :table=>"foo", :argument=>'a')
316
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name <= 'a')))"]
317
- end
318
-
319
- it "should support :operator :> constraint validation with string" do
320
- @db.create_table(:foo){String :name; validate{operator :>, 'a', :name}}
321
- sqls = @db.sqls
322
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_gt", :column=>"name", :table=>"foo", :argument=>'a')
323
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name > 'a')))"]
324
- end
325
-
326
- it "should support :operator :>= constraint validation with string" do
327
- @db.create_table(:foo){String :name; validate{operator :>=, 'a', :name}}
328
- sqls = @db.sqls
329
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_gte", :column=>"name", :table=>"foo", :argument=>'a')
330
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 'a')))"]
331
- end
332
-
333
- it "should support :operator :< constraint validation with integer" do
334
- @db.create_table(:foo){Integer :name; validate{operator :<, 2, :name}}
335
- sqls = @db.sqls
336
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_lt", :column=>"name", :table=>"foo", :argument=>'2')
337
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name < 2)))"]
338
- end
339
-
340
- it "should support :operator :<= constraint validation with integer" do
341
- @db.create_table(:foo){Integer :name; validate{operator :<=, 2, :name}}
342
- sqls = @db.sqls
343
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_lte", :column=>"name", :table=>"foo", :argument=>'2')
344
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name <= 2)))"]
345
- end
346
-
347
- it "should support :operator :> constraint validation with integer" do
348
- @db.create_table(:foo){Integer :name; validate{operator :>, 2, :name}}
349
- sqls = @db.sqls
350
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_gt", :column=>"name", :table=>"foo", :argument=>'2')
351
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name > 2)))"]
352
- end
353
-
354
- it "should support :operator :>= constraint validation with integer" do
355
- @db.create_table(:foo){Integer :name; validate{operator :>=, 2, :name}}
356
- sqls = @db.sqls
357
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_gte", :column=>"name", :table=>"foo", :argument=>'2')
358
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name >= 2)))"]
359
- end
360
-
361
- it "should support :unique constraint validation" do
362
- @db.create_table(:foo){String :name; validate{unique :name}}
363
- sqls = @db.sqls
364
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
365
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), UNIQUE (name))"]
366
- end
367
-
368
- it "should support :unique constraint validation with multiple columns" do
369
- @db.create_table(:foo){String :name; Integer :id; validate{unique [:name, :id]}}
370
- sqls = @db.sqls
371
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name,id", :table=>"foo")
372
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), id integer, UNIQUE (name, id))"]
373
- end
374
-
375
- it "should support :unique constraint validation in alter_table" do
376
- @db.alter_table(:foo){validate{unique :name}}
377
- sqls = @db.sqls
378
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
379
- sqls.must_equal ["BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)"]
380
- end
381
-
382
- it "should drop constraints and validations when dropping a constraint validation" do
383
- @db.alter_table(:foo){String :name; validate{drop :bar}}
384
- @db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "ALTER TABLE foo DROP CONSTRAINT bar"]
385
- end
386
-
387
- it "should drop constraints and validations before adding new ones" do
388
- @db.alter_table(:foo){String :name; validate{unique :name; drop :bar}}
389
- sqls = @db.sqls
390
- parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
391
- sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)", "ALTER TABLE foo DROP CONSTRAINT bar"]
392
- end
393
-
394
- it "should raise an error if attempting to validate inclusion with a range of non-integers" do
395
- proc{@db.create_table(:foo){String :name; validate{includes 'a'..'z', :name}}}.must_raise(Sequel::Error)
396
- end
397
-
398
- it "should raise an error if attempting to validate inclusion with a range of non-integers or strings" do
399
- proc{@db.create_table(:foo){String :name; validate{includes [1.0, 2.0], :name}}}.must_raise(Sequel::Error)
400
- end
401
-
402
- it "should raise an error if attempting to validate inclusion with a unsupported object" do
403
- proc{@db.create_table(:foo){String :name; validate{includes 'a', :name}}}.must_raise(Sequel::Error)
404
- end
405
-
406
- it "should raise an error if attempting attempting to process an operator validation with an unsupported operator" do
407
- proc{@db.alter_table(:foo){String :name; validate{operator :===, 'a', :name}}}.must_raise(Sequel::Error)
408
- end
409
-
410
- it "should raise an error if attempting attempting to process an operator validation with an unsupported argument" do
411
- proc{@db.alter_table(:foo){String :name; validate{operator :>, [], :name}}}.must_raise(Sequel::Error)
412
- end
413
-
414
- it "should raise an error if attempting to drop a constraint validation in a create_table generator" do
415
- proc{@db.create_table(:foo){String :name; validate{drop :foo}}}.must_raise(Sequel::Error)
416
- end
417
-
418
- it "should raise an error if attempting to drop a constraint validation without a name" do
419
- proc{@db.alter_table(:foo){String :name; validate{drop nil}}}.must_raise(Sequel::Error)
420
- end
421
-
422
- it "should raise an error if attempting attempting to process a constraint validation with an unsupported type" do
423
- proc{@db.alter_table(:foo){String :name; validations << {:type=>:foo}}}.must_raise(Sequel::Error)
424
- end
425
-
426
- it "should allow adding constraint validations for tables specified as a SQL::Identifier" do
427
- @db.create_table(Sequel.identifier(:sch__foo)){String :name; validate{presence :name}}
428
- sqls = @db.sqls
429
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch__foo")
430
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch__foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
431
- end
432
-
433
- it "should allow adding constraint validations for tables specified as a SQL::QualifiedIdentifier" do
434
- @db.create_table(Sequel.qualify(:sch, :foo)){String :name; validate{presence :name}}
435
- sqls = @db.sqls
436
- parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch.foo")
437
- sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch.foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
438
- end
439
- end
@@ -1,528 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') || (RUBY_ENGINE == 'jruby' && (JRUBY_VERSION >= '9.3' || (JRUBY_VERSION.match(/\A9\.2\.(\d+)/) && $1.to_i >= 7)))
4
- Sequel.extension :core_refinements, :pg_array, :pg_hstore, :pg_row, :pg_range, :pg_row_ops, :pg_range_ops, :pg_array_ops, :pg_hstore_ops, :pg_json, :pg_json_ops
5
- using Sequel::CoreRefinements
6
-
7
- describe "Core refinements" do
8
- before do
9
- db = Sequel.mock
10
- @d = db[:items].with_extend do
11
- def supports_regexp?; true end
12
- def l(*args, &block)
13
- literal(filter_expr(*args, &block))
14
- end
15
- def lit(*args)
16
- literal(*args)
17
- end
18
- end
19
- end
20
-
21
- it "should support NOT via Symbol#~" do
22
- @d.l(~:x).must_equal 'NOT x'
23
- end
24
-
25
- with_symbol_splitting "should support NOT via Symbol#~ for splittable symbols" do
26
- @d.l(~:x__y).must_equal 'NOT x.y'
27
- end
28
-
29
- it "should support + - * / power via Symbol#+,-,*,/,**" do
30
- @d.l(:x + 1 > 100).must_equal '((x + 1) > 100)'
31
- @d.l((:x * :y) < 100.01).must_equal '((x * y) < 100.01)'
32
- @d.l((:x - :y/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
33
- @d.l((((:x - :y)/(:x + :y))*:z) <= 100).must_equal '((((x - y) / (x + y)) * z) <= 100)'
34
- @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
35
- @d.l(~((((:x ** :y)/(:x + :y))*:z) <= 100)).must_equal '(((power(x, y) / (x + y)) * z) > 100)'
36
- end
37
-
38
- it "should support LIKE via Symbol#like" do
39
- @d.l(:x.like('a')).must_equal '(x LIKE \'a\' ESCAPE \'\\\')'
40
- @d.l(:x.like(/a/)).must_equal '(x ~ \'a\')'
41
- @d.l(:x.like('a', 'b')).must_equal '((x LIKE \'a\' ESCAPE \'\\\') OR (x LIKE \'b\' ESCAPE \'\\\'))'
42
- @d.l(:x.like(/a/, /b/i)).must_equal '((x ~ \'a\') OR (x ~* \'b\'))'
43
- @d.l(:x.like('a', /b/)).must_equal '((x LIKE \'a\' ESCAPE \'\\\') OR (x ~ \'b\'))'
44
- end
45
-
46
- it "should support NOT LIKE via Symbol#like and Symbol#~" do
47
- @d.l(~:x.like('a')).must_equal '(x NOT LIKE \'a\' ESCAPE \'\\\')'
48
- @d.l(~:x.like(/a/)).must_equal '(x !~ \'a\')'
49
- @d.l(~:x.like('a', 'b')).must_equal '((x NOT LIKE \'a\' ESCAPE \'\\\') AND (x NOT LIKE \'b\' ESCAPE \'\\\'))'
50
- @d.l(~:x.like(/a/, /b/i)).must_equal '((x !~ \'a\') AND (x !~* \'b\'))'
51
- @d.l(~:x.like('a', /b/)).must_equal '((x NOT LIKE \'a\' ESCAPE \'\\\') AND (x !~ \'b\'))'
52
- end
53
-
54
- it "should support ILIKE via Symbol#ilike" do
55
- @d.l(:x.ilike('a')).must_equal '(UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\')'
56
- @d.l(:x.ilike(/a/)).must_equal '(x ~* \'a\')'
57
- @d.l(:x.ilike('a', 'b')).must_equal '((UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\') OR (UPPER(x) LIKE UPPER(\'b\') ESCAPE \'\\\'))'
58
- @d.l(:x.ilike(/a/, /b/i)).must_equal '((x ~* \'a\') OR (x ~* \'b\'))'
59
- @d.l(:x.ilike('a', /b/)).must_equal '((UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\') OR (x ~* \'b\'))'
60
- end
61
-
62
- it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
63
- @d.l(~:x.ilike('a')).must_equal '(UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\')'
64
- @d.l(~:x.ilike(/a/)).must_equal '(x !~* \'a\')'
65
- @d.l(~:x.ilike('a', 'b')).must_equal '((UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\') AND (UPPER(x) NOT LIKE UPPER(\'b\') ESCAPE \'\\\'))'
66
- @d.l(~:x.ilike(/a/, /b/i)).must_equal '((x !~* \'a\') AND (x !~* \'b\'))'
67
- @d.l(~:x.ilike('a', /b/)).must_equal '((UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\') AND (x !~* \'b\'))'
68
- end
69
-
70
- it "should support sql_expr on arrays with all two pairs" do
71
- @d.l([[:x, 100],[:y, 'a']].sql_expr).must_equal '((x = 100) AND (y = \'a\'))'
72
- @d.l([[:x, true], [:y, false]].sql_expr).must_equal '((x IS TRUE) AND (y IS FALSE))'
73
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).must_equal '((x IS NULL) AND (y IN (1, 2, 3)))'
74
- end
75
-
76
- it "should support sql_negate on arrays with all two pairs" do
77
- @d.l([[:x, 100],[:y, 'a']].sql_negate).must_equal '((x != 100) AND (y != \'a\'))'
78
- @d.l([[:x, true], [:y, false]].sql_negate).must_equal '((x IS NOT TRUE) AND (y IS NOT FALSE))'
79
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).must_equal '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
80
- end
81
-
82
- it "should support ~ on arrays with all two pairs" do
83
- @d.l(~[[:x, 100],[:y, 'a']]).must_equal '((x != 100) OR (y != \'a\'))'
84
- @d.l(~[[:x, true], [:y, false]]).must_equal '((x IS NOT TRUE) OR (y IS NOT FALSE))'
85
- @d.l(~[[:x, nil], [:y, [1,2,3]]]).must_equal '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
86
- end
87
-
88
- it "should support sql_or on arrays with all two pairs" do
89
- @d.l([[:x, 100],[:y, 'a']].sql_or).must_equal '((x = 100) OR (y = \'a\'))'
90
- @d.l([[:x, true], [:y, false]].sql_or).must_equal '((x IS TRUE) OR (y IS FALSE))'
91
- @d.l([[:x, nil], [:y, [1,2,3]]].sql_or).must_equal '((x IS NULL) OR (y IN (1, 2, 3)))'
92
- end
93
-
94
- it "should support Array#sql_string_join for concatenation of SQL strings" do
95
- @d.lit([:x].sql_string_join).must_equal '(x)'
96
- @d.lit([:x].sql_string_join(', ')).must_equal '(x)'
97
- @d.lit([:x, :y].sql_string_join).must_equal '(x || y)'
98
- @d.lit([:x, :y].sql_string_join(', ')).must_equal "(x || ', ' || y)"
99
- @d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).must_equal '(x(1) || y[1])'
100
- @d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).must_equal "(x(1) || ', ' || y.z)"
101
- @d.lit([:x, 1, :y].sql_string_join).must_equal "(x || '1' || y)"
102
- @d.lit([:x, 1, :y].sql_string_join(', ')).must_equal "(x || ', ' || '1' || ', ' || y)"
103
- @d.lit([:x, 1, :y].sql_string_join(Sequel[:y][:z])).must_equal "(x || y.z || '1' || y.z || y)"
104
- @d.lit([:x, 1, :y].sql_string_join(1)).must_equal "(x || '1' || '1' || '1' || y)"
105
- @d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).must_equal "(x || y.x || x.y || y)"
106
- @d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).must_equal "(x || y || a || b)"
107
- end
108
-
109
- it "should support sql_expr on hashes" do
110
- @d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x = 100)', '(y = \'a\')']
111
- @d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x IS TRUE)', '(y IS FALSE)']
112
- @d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x IS NULL)', '(y IN (1, 2, 3))']
113
- end
114
-
115
- it "should support sql_negate on hashes" do
116
- @d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x != 100)', '(y != \'a\')']
117
- @d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
118
- @d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
119
- end
120
-
121
- it "should support ~ on hashes" do
122
- @d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.must_equal ['(x != 100)', '(y != \'a\')']
123
- @d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.must_equal ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
124
- @d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.must_equal ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
125
- end
126
-
127
- it "should support sql_or on hashes" do
128
- @d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x = 100)', '(y = \'a\')']
129
- @d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x IS TRUE)', '(y IS FALSE)']
130
- @d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x IS NULL)', '(y IN (1, 2, 3))']
131
- end
132
-
133
- it "should Hash#& and Hash#|" do
134
- @d.l({:y => :z} & :x).must_equal '((y = z) AND x)'
135
- @d.l({:x => :a} & {:y => :z}).must_equal '((x = a) AND (y = z))'
136
- @d.l({:y => :z} | :x).must_equal '((y = z) OR x)'
137
- @d.l({:x => :a} | {:y => :z}).must_equal '((x = a) OR (y = z))'
138
- end
139
- end
140
-
141
- describe "Array#case and Hash#case" do
142
- before do
143
- @d = Sequel.mock.dataset
144
- end
145
-
146
- it "should return SQL CASE expression" do
147
- @d.literal({:x=>:y}.case(:z)).must_equal '(CASE WHEN x THEN y ELSE z END)'
148
- @d.literal({:x=>:y}.case(:z, :exp)).must_equal '(CASE exp WHEN x THEN y ELSE z END)'
149
- ['(CASE WHEN x THEN y WHEN a THEN b ELSE z END)',
150
- '(CASE WHEN a THEN b WHEN x THEN y ELSE z END)'].must_include(@d.literal({:x=>:y, :a=>:b}.case(:z)))
151
- @d.literal([[:x, :y]].case(:z)).must_equal '(CASE WHEN x THEN y ELSE z END)'
152
- @d.literal([[:x, :y], [:a, :b]].case(:z)).must_equal '(CASE WHEN x THEN y WHEN a THEN b ELSE z END)'
153
- @d.literal([[:x, :y], [:a, :b]].case(:z, :exp)).must_equal '(CASE exp WHEN x THEN y WHEN a THEN b ELSE z END)'
154
- @d.literal([[:x, :y], [:a, :b]].case(:z, Sequel[:exp][:w])).must_equal '(CASE exp.w WHEN x THEN y WHEN a THEN b ELSE z END)'
155
- end
156
-
157
- it "should return SQL CASE expression with expression even if nil" do
158
- @d.literal({:x=>:y}.case(:z, nil)).must_equal '(CASE NULL WHEN x THEN y ELSE z END)'
159
- end
160
-
161
- it "should raise an error if an array that isn't all two pairs is used" do
162
- proc{[:b].case(:a)}.must_raise(Sequel::Error)
163
- proc{[:b, :c].case(:a)}.must_raise(Sequel::Error)
164
- proc{[[:b, :c], :d].case(:a)}.must_raise(Sequel::Error)
165
- end
166
-
167
- it "should raise an error if an empty array/hash is used" do
168
- proc{[].case(:a)}.must_raise(Sequel::Error)
169
- proc{{}.case(:a)}.must_raise(Sequel::Error)
170
- end
171
- end
172
-
173
- describe "Array#sql_value_list and #sql_array" do
174
- before do
175
- @d = Sequel.mock.dataset
176
- end
177
-
178
- it "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
179
- @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]])).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
180
- @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
181
- end
182
-
183
- it "should be no difference when used as a hash value" do
184
- @d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
185
- @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
186
- end
187
- end
188
-
189
- describe "String#lit" do
190
- before do
191
- @ds = Sequel.mock[:t]
192
- end
193
-
194
- it "should return an LiteralString object" do
195
- 'xyz'.lit.must_be_kind_of(Sequel::LiteralString)
196
- 'xyz'.lit.to_s.must_equal 'xyz'
197
- end
198
-
199
- it "should inhibit string literalization" do
200
- @ds.update_sql(:stamp => "NOW()".lit).must_equal "UPDATE t SET stamp = NOW()"
201
- end
202
-
203
- it "should return a PlaceholderLiteralString object if args are given" do
204
- a = 'DISTINCT ?'.lit(:a)
205
- a.must_be_kind_of(Sequel::SQL::PlaceholderLiteralString)
206
- @ds.literal(a).must_equal 'DISTINCT a'
207
- @ds.with_quote_identifiers(true).literal(a).must_equal 'DISTINCT "a"'
208
- end
209
-
210
- it "should handle named placeholders if given a single argument hash" do
211
- a = 'DISTINCT :b'.lit(:b=>:a)
212
- a.must_be_kind_of(Sequel::SQL::PlaceholderLiteralString)
213
- @ds.literal(a).must_equal 'DISTINCT a'
214
- @ds.with_quote_identifiers(true).literal(a).must_equal 'DISTINCT "a"'
215
- end
216
-
217
- it "should treat placeholder literal strings as generic expressions" do
218
- a = ':b'.lit(:b=>:a)
219
- @ds.literal(a + 1).must_equal "(a + 1)"
220
- @ds.literal(a & :b).must_equal "(a AND b)"
221
- @ds.literal(a.sql_string + :b).must_equal "(a || b)"
222
- end
223
- end
224
-
225
- describe "String#to_sequel_blob" do
226
- it "should return a Blob object" do
227
- 'xyz'.to_sequel_blob.must_be_kind_of(::Sequel::SQL::Blob)
228
- 'xyz'.to_sequel_blob.must_equal 'xyz'
229
- end
230
-
231
- it "should retain binary data" do
232
- "\1\2\3\4".to_sequel_blob.must_equal "\1\2\3\4"
233
- end
234
- end
235
-
236
- describe "#desc" do
237
- before do
238
- @ds = Sequel.mock.dataset
239
- end
240
-
241
- it "should format a DESC clause for a column ref" do
242
- @ds.literal(:test.desc).must_equal 'test DESC'
243
- end
244
-
245
- with_symbol_splitting "should format a DESC clause for a column ref with splittable symbol" do
246
- @ds.literal(:items__price.desc).must_equal 'items.price DESC'
247
- end
248
-
249
- it "should format a DESC clause for a function" do
250
- @ds.literal(:avg.sql_function(:test).desc).must_equal 'avg(test) DESC'
251
- end
252
- end
253
-
254
- describe "#asc" do
255
- before do
256
- @ds = Sequel.mock.dataset
257
- end
258
-
259
- it "should format a ASC clause for a column ref" do
260
- @ds.literal(:test.asc).must_equal 'test ASC'
261
- end
262
-
263
- with_symbol_splitting "should format a ASC clause for a column ref with splittable symbol" do
264
- @ds.literal(:items__price.asc).must_equal 'items.price ASC'
265
- end
266
-
267
- it "should format a ASC clause for a function" do
268
- @ds.literal(:avg.sql_function(:test).asc).must_equal 'avg(test) ASC'
269
- end
270
- end
271
-
272
- describe "#as" do
273
- before do
274
- @ds = Sequel.mock.dataset
275
- end
276
-
277
- it "should format a AS clause for a column ref" do
278
- @ds.literal(:test.as(:t)).must_equal 'test AS t'
279
- end
280
-
281
- with_symbol_splitting "should format a AS clause for a column ref with splittable symbols" do
282
- @ds.literal(:items__price.as(:p)).must_equal 'items.price AS p'
283
- end
284
-
285
- it "should format a AS clause for a function" do
286
- @ds.literal(:avg.sql_function(:test).as(:avg)).must_equal 'avg(test) AS avg'
287
- end
288
-
289
- it "should format a AS clause for a literal value" do
290
- @ds.literal('abc'.as(:abc)).must_equal "'abc' AS abc"
291
- end
292
- end
293
-
294
- describe "Column references" do
295
- before do
296
- @ds = Sequel.mock.dataset.with_quote_identifiers(true).with_extend{def quoted_identifier_append(sql, c) sql << "`#{c}`" end}
297
- end
298
-
299
- it "should be quoted properly" do
300
- @ds.literal(:xyz).must_equal "`xyz`"
301
- @ds.literal(:xyz.as(:x)).must_equal "`xyz` AS `x`"
302
- end
303
-
304
- it "should be quoted properly in SQL functions" do
305
- @ds.literal(:avg.sql_function(:xyz)).must_equal "avg(`xyz`)"
306
- @ds.literal(:avg.sql_function(:xyz, 1)).must_equal "avg(`xyz`, 1)"
307
- @ds.literal(:avg.sql_function(:xyz).as(:a)).must_equal "avg(`xyz`) AS `a`"
308
- end
309
-
310
- it "should be quoted properly in ASC/DESC clauses" do
311
- @ds.literal(:xyz.asc).must_equal "`xyz` ASC"
312
- @ds.literal(:avg.sql_function(:xyz, 1).desc).must_equal "avg(`xyz`, 1) DESC"
313
- end
314
-
315
- it "should be quoted properly in a cast function" do
316
- @ds.literal(:x.cast(:integer)).must_equal "CAST(`x` AS integer)"
317
- end
318
-
319
- with_symbol_splitting "should be quoted properly when using splittable symbols" do
320
- @ds.literal(:xyz__abc).must_equal "`xyz`.`abc`"
321
- @ds.literal(:xyz__abc.as(:x)).must_equal "`xyz`.`abc` AS `x`"
322
- @ds.literal(:xyz___x).must_equal "`xyz` AS `x`"
323
- @ds.literal(:xyz__abc___x).must_equal "`xyz`.`abc` AS `x`"
324
- @ds.literal(:x__y.cast('varchar(20)')).must_equal "CAST(`x`.`y` AS varchar(20))"
325
- end
326
- end
327
-
328
- describe "Blob" do
329
- it "#to_sequel_blob should return self" do
330
- blob = "x".to_sequel_blob
331
- blob.to_sequel_blob.object_id.must_equal blob.object_id
332
- end
333
- end
334
-
335
- describe "Symbol#*" do
336
- before do
337
- @ds = Sequel.mock.dataset
338
- end
339
-
340
- it "should format a qualified wildcard if no argument" do
341
- @ds.literal(:xyz.*).must_equal 'xyz.*'
342
- @ds.literal(:abc.*).must_equal 'abc.*'
343
- end
344
-
345
- it "should format a filter expression if an argument" do
346
- @ds.literal(:xyz.*(3)).must_equal '(xyz * 3)'
347
- @ds.literal(:abc.*(5)).must_equal '(abc * 5)'
348
- end
349
-
350
- with_symbol_splitting "should support qualified symbols if no argument" do
351
- @ds.literal(:xyz__abc.*).must_equal 'xyz.abc.*'
352
- end
353
- end
354
-
355
- describe "Symbol" do
356
- before do
357
- @ds = Sequel.mock.dataset.with_quote_identifiers(true)
358
- end
359
-
360
- it "#identifier should format an identifier" do
361
- @ds.literal(:xyz__abc.identifier).must_equal '"xyz__abc"'
362
- end
363
-
364
- it "#qualify should format a qualified column" do
365
- @ds.literal(:xyz.qualify(:abc)).must_equal '"abc"."xyz"'
366
- end
367
-
368
- it "#qualify should work on QualifiedIdentifiers" do
369
- @ds.literal(:xyz.qualify(:abc).qualify(:def)).must_equal '"def"."abc"."xyz"'
370
- end
371
-
372
- it "should be able to qualify an identifier" do
373
- @ds.literal(:xyz.identifier.qualify(Sequel[:xyz][:abc])).must_equal '"xyz"."abc"."xyz"'
374
- end
375
-
376
- with_symbol_splitting "should be able to qualify an identifier with qualified symbol" do
377
- @ds.literal(:xyz.identifier.qualify(:xyz__abc)).must_equal '"xyz"."abc"."xyz"'
378
- end
379
-
380
- it "should be able to specify a schema.table.column" do
381
- @ds.literal(:column.qualify(:table.qualify(:schema))).must_equal '"schema"."table"."column"'
382
- @ds.literal(:column.qualify(:table__name.identifier.qualify(:schema))).must_equal '"schema"."table__name"."column"'
383
- end
384
-
385
- it "should be able to specify order" do
386
- @oe = :xyz.desc
387
- @oe.class.must_equal Sequel::SQL::OrderedExpression
388
- @oe.descending.must_equal true
389
- @oe = :xyz.asc
390
- @oe.class.must_equal Sequel::SQL::OrderedExpression
391
- @oe.descending.must_equal false
392
- end
393
-
394
- it "should work correctly with objects" do
395
- o = Object.new
396
- def o.sql_literal(ds) "(foo)" end
397
- @ds.literal(:column.qualify(o)).must_equal '(foo)."column"'
398
- end
399
- end
400
-
401
- describe "Symbol" do
402
- before do
403
- @ds = Sequel.mock.dataset
404
- end
405
-
406
- it "should support sql_function method" do
407
- @ds.literal(:COUNT.sql_function('1')).must_equal "COUNT('1')"
408
- @ds.select(:COUNT.sql_function('1')).sql.must_equal "SELECT COUNT('1')"
409
- end
410
-
411
- it "should support cast method" do
412
- @ds.literal(:abc.cast(:integer)).must_equal "CAST(abc AS integer)"
413
- end
414
-
415
- with_symbol_splitting "should support sql array accesses via sql_subscript for splittable symbols" do
416
- @ds.literal(:abc__def.sql_subscript(1)).must_equal "abc.def[1]"
417
- end
418
-
419
- it "should support sql array accesses via sql_subscript" do
420
- @ds.literal(:abc.sql_subscript(1)).must_equal "abc[1]"
421
- @ds.literal(:abc.sql_subscript(1)|2).must_equal "abc[1, 2]"
422
- @ds.literal(:abc.sql_subscript(1)[2]).must_equal "abc[1][2]"
423
- end
424
-
425
- it "should support cast_numeric and cast_string" do
426
- x = :abc.cast_numeric
427
- x.must_be_kind_of(Sequel::SQL::NumericExpression)
428
- @ds.literal(x).must_equal "CAST(abc AS integer)"
429
-
430
- x = :abc.cast_numeric(:real)
431
- x.must_be_kind_of(Sequel::SQL::NumericExpression)
432
- @ds.literal(x).must_equal "CAST(abc AS real)"
433
-
434
- x = :abc.cast_string
435
- x.must_be_kind_of(Sequel::SQL::StringExpression)
436
- @ds.literal(x).must_equal "CAST(abc AS varchar(255))"
437
-
438
- x = :abc.cast_string(:varchar)
439
- x.must_be_kind_of(Sequel::SQL::StringExpression)
440
- @ds.literal(x).must_equal "CAST(abc AS varchar(255))"
441
- end
442
-
443
- it "should allow database independent types when casting" do
444
- db = @ds.db
445
- def db.cast_type_literal(type)
446
- return :foo if type == Integer
447
- return :bar if type == String
448
- type
449
- end
450
- @ds.literal(:abc.cast(String)).must_equal "CAST(abc AS bar)"
451
- @ds.literal(:abc.cast(String)).must_equal "CAST(abc AS bar)"
452
- @ds.literal(:abc.cast_string).must_equal "CAST(abc AS bar)"
453
- @ds.literal(:abc.cast_string(Integer)).must_equal "CAST(abc AS foo)"
454
- @ds.literal(:abc.cast_numeric).must_equal "CAST(abc AS foo)"
455
- @ds.literal(:abc.cast_numeric(String)).must_equal "CAST(abc AS bar)"
456
- end
457
-
458
- it "should support SQL EXTRACT function via #extract " do
459
- @ds.literal(:abc.extract(:year)).must_equal "extract(year FROM abc)"
460
- end
461
- end
462
-
463
- describe "Postgres extensions integration" do
464
- before do
465
- @db = Sequel.mock
466
- end
467
-
468
- it "Symbol#pg_array should return an ArrayOp" do
469
- @db.literal(:a.pg_array.unnest).must_equal "unnest(a)"
470
- end
471
-
472
- it "Symbol#pg_row should return a PGRowOp" do
473
- @db.literal(:a.pg_row[:a]).must_equal "(a).a"
474
- end
475
-
476
- it "Symbol#hstore should return an HStoreOp" do
477
- @db.literal(:a.hstore['a']).must_equal "(a -> 'a')"
478
- end
479
-
480
- it "Symbol#pg_json should return an JSONOp" do
481
- @db.literal(:a.pg_json[%w'a b']).must_equal "(a #> ARRAY['a','b'])"
482
- @db.literal(:a.pg_json.extract('a')).must_equal "json_extract_path(a, 'a')"
483
- end
484
-
485
- it "Symbol#pg_jsonb should return an JSONBOp" do
486
- @db.literal(:a.pg_jsonb[%w'a b']).must_equal "(a #> ARRAY['a','b'])"
487
- @db.literal(:a.pg_jsonb.extract('a')).must_equal "jsonb_extract_path(a, 'a')"
488
- end
489
-
490
- it "Symbol#pg_range should return a RangeOp" do
491
- @db.literal(:a.pg_range.lower).must_equal "lower(a)"
492
- end
493
-
494
- it "Array#pg_array should return a PGArray" do
495
- @db.literal([1].pg_array.op.unnest).must_equal "unnest(ARRAY[1])"
496
- @db.literal([1].pg_array(:int4).op.unnest).must_equal "unnest(ARRAY[1]::int4[])"
497
- end
498
-
499
- it "Array#pg_json should return a JSONArray" do
500
- @db.literal([1].pg_json).must_equal "'[1]'::json"
501
- end
502
-
503
- it "Array#pg_jsonb should return a JSONBArray" do
504
- @db.literal([1].pg_jsonb).must_equal "'[1]'::jsonb"
505
- end
506
-
507
- it "Array#pg_row should return a ArrayRow" do
508
- @db.literal([1].pg_row).must_equal "ROW(1)"
509
- end
510
-
511
- it "Hash#hstore should return an HStore" do
512
- @db.literal({'a'=>1}.hstore.op['a']).must_equal '(\'"a"=>"1"\'::hstore -> \'a\')'
513
- end
514
-
515
- it "Hash#pg_json should return an JSONHash" do
516
- @db.literal({'a'=>'b'}.pg_json).must_equal "'{\"a\":\"b\"}'::json"
517
- end
518
-
519
- it "Hash#pg_jsonb should return an JSONBHash" do
520
- @db.literal({'a'=>'b'}.pg_jsonb).must_equal "'{\"a\":\"b\"}'::jsonb"
521
- end
522
-
523
- it "Range#pg_range should return an PGRange" do
524
- @db.literal((1..2).pg_range).must_equal "'[1,2]'"
525
- @db.literal((1..2).pg_range(:int4range)).must_equal "int4range(1,2,'[]')"
526
- end
527
- end
528
- end