sequel 4.36.0 → 5.61.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 (760) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +548 -5749
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +265 -159
  5. data/bin/sequel +34 -12
  6. data/doc/advanced_associations.rdoc +228 -187
  7. data/doc/association_basics.rdoc +281 -291
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +86 -51
  10. data/doc/code_order.rdoc +25 -19
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/fork_safety.rdoc +84 -0
  16. data/doc/mass_assignment.rdoc +74 -31
  17. data/doc/migration.rdoc +59 -51
  18. data/doc/model_dataset_method_design.rdoc +129 -0
  19. data/doc/model_hooks.rdoc +15 -25
  20. data/doc/model_plugins.rdoc +12 -12
  21. data/doc/mssql_stored_procedures.rdoc +3 -3
  22. data/doc/object_model.rdoc +58 -68
  23. data/doc/opening_databases.rdoc +85 -95
  24. data/doc/postgresql.rdoc +263 -38
  25. data/doc/prepared_statements.rdoc +29 -24
  26. data/doc/querying.rdoc +189 -167
  27. data/doc/reflection.rdoc +5 -6
  28. data/doc/release_notes/5.0.0.txt +159 -0
  29. data/doc/release_notes/5.1.0.txt +31 -0
  30. data/doc/release_notes/5.10.0.txt +84 -0
  31. data/doc/release_notes/5.11.0.txt +83 -0
  32. data/doc/release_notes/5.12.0.txt +141 -0
  33. data/doc/release_notes/5.13.0.txt +27 -0
  34. data/doc/release_notes/5.14.0.txt +63 -0
  35. data/doc/release_notes/5.15.0.txt +39 -0
  36. data/doc/release_notes/5.16.0.txt +110 -0
  37. data/doc/release_notes/5.17.0.txt +31 -0
  38. data/doc/release_notes/5.18.0.txt +69 -0
  39. data/doc/release_notes/5.19.0.txt +28 -0
  40. data/doc/release_notes/5.2.0.txt +33 -0
  41. data/doc/release_notes/5.20.0.txt +89 -0
  42. data/doc/release_notes/5.21.0.txt +87 -0
  43. data/doc/release_notes/5.22.0.txt +48 -0
  44. data/doc/release_notes/5.23.0.txt +56 -0
  45. data/doc/release_notes/5.24.0.txt +56 -0
  46. data/doc/release_notes/5.25.0.txt +32 -0
  47. data/doc/release_notes/5.26.0.txt +35 -0
  48. data/doc/release_notes/5.27.0.txt +21 -0
  49. data/doc/release_notes/5.28.0.txt +16 -0
  50. data/doc/release_notes/5.29.0.txt +22 -0
  51. data/doc/release_notes/5.3.0.txt +121 -0
  52. data/doc/release_notes/5.30.0.txt +20 -0
  53. data/doc/release_notes/5.31.0.txt +148 -0
  54. data/doc/release_notes/5.32.0.txt +46 -0
  55. data/doc/release_notes/5.33.0.txt +24 -0
  56. data/doc/release_notes/5.34.0.txt +40 -0
  57. data/doc/release_notes/5.35.0.txt +56 -0
  58. data/doc/release_notes/5.36.0.txt +60 -0
  59. data/doc/release_notes/5.37.0.txt +30 -0
  60. data/doc/release_notes/5.38.0.txt +28 -0
  61. data/doc/release_notes/5.39.0.txt +19 -0
  62. data/doc/release_notes/5.4.0.txt +80 -0
  63. data/doc/release_notes/5.40.0.txt +40 -0
  64. data/doc/release_notes/5.41.0.txt +25 -0
  65. data/doc/release_notes/5.42.0.txt +136 -0
  66. data/doc/release_notes/5.43.0.txt +98 -0
  67. data/doc/release_notes/5.44.0.txt +32 -0
  68. data/doc/release_notes/5.45.0.txt +34 -0
  69. data/doc/release_notes/5.46.0.txt +87 -0
  70. data/doc/release_notes/5.47.0.txt +59 -0
  71. data/doc/release_notes/5.48.0.txt +14 -0
  72. data/doc/release_notes/5.49.0.txt +59 -0
  73. data/doc/release_notes/5.5.0.txt +61 -0
  74. data/doc/release_notes/5.50.0.txt +78 -0
  75. data/doc/release_notes/5.51.0.txt +47 -0
  76. data/doc/release_notes/5.52.0.txt +87 -0
  77. data/doc/release_notes/5.53.0.txt +23 -0
  78. data/doc/release_notes/5.54.0.txt +27 -0
  79. data/doc/release_notes/5.55.0.txt +21 -0
  80. data/doc/release_notes/5.56.0.txt +51 -0
  81. data/doc/release_notes/5.57.0.txt +23 -0
  82. data/doc/release_notes/5.58.0.txt +31 -0
  83. data/doc/release_notes/5.59.0.txt +73 -0
  84. data/doc/release_notes/5.6.0.txt +31 -0
  85. data/doc/release_notes/5.60.0.txt +22 -0
  86. data/doc/release_notes/5.61.0.txt +43 -0
  87. data/doc/release_notes/5.7.0.txt +108 -0
  88. data/doc/release_notes/5.8.0.txt +170 -0
  89. data/doc/release_notes/5.9.0.txt +99 -0
  90. data/doc/schema_modification.rdoc +95 -75
  91. data/doc/security.rdoc +109 -80
  92. data/doc/sharding.rdoc +74 -47
  93. data/doc/sql.rdoc +147 -122
  94. data/doc/testing.rdoc +43 -20
  95. data/doc/thread_safety.rdoc +2 -4
  96. data/doc/transactions.rdoc +97 -18
  97. data/doc/validations.rdoc +52 -50
  98. data/doc/virtual_rows.rdoc +90 -109
  99. data/lib/sequel/adapters/ado/access.rb +15 -17
  100. data/lib/sequel/adapters/ado/mssql.rb +6 -15
  101. data/lib/sequel/adapters/ado.rb +150 -20
  102. data/lib/sequel/adapters/amalgalite.rb +11 -23
  103. data/lib/sequel/adapters/ibmdb.rb +47 -55
  104. data/lib/sequel/adapters/jdbc/db2.rb +29 -39
  105. data/lib/sequel/adapters/jdbc/derby.rb +58 -54
  106. data/lib/sequel/adapters/jdbc/h2.rb +93 -35
  107. data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
  108. data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
  109. data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
  110. data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
  111. data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
  112. data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
  113. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
  114. data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
  115. data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
  116. data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
  117. data/lib/sequel/adapters/jdbc.rb +145 -130
  118. data/lib/sequel/adapters/mock.rb +100 -111
  119. data/lib/sequel/adapters/mysql.rb +114 -122
  120. data/lib/sequel/adapters/mysql2.rb +147 -63
  121. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  122. data/lib/sequel/adapters/odbc/mssql.rb +8 -14
  123. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  124. data/lib/sequel/adapters/odbc.rb +20 -25
  125. data/lib/sequel/adapters/oracle.rb +50 -56
  126. data/lib/sequel/adapters/postgres.rb +305 -327
  127. data/lib/sequel/adapters/postgresql.rb +1 -1
  128. data/lib/sequel/adapters/shared/access.rb +74 -78
  129. data/lib/sequel/adapters/shared/db2.rb +118 -71
  130. data/lib/sequel/adapters/shared/mssql.rb +301 -220
  131. data/lib/sequel/adapters/shared/mysql.rb +299 -217
  132. data/lib/sequel/adapters/shared/oracle.rb +226 -65
  133. data/lib/sequel/adapters/shared/postgres.rb +935 -395
  134. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
  135. data/lib/sequel/adapters/shared/sqlite.rb +447 -173
  136. data/lib/sequel/adapters/sqlanywhere.rb +48 -35
  137. data/lib/sequel/adapters/sqlite.rb +156 -111
  138. data/lib/sequel/adapters/tinytds.rb +30 -38
  139. data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
  140. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
  141. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
  142. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  143. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  144. data/lib/sequel/adapters/utils/replace.rb +1 -4
  145. data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
  146. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  147. data/lib/sequel/ast_transformer.rb +17 -89
  148. data/lib/sequel/connection_pool/sharded_single.rb +18 -15
  149. data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
  150. data/lib/sequel/connection_pool/single.rb +18 -13
  151. data/lib/sequel/connection_pool/threaded.rb +121 -120
  152. data/lib/sequel/connection_pool.rb +48 -29
  153. data/lib/sequel/core.rb +351 -301
  154. data/lib/sequel/database/connecting.rb +69 -57
  155. data/lib/sequel/database/dataset.rb +13 -5
  156. data/lib/sequel/database/dataset_defaults.rb +18 -102
  157. data/lib/sequel/database/features.rb +18 -4
  158. data/lib/sequel/database/logging.rb +12 -11
  159. data/lib/sequel/database/misc.rb +180 -122
  160. data/lib/sequel/database/query.rb +47 -27
  161. data/lib/sequel/database/schema_generator.rb +178 -84
  162. data/lib/sequel/database/schema_methods.rb +172 -97
  163. data/lib/sequel/database/transactions.rb +205 -44
  164. data/lib/sequel/database.rb +17 -2
  165. data/lib/sequel/dataset/actions.rb +339 -155
  166. data/lib/sequel/dataset/dataset_module.rb +46 -0
  167. data/lib/sequel/dataset/features.rb +90 -35
  168. data/lib/sequel/dataset/graph.rb +80 -58
  169. data/lib/sequel/dataset/misc.rb +137 -47
  170. data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
  171. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  172. data/lib/sequel/dataset/query.rb +530 -222
  173. data/lib/sequel/dataset/sql.rb +590 -368
  174. data/lib/sequel/dataset.rb +26 -16
  175. data/lib/sequel/deprecated.rb +12 -2
  176. data/lib/sequel/exceptions.rb +46 -16
  177. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  178. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  179. data/lib/sequel/extensions/_pretty_table.rb +2 -5
  180. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  181. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  182. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  183. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  184. data/lib/sequel/extensions/blank.rb +8 -0
  185. data/lib/sequel/extensions/caller_logging.rb +79 -0
  186. data/lib/sequel/extensions/columns_introspection.rb +4 -3
  187. data/lib/sequel/extensions/connection_expiration.rb +20 -10
  188. data/lib/sequel/extensions/connection_validator.rb +11 -10
  189. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  190. data/lib/sequel/extensions/constraint_validations.rb +62 -39
  191. data/lib/sequel/extensions/core_extensions.rb +42 -48
  192. data/lib/sequel/extensions/core_refinements.rb +80 -59
  193. data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
  194. data/lib/sequel/extensions/date_arithmetic.rb +98 -39
  195. data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
  196. data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
  197. data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
  198. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  199. data/lib/sequel/extensions/escaped_like.rb +100 -0
  200. data/lib/sequel/extensions/eval_inspect.rb +12 -15
  201. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  202. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  203. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  204. data/lib/sequel/extensions/from_block.rb +1 -34
  205. data/lib/sequel/extensions/graph_each.rb +4 -4
  206. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  207. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  208. data/lib/sequel/extensions/index_caching.rb +109 -0
  209. data/lib/sequel/extensions/inflector.rb +13 -5
  210. data/lib/sequel/extensions/integer64.rb +32 -0
  211. data/lib/sequel/extensions/is_distinct_from.rb +141 -0
  212. data/lib/sequel/extensions/looser_typecasting.rb +17 -8
  213. data/lib/sequel/extensions/migration.rb +119 -78
  214. data/lib/sequel/extensions/named_timezones.rb +88 -23
  215. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
  216. data/lib/sequel/extensions/null_dataset.rb +8 -8
  217. data/lib/sequel/extensions/pagination.rb +32 -29
  218. data/lib/sequel/extensions/pg_array.rb +221 -287
  219. data/lib/sequel/extensions/pg_array_ops.rb +17 -9
  220. data/lib/sequel/extensions/pg_enum.rb +63 -23
  221. data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
  222. data/lib/sequel/extensions/pg_hstore.rb +45 -54
  223. data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
  224. data/lib/sequel/extensions/pg_inet.rb +31 -12
  225. data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
  226. data/lib/sequel/extensions/pg_interval.rb +56 -29
  227. data/lib/sequel/extensions/pg_json.rb +417 -140
  228. data/lib/sequel/extensions/pg_json_ops.rb +270 -18
  229. data/lib/sequel/extensions/pg_loose_count.rb +4 -2
  230. data/lib/sequel/extensions/pg_multirange.rb +372 -0
  231. data/lib/sequel/extensions/pg_range.rb +131 -191
  232. data/lib/sequel/extensions/pg_range_ops.rb +42 -13
  233. data/lib/sequel/extensions/pg_row.rb +48 -81
  234. data/lib/sequel/extensions/pg_row_ops.rb +33 -14
  235. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  236. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  237. data/lib/sequel/extensions/query.rb +9 -7
  238. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  239. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  240. data/lib/sequel/extensions/s.rb +60 -0
  241. data/lib/sequel/extensions/schema_caching.rb +10 -1
  242. data/lib/sequel/extensions/schema_dumper.rb +71 -48
  243. data/lib/sequel/extensions/select_remove.rb +4 -4
  244. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  245. data/lib/sequel/extensions/server_block.rb +51 -27
  246. data/lib/sequel/extensions/split_array_nil.rb +4 -4
  247. data/lib/sequel/extensions/sql_comments.rb +119 -7
  248. data/lib/sequel/extensions/sql_expr.rb +2 -1
  249. data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
  250. data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
  251. data/lib/sequel/extensions/string_agg.rb +11 -8
  252. data/lib/sequel/extensions/string_date_time.rb +19 -23
  253. data/lib/sequel/extensions/symbol_aref.rb +55 -0
  254. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  255. data/lib/sequel/extensions/symbol_as.rb +23 -0
  256. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  257. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  258. data/lib/sequel/extensions/to_dot.rb +10 -4
  259. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  260. data/lib/sequel/model/associations.rb +1006 -284
  261. data/lib/sequel/model/base.rb +560 -805
  262. data/lib/sequel/model/dataset_module.rb +11 -10
  263. data/lib/sequel/model/default_inflections.rb +1 -1
  264. data/lib/sequel/model/errors.rb +10 -3
  265. data/lib/sequel/model/exceptions.rb +8 -10
  266. data/lib/sequel/model/inflections.rb +7 -20
  267. data/lib/sequel/model/plugins.rb +114 -0
  268. data/lib/sequel/model.rb +32 -82
  269. data/lib/sequel/plugins/active_model.rb +30 -14
  270. data/lib/sequel/plugins/after_initialize.rb +1 -1
  271. data/lib/sequel/plugins/association_dependencies.rb +25 -18
  272. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  273. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  274. data/lib/sequel/plugins/association_pks.rb +147 -70
  275. data/lib/sequel/plugins/association_proxies.rb +33 -9
  276. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  277. data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
  278. data/lib/sequel/plugins/auto_validations.rb +95 -28
  279. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  280. data/lib/sequel/plugins/before_after_save.rb +0 -42
  281. data/lib/sequel/plugins/blacklist_security.rb +21 -12
  282. data/lib/sequel/plugins/boolean_readers.rb +5 -5
  283. data/lib/sequel/plugins/boolean_subsets.rb +13 -8
  284. data/lib/sequel/plugins/caching.rb +25 -16
  285. data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
  286. data/lib/sequel/plugins/column_conflicts.rb +16 -3
  287. data/lib/sequel/plugins/column_encryption.rb +728 -0
  288. data/lib/sequel/plugins/column_select.rb +7 -5
  289. data/lib/sequel/plugins/columns_updated.rb +42 -0
  290. data/lib/sequel/plugins/composition.rb +42 -26
  291. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  292. data/lib/sequel/plugins/constraint_validations.rb +20 -14
  293. data/lib/sequel/plugins/csv_serializer.rb +56 -35
  294. data/lib/sequel/plugins/dataset_associations.rb +40 -17
  295. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  296. data/lib/sequel/plugins/defaults_setter.rb +65 -10
  297. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  298. data/lib/sequel/plugins/dirty.rb +62 -24
  299. data/lib/sequel/plugins/eager_each.rb +3 -3
  300. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  301. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  302. data/lib/sequel/plugins/enum.rb +124 -0
  303. data/lib/sequel/plugins/error_splitter.rb +17 -12
  304. data/lib/sequel/plugins/finder.rb +246 -0
  305. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  306. data/lib/sequel/plugins/force_encoding.rb +7 -12
  307. data/lib/sequel/plugins/hook_class_methods.rb +37 -54
  308. data/lib/sequel/plugins/input_transformer.rb +18 -10
  309. data/lib/sequel/plugins/insert_conflict.rb +76 -0
  310. data/lib/sequel/plugins/insert_returning_select.rb +2 -2
  311. data/lib/sequel/plugins/instance_filters.rb +10 -8
  312. data/lib/sequel/plugins/instance_hooks.rb +34 -17
  313. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  314. data/lib/sequel/plugins/inverted_subsets.rb +22 -13
  315. data/lib/sequel/plugins/json_serializer.rb +124 -64
  316. data/lib/sequel/plugins/lazy_attributes.rb +21 -14
  317. data/lib/sequel/plugins/list.rb +35 -21
  318. data/lib/sequel/plugins/many_through_many.rb +134 -21
  319. data/lib/sequel/plugins/modification_detection.rb +15 -5
  320. data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
  321. data/lib/sequel/plugins/nested_attributes.rb +61 -31
  322. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  323. data/lib/sequel/plugins/pg_array_associations.rb +103 -53
  324. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
  325. data/lib/sequel/plugins/pg_row.rb +5 -51
  326. data/lib/sequel/plugins/prepared_statements.rb +60 -72
  327. data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
  328. data/lib/sequel/plugins/rcte_tree.rb +68 -82
  329. data/lib/sequel/plugins/require_valid_schema.rb +67 -0
  330. data/lib/sequel/plugins/serialization.rb +43 -46
  331. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
  332. data/lib/sequel/plugins/sharding.rb +15 -10
  333. data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
  334. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  335. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  336. data/lib/sequel/plugins/split_values.rb +11 -6
  337. data/lib/sequel/plugins/sql_comments.rb +189 -0
  338. data/lib/sequel/plugins/static_cache.rb +77 -53
  339. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  340. data/lib/sequel/plugins/string_stripper.rb +3 -3
  341. data/lib/sequel/plugins/subclasses.rb +43 -10
  342. data/lib/sequel/plugins/subset_conditions.rb +15 -5
  343. data/lib/sequel/plugins/table_select.rb +2 -2
  344. data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
  345. data/lib/sequel/plugins/throw_failures.rb +110 -0
  346. data/lib/sequel/plugins/timestamps.rb +20 -8
  347. data/lib/sequel/plugins/touch.rb +19 -8
  348. data/lib/sequel/plugins/tree.rb +62 -32
  349. data/lib/sequel/plugins/typecast_on_load.rb +12 -4
  350. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  351. data/lib/sequel/plugins/unused_associations.rb +521 -0
  352. data/lib/sequel/plugins/update_or_create.rb +4 -4
  353. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  354. data/lib/sequel/plugins/update_refresh.rb +26 -15
  355. data/lib/sequel/plugins/uuid.rb +7 -11
  356. data/lib/sequel/plugins/validate_associated.rb +18 -0
  357. data/lib/sequel/plugins/validation_class_methods.rb +38 -19
  358. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  359. data/lib/sequel/plugins/validation_helpers.rb +57 -41
  360. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  361. data/lib/sequel/plugins/xml_serializer.rb +30 -31
  362. data/lib/sequel/sql.rb +471 -331
  363. data/lib/sequel/timezones.rb +78 -47
  364. data/lib/sequel/version.rb +7 -2
  365. data/lib/sequel.rb +1 -1
  366. metadata +217 -521
  367. data/Rakefile +0 -164
  368. data/doc/active_record.rdoc +0 -928
  369. data/doc/release_notes/1.0.txt +0 -38
  370. data/doc/release_notes/1.1.txt +0 -143
  371. data/doc/release_notes/1.3.txt +0 -101
  372. data/doc/release_notes/1.4.0.txt +0 -53
  373. data/doc/release_notes/1.5.0.txt +0 -155
  374. data/doc/release_notes/2.0.0.txt +0 -298
  375. data/doc/release_notes/2.1.0.txt +0 -271
  376. data/doc/release_notes/2.10.0.txt +0 -328
  377. data/doc/release_notes/2.11.0.txt +0 -215
  378. data/doc/release_notes/2.12.0.txt +0 -534
  379. data/doc/release_notes/2.2.0.txt +0 -253
  380. data/doc/release_notes/2.3.0.txt +0 -88
  381. data/doc/release_notes/2.4.0.txt +0 -106
  382. data/doc/release_notes/2.5.0.txt +0 -137
  383. data/doc/release_notes/2.6.0.txt +0 -157
  384. data/doc/release_notes/2.7.0.txt +0 -166
  385. data/doc/release_notes/2.8.0.txt +0 -171
  386. data/doc/release_notes/2.9.0.txt +0 -97
  387. data/doc/release_notes/3.0.0.txt +0 -221
  388. data/doc/release_notes/3.1.0.txt +0 -406
  389. data/doc/release_notes/3.10.0.txt +0 -286
  390. data/doc/release_notes/3.11.0.txt +0 -254
  391. data/doc/release_notes/3.12.0.txt +0 -304
  392. data/doc/release_notes/3.13.0.txt +0 -210
  393. data/doc/release_notes/3.14.0.txt +0 -118
  394. data/doc/release_notes/3.15.0.txt +0 -78
  395. data/doc/release_notes/3.16.0.txt +0 -45
  396. data/doc/release_notes/3.17.0.txt +0 -58
  397. data/doc/release_notes/3.18.0.txt +0 -120
  398. data/doc/release_notes/3.19.0.txt +0 -67
  399. data/doc/release_notes/3.2.0.txt +0 -268
  400. data/doc/release_notes/3.20.0.txt +0 -41
  401. data/doc/release_notes/3.21.0.txt +0 -87
  402. data/doc/release_notes/3.22.0.txt +0 -39
  403. data/doc/release_notes/3.23.0.txt +0 -172
  404. data/doc/release_notes/3.24.0.txt +0 -420
  405. data/doc/release_notes/3.25.0.txt +0 -88
  406. data/doc/release_notes/3.26.0.txt +0 -88
  407. data/doc/release_notes/3.27.0.txt +0 -82
  408. data/doc/release_notes/3.28.0.txt +0 -304
  409. data/doc/release_notes/3.29.0.txt +0 -459
  410. data/doc/release_notes/3.3.0.txt +0 -192
  411. data/doc/release_notes/3.30.0.txt +0 -135
  412. data/doc/release_notes/3.31.0.txt +0 -146
  413. data/doc/release_notes/3.32.0.txt +0 -202
  414. data/doc/release_notes/3.33.0.txt +0 -157
  415. data/doc/release_notes/3.34.0.txt +0 -671
  416. data/doc/release_notes/3.35.0.txt +0 -144
  417. data/doc/release_notes/3.36.0.txt +0 -245
  418. data/doc/release_notes/3.37.0.txt +0 -338
  419. data/doc/release_notes/3.38.0.txt +0 -234
  420. data/doc/release_notes/3.39.0.txt +0 -237
  421. data/doc/release_notes/3.4.0.txt +0 -325
  422. data/doc/release_notes/3.40.0.txt +0 -73
  423. data/doc/release_notes/3.41.0.txt +0 -155
  424. data/doc/release_notes/3.42.0.txt +0 -74
  425. data/doc/release_notes/3.43.0.txt +0 -105
  426. data/doc/release_notes/3.44.0.txt +0 -152
  427. data/doc/release_notes/3.45.0.txt +0 -179
  428. data/doc/release_notes/3.46.0.txt +0 -122
  429. data/doc/release_notes/3.47.0.txt +0 -270
  430. data/doc/release_notes/3.48.0.txt +0 -477
  431. data/doc/release_notes/3.5.0.txt +0 -510
  432. data/doc/release_notes/3.6.0.txt +0 -366
  433. data/doc/release_notes/3.7.0.txt +0 -179
  434. data/doc/release_notes/3.8.0.txt +0 -151
  435. data/doc/release_notes/3.9.0.txt +0 -233
  436. data/doc/release_notes/4.0.0.txt +0 -262
  437. data/doc/release_notes/4.1.0.txt +0 -85
  438. data/doc/release_notes/4.10.0.txt +0 -226
  439. data/doc/release_notes/4.11.0.txt +0 -147
  440. data/doc/release_notes/4.12.0.txt +0 -105
  441. data/doc/release_notes/4.13.0.txt +0 -169
  442. data/doc/release_notes/4.14.0.txt +0 -68
  443. data/doc/release_notes/4.15.0.txt +0 -56
  444. data/doc/release_notes/4.16.0.txt +0 -36
  445. data/doc/release_notes/4.17.0.txt +0 -38
  446. data/doc/release_notes/4.18.0.txt +0 -36
  447. data/doc/release_notes/4.19.0.txt +0 -45
  448. data/doc/release_notes/4.2.0.txt +0 -129
  449. data/doc/release_notes/4.20.0.txt +0 -79
  450. data/doc/release_notes/4.21.0.txt +0 -94
  451. data/doc/release_notes/4.22.0.txt +0 -72
  452. data/doc/release_notes/4.23.0.txt +0 -65
  453. data/doc/release_notes/4.24.0.txt +0 -99
  454. data/doc/release_notes/4.25.0.txt +0 -181
  455. data/doc/release_notes/4.26.0.txt +0 -44
  456. data/doc/release_notes/4.27.0.txt +0 -78
  457. data/doc/release_notes/4.28.0.txt +0 -57
  458. data/doc/release_notes/4.29.0.txt +0 -41
  459. data/doc/release_notes/4.3.0.txt +0 -40
  460. data/doc/release_notes/4.30.0.txt +0 -37
  461. data/doc/release_notes/4.31.0.txt +0 -57
  462. data/doc/release_notes/4.32.0.txt +0 -132
  463. data/doc/release_notes/4.33.0.txt +0 -88
  464. data/doc/release_notes/4.34.0.txt +0 -86
  465. data/doc/release_notes/4.35.0.txt +0 -130
  466. data/doc/release_notes/4.36.0.txt +0 -116
  467. data/doc/release_notes/4.4.0.txt +0 -92
  468. data/doc/release_notes/4.5.0.txt +0 -34
  469. data/doc/release_notes/4.6.0.txt +0 -30
  470. data/doc/release_notes/4.7.0.txt +0 -103
  471. data/doc/release_notes/4.8.0.txt +0 -175
  472. data/doc/release_notes/4.9.0.txt +0 -190
  473. data/lib/sequel/adapters/cubrid.rb +0 -144
  474. data/lib/sequel/adapters/do/mysql.rb +0 -66
  475. data/lib/sequel/adapters/do/postgres.rb +0 -44
  476. data/lib/sequel/adapters/do/sqlite3.rb +0 -42
  477. data/lib/sequel/adapters/do.rb +0 -158
  478. data/lib/sequel/adapters/jdbc/as400.rb +0 -84
  479. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
  480. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
  481. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
  482. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
  483. data/lib/sequel/adapters/odbc/progress.rb +0 -10
  484. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  485. data/lib/sequel/adapters/shared/firebird.rb +0 -247
  486. data/lib/sequel/adapters/shared/informix.rb +0 -54
  487. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
  488. data/lib/sequel/adapters/shared/progress.rb +0 -40
  489. data/lib/sequel/adapters/swift/mysql.rb +0 -49
  490. data/lib/sequel/adapters/swift/postgres.rb +0 -47
  491. data/lib/sequel/adapters/swift/sqlite.rb +0 -49
  492. data/lib/sequel/adapters/swift.rb +0 -160
  493. data/lib/sequel/adapters/utils/pg_types.rb +0 -70
  494. data/lib/sequel/dataset/mutation.rb +0 -111
  495. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
  496. data/lib/sequel/extensions/filter_having.rb +0 -63
  497. data/lib/sequel/extensions/hash_aliases.rb +0 -49
  498. data/lib/sequel/extensions/meta_def.rb +0 -35
  499. data/lib/sequel/extensions/query_literals.rb +0 -84
  500. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
  501. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
  502. data/lib/sequel/extensions/set_overrides.rb +0 -76
  503. data/lib/sequel/no_core_ext.rb +0 -3
  504. data/lib/sequel/plugins/association_autoreloading.rb +0 -9
  505. data/lib/sequel/plugins/identifier_columns.rb +0 -47
  506. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
  507. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
  508. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
  509. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
  510. data/lib/sequel/plugins/schema.rb +0 -82
  511. data/lib/sequel/plugins/scissors.rb +0 -35
  512. data/spec/adapter_spec.rb +0 -4
  513. data/spec/adapters/db2_spec.rb +0 -160
  514. data/spec/adapters/firebird_spec.rb +0 -411
  515. data/spec/adapters/informix_spec.rb +0 -100
  516. data/spec/adapters/mssql_spec.rb +0 -733
  517. data/spec/adapters/mysql_spec.rb +0 -1319
  518. data/spec/adapters/oracle_spec.rb +0 -313
  519. data/spec/adapters/postgres_spec.rb +0 -3790
  520. data/spec/adapters/spec_helper.rb +0 -49
  521. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  522. data/spec/adapters/sqlite_spec.rb +0 -688
  523. data/spec/bin_spec.rb +0 -258
  524. data/spec/core/connection_pool_spec.rb +0 -1045
  525. data/spec/core/database_spec.rb +0 -2636
  526. data/spec/core/dataset_spec.rb +0 -5175
  527. data/spec/core/deprecated_spec.rb +0 -70
  528. data/spec/core/expression_filters_spec.rb +0 -1247
  529. data/spec/core/mock_adapter_spec.rb +0 -464
  530. data/spec/core/object_graph_spec.rb +0 -303
  531. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  532. data/spec/core/schema_generator_spec.rb +0 -203
  533. data/spec/core/schema_spec.rb +0 -1676
  534. data/spec/core/spec_helper.rb +0 -34
  535. data/spec/core/version_spec.rb +0 -7
  536. data/spec/core_extensions_spec.rb +0 -699
  537. data/spec/core_model_spec.rb +0 -2
  538. data/spec/core_spec.rb +0 -1
  539. data/spec/extensions/accessed_columns_spec.rb +0 -51
  540. data/spec/extensions/active_model_spec.rb +0 -85
  541. data/spec/extensions/after_initialize_spec.rb +0 -24
  542. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  543. data/spec/extensions/association_dependencies_spec.rb +0 -117
  544. data/spec/extensions/association_pks_spec.rb +0 -405
  545. data/spec/extensions/association_proxies_spec.rb +0 -86
  546. data/spec/extensions/auto_validations_spec.rb +0 -192
  547. data/spec/extensions/before_after_save_spec.rb +0 -40
  548. data/spec/extensions/blacklist_security_spec.rb +0 -88
  549. data/spec/extensions/blank_spec.rb +0 -69
  550. data/spec/extensions/boolean_readers_spec.rb +0 -93
  551. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  552. data/spec/extensions/caching_spec.rb +0 -270
  553. data/spec/extensions/class_table_inheritance_spec.rb +0 -444
  554. data/spec/extensions/column_conflicts_spec.rb +0 -60
  555. data/spec/extensions/column_select_spec.rb +0 -108
  556. data/spec/extensions/columns_introspection_spec.rb +0 -91
  557. data/spec/extensions/composition_spec.rb +0 -242
  558. data/spec/extensions/connection_expiration_spec.rb +0 -121
  559. data/spec/extensions/connection_validator_spec.rb +0 -127
  560. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
  561. data/spec/extensions/constraint_validations_spec.rb +0 -389
  562. data/spec/extensions/core_refinements_spec.rb +0 -519
  563. data/spec/extensions/csv_serializer_spec.rb +0 -180
  564. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  565. data/spec/extensions/dataset_associations_spec.rb +0 -343
  566. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  567. data/spec/extensions/date_arithmetic_spec.rb +0 -167
  568. data/spec/extensions/defaults_setter_spec.rb +0 -102
  569. data/spec/extensions/delay_add_association_spec.rb +0 -74
  570. data/spec/extensions/dirty_spec.rb +0 -180
  571. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
  572. data/spec/extensions/eager_each_spec.rb +0 -66
  573. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  574. data/spec/extensions/error_splitter_spec.rb +0 -18
  575. data/spec/extensions/error_sql_spec.rb +0 -20
  576. data/spec/extensions/eval_inspect_spec.rb +0 -73
  577. data/spec/extensions/filter_having_spec.rb +0 -40
  578. data/spec/extensions/force_encoding_spec.rb +0 -114
  579. data/spec/extensions/from_block_spec.rb +0 -21
  580. data/spec/extensions/graph_each_spec.rb +0 -119
  581. data/spec/extensions/hash_aliases_spec.rb +0 -24
  582. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  583. data/spec/extensions/identifier_columns_spec.rb +0 -17
  584. data/spec/extensions/inflector_spec.rb +0 -183
  585. data/spec/extensions/input_transformer_spec.rb +0 -54
  586. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  587. data/spec/extensions/instance_filters_spec.rb +0 -79
  588. data/spec/extensions/instance_hooks_spec.rb +0 -276
  589. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  590. data/spec/extensions/json_serializer_spec.rb +0 -304
  591. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  592. data/spec/extensions/list_spec.rb +0 -278
  593. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  594. data/spec/extensions/many_through_many_spec.rb +0 -2172
  595. data/spec/extensions/meta_def_spec.rb +0 -21
  596. data/spec/extensions/migration_spec.rb +0 -728
  597. data/spec/extensions/modification_detection_spec.rb +0 -80
  598. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  599. data/spec/extensions/named_timezones_spec.rb +0 -108
  600. data/spec/extensions/nested_attributes_spec.rb +0 -697
  601. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -65
  602. data/spec/extensions/null_dataset_spec.rb +0 -85
  603. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  604. data/spec/extensions/pagination_spec.rb +0 -118
  605. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  606. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  607. data/spec/extensions/pg_array_spec.rb +0 -390
  608. data/spec/extensions/pg_enum_spec.rb +0 -92
  609. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  610. data/spec/extensions/pg_hstore_spec.rb +0 -206
  611. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  612. data/spec/extensions/pg_inet_spec.rb +0 -52
  613. data/spec/extensions/pg_interval_spec.rb +0 -76
  614. data/spec/extensions/pg_json_ops_spec.rb +0 -275
  615. data/spec/extensions/pg_json_spec.rb +0 -218
  616. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  617. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  618. data/spec/extensions/pg_range_spec.rb +0 -473
  619. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  620. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  621. data/spec/extensions/pg_row_spec.rb +0 -360
  622. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  623. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  624. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  625. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  626. data/spec/extensions/prepared_statements_spec.rb +0 -103
  627. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  628. data/spec/extensions/pretty_table_spec.rb +0 -92
  629. data/spec/extensions/query_literals_spec.rb +0 -183
  630. data/spec/extensions/query_spec.rb +0 -102
  631. data/spec/extensions/rcte_tree_spec.rb +0 -392
  632. data/spec/extensions/round_timestamps_spec.rb +0 -43
  633. data/spec/extensions/schema_caching_spec.rb +0 -41
  634. data/spec/extensions/schema_dumper_spec.rb +0 -814
  635. data/spec/extensions/schema_spec.rb +0 -117
  636. data/spec/extensions/scissors_spec.rb +0 -26
  637. data/spec/extensions/select_remove_spec.rb +0 -38
  638. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  639. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  640. data/spec/extensions/serialization_spec.rb +0 -362
  641. data/spec/extensions/server_block_spec.rb +0 -90
  642. data/spec/extensions/server_logging_spec.rb +0 -45
  643. data/spec/extensions/set_overrides_spec.rb +0 -61
  644. data/spec/extensions/sharding_spec.rb +0 -198
  645. data/spec/extensions/shared_caching_spec.rb +0 -175
  646. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  647. data/spec/extensions/singular_table_names_spec.rb +0 -22
  648. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  649. data/spec/extensions/spec_helper.rb +0 -71
  650. data/spec/extensions/split_array_nil_spec.rb +0 -24
  651. data/spec/extensions/split_values_spec.rb +0 -22
  652. data/spec/extensions/sql_comments_spec.rb +0 -27
  653. data/spec/extensions/sql_expr_spec.rb +0 -60
  654. data/spec/extensions/static_cache_spec.rb +0 -361
  655. data/spec/extensions/string_agg_spec.rb +0 -85
  656. data/spec/extensions/string_date_time_spec.rb +0 -95
  657. data/spec/extensions/string_stripper_spec.rb +0 -68
  658. data/spec/extensions/subclasses_spec.rb +0 -66
  659. data/spec/extensions/subset_conditions_spec.rb +0 -38
  660. data/spec/extensions/table_select_spec.rb +0 -71
  661. data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
  662. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  663. data/spec/extensions/timestamps_spec.rb +0 -175
  664. data/spec/extensions/to_dot_spec.rb +0 -154
  665. data/spec/extensions/touch_spec.rb +0 -203
  666. data/spec/extensions/tree_spec.rb +0 -274
  667. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  668. data/spec/extensions/unlimited_update_spec.rb +0 -20
  669. data/spec/extensions/update_or_create_spec.rb +0 -87
  670. data/spec/extensions/update_primary_key_spec.rb +0 -100
  671. data/spec/extensions/update_refresh_spec.rb +0 -53
  672. data/spec/extensions/uuid_spec.rb +0 -106
  673. data/spec/extensions/validate_associated_spec.rb +0 -52
  674. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  675. data/spec/extensions/validation_helpers_spec.rb +0 -554
  676. data/spec/extensions/xml_serializer_spec.rb +0 -207
  677. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  678. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  679. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  680. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  681. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  682. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  683. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  684. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  685. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  686. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  687. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  688. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  689. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  690. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  691. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  692. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  693. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  694. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  695. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  696. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  697. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  698. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  699. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  700. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  701. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  702. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  703. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  704. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  705. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  706. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  707. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  708. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  709. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  710. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  711. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  712. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  713. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  714. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  715. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  716. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  717. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  718. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  719. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  720. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  721. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  722. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  723. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  724. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  725. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  726. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  727. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  728. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  729. data/spec/guards_helper.rb +0 -55
  730. data/spec/integration/associations_test.rb +0 -2506
  731. data/spec/integration/database_test.rb +0 -113
  732. data/spec/integration/dataset_test.rb +0 -1858
  733. data/spec/integration/eager_loader_test.rb +0 -687
  734. data/spec/integration/migrator_test.rb +0 -262
  735. data/spec/integration/model_test.rb +0 -230
  736. data/spec/integration/plugin_test.rb +0 -2297
  737. data/spec/integration/prepared_statement_test.rb +0 -467
  738. data/spec/integration/schema_test.rb +0 -815
  739. data/spec/integration/spec_helper.rb +0 -56
  740. data/spec/integration/timezone_test.rb +0 -86
  741. data/spec/integration/transaction_test.rb +0 -406
  742. data/spec/integration/type_test.rb +0 -133
  743. data/spec/model/association_reflection_spec.rb +0 -565
  744. data/spec/model/associations_spec.rb +0 -4589
  745. data/spec/model/base_spec.rb +0 -759
  746. data/spec/model/class_dataset_methods_spec.rb +0 -150
  747. data/spec/model/dataset_methods_spec.rb +0 -149
  748. data/spec/model/eager_loading_spec.rb +0 -2197
  749. data/spec/model/hooks_spec.rb +0 -604
  750. data/spec/model/inflector_spec.rb +0 -26
  751. data/spec/model/model_spec.rb +0 -1097
  752. data/spec/model/plugins_spec.rb +0 -299
  753. data/spec/model/record_spec.rb +0 -2162
  754. data/spec/model/spec_helper.rb +0 -46
  755. data/spec/model/validations_spec.rb +0 -193
  756. data/spec/model_no_assoc_spec.rb +0 -1
  757. data/spec/model_spec.rb +0 -1
  758. data/spec/plugin_spec.rb +0 -1
  759. data/spec/sequel_coverage.rb +0 -15
  760. data/spec/spec_config.rb +0 -10
