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