data/lib/sequel/sql.rb CHANGED
@@ -1,41 +1,16 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Sequel
4
- if RUBY_VERSION < '1.9.0'
5
- # :nocov:
6
- # If on Ruby 1.8, create a <tt>Sequel::BasicObject</tt> class that is similar to the
7
- # the Ruby 1.9 +BasicObject+ class. This is used in a few places where proxy
8
- # objects are needed that respond to any method call.
9
- class BasicObject
10
- # The instance methods to not remove from the class when removing
11
- # other methods.
12
- KEEP_METHODS = %w"__id__ __send__ __metaclass__ instance_eval instance_exec == equal? initialize method_missing"
13
-
14
- # Remove all but the most basic instance methods from the class. A separate
15
- # method so that it can be called again if necessary if you load libraries
16
- # after Sequel that add instance methods to +Object+.
17
- def self.remove_methods!
18
- ((private_instance_methods + instance_methods) - KEEP_METHODS).each{|m| undef_method(m)}
19
- end
20
- remove_methods!
21
- end
22
- # :nocov:
23
- else
24
- # If on 1.9, create a <tt>Sequel::BasicObject</tt> class that is just like the
25
- # default +BasicObject+ class, except that missing constants are resolved in
26
- # +Object+. This allows the virtual row support to work with classes
27
- # without prefixing them with ::, such as:
28
- #
29
- # DB[:bonds].filter{maturity_date > Time.now}
30
- class BasicObject < ::BasicObject
31
- # Lookup missing constants in <tt>::Object</tt>
32
- def self.const_missing(name)
33
- ::Object.const_get(name)
34
- end
35
-
36
- # No-op method on ruby 1.9, which has a real +BasicObject+ class.
37
- def self.remove_methods!
38
- end
4
+ # The <tt>Sequel::BasicObject</tt> class is just like the
5
+ # default +BasicObject+ class, except that missing constants are resolved in
6
+ # +Object+. This allows the virtual row support to work with classes
7
+ # without prefixing them with ::, such as:
8
+ #
9
+ # DB[:bonds].where{maturity_date > Time.now}
10
+ class BasicObject < ::BasicObject
11
+ # Lookup missing constants in <tt>::Object</tt>
12
+ def self.const_missing(name)
13
+ ::Object.const_get(name)
39
14
  end
40
15
  end
41
16
 
@@ -43,12 +18,47 @@ module Sequel
43
18
  end
44
19
 
45
20
  # Time subclass that gets literalized with only the time value, so it operates
46
- # like a standard SQL time type.
21
+ # like a standard SQL time type. This type does not support timezones, by design,
22
+ # so it will not work correctly with <tt>time with time zone</tt> types.
47
23
  class SQLTime < ::Time
48
- # Create a new SQLTime instance given an hour, minute, and second.
49
- def self.create(hour, minute, second, usec = 0)
50
- t = now
51
- local(t.year, t.month, t.day, hour, minute, second, usec)
24
+ @date = nil
25
+
26
+ class << self
27
+ # Set the date used for SQLTime instances.
28
+ attr_writer :date
29
+
30
+ # Use the date explicitly set, or the current date if there is not a
31
+ # date set.
32
+ def date
33
+ @date || now
34
+ end
35
+
36
+ # Set the correct date and timezone when parsing times.
37
+ def parse(*)
38
+ t = super
39
+
40
+ utc = Sequel.application_timezone == :utc
41
+ d = @date
42
+ if d || utc
43
+ meth = utc ? :utc : :local
44
+ d ||= t
45
+ t = public_send(meth, d.year, d.month, d.day, t.hour, t.min, t.sec, t.usec)
46
+ end
47
+
48
+ t
49
+ end
50
+
51
+ # Create a new SQLTime instance given an hour, minute, second, and usec.
52
+ def create(hour, minute, second, usec = 0)
53
+ t = date
54
+ meth = Sequel.application_timezone == :utc ? :utc : :local
55
+ public_send(meth, t.year, t.month, t.day, hour, minute, second, usec)
56
+ end
57
+ end
58
+
59
+ # Show that this is an SQLTime, and the time represented
60
+ def inspect
61
+ "#<#{self.class} #{to_s}>"
52
62
  end
53
63
 
54
64
  # Return a string in HH:MM:SS format representing the time.
@@ -64,18 +74,11 @@ module Sequel
64
74
  end
65
75
 
66
76
  # The SQL module holds classes whose instances represent SQL fragments.
67
- # It also holds modules that are included in core ruby classes that
68
- # make Sequel a friendly DSL.
77
+ # It also holds modules that are used by these classes.
69
78
  module SQL
70
-
71
- ### Parent Classes ###
72
-
73
- # Classes/Modules aren't in alphabetical order due to the fact that
74
- # some reference constants defined in others at load time.
75
-
76
79
  # Base class for all SQL expression objects.
77
80
  class Expression
78
- @comparison_attrs = []
81
+ @comparison_attrs = [].freeze
79
82
 
80
83
  class << self
81
84
  # All attributes used for equality and hash methods.
@@ -97,7 +100,7 @@ module Sequel
97
100
  subclass.instance_variable_set(:@comparison_attrs, comparison_attrs.dup)
98
101
  end
99
102
 
100
- private
103
+ private
101
104
 
102
105
  # Create a to_s instance method that takes a dataset, and calls
103
106
  # the method provided on the dataset with args as the argument (self by default).
@@ -107,9 +110,17 @@ module Sequel
107
110
  # arbitrary code execution.
108
111
  def to_s_method(meth, args=:self) # :nodoc:
109
112
  class_eval("def to_s_append(ds, sql) ds.#{meth}_append(sql, #{args}) end", __FILE__, __LINE__)
113
+ @comparison_attrs.freeze
110
114
  end
111
115
  end
112
116
 
117
+ # Make clone/dup return self, since Expression objects are supposed to
118
+ # be frozen value objects
119
+ def clone
120
+ self
121
+ end
122
+ alias dup clone
123
+
113
124
  # Alias of <tt>eql?</tt>
114
125
  def ==(other)
115
126
  eql?(other)
@@ -118,34 +129,21 @@ module Sequel
118
129
  # Returns true if the receiver is the same expression as the
119
130
  # the +other+ expression.
120
131
  def eql?(other)
121
- other.is_a?(self.class) && !self.class.comparison_attrs.find{|a| send(a) != other.send(a)}
132
+ other.is_a?(self.class) && !self.class.comparison_attrs.find{|a| public_send(a) != other.public_send(a)}
122
133
  end
123
134
 
124
135
  # Make sure that the hash value is the same if the attributes are the same.
125
136
  def hash
126
- ([self.class] + self.class.comparison_attrs.map{|x| send(x)}).hash
137
+ ([self.class] + self.class.comparison_attrs.map{|x| public_send(x)}).hash
127
138
  end
128
139
 
129
- # Show the class name and instance variables for the object, necessary
130
- # for correct operation on ruby 1.9.2.
140
+ # Show the class name and instance variables for the object.
131
141
  def inspect
132
142
  "#<#{self.class} #{instance_variables.map{|iv| "#{iv}=>#{instance_variable_get(iv).inspect}"}.join(', ')}>"
133
143
  end
134
-
135
- # Returns +self+, because <tt>SQL::Expression</tt> already acts like +LiteralString+.
136
- def lit
137
- self
138
- end
139
-
140
- # Alias of +to_s+
141
- def sql_literal(ds)
142
- s = String.new
143
- to_s_append(ds, s)
144
- s
145
- end
146
144
  end
147
145
 
148
- # Represents a complex SQL expression, with a given operator and one
146
+ # Represents a SQL expression, with a given operator and one
149
147
  # or more attributes (which may also be ComplexExpressions, forming
150
148
  # a tree). This class is the backbone of Sequel's ruby expression DSL.
151
149
  #
@@ -160,46 +158,49 @@ module Sequel
160
158
  :'NOT LIKE' => :LIKE, :~ => :'!~', :'!~' => :~, :IN => :'NOT IN',
161
159
  :'NOT IN' => :IN, :IS => :'IS NOT', :'IS NOT' => :IS, :'~*' => :'!~*',
162
160
  :'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
163
- :'NOT ILIKE'=>:ILIKE}
161
+ :'NOT ILIKE'=>:ILIKE}.freeze
164
162
 
165
163
  # Standard mathematical operators used in +NumericMethods+
166
- MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
164
+ MATHEMATICAL_OPERATORS = [:+, :-, :/, :*, :**].freeze
167
165
 
168
- # Bitwise mathematical operators used in +NumericMethods+
169
- BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>, :%]
166
+ # Bitwise mathematical operators used in +BitwiseMethods+
167
+ BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>, :%].freeze
170
168
 
171
169
  # Operators that check for equality
172
- EQUALITY_OPERATORS = [:'=', :'!=']
170
+ EQUALITY_OPERATORS = [:'=', :'!='].freeze
173
171
 
174
172
  # Inequality operators used in +InequalityMethods+
175
- INEQUALITY_OPERATORS = [:<, :>, :<=, :>=]
173
+ INEQUALITY_OPERATORS = [:<, :>, :<=, :>=].freeze
176
174
 
177
175
  # Hash of ruby operator symbols to SQL operators, used in +BooleanMethods+
178
- BOOLEAN_OPERATOR_METHODS = {:& => :AND, :| =>:OR}
176
+ BOOLEAN_OPERATOR_METHODS = {:& => :AND, :| =>:OR}.freeze
179
177
 
180
178
  # Operators that use IN/NOT IN for inclusion/exclusion
181
- IN_OPERATORS = [:IN, :'NOT IN']
179
+ IN_OPERATORS = [:IN, :'NOT IN'].freeze
182
180
 
183
181
  # Operators that use IS, used for special casing to override literal true/false values
184
- IS_OPERATORS = [:IS, :'IS NOT']
182
+ IS_OPERATORS = [:IS, :'IS NOT'].freeze
185
183
 
186
184
  # Operators that do pattern matching via regular expressions
187
- REGEXP_OPERATORS = [:~, :'!~', :'~*', :'!~*']
185
+ REGEXP_OPERATORS = [:~, :'!~', :'~*', :'!~*'].freeze
188
186
 
189
187
  # Operators that do pattern matching via LIKE
190
- LIKE_OPERATORS = [:LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE']
188
+ LIKE_OPERATORS = [:LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE'].freeze
191
189
 
192
190
  # Operator symbols that take exactly two arguments
193
- TWO_ARITY_OPERATORS = EQUALITY_OPERATORS + INEQUALITY_OPERATORS + IS_OPERATORS + IN_OPERATORS + REGEXP_OPERATORS + LIKE_OPERATORS
191
+ TWO_ARITY_OPERATORS = (EQUALITY_OPERATORS + INEQUALITY_OPERATORS + IS_OPERATORS + IN_OPERATORS + REGEXP_OPERATORS + LIKE_OPERATORS + [:**]).freeze
194
192
 
195
193
  # Operator symbols that take one or more arguments
196
- N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS
194
+ N_ARITY_OPERATORS = ([:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS - [:**]).freeze
195
+
196
+ # Operator symbols that are associative
197
+ ASSOCIATIVE_OPERATORS = [:AND, :OR, :'||', :+, :*, :&, :|].freeze
197
198
 
198
199
  # Operator symbols that take only a single argument
199
- ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~']
200
+ ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~'].freeze
200
201
 
201
202
  # Custom expressions that may have different syntax on different databases
202
- CUSTOM_EXPRESSIONS = [:extract]
203
+ CUSTOM_EXPRESSIONS = [:extract].freeze
203
204
 
204
205
  # The operator symbol for this object
205
206
  attr_reader :op
@@ -218,9 +219,12 @@ module Sequel
218
219
  case op
219
220
  when *N_ARITY_OPERATORS
220
221
  raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
221
- old_args = args.map{|a| a.is_a?(self.class) && a.op == :NOOP ? a.args.first : a}
222
- args = []
223
- old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
222
+ args.map!{|a| a.is_a?(self.class) && a.op == :NOOP ? a.args.first : a}
223
+ if ASSOCIATIVE_OPERATORS.include?(op)
224
+ old_args = args
225
+ args = []
226
+ old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
227
+ end
224
228
  when *TWO_ARITY_OPERATORS
225
229
  raise(Error, "The #{op} operator requires precisely 2 arguments") unless args.length == 2
226
230
  # With IN/NOT IN, even if the second argument is an array of two element arrays,
@@ -235,7 +239,8 @@ module Sequel
235
239
  raise(Error, "Invalid operator #{op}")
236
240
  end
237
241
  @op = op
238
- @args = args
242
+ @args = args.freeze
243
+ freeze
239
244
  end
240
245
 
241
246
  to_s_method :complex_expression_sql, '@op, @args'
@@ -246,8 +251,6 @@ module Sequel
246
251
  class GenericExpression < Expression
247
252
  end
248
253
 
249
- ### Modules ###
250
-
251
254
  # Includes an +as+ method that creates an SQL alias.
252
255
  module AliasMethods
253
256
  # Create an SQL alias (+AliasedExpression+) of the receiving column or expression to the given alias.
@@ -263,12 +266,12 @@ module Sequel
263
266
  # methods overlap with the standard +BooleanMethods methods+, and they only
264
267
  # make sense for integers, they are only included in +NumericExpression+.
265
268
  #
266
- # :a.sql_number & :b # "a" & "b"
267
- # :a.sql_number | :b # "a" | "b"
268
- # :a.sql_number ^ :b # "a" ^ "b"
269
- # :a.sql_number << :b # "a" << "b"
270
- # :a.sql_number >> :b # "a" >> "b"
271
- # ~:a.sql_number # ~"a"
269
+ # Sequel[:a].sql_number & :b # "a" & "b"
270
+ # Sequel[:a].sql_number | :b # "a" | "b"
271
+ # Sequel[:a].sql_number ^ :b # "a" ^ "b"
272
+ # Sequel[:a].sql_number << :b # "a" << "b"
273
+ # Sequel[:a].sql_number >> :b # "a" >> "b"
274
+ # ~Sequel[:a].sql_number # ~"a"
272
275
  module BitwiseMethods
273
276
  ComplexExpression::BITWISE_OPERATORS.each do |o|
274
277
  module_eval("def #{o}(o) NumericExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__)
@@ -276,25 +279,24 @@ module Sequel
276
279
 
277
280
  # Do the bitwise compliment of the self
278
281
  #
279
- # ~:a.sql_number # ~"a"
282
+ # ~(Sequel[:a].sql_number) # ~"a"
280
283
  def ~
281
284
  NumericExpression.new(:'B~', self)
282
285
  end
283
286
  end
284
287
 
285
288
  # This module includes the boolean/logical AND (&), OR (|) and NOT (~) operators
286
- # that are defined on objects that can be used in a boolean context in SQL
287
- # (+Symbol+, +LiteralString+, and <tt>SQL::GenericExpression</tt>).
289
+ # that are defined on objects that can be used in a boolean context in SQL.
288
290
  #
289
- # :a & :b # "a" AND "b"
290
- # :a | :b # "a" OR "b"
291
- # ~:a # NOT "a"
291
+ # Sequel[:a] & Sequel[:b] # "a" AND "b"
292
+ # Sequel[:a] | Sequel[:b] # "a" OR "b"
293
+ # ~Sequel[:a] # NOT "a"
292
294
  #
293
295
  # One exception to this is when a NumericExpression or Integer is the argument
294
296
  # to & or |, in which case a bitwise method will be used:
295
297
  #
296
- # :a & 1 # "a" & 1
297
- # :a | (:b + 1) # "a" | ("b" + 1)
298
+ # Sequel[:a] & 1 # "a" & 1
299
+ # Sequel[:a] | (Sequel[:b] + 1) # "a" | ("b" + 1)
298
300
  module BooleanMethods
299
301
  ComplexExpression::BOOLEAN_OPERATOR_METHODS.each do |m, o|
300
302
  module_eval(<<-END, __FILE__, __LINE__+1)
@@ -311,14 +313,14 @@ module Sequel
311
313
 
312
314
  # Create a new BooleanExpression with NOT, representing the inversion of whatever self represents.
313
315
  #
314
- # ~:a # NOT :a
316
+ # ~Sequel[:a] # NOT :a
315
317
  def ~
316
318
  BooleanExpression.invert(self)
317
319
  end
318
320
  end
319
321
 
320
- # These methods are designed as replacements for the core extensions, so that
321
- # Sequel is still easy to use if the core extensions are not enabled.
322
+ # These methods make it easier to create Sequel expressions without
323
+ # using the core extensions.
322
324
  module Builders
323
325
  # Create an SQL::AliasedExpression for the given expression and alias.
324
326
  #
@@ -336,7 +338,7 @@ module Sequel
336
338
  # are ordered after other values).
337
339
  #
338
340
  # Sequel.asc(:a) # a ASC
339
- # Sequel.asc(:b, :nulls=>:last) # b ASC NULLS LAST
341
+ # Sequel.asc(:b, nulls: :last) # b ASC NULLS LAST
340
342
  def asc(arg, opts=OPTS)
341
343
  SQL::OrderedExpression.new(arg, false, opts)
342
344
  end
@@ -353,10 +355,16 @@ module Sequel
353
355
  end
354
356
 
355
357
  # Return an <tt>SQL::CaseExpression</tt> created with the given arguments.
356
- #
357
- # Sequel.case([[{:a=>[2,3]}, 1]], 0) # SQL: CASE WHEN a IN (2, 3) THEN 1 ELSE 0 END
358
- # Sequel.case({:a=>1}, 0, :b) # SQL: CASE b WHEN a THEN 1 ELSE 0 END
359
- def case(*args) # core_sql ignore
358
+ # The first argument are the <tt>WHEN</tt>/<tt>THEN</tt> conditions,
359
+ # specified as an array or a hash. The second argument is the
360
+ # <tt>ELSE</tt> default value. The third optional argument is the
361
+ # <tt>CASE</tt> expression.
362
+ #
363
+ # Sequel.case({a: 1}, 0) # SQL: CASE WHEN a THEN 1 ELSE 0 END
364
+ # Sequel.case({a: 1}, 0, :b) # SQL: CASE b WHEN a THEN 1 ELSE 0 END
365
+ # Sequel.case({{a: [2,3]} => 1}, 0) # SQL: CASE WHEN a IN (2, 3) THEN 1 ELSE 0 END
366
+ # Sequel.case([[{a: [2,3]}, 1]], 0) # SQL: CASE WHEN a IN (2, 3) THEN 1 ELSE 0 END
367
+ def case(*args)
360
368
  SQL::CaseExpression.new(*args)
361
369
  end
362
370
 
@@ -402,10 +410,10 @@ module Sequel
402
410
  # nested structures.
403
411
  #
404
412
  # Sequel.deep_qualify(:table, :column) # "table"."column"
405
- # Sequel.deep_qualify(:table, Sequel.+(:column, 1)) # "table"."column" + 1
406
- # Sequel.deep_qualify(:table, Sequel.like(:a, 'b')) # "table"."a" LIKE 'b' ESCAPE '\'
413
+ # Sequel.deep_qualify(:table, Sequel[:column] + 1) # "table"."column" + 1
414
+ # Sequel.deep_qualify(:table, Sequel[:a].like('b')) # "table"."a" LIKE 'b' ESCAPE '\'
407
415
  def deep_qualify(qualifier, expr)
408
- Sequel::Qualifier.new(Sequel, qualifier).transform(expr)
416
+ Sequel::Qualifier.new(qualifier).transform(expr)
409
417
  end
410
418
 
411
419
  # Return a delayed evaluation that uses the passed block. This is used
@@ -437,7 +445,7 @@ module Sequel
437
445
  # are ordered after other values).
438
446
  #
439
447
  # Sequel.desc(:a) # b DESC
440
- # Sequel.desc(:b, :nulls=>:first) # b DESC NULLS FIRST
448
+ # Sequel.desc(:b, nulls: :first) # b DESC NULLS FIRST
441
449
  def desc(arg, opts=OPTS)
442
450
  SQL::OrderedExpression.new(arg, true, opts)
443
451
  end
@@ -454,8 +462,12 @@ module Sequel
454
462
  # to construct via other methods. For example:
455
463
  #
456
464
  # Sequel.expr(1) - :a # SQL: (1 - a)
465
+ #
466
+ # On the Sequel module, this is aliased as #[], for easier use:
467
+ #
468
+ # Sequel[1] - :a # SQL: (1 - a)
457
469
  def expr(arg=(no_arg=true), &block)
458
- if block_given?
470
+ if defined?(yield)
459
471
  if no_arg
460
472
  return expr(block)
461
473
  else
@@ -522,7 +534,7 @@ module Sequel
522
534
 
523
535
  # Return the argument wrapped as an <tt>SQL::Identifier</tt>.
524
536
  #
525
- # Sequel.identifier(:a__b) # "a__b"
537
+ # Sequel.identifier(:a) # "a"
526
538
  def identifier(name)
527
539
  SQL::Identifier.new(name)
528
540
  end
@@ -575,17 +587,17 @@ module Sequel
575
587
  # Converts a string into a <tt>Sequel::LiteralString</tt>, in order to override string
576
588
  # literalization, e.g.:
577
589
  #
578
- # DB[:items].filter(:abc => 'def').sql #=>
590
+ # DB[:items].where(abc: 'def').sql #=>
579
591
  # "SELECT * FROM items WHERE (abc = 'def')"
580
592
  #
581
- # DB[:items].filter(:abc => Sequel.lit('def')).sql #=>
593
+ # DB[:items].where(abc: Sequel.lit('def')).sql #=>
582
594
  # "SELECT * FROM items WHERE (abc = def)"
583
595
  #
584
596
  # You can also provide arguments, to create a <tt>Sequel::SQL::PlaceholderLiteralString</tt>:
585
597
  #
586
598
  # DB[:items].select{|o| o.count(Sequel.lit('DISTINCT ?', :a))}.sql #=>
587
599
  # "SELECT count(DISTINCT a) FROM items"
588
- def lit(s, *args) # core_sql ignore
600
+ def lit(s, *args)
589
601
  if args.empty?
590
602
  if s.is_a?(LiteralString)
591
603
  s
@@ -600,7 +612,7 @@ module Sequel
600
612
  # Return a <tt>Sequel::SQL::BooleanExpression</tt> created from the condition
601
613
  # specifier, matching none of the conditions.
602
614
  #
603
- # Sequel.negate(:a=>true) # SQL: a IS NOT TRUE
615
+ # Sequel.negate(a: true) # SQL: a IS NOT TRUE
604
616
  # Sequel.negate([[:a, true]]) # SQL: a IS NOT TRUE
605
617
  # Sequel.negate([[:a, 1], [:b, 2]]) # SQL: ((a != 1) AND (b != 2))
606
618
  def negate(arg)
@@ -614,7 +626,7 @@ module Sequel
614
626
  # Return a <tt>Sequel::SQL::BooleanExpression</tt> created from the condition
615
627
  # specifier, matching any of the conditions.
616
628
  #
617
- # Sequel.or(:a=>true) # SQL: a IS TRUE
629
+ # Sequel.or(a: true) # SQL: a IS TRUE
618
630
  # Sequel.or([[:a, true]]) # SQL: a IS TRUE
619
631
  # Sequel.or([[:a, 1], [:b, 2]]) # SQL: ((a = 1) OR (b = 2))
620
632
  def or(arg)
@@ -661,9 +673,9 @@ module Sequel
661
673
  # this array as a value in a filter, but may be necessary if you are using it as a
662
674
  # value with placeholder SQL:
663
675
  #
664
- # DB[:a].filter([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
665
- # DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
666
- # DB[:a].filter('(a, b) IN ?', Sequel.value_list([[1, 2], [3, 4]])) # SQL: (a, b) IN ((1, 2), (3, 4))
676
+ # DB[:a].where([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
677
+ # DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
678
+ # DB[:a].where('(a, b) IN ?', Sequel.value_list([[1, 2], [3, 4]])) # SQL: (a, b) IN ((1, 2), (3, 4))
667
679
  def value_list(arg)
668
680
  raise Error, 'argument to Sequel.value_list must be an array' unless arg.is_a?(Array)
669
681
  SQL::ValueList.new(arg)
@@ -703,22 +715,11 @@ module Sequel
703
715
  end
704
716
 
705
717
  # Adds methods that allow you to treat an object as an instance of a specific
706
- # +ComplexExpression+ subclass. This is useful if another library
707
- # overrides the methods defined by Sequel.
708
- #
709
- # For example, if <tt>Symbol#/</tt> is overridden to produce a string (for
710
- # example, to make file system path creation easier), the
711
- # following code will not do what you want:
712
- #
713
- # :price/10 > 100
714
- #
715
- # In that case, you need to do the following:
716
- #
717
- # :price.sql_number/10 > 100
718
+ # +ComplexExpression+ subclass.
718
719
  module ComplexExpressionMethods
719
720
  # Extract a datetime part (e.g. year, month) from self:
720
721
  #
721
- # :date.extract(:year) # extract(year FROM "date")
722
+ # Sequel[:date].extract(:year) # extract(year FROM "date")
722
723
  #
723
724
  # Also has the benefit of returning the result as a
724
725
  # NumericExpression instead of a generic ComplexExpression.
@@ -733,16 +734,16 @@ module Sequel
733
734
 
734
735
  # Return a NumericExpression representation of +self+.
735
736
  #
736
- # ~:a # NOT "a"
737
- # ~:a.sql_number # ~"a"
737
+ # ~Sequel[:a] # NOT "a"
738
+ # ~(Sequel[:a].sql_number) # ~"a"
738
739
  def sql_number
739
740
  NumericExpression.new(:NOOP, self)
740
741
  end
741
742
 
742
743
  # Return a StringExpression representation of +self+.
743
744
  #
744
- # :a + :b # "a" + "b"
745
- # :a.sql_string + :b # "a" || "b"
745
+ # Sequel[:a] + :b # "a" + "b"
746
+ # Sequel[:a].sql_string + :b # "a" || "b"
746
747
  def sql_string
747
748
  StringExpression.new(:NOOP, self)
748
749
  end
@@ -751,10 +752,10 @@ module Sequel
751
752
  # This module includes the inequality methods (>, <, >=, <=) that are defined on objects that can be
752
753
  # used in a numeric or string context in SQL.
753
754
  #
754
- # Sequel.lit('a') > :b # a > "b"
755
- # Sequel.lit('a') < :b # a > "b"
756
- # Sequel.lit('a') >= :b # a >= "b"
757
- # Sequel.lit('a') <= :b # a <= "b"
755
+ # Sequel[:a] > :b # a > "b"
756
+ # Sequel[:a] < :b # a > "b"
757
+ # Sequel[:a] >= :b # a >= "b"
758
+ # Sequel[:a] <= :b # a <= "b"
758
759
  module InequalityMethods
759
760
  ComplexExpression::INEQUALITY_OPERATORS.each do |o|
760
761
  module_eval("def #{o}(o) BooleanExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__)
@@ -765,18 +766,33 @@ module Sequel
765
766
  # that are defined on objects that can be used in a numeric context in SQL
766
767
  # (+Symbol+, +LiteralString+, and +SQL::GenericExpression+).
767
768
  #
768
- # :a + :b # "a" + "b"
769
- # :a - :b # "a" - "b"
770
- # :a * :b # "a" * "b"
771
- # :a / :b # "a" / "b"
769
+ # Sequel[:a] + :b # "a" + "b"
770
+ # Sequel[:a] - :b # "a" - "b"
771
+ # Sequel[:a] * :b # "a" * "b"
772
+ # Sequel[:a] / :b # "a" / "b"
772
773
  #
773
774
  # One exception to this is if + is called with a +String+ or +StringExpression+,
774
775
  # in which case the || operator is used instead of the + operator:
775
776
  #
776
- # :a + 'b' # "a" || 'b'
777
+ # Sequel[:a] + 'b' # "a" || 'b'
777
778
  module NumericMethods
778
- ComplexExpression::MATHEMATICAL_OPERATORS.each do |o|
779
- module_eval("def #{o}(o) NumericExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__) unless o == :+
779
+ (ComplexExpression::MATHEMATICAL_OPERATORS - [:+]).each do |o|
780
+ module_eval("def #{o}(o) NumericExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__)
781
+ end
782
+
783
+ # If the argument given is Numeric, treat it as a NumericExpression,
784
+ # allowing code such as:
785
+ #
786
+ # 1 + Sequel[:x] # SQL: (1 + x)
787
+ # Sequel.expr{1 - x(y)} # SQL: (1 - x(y))
788
+ def coerce(other)
789
+ if other.is_a?(Numeric)
790
+ [SQL::NumericExpression.new(:NOOP, other), self]
791
+ elsif defined?(super)
792
+ super
793
+ else
794
+ [self, other]
795
+ end
780
796
  end
781
797
 
782
798
  # Use || as the operator when called with StringExpression and String instances,
@@ -798,17 +814,17 @@ module Sequel
798
814
  # return when using a hash with a single entry, where the receiver was the key
799
815
  # and the argument was the value. Example:
800
816
  #
801
- # Sequel.expr(:a) =~ 1 # (a = 1)
802
- # Sequel.expr(:a) =~ [1, 2] # (a IN [1, 2])
803
- # Sequel.expr(:a) =~ nil # (a IS NULL)
817
+ # Sequel[:a] =~ 1 # (a = 1)
818
+ # Sequel[:a] =~ [1, 2] # (a IN [1, 2])
819
+ # Sequel[:a] =~ nil # (a IS NULL)
804
820
  #
805
- # On Ruby 1.9+, this also adds the !~ method, for easily setting up not equals,
821
+ # This also adds the !~ method, for easily setting up not equals,
806
822
  # exclusion, and inverse pattern matching. This is the same as as inverting the
807
823
  # result of the =~ method
808
824
  #
809
- # Sequel.expr(:a) !~ 1 # (a != 1)
810
- # Sequel.expr(:a) !~ [1, 2] # (a NOT IN [1, 2])
811
- # Sequel.expr(:a) !~ nil # (a IS NOT NULL)
825
+ # Sequel[:a] !~ 1 # (a != 1)
826
+ # Sequel[:a] !~ [1, 2] # (a NOT IN [1, 2])
827
+ # Sequel[:a] !~ nil # (a IS NOT NULL)
812
828
  module PatternMatchMethods
813
829
  # Set up an equality, inclusion, or pattern match operation, based on the type
814
830
  # of the argument.
@@ -816,23 +832,19 @@ module Sequel
816
832
  BooleanExpression.send(:from_value_pair, self, other)
817
833
  end
818
834
 
819
- if RUBY_VERSION >= '1.9'
820
- module_eval(<<-END, __FILE__, __LINE__+1)
821
- def !~(other)
822
- ~(self =~ other)
823
- end
824
- END
835
+ def !~(other)
836
+ ~(self =~ other)
825
837
  end
826
838
  end
827
839
 
828
- # These methods are designed as replacements for the core extension operator
829
- # methods, so that Sequel is still easy to use if the core extensions are not
830
- # enabled.
840
+ # This adds methods to create SQL expressions using operators:
831
841
  #
832
- # The following methods are defined via metaprogramming: +, -, *, /, &, |.
833
- # The +, -, *, and / operators return numeric expressions combining all the
834
- # arguments with the appropriate operator, and the & and | operators return
835
- # boolean expressions combining all of the arguments with either AND or OR.
842
+ # Sequel.+(1, :a) # (1 + a)
843
+ # Sequel.-(1, :a) # (1 - a)
844
+ # Sequel.*(1, :a) # (1 * a)
845
+ # Sequel./(1, :a) # (1 / a)
846
+ # Sequel.&(:b, :a) # (b AND a)
847
+ # Sequel.|(:b, :a) # (b OR a)
836
848
  module OperatorBuilders
837
849
  {'::Sequel::SQL::NumericExpression'=>{'+'=>'+', '-'=>'-', '*'=>'*', '/'=>'/'},
838
850
  '::Sequel::SQL::BooleanExpression'=>{'&'=>'AND', '|'=>'OR'}}.each do |klass, ops|
@@ -852,6 +864,13 @@ module Sequel
852
864
  END
853
865
  end
854
866
  end
867
+
868
+ # Return NumericExpression for the exponentiation:
869
+ #
870
+ # Sequel.**(2, 3) # SQL: power(2, 3)
871
+ def **(a, b)
872
+ SQL::NumericExpression.new(:**, a, b)
873
+ end
855
874
 
856
875
  # Invert the given expression. Returns a <tt>Sequel::SQL::BooleanExpression</tt>
857
876
  # created from this argument, not matching all of the conditions.
@@ -892,13 +911,13 @@ module Sequel
892
911
  end
893
912
  end
894
913
 
895
- # Includes a +qualify+ method that created <tt>QualifiedIdentifier</tt>s, used for qualifying column
914
+ # Includes a +qualify+ and <tt>[]</tt> methods that create <tt>QualifiedIdentifier</tt>s, used for qualifying column
896
915
  # names with a table or table names with a schema, and the * method for returning all columns in
897
916
  # the identifier if no arguments are given.
898
917
  module QualifyingMethods
899
918
  # If no arguments are given, return an SQL::ColumnAll:
900
919
  #
901
- # Sequel.expr(:a__b).* # a.b.*
920
+ # Sequel[:a].* # a.*
902
921
  def *(ce=(arg=false;nil))
903
922
  if arg == false
904
923
  Sequel::SQL::ColumnAll.new(self)
@@ -909,12 +928,21 @@ module Sequel
909
928
 
910
929
  # Qualify the receiver with the given +qualifier+ (table for column/schema for table).
911
930
  #
912
- # Sequel.expr(:column).qualify(:table) # "table"."column"
913
- # Sequel.expr(:table).qualify(:schema) # "schema"."table"
931
+ # Sequel[:column].qualify(:table) # "table"."column"
932
+ # Sequel[:table].qualify(:schema) # "schema"."table"
914
933
  # Sequel.qualify(:table, :column).qualify(:schema) # "schema"."table"."column"
915
934
  def qualify(qualifier)
916
935
  QualifiedIdentifier.new(qualifier, self)
917
936
  end
937
+
938
+ # Qualify the receiver with the given +qualifier+ (table for column/schema for table).
939
+ #
940
+ # Sequel[:table][:column] # "table"."column"
941
+ # Sequel[:schema][:table] # "schema"."table"
942
+ # Sequel[:schema][:table][:column] # "schema"."table"."column"
943
+ def [](identifier)
944
+ QualifiedIdentifier.new(self, identifier)
945
+ end
918
946
  end
919
947
 
920
948
  # This module includes the +like+ and +ilike+ methods used for pattern matching that are defined on objects that can be
@@ -923,7 +951,7 @@ module Sequel
923
951
  # Create a +BooleanExpression+ case insensitive pattern match of the receiver
924
952
  # with the given patterns. See <tt>StringExpression.like</tt>.
925
953
  #
926
- # :a.ilike('A%') # "a" ILIKE 'A%' ESCAPE '\'
954
+ # Sequel[:a].ilike('A%') # "a" ILIKE 'A%' ESCAPE '\'
927
955
  def ilike(*ces)
928
956
  StringExpression.like(self, *(ces << {:case_insensitive=>true}))
929
957
  end
@@ -931,7 +959,7 @@ module Sequel
931
959
  # Create a +BooleanExpression+ case sensitive (if the database supports it) pattern match of the receiver with
932
960
  # the given patterns. See <tt>StringExpression.like</tt>.
933
961
  #
934
- # :a.like('A%') # "a" LIKE 'A%' ESCAPE '\'
962
+ # Sequel[:a].like('A%') # "a" LIKE 'A%' ESCAPE '\'
935
963
  def like(*ces)
936
964
  StringExpression.like(self, *ces)
937
965
  end
@@ -943,7 +971,7 @@ module Sequel
943
971
  # Return a +StringExpression+ representing the concatenation of the receiver
944
972
  # with the given argument.
945
973
  #
946
- # :x.sql_string + :y # => "x" || "y"
974
+ # Sequel[:x].sql_string + :y # => "x" || "y"
947
975
  def +(ce)
948
976
  StringExpression.new(:'||', self, ce)
949
977
  end
@@ -954,37 +982,34 @@ module Sequel
954
982
  # Return a <tt>Subscript</tt> with the given arguments, representing an
955
983
  # SQL array access.
956
984
  #
957
- # :array.sql_subscript(1) # array[1]
958
- # :array.sql_subscript(1, 2) # array[1, 2]
959
- # :array.sql_subscript([1, 2]) # array[1, 2]
960
- # :array.sql_subscript(:array, 1..2) # array[1:2]
961
- # :array.sql_subscript(:array, 1...3) # array[1:2]
985
+ # Sequel[:array].sql_subscript(1) # array[1]
986
+ # Sequel[:array].sql_subscript(1, 2) # array[1, 2]
987
+ # Sequel[:array].sql_subscript([1, 2]) # array[1, 2]
988
+ # Sequel[:array].sql_subscript(1..2) # array[1:2]
989
+ # Sequel[:array].sql_subscript(1...3) # array[1:2]
962
990
  def sql_subscript(*sub)
963
991
  Subscript.new(self, sub.flatten)
964
992
  end
965
993
  end
966
994
 
967
- ### Classes ###
968
-
969
995
  # Represents an aliasing of an expression to a given alias.
970
996
  class AliasedExpression < Expression
971
997
  # The expression to alias
972
998
  attr_reader :expression
973
999
 
974
- # The alias to use for the expression, not +alias+ since that is
975
- # a keyword in ruby.
976
- attr_reader :aliaz
977
- alias_method :alias, :aliaz
1000
+ # The alias to use for the expression.
1001
+ attr_reader :alias
978
1002
 
979
- # The columns aliases to use, for when the aliased expression is
1003
+ # The columns aliases (derived column list) to use, for when the aliased expression is
980
1004
  # a record or set of records (such as a dataset).
981
1005
  attr_reader :columns
982
1006
 
983
- # Create an object with the given expression and alias.
1007
+ # Create an object with the given expression, alias, and optional column aliases.
984
1008
  def initialize(expression, aliaz, columns=nil)
985
1009
  @expression = expression
986
- @aliaz = aliaz
1010
+ @alias = aliaz
987
1011
  @columns = columns
1012
+ freeze
988
1013
  end
989
1014
 
990
1015
  to_s_method :aliased_expression_sql
@@ -997,11 +1022,30 @@ module Sequel
997
1022
  include SQL::AliasMethods
998
1023
  include SQL::CastMethods
999
1024
 
1025
+ class << self
1026
+ # Alias new to call for usage in conversion procs
1027
+ alias call new
1028
+ end
1029
+
1000
1030
  # Return a LiteralString with the same content if no args are given, otherwise
1001
1031
  # return a SQL::PlaceholderLiteralString with the current string and the given args.
1002
1032
  def lit(*args)
1003
1033
  args.empty? ? LiteralString.new(self) : SQL::PlaceholderLiteralString.new(self, args)
1004
1034
  end
1035
+
1036
+ # Return a string showing that this is a blob, the size, and the some or all of the content,
1037
+ # depending on the size.
1038
+ def inspect
1039
+ size = length
1040
+
1041
+ content = if size > 20
1042
+ "start=#{self[0...10].to_s.inspect} end=#{self[-10..-1].to_s.inspect}"
1043
+ else
1044
+ "content=#{super}"
1045
+ end
1046
+
1047
+ "#<#{self.class}:0x#{"%x" % object_id} bytes=#{size} #{content}>"
1048
+ end
1005
1049
 
1006
1050
  # Returns +self+, since it is already a blob.
1007
1051
  def to_sequel_blob
@@ -1037,15 +1081,37 @@ module Sequel
1037
1081
  def self.from_value_pairs(pairs, op=:AND, negate=false)
1038
1082
  pairs = pairs.map{|l,r| from_value_pair(l, r)}
1039
1083
  pairs.map!{|ce| invert(ce)} if negate
1040
- pairs.length == 1 ? pairs.at(0) : new(op, *pairs)
1084
+ pairs.length == 1 ? pairs[0] : new(op, *pairs)
1041
1085
  end
1042
1086
 
1043
1087
  # Return a BooleanExpression based on the right side of the pair.
1044
1088
  def self.from_value_pair(l, r)
1045
1089
  case r
1046
1090
  when Range
1047
- new(:AND, new(:>=, l, r.begin), new(r.exclude_end? ? :< : :<=, l, r.end))
1048
- when ::Array, ::Sequel::Dataset
1091
+ unless r.begin.nil?
1092
+ begin_expr = new(:>=, l, r.begin)
1093
+ end
1094
+ unless r.end.nil?
1095
+ end_expr = new(r.exclude_end? ? :< : :<=, l, r.end)
1096
+ end
1097
+ if begin_expr
1098
+ if end_expr
1099
+ new(:AND, begin_expr, end_expr)
1100
+ else
1101
+ begin_expr
1102
+ end
1103
+ elsif end_expr
1104
+ end_expr
1105
+ else
1106
+ new(:'=', 1, 1)
1107
+ end
1108
+ when ::Array
1109
+ r = r.dup.freeze unless r.frozen?
1110
+ new(:IN, l, r)
1111
+ when ::String
1112
+ r = r.dup.freeze unless r.frozen?
1113
+ new(:'=', l, r)
1114
+ when ::Sequel::Dataset
1049
1115
  new(:IN, l, r)
1050
1116
  when NegativeBooleanConstant
1051
1117
  new(:"IS NOT", l, r.constant)
@@ -1076,9 +1142,22 @@ module Sequel
1076
1142
  when BooleanExpression
1077
1143
  case op = ce.op
1078
1144
  when :AND, :OR
1079
- BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.collect{|a| BooleanExpression.invert(a)})
1080
- else
1145
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)})
1146
+ when :IN, :"NOT IN"
1081
1147
  BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup)
1148
+ else
1149
+ if ce.args.length == 2
1150
+ case ce.args[1]
1151
+ when Function, LiteralString, PlaceholderLiteralString
1152
+ # Special behavior to not push down inversion in this case because doing so
1153
+ # can result in incorrect behavior for ANY/SOME/ALL operators.
1154
+ BooleanExpression.new(:NOT, ce)
1155
+ else
1156
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup)
1157
+ end
1158
+ else
1159
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup)
1160
+ end
1082
1161
  end
1083
1162
  when StringExpression, NumericExpression
1084
1163
  raise(Sequel::Error, "cannot invert #{ce.inspect}")
@@ -1115,16 +1194,20 @@ module Sequel
1115
1194
  # The default value if no conditions match.
1116
1195
  attr_reader :default
1117
1196
 
1118
- # The expression to test the conditions against
1197
+ # An optional expression to test the conditions against
1119
1198
  attr_reader :expression
1120
1199
 
1121
1200
  # Create an object with the given conditions and
1122
- # default value. An expression can be provided to
1201
+ # default value, and optional expression. An expression can be provided to
1123
1202
  # test each condition against, instead of having
1124
1203
  # all conditions represent their own boolean expression.
1125
1204
  def initialize(conditions, default, expression=(no_expression=true; nil))
1126
1205
  raise(Sequel::Error, 'CaseExpression conditions must be a hash or array of all two pairs') unless Sequel.condition_specifier?(conditions)
1127
- @conditions, @default, @expression, @no_expression = conditions.to_a, default, expression, no_expression
1206
+ @conditions = conditions.to_a.dup.freeze
1207
+ @default = default
1208
+ @expression = expression
1209
+ @no_expression = no_expression
1210
+ freeze
1128
1211
  end
1129
1212
 
1130
1213
  # Whether to use an expression for this CASE expression.
@@ -1154,10 +1237,11 @@ module Sequel
1154
1237
  # The type to which to cast the expression
1155
1238
  attr_reader :type
1156
1239
 
1157
- # Set the attributes to the given arguments
1240
+ # Set the expression and type for the cast
1158
1241
  def initialize(expr, type)
1159
1242
  @expr = expr
1160
1243
  @type = type
1244
+ freeze
1161
1245
  end
1162
1246
 
1163
1247
  to_s_method :cast_sql, '@expr, @type'
@@ -1171,6 +1255,7 @@ module Sequel
1171
1255
  # Create an object with the given table
1172
1256
  def initialize(table)
1173
1257
  @table = table
1258
+ freeze
1174
1259
  end
1175
1260
 
1176
1261
  to_s_method :column_all_sql
@@ -1185,17 +1270,17 @@ module Sequel
1185
1270
 
1186
1271
  # Return a BooleanExpression with the same op and args.
1187
1272
  def sql_boolean
1188
- BooleanExpression.new(self.op, *self.args)
1273
+ BooleanExpression.new(op, *args)
1189
1274
  end
1190
1275
 
1191
1276
  # Return a NumericExpression with the same op and args.
1192
1277
  def sql_number
1193
- NumericExpression.new(self.op, *self.args)
1278
+ NumericExpression.new(op, *args)
1194
1279
  end
1195
1280
 
1196
1281
  # Return a StringExpression with the same op and args.
1197
1282
  def sql_string
1198
- StringExpression.new(self.op, *self.args)
1283
+ StringExpression.new(op, *args)
1199
1284
  end
1200
1285
  end
1201
1286
 
@@ -1204,15 +1289,16 @@ module Sequel
1204
1289
  # The underlying constant related to this object.
1205
1290
  attr_reader :constant
1206
1291
 
1207
- # Create an constant with the given value
1292
+ # Create a constant with the given value
1208
1293
  def initialize(constant)
1209
1294
  @constant = constant
1295
+ freeze
1210
1296
  end
1211
1297
 
1212
1298
  to_s_method :constant_sql, '@constant'
1213
1299
  end
1214
1300
 
1215
- # Represents boolean constants such as +NULL+, +NOTNULL+, +TRUE+, and +FALSE+.
1301
+ # Represents boolean constants such as +NULL+, +TRUE+, and +FALSE+.
1216
1302
  class BooleanConstant < Constant
1217
1303
  to_s_method :boolean_constant_sql, '@constant'
1218
1304
  end
@@ -1231,6 +1317,7 @@ module Sequel
1231
1317
  CURRENT_DATE = Constant.new(:CURRENT_DATE)
1232
1318
  CURRENT_TIME = Constant.new(:CURRENT_TIME)
1233
1319
  CURRENT_TIMESTAMP = Constant.new(:CURRENT_TIMESTAMP)
1320
+ DEFAULT = Constant.new(:DEFAULT)
1234
1321
  SQLTRUE = TRUE = BooleanConstant.new(true)
1235
1322
  SQLFALSE = FALSE = BooleanConstant.new(false)
1236
1323
  NULL = BooleanConstant.new(nil)
@@ -1240,7 +1327,7 @@ module Sequel
1240
1327
  class ComplexExpression
1241
1328
  # A hash of the opposite for each constant, used for inverting constants.
1242
1329
  CONSTANT_INVERSIONS = {Constants::TRUE=>Constants::FALSE, Constants::FALSE=>Constants::TRUE,
1243
- Constants::NULL=>Constants::NOTNULL, Constants::NOTNULL=>Constants::NULL}
1330
+ Constants::NULL=>Constants::NOTNULL, Constants::NOTNULL=>Constants::NULL}.freeze
1244
1331
  end
1245
1332
 
1246
1333
  # Represents a delayed evaluation, encapsulating a callable
@@ -1253,6 +1340,7 @@ module Sequel
1253
1340
  # Set the callable object
1254
1341
  def initialize(callable)
1255
1342
  @callable = callable
1343
+ freeze
1256
1344
  end
1257
1345
 
1258
1346
  # Call the underlying callable and return the result. If the
@@ -1277,8 +1365,7 @@ module Sequel
1277
1365
 
1278
1366
  # The SQL function to call
1279
1367
  attr_reader :name
1280
- alias f name
1281
-
1368
+
1282
1369
  # The array of arguments to pass to the function (may be blank)
1283
1370
  attr_reader :args
1284
1371
 
@@ -1287,15 +1374,12 @@ module Sequel
1287
1374
 
1288
1375
  # Set the name and args for the function
1289
1376
  def initialize(name, *args)
1290
- @name = name
1291
- @args = args
1292
- @opts = OPTS
1377
+ _initialize(name, args, OPTS)
1293
1378
  end
1294
1379
 
1295
- def self.new!(name, args, opts)
1296
- f = new(name, *args)
1297
- f.instance_variable_set(:@opts, opts)
1298
- f
1380
+ # Set the name, args, and options, for internal use only.
1381
+ def self.new!(name, args, opts) # :nodoc:
1382
+ allocate.send(:_initialize, name, args, opts)
1299
1383
  end
1300
1384
 
1301
1385
  # If no arguments are given, return a new function with the wildcard prepended to the arguments.
@@ -1320,9 +1404,14 @@ module Sequel
1320
1404
  # Return a new function with FILTER added to it, for filtered
1321
1405
  # aggregate functions:
1322
1406
  #
1323
- # Sequel.function(:foo, :col).filter(:a=>1) # foo(col) FILTER (WHERE a = 1)
1407
+ # Sequel.function(:foo, :col).filter(a: 1) # foo(col) FILTER (WHERE (a = 1))
1324
1408
  def filter(*args, &block)
1325
- args = args.first if args.length == 1
1409
+ if args.length == 1
1410
+ args = args.first
1411
+ else
1412
+ args.freeze
1413
+ end
1414
+
1326
1415
  with_opts(:filter=>args, :filter_block=>block)
1327
1416
  end
1328
1417
 
@@ -1338,12 +1427,13 @@ module Sequel
1338
1427
  #
1339
1428
  # Sequel.function(:foo, :a).order(:a, Sequel.desc(:b)) # foo(a ORDER BY a, b DESC)
1340
1429
  def order(*args)
1341
- with_opts(:order=>args)
1430
+ with_opts(:order=>args.freeze)
1342
1431
  end
1343
1432
 
1344
1433
  # Return a new function with an OVER clause (making it a window function).
1434
+ # See Sequel::SQL::Window for the list of options +over+ can receive.
1345
1435
  #
1346
- # Sequel.function(:row_number).over(:partition=>:col) # row_number() OVER (PARTITION BY col)
1436
+ # Sequel.function(:row_number).over(partition: :col) # row_number() OVER (PARTITION BY col)
1347
1437
  def over(window=OPTS)
1348
1438
  raise Error, "function already has a window applied to it" if opts[:over]
1349
1439
  window = Window.new(window) unless window.is_a?(Window)
@@ -1361,7 +1451,7 @@ module Sequel
1361
1451
  # Return a new function where the function name will not be quoted even
1362
1452
  # if the database supports quoted functions:
1363
1453
  #
1364
- # Sequel.expr(:foo).function.unquoted # foo()
1454
+ # Sequel[:foo][:bar].function.unquoted # foo.bar()
1365
1455
  def unquoted
1366
1456
  with_opts(:quoted=>false)
1367
1457
  end
@@ -1380,16 +1470,24 @@ module Sequel
1380
1470
  # Sequel.function(:rank, :a).within_group(:b, :c)
1381
1471
  # # rank(a) WITHIN GROUP (ORDER BY b, c)
1382
1472
  def within_group(*expressions)
1383
- with_opts(:within_group=>expressions)
1473
+ with_opts(:within_group=>expressions.freeze)
1384
1474
  end
1385
1475
 
1386
1476
  to_s_method :function_sql
1387
1477
 
1388
1478
  private
1389
1479
 
1480
+ # Set name, args, and opts
1481
+ def _initialize(name, args, opts)
1482
+ @name = name
1483
+ @args = args.freeze
1484
+ @opts = opts.freeze
1485
+ freeze
1486
+ end
1487
+
1390
1488
  # Return a new function call with the given opts merged into the current opts.
1391
1489
  def with_opts(opts)
1392
- self.class.new!(name, args, Hash[@opts].merge!(opts))
1490
+ self.class.new!(name, args, @opts.merge(opts))
1393
1491
  end
1394
1492
  end
1395
1493
 
@@ -1406,18 +1504,17 @@ module Sequel
1406
1504
  include SubscriptMethods
1407
1505
  end
1408
1506
 
1409
- # Represents an identifier (column or table). Can be used
1410
- # to specify a +Symbol+ with multiple underscores should not be
1411
- # split, or for creating an identifier without using a symbol.
1507
+ # Represents an identifier (column, table, schema, etc.).
1412
1508
  class Identifier < GenericExpression
1413
1509
  include QualifyingMethods
1414
1510
 
1415
- # The table or column to reference
1511
+ # The identifier to reference
1416
1512
  attr_reader :value
1417
1513
 
1418
- # Set the value to the given argument
1514
+ # Set the identifier to the given argument
1419
1515
  def initialize(value)
1420
1516
  @value = value
1517
+ freeze
1421
1518
  end
1422
1519
 
1423
1520
  # Create a Function using this identifier as the functions name, with
@@ -1442,6 +1539,7 @@ module Sequel
1442
1539
  def initialize(join_type, table_expr)
1443
1540
  @join_type = join_type
1444
1541
  @table_expr = table_expr
1542
+ freeze
1445
1543
  end
1446
1544
 
1447
1545
  # The table/set related to the JOIN, without any alias.
@@ -1495,8 +1593,8 @@ module Sequel
1495
1593
 
1496
1594
  # Create an object with the given USING conditions and call super
1497
1595
  # with the remaining args.
1498
- def initialize(using, *args)
1499
- @using = using
1596
+ def initialize(cols, *args)
1597
+ @using = cols
1500
1598
  super(*args)
1501
1599
  end
1502
1600
 
@@ -1524,8 +1622,14 @@ module Sequel
1524
1622
  # Create an object with the given string, placeholder arguments, and parens flag.
1525
1623
  def initialize(str, args, parens=false)
1526
1624
  @str = str
1527
- @args = args.is_a?(Array) && args.length == 1 && (v = args.at(0)).is_a?(Hash) ? v : args
1625
+ @args = args.is_a?(Array) && args.length == 1 && (v = args[0]).is_a?(Hash) ? v : args
1528
1626
  @parens = parens
1627
+ freeze
1628
+ end
1629
+
1630
+ # Return a copy of the that will be surrounded by parantheses.
1631
+ def with_parens
1632
+ @parens ? self : self.class.new(@str, @args, true)
1529
1633
  end
1530
1634
 
1531
1635
  to_s_method :placeholder_literal_string_sql
@@ -1567,7 +1671,10 @@ module Sequel
1567
1671
  #
1568
1672
  # :nulls :: Can be :first/:last for NULLS FIRST/LAST.
1569
1673
  def initialize(expression, descending = true, opts=OPTS)
1570
- @expression, @descending, @nulls = expression, descending, opts[:nulls]
1674
+ @expression = expression
1675
+ @descending = descending
1676
+ @nulls = opts[:nulls]
1677
+ freeze
1571
1678
  end
1572
1679
 
1573
1680
  # Return a copy that is ordered ASC
@@ -1600,7 +1707,9 @@ module Sequel
1600
1707
 
1601
1708
  # Set the table and column to the given arguments
1602
1709
  def initialize(table, column)
1603
- @table, @column = table, column
1710
+ @table = convert_identifier(table)
1711
+ @column = convert_identifier(column)
1712
+ freeze
1604
1713
  end
1605
1714
 
1606
1715
  # Create a Function using this identifier as the functions name, with
@@ -1610,6 +1719,18 @@ module Sequel
1610
1719
  end
1611
1720
 
1612
1721
  to_s_method :qualified_identifier_sql, "@table, @column"
1722
+
1723
+ private
1724
+
1725
+ # Automatically convert SQL::Identifiers to strings
1726
+ def convert_identifier(identifier)
1727
+ case identifier
1728
+ when SQL::Identifier
1729
+ identifier.value.to_s
1730
+ else
1731
+ identifier
1732
+ end
1733
+ end
1613
1734
  end
1614
1735
 
1615
1736
  # Subclass of +ComplexExpression+ where the expression results
@@ -1620,15 +1741,16 @@ module Sequel
1620
1741
  include InequalityMethods
1621
1742
 
1622
1743
  # Map of [regexp, case_insenstive] to +ComplexExpression+ operator symbol
1623
- LIKE_MAP = {[true, true]=>:'~*', [true, false]=>:~, [false, true]=>:ILIKE, [false, false]=>:LIKE}
1744
+ LIKE_MAP = {[true, true]=>:'~*', [true, false]=>:~, [false, true]=>:ILIKE, [false, false]=>:LIKE}.freeze
1745
+ LIKE_MAP.each_key(&:freeze)
1624
1746
 
1625
1747
  # Creates a SQL pattern match exprssion. left (l) is the SQL string we
1626
1748
  # are matching against, and ces are the patterns we are matching.
1627
1749
  # The match succeeds if any of the patterns match (SQL OR).
1628
1750
  #
1629
1751
  # If a regular expression is used as a pattern, an SQL regular expression will be
1630
- # used, which is currently only supported on MySQL and PostgreSQL. Be aware
1631
- # that MySQL and PostgreSQL regular expression syntax is similar to ruby
1752
+ # used, which is currently only supported on some databases. Be aware
1753
+ # that SQL regular expression syntax is similar to ruby
1632
1754
  # regular expression syntax, but it not exactly the same, especially for
1633
1755
  # advanced regular expression features. Sequel just uses the source of the
1634
1756
  # ruby regular expression verbatim as the SQL regular expression string.
@@ -1641,17 +1763,17 @@ module Sequel
1641
1763
  # if a case insensitive regular expression is used (//i), that particular
1642
1764
  # pattern which will always be case insensitive.
1643
1765
  #
1644
- # StringExpression.like(:a, 'a%') # "a" LIKE 'a%' ESCAPE '\'
1645
- # StringExpression.like(:a, 'a%', :case_insensitive=>true) # "a" ILIKE 'a%' ESCAPE '\'
1646
- # StringExpression.like(:a, 'a%', /^a/i) # "a" LIKE 'a%' ESCAPE '\' OR "a" ~* '^a'
1766
+ # StringExpression.like(:a, 'a%') # ("a" LIKE 'a%' ESCAPE '\')
1767
+ # StringExpression.like(:a, 'a%', case_insensitive: true) # ("a" ILIKE 'a%' ESCAPE '\')
1768
+ # StringExpression.like(:a, 'a%', /^a/i) # (("a" LIKE 'a%' ESCAPE '\') OR ("a" ~* '^a'))
1647
1769
  def self.like(l, *ces)
1648
1770
  l, lre, lci = like_element(l)
1649
- lci = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive] ? true : lci
1650
- ces.collect! do |ce|
1771
+ lci = (ces.last.is_a?(Hash) ? ces.pop : OPTS)[:case_insensitive] ? true : lci
1772
+ ces.map! do |ce|
1651
1773
  r, rre, rci = like_element(ce)
1652
1774
  BooleanExpression.new(LIKE_MAP[[lre||rre, lci||rci]], l, r)
1653
1775
  end
1654
- ces.length == 1 ? ces.at(0) : BooleanExpression.new(:OR, *ces)
1776
+ ces.length == 1 ? ces[0] : BooleanExpression.new(:OR, *ces)
1655
1777
  end
1656
1778
 
1657
1779
  # Returns a three element array, made up of:
@@ -1676,30 +1798,33 @@ module Sequel
1676
1798
  # Represents an SQL array access, with multiple possible arguments.
1677
1799
  class Subscript < GenericExpression
1678
1800
  # The SQL array column
1679
- attr_reader :f
1801
+ attr_reader :expression
1802
+ alias f expression
1680
1803
 
1681
1804
  # The array of subscripts to use (should be an array of numbers)
1682
1805
  attr_reader :sub
1683
1806
 
1684
1807
  # Set the array column and subscripts to the given arguments
1685
- def initialize(f, sub)
1686
- @f, @sub = f, sub
1808
+ def initialize(expression, sub)
1809
+ @expression = expression
1810
+ @sub = sub
1811
+ freeze
1687
1812
  end
1688
1813
 
1689
1814
  # Create a new +Subscript+ appending the given subscript(s)
1690
1815
  # to the current array of subscripts.
1691
1816
  #
1692
- # :a.sql_subscript(2) # a[2]
1693
- # :a.sql_subscript(2) | 1 # a[2, 1]
1817
+ # Sequel[:a].sql_subscript(2) # a[2]
1818
+ # Sequel[:a].sql_subscript(2) | 1 # a[2, 1]
1694
1819
  def |(sub)
1695
- Subscript.new(@f, @sub + Array(sub))
1820
+ Subscript.new(@expression, @sub + Array(sub))
1696
1821
  end
1697
1822
 
1698
1823
  # Create a new +Subscript+ by accessing a subarray of a multidimensional
1699
1824
  # array.
1700
1825
  #
1701
- # :a.sql_subscript(2) # a[2]
1702
- # :a.sql_subscript(2)[1] # a[2][1]
1826
+ # Sequel[:a].sql_subscript(2) # a[2]
1827
+ # Sequel[:a].sql_subscript(2)[1] # a[2][1]
1703
1828
  def [](sub)
1704
1829
  Subscript.new(self, Array(sub))
1705
1830
  end
@@ -1711,64 +1836,46 @@ module Sequel
1711
1836
  # ruby array of two element arrays as an SQL value list instead of an ordered
1712
1837
  # hash-like conditions specifier.
1713
1838
  class ValueList < ::Array
1839
+ # Show that this is a value list and not just an array
1840
+ def inspect
1841
+ "#<#{self.class} #{super}>"
1842
+ end
1714
1843
  end
1715
1844
 
1716
- # The purpose of the +VirtualRow+ class is to allow the easy creation of SQL identifiers and functions
1717
- # without relying on methods defined on +Symbol+. This is useful if another library defines
1718
- # the methods defined by Sequel, if you are running on ruby 1.9, or if you are not using the
1719
- # core extensions.
1845
+ # The purpose of the +VirtualRow+ class is to allow the easy creation of SQL identifiers and functions,
1846
+ # in a way that leads to more compact code.
1720
1847
  #
1721
- # An instance of this class is yielded to the block supplied to <tt>Dataset#filter</tt>, <tt>Dataset#order</tt>, and <tt>Dataset#select</tt>
1848
+ # An instance of this class is yielded to the block supplied to <tt>Dataset#where</tt>, <tt>Dataset#order</tt>, and <tt>Dataset#select</tt>
1722
1849
  # (and the other methods that accept a block and pass it to one of those methods).
1723
1850
  # If the block doesn't take an argument, the block is instance_execed in the context of
1724
1851
  # an instance of this class.
1725
1852
  #
1726
- # +VirtualRow+ uses +method_missing+ to return either an +Identifier+, +QualifiedIdentifier+, or +Function+
1853
+ # +VirtualRow+ uses +method_missing+ to return either an +Identifier+, +Function+
1727
1854
  # depending on how it is called.
1728
1855
  #
1729
- # If a block is _not_ given, creates one of the following objects:
1730
- #
1731
1856
  # +Function+ :: Returned if any arguments are supplied, using the method name
1732
1857
  # as the function name, and the arguments as the function arguments.
1733
- # +QualifiedIdentifier+ :: Returned if the method name contains __, with the
1734
- # table being the part before __, and the column being the part after.
1735
1858
  # +Identifier+ :: Returned otherwise, using the method name.
1736
1859
  #
1737
- # If a block is given, it returns a +Function+. Note that the block is currently not called by the code, though
1738
- # this may change in a future version. If the first argument is:
1739
- #
1740
- # no arguments given :: creates a +Function+ with no arguments.
1741
- # :* :: creates a +Function+ with a literal wildcard argument (*), mostly useful for COUNT.
1742
- # :distinct :: creates a +Function+ that prepends DISTINCT to the rest of the arguments, mostly
1743
- # useful for aggregate functions.
1744
- # :over :: creates a +Function+ with a window. If a second argument is provided, it should be a hash
1745
- # of options which are used to create the +Window+ (with possible keys :window, :partition, :order, and :frame). The
1746
- # arguments to the function itself should be specified as <tt>:*=>true</tt> for a wildcard, or via
1747
- # the <tt>:args</tt> option.
1860
+ # If splitting symbols has been enabled (not the default), then method calls without
1861
+ # arguments will return +QualifiedIdentifier+ instances if the method call includes a
1862
+ # double underscore.
1748
1863
  #
1749
1864
  # Examples:
1750
1865
  #
1751
1866
  # ds = DB[:t]
1752
1867
  #
1753
1868
  # # Argument yielded to block
1754
- # ds.filter{|r| r.name < 2} # SELECT * FROM t WHERE (name < 2)
1755
- #
1756
- # # Block without argument (instance_eval)
1757
- # ds.filter{name < 2} # SELECT * FROM t WHERE (name < 2)
1869
+ # ds.where{|r| r.name < 2} # SELECT * FROM t WHERE (name < 2)
1758
1870
  #
1759
- # # Qualified identifiers
1760
- # ds.filter{table__column + 1 < 2} # SELECT * FROM t WHERE ((table.column + 1) < 2)
1871
+ # # Block without argument (instance_exec)
1872
+ # ds.where{name < 2} # SELECT * FROM t WHERE (name < 2)
1761
1873
  #
1762
1874
  # # Functions
1763
- # ds.filter{is_active(1, 'arg2')} # SELECT * FROM t WHERE is_active(1, 'arg2')
1764
- # ds.select{version{}} # SELECT version() FROM t
1765
- # ds.select{count(:*){}} # SELECT count(*) FROM t
1766
- # ds.select{count(:distinct, col1){}} # SELECT count(DISTINCT col1) FROM t
1767
- #
1768
- # # Window Functions
1769
- # ds.select{rank(:over){}} # SELECT rank() OVER () FROM t
1770
- # ds.select{count(:over, :*=>true){}} # SELECT count(*) OVER () FROM t
1771
- # ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}} # SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3) FROM t
1875
+ # ds.where{is_active(1, 'arg2')} # SELECT * FROM t WHERE is_active(1, 'arg2')
1876
+ # ds.select{version.function} # SELECT version() FROM t
1877
+ # ds.select{count.function.*} # SELECT count(*) FROM t
1878
+ # ds.select{count(col1).distinct} # SELECT count(DISTINCT col1) FROM t
1772
1879
  #
1773
1880
  # # Math Operators
1774
1881
  # ds.select{|o| o.+(1, :a).as(:b)} # SELECT (1 + a) AS b FROM t
@@ -1777,25 +1884,19 @@ module Sequel
1777
1884
  # ds.select{|o| o./(4, :a).as(:b)} # SELECT (4 / a) AS b FROM t
1778
1885
  #
1779
1886
  # # Boolean Operators
1780
- # ds.filter{|o| o.&({:a=>1}, :b)} # SELECT * FROM t WHERE ((a = 1) AND b)
1781
- # ds.filter{|o| o.|({:a=>1}, :b)} # SELECT * FROM t WHERE ((a = 1) OR b)
1782
- # ds.filter{|o| o.~({:a=>1})} # SELECT * FROM t WHERE (a != 1)
1783
- # ds.filter{|o| o.~({:a=>1, :b=>2})} # SELECT * FROM t WHERE ((a != 1) OR (b != 2))
1887
+ # ds.where{|o| o.&({a: 1}, :b)} # SELECT * FROM t WHERE ((a = 1) AND b)
1888
+ # ds.where{|o| o.|({a: 1}, :b)} # SELECT * FROM t WHERE ((a = 1) OR b)
1889
+ # ds.where{|o| o.~(a: 1)} # SELECT * FROM t WHERE (a != 1)
1890
+ # ds.where{|o| o.~(a: 1, b: 2)} # SELECT * FROM t WHERE ((a != 1) OR (b != 2))
1784
1891
  #
1785
1892
  # # Inequality Operators
1786
- # ds.filter{|o| o.>(1, :a)} # SELECT * FROM t WHERE (1 > a)
1787
- # ds.filter{|o| o.<(2, :a)} # SELECT * FROM t WHERE (2 < a)
1788
- # ds.filter{|o| o.>=(3, :a)} # SELECT * FROM t WHERE (3 >= a)
1789
- # ds.filter{|o| o.<=(4, :a)} # SELECT * FROM t WHERE (4 <= a)
1790
- #
1791
- # # Literal Strings
1792
- # ds.filter{{a=>`some SQL`}} # SELECT * FROM t WHERE (a = some SQL)
1893
+ # ds.where{|o| o.>(1, :a)} # SELECT * FROM t WHERE (1 > a)
1894
+ # ds.where{|o| o.<(2, :a)} # SELECT * FROM t WHERE (2 < a)
1895
+ # ds.where{|o| o.>=(3, :a)} # SELECT * FROM t WHERE (3 >= a)
1896
+ # ds.where{|o| o.<=(4, :a)} # SELECT * FROM t WHERE (4 <= a)
1793
1897
  #
1794
1898
  # For a more detailed explanation, see the {Virtual Rows guide}[rdoc-ref:doc/virtual_rows.rdoc].
1795
1899
  class VirtualRow < BasicObject
1796
- QUESTION_MARK = LiteralString.new('?').freeze
1797
- DOUBLE_UNDERSCORE = '__'.freeze
1798
-
1799
1900
  include OperatorBuilders
1800
1901
 
1801
1902
  %w'> < >= <='.each do |op|
@@ -1806,50 +1907,82 @@ module Sequel
1806
1907
  END
1807
1908
  end
1808
1909
 
1809
- # Return a literal string created with the given string.
1810
- def `(s)
1811
- Sequel::LiteralString.new(s)
1910
+ def initialize
1911
+ freeze
1812
1912
  end
1813
1913
 
1814
- # Return an +Identifier+, +QualifiedIdentifier+, or +Function+, depending
1815
- # on arguments and whether a block is provided. Does not currently call the block.
1816
- # See the class level documentation.
1817
- def method_missing(m, *args, &block)
1818
- if block
1914
+ m = Module.new do
1915
+ # Return an +Identifier+, +QualifiedIdentifier+, or +Function+, depending
1916
+ # on arguments and whether a block is provided. Does not currently call the block.
1917
+ # See the class level documentation.
1918
+ def method_missing(m, *args)
1819
1919
  if args.empty?
1820
- Function.new(m)
1821
- else
1822
- case args.shift
1823
- when :*
1824
- Function.new(m, *args).*
1825
- when :distinct
1826
- Function.new(m, *args).distinct
1827
- when :over
1828
- opts = args.shift || OPTS
1829
- f = Function.new(m, *::Kernel.Array(opts[:args]))
1830
- f = f.* if opts[:*]
1831
- f.over(opts)
1920
+ if Sequel.split_symbols?
1921
+ table, column = m.to_s.split('__', 2)
1922
+ column ? QualifiedIdentifier.new(table, column) : Identifier.new(m)
1832
1923
  else
1833
- Kernel.raise(Error, 'unsupported VirtualRow method argument used with block')
1924
+ Identifier.new(m)
1834
1925
  end
1926
+ else
1927
+ Function.new(m, *args)
1835
1928
  end
1836
- elsif args.empty?
1837
- table, column = m.to_s.split(DOUBLE_UNDERSCORE, 2)
1838
- column ? QualifiedIdentifier.new(table, column) : Identifier.new(m)
1839
- else
1840
- Function.new(m, *args)
1841
1929
  end
1842
1930
  end
1931
+ include m
1843
1932
 
1844
1933
  Sequel::VIRTUAL_ROW = new
1845
1934
  end
1846
1935
 
1847
1936
  # A +Window+ is part of a window function specifying the window over which a window function operates.
1937
+ #
1938
+ # Sequel::SQL::Window.new(partition: :col1)
1939
+ # # (PARTITION BY col1)
1940
+ # Sequel::SQL::Window.new(partition: [:col2, :col3])
1941
+ # # (PARTITION BY col2, col3)
1942
+ #
1943
+ # Sequel::SQL::Window.new(order: :col4)
1944
+ # # (ORDER BY col4)
1945
+ # Sequel::SQL::Window.new(order: [:col5, Sequel.desc(:col6)])
1946
+ # # (ORDER BY col5, col6 DESC)
1947
+ #
1948
+ # Sequel::SQL::Window.new(partition: :col7, frame: :all)
1949
+ # # (PARTITION BY col7 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
1950
+ # Sequel::SQL::Window.new(partition: :col7, frame: :rows)
1951
+ # # (PARTITION BY col7 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
1952
+ # Sequel::SQL::Window.new(partition: :col7, frame: {type: :range, start: current})
1953
+ # # (PARTITION BY col7 RANGE CURRENT ROW)
1954
+ # Sequel::SQL::Window.new(partition: :col7, frame: {type: :range, start: 1, end: 1})
1955
+ # # (PARTITION BY col7 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING)
1956
+ # Sequel::SQL::Window.new(partition: :col7, frame: {type: :range, start: 2, end: [1, :preceding]})
1957
+ # # (PARTITION BY col7 RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING)
1958
+ # Sequel::SQL::Window.new(partition: :col7, frame: {type: :range, start: 1, end: [2, :following]})
1959
+ # # (PARTITION BY col7 RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING)
1960
+ # Sequel::SQL::Window.new(partition: :col7, frame: {type: :range, start: :preceding, exclude: :current})
1961
+ # # (PARTITION BY col7 RANGE UNBOUNDED PRECEDING EXCLUDE CURRENT ROW)
1962
+ #
1963
+ # Sequel::SQL::Window.new(window: :named_window) # you can create a named window with Dataset#window
1964
+ # # (named_window)
1848
1965
  class Window < Expression
1849
1966
  # The options for this window. Options currently supported:
1850
- # :frame :: if specified, should be :all, :rows, or a String that is used literally. :all always operates over all rows in the
1851
- # partition, while :rows excludes the current row's later peers. The default is to include
1852
- # all previous rows in the partition up to the current row's last peer.
1967
+ # :frame :: if specified, should be :all, :rows, :range, :groups, a String, or a Hash.
1968
+ # :all :: Always operates over all rows in the partition
1969
+ # :rows :: Includes rows in the partition up to and including the current row
1970
+ # :range, :groups :: Includes rows in the partition up to and including the current group
1971
+ # String :: Used as literal SQL code, try to avoid
1972
+ # Hash :: Hash of options for the frame:
1973
+ # :type :: The type of frame, must be :rows, :range, or :groups (required)
1974
+ # :start :: The start of the frame (required). Possible values:
1975
+ # :preceding :: UNBOUNDED PRECEDING
1976
+ # :following :: UNBOUNDED FOLLOWING
1977
+ # :current :: CURRENT ROW
1978
+ # String, Numeric, or Cast :: Used as the offset of rows/values preceding
1979
+ # Array :: Must have two elements, with first element being String, Numeric, or
1980
+ # Cast and second element being :preceding or :following
1981
+ # :end :: The end of the frame. Can be left out. If present, takes the same values as
1982
+ # :start, except that when a String, Numeric, or Hash, it is used as the offset
1983
+ # for rows following
1984
+ # :exclude :: Which rows to exclude. Possible values are :current, :ties, :group
1985
+ # :no_others.
1853
1986
  # :order :: order on the column(s) given
1854
1987
  # :partition :: partition/group on the column(s) given
1855
1988
  # :window :: base results on a previously specified named window
@@ -1857,7 +1990,8 @@ module Sequel
1857
1990
 
1858
1991
  # Set the options to the options given
1859
1992
  def initialize(opts=OPTS)
1860
- @opts = opts
1993
+ @opts = opts.frozen? ? opts : Hash[opts].freeze
1994
+ freeze
1861
1995
  end
1862
1996
 
1863
1997
  to_s_method :window_sql, '@opts'
@@ -1872,6 +2006,7 @@ module Sequel
1872
2006
  # Set the value wrapped by the object.
1873
2007
  def initialize(value)
1874
2008
  @value = value
2009
+ freeze
1875
2010
  end
1876
2011
 
1877
2012
  to_s_method :literal, '@value'
@@ -1890,6 +2025,11 @@ module Sequel
1890
2025
  include SQL::InequalityMethods
1891
2026
  include SQL::AliasMethods
1892
2027
  include SQL::CastMethods
2028
+
2029
+ # Show that the current string is a literal string in addition to the output.
2030
+ def inspect
2031
+ "#<#{self.class} #{super}>"
2032
+ end
1893
2033
 
1894
2034
  # Return self if no args are given, otherwise return a SQL::PlaceholderLiteralString
1895
2035
  # with the current string and the given args.