sequel 4.36.0 → 5.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (760) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +548 -5749
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +265 -159
  5. data/bin/sequel +34 -12
  6. data/doc/advanced_associations.rdoc +228 -187
  7. data/doc/association_basics.rdoc +281 -291
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +86 -51
  10. data/doc/code_order.rdoc +25 -19
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/fork_safety.rdoc +84 -0
  16. data/doc/mass_assignment.rdoc +74 -31
  17. data/doc/migration.rdoc +59 -51
  18. data/doc/model_dataset_method_design.rdoc +129 -0
  19. data/doc/model_hooks.rdoc +15 -25
  20. data/doc/model_plugins.rdoc +12 -12
  21. data/doc/mssql_stored_procedures.rdoc +3 -3
  22. data/doc/object_model.rdoc +58 -68
  23. data/doc/opening_databases.rdoc +85 -95
  24. data/doc/postgresql.rdoc +263 -38
  25. data/doc/prepared_statements.rdoc +29 -24
  26. data/doc/querying.rdoc +189 -167
  27. data/doc/reflection.rdoc +5 -6
  28. data/doc/release_notes/5.0.0.txt +159 -0
  29. data/doc/release_notes/5.1.0.txt +31 -0
  30. data/doc/release_notes/5.10.0.txt +84 -0
  31. data/doc/release_notes/5.11.0.txt +83 -0
  32. data/doc/release_notes/5.12.0.txt +141 -0
  33. data/doc/release_notes/5.13.0.txt +27 -0
  34. data/doc/release_notes/5.14.0.txt +63 -0
  35. data/doc/release_notes/5.15.0.txt +39 -0
  36. data/doc/release_notes/5.16.0.txt +110 -0
  37. data/doc/release_notes/5.17.0.txt +31 -0
  38. data/doc/release_notes/5.18.0.txt +69 -0
  39. data/doc/release_notes/5.19.0.txt +28 -0
  40. data/doc/release_notes/5.2.0.txt +33 -0
  41. data/doc/release_notes/5.20.0.txt +89 -0
  42. data/doc/release_notes/5.21.0.txt +87 -0
  43. data/doc/release_notes/5.22.0.txt +48 -0
  44. data/doc/release_notes/5.23.0.txt +56 -0
  45. data/doc/release_notes/5.24.0.txt +56 -0
  46. data/doc/release_notes/5.25.0.txt +32 -0
  47. data/doc/release_notes/5.26.0.txt +35 -0
  48. data/doc/release_notes/5.27.0.txt +21 -0
  49. data/doc/release_notes/5.28.0.txt +16 -0
  50. data/doc/release_notes/5.29.0.txt +22 -0
  51. data/doc/release_notes/5.3.0.txt +121 -0
  52. data/doc/release_notes/5.30.0.txt +20 -0
  53. data/doc/release_notes/5.31.0.txt +148 -0
  54. data/doc/release_notes/5.32.0.txt +46 -0
  55. data/doc/release_notes/5.33.0.txt +24 -0
  56. data/doc/release_notes/5.34.0.txt +40 -0
  57. data/doc/release_notes/5.35.0.txt +56 -0
  58. data/doc/release_notes/5.36.0.txt +60 -0
  59. data/doc/release_notes/5.37.0.txt +30 -0
  60. data/doc/release_notes/5.38.0.txt +28 -0
  61. data/doc/release_notes/5.39.0.txt +19 -0
  62. data/doc/release_notes/5.4.0.txt +80 -0
  63. data/doc/release_notes/5.40.0.txt +40 -0
  64. data/doc/release_notes/5.41.0.txt +25 -0
  65. data/doc/release_notes/5.42.0.txt +136 -0
  66. data/doc/release_notes/5.43.0.txt +98 -0
  67. data/doc/release_notes/5.44.0.txt +32 -0
  68. data/doc/release_notes/5.45.0.txt +34 -0
  69. data/doc/release_notes/5.46.0.txt +87 -0
  70. data/doc/release_notes/5.47.0.txt +59 -0
  71. data/doc/release_notes/5.48.0.txt +14 -0
  72. data/doc/release_notes/5.49.0.txt +59 -0
  73. data/doc/release_notes/5.5.0.txt +61 -0
  74. data/doc/release_notes/5.50.0.txt +78 -0
  75. data/doc/release_notes/5.51.0.txt +47 -0
  76. data/doc/release_notes/5.52.0.txt +87 -0
  77. data/doc/release_notes/5.53.0.txt +23 -0
  78. data/doc/release_notes/5.54.0.txt +27 -0
  79. data/doc/release_notes/5.55.0.txt +21 -0
  80. data/doc/release_notes/5.56.0.txt +51 -0
  81. data/doc/release_notes/5.57.0.txt +23 -0
  82. data/doc/release_notes/5.58.0.txt +31 -0
  83. data/doc/release_notes/5.59.0.txt +73 -0
  84. data/doc/release_notes/5.6.0.txt +31 -0
  85. data/doc/release_notes/5.60.0.txt +22 -0
  86. data/doc/release_notes/5.61.0.txt +43 -0
  87. data/doc/release_notes/5.7.0.txt +108 -0
  88. data/doc/release_notes/5.8.0.txt +170 -0
  89. data/doc/release_notes/5.9.0.txt +99 -0
  90. data/doc/schema_modification.rdoc +95 -75
  91. data/doc/security.rdoc +109 -80
  92. data/doc/sharding.rdoc +74 -47
  93. data/doc/sql.rdoc +147 -122
  94. data/doc/testing.rdoc +43 -20
  95. data/doc/thread_safety.rdoc +2 -4
  96. data/doc/transactions.rdoc +97 -18
  97. data/doc/validations.rdoc +52 -50
  98. data/doc/virtual_rows.rdoc +90 -109
  99. data/lib/sequel/adapters/ado/access.rb +15 -17
  100. data/lib/sequel/adapters/ado/mssql.rb +6 -15
  101. data/lib/sequel/adapters/ado.rb +150 -20
  102. data/lib/sequel/adapters/amalgalite.rb +11 -23
  103. data/lib/sequel/adapters/ibmdb.rb +47 -55
  104. data/lib/sequel/adapters/jdbc/db2.rb +29 -39
  105. data/lib/sequel/adapters/jdbc/derby.rb +58 -54
  106. data/lib/sequel/adapters/jdbc/h2.rb +93 -35
  107. data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
  108. data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
  109. data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
  110. data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
  111. data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
  112. data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
  113. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
  114. data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
  115. data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
  116. data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
  117. data/lib/sequel/adapters/jdbc.rb +145 -130
  118. data/lib/sequel/adapters/mock.rb +100 -111
  119. data/lib/sequel/adapters/mysql.rb +114 -122
  120. data/lib/sequel/adapters/mysql2.rb +147 -63
  121. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  122. data/lib/sequel/adapters/odbc/mssql.rb +8 -14
  123. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  124. data/lib/sequel/adapters/odbc.rb +20 -25
  125. data/lib/sequel/adapters/oracle.rb +50 -56
  126. data/lib/sequel/adapters/postgres.rb +305 -327
  127. data/lib/sequel/adapters/postgresql.rb +1 -1
  128. data/lib/sequel/adapters/shared/access.rb +74 -78
  129. data/lib/sequel/adapters/shared/db2.rb +118 -71
  130. data/lib/sequel/adapters/shared/mssql.rb +301 -220
  131. data/lib/sequel/adapters/shared/mysql.rb +299 -217
  132. data/lib/sequel/adapters/shared/oracle.rb +226 -65
  133. data/lib/sequel/adapters/shared/postgres.rb +935 -395
  134. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
  135. data/lib/sequel/adapters/shared/sqlite.rb +447 -173
  136. data/lib/sequel/adapters/sqlanywhere.rb +48 -35
  137. data/lib/sequel/adapters/sqlite.rb +156 -111
  138. data/lib/sequel/adapters/tinytds.rb +30 -38
  139. data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
  140. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
  141. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
  142. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  143. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  144. data/lib/sequel/adapters/utils/replace.rb +1 -4
  145. data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
  146. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  147. data/lib/sequel/ast_transformer.rb +17 -89
  148. data/lib/sequel/connection_pool/sharded_single.rb +18 -15
  149. data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
  150. data/lib/sequel/connection_pool/single.rb +18 -13
  151. data/lib/sequel/connection_pool/threaded.rb +121 -120
  152. data/lib/sequel/connection_pool.rb +48 -29
  153. data/lib/sequel/core.rb +351 -301
  154. data/lib/sequel/database/connecting.rb +69 -57
  155. data/lib/sequel/database/dataset.rb +13 -5
  156. data/lib/sequel/database/dataset_defaults.rb +18 -102
  157. data/lib/sequel/database/features.rb +18 -4
  158. data/lib/sequel/database/logging.rb +12 -11
  159. data/lib/sequel/database/misc.rb +180 -122
  160. data/lib/sequel/database/query.rb +47 -27
  161. data/lib/sequel/database/schema_generator.rb +178 -84
  162. data/lib/sequel/database/schema_methods.rb +172 -97
  163. data/lib/sequel/database/transactions.rb +205 -44
  164. data/lib/sequel/database.rb +17 -2
  165. data/lib/sequel/dataset/actions.rb +339 -155
  166. data/lib/sequel/dataset/dataset_module.rb +46 -0
  167. data/lib/sequel/dataset/features.rb +90 -35
  168. data/lib/sequel/dataset/graph.rb +80 -58
  169. data/lib/sequel/dataset/misc.rb +137 -47
  170. data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
  171. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  172. data/lib/sequel/dataset/query.rb +530 -222
  173. data/lib/sequel/dataset/sql.rb +590 -368
  174. data/lib/sequel/dataset.rb +26 -16
  175. data/lib/sequel/deprecated.rb +12 -2
  176. data/lib/sequel/exceptions.rb +46 -16
  177. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  178. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  179. data/lib/sequel/extensions/_pretty_table.rb +2 -5
  180. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  181. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  182. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  183. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  184. data/lib/sequel/extensions/blank.rb +8 -0
  185. data/lib/sequel/extensions/caller_logging.rb +79 -0
  186. data/lib/sequel/extensions/columns_introspection.rb +4 -3
  187. data/lib/sequel/extensions/connection_expiration.rb +20 -10
  188. data/lib/sequel/extensions/connection_validator.rb +11 -10
  189. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  190. data/lib/sequel/extensions/constraint_validations.rb +62 -39
  191. data/lib/sequel/extensions/core_extensions.rb +42 -48
  192. data/lib/sequel/extensions/core_refinements.rb +80 -59
  193. data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
  194. data/lib/sequel/extensions/date_arithmetic.rb +98 -39
  195. data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
  196. data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
  197. data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
  198. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  199. data/lib/sequel/extensions/escaped_like.rb +100 -0
  200. data/lib/sequel/extensions/eval_inspect.rb +12 -15
  201. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  202. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  203. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  204. data/lib/sequel/extensions/from_block.rb +1 -34
  205. data/lib/sequel/extensions/graph_each.rb +4 -4
  206. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  207. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  208. data/lib/sequel/extensions/index_caching.rb +109 -0
  209. data/lib/sequel/extensions/inflector.rb +13 -5
  210. data/lib/sequel/extensions/integer64.rb +32 -0
  211. data/lib/sequel/extensions/is_distinct_from.rb +141 -0
  212. data/lib/sequel/extensions/looser_typecasting.rb +17 -8
  213. data/lib/sequel/extensions/migration.rb +119 -78
  214. data/lib/sequel/extensions/named_timezones.rb +88 -23
  215. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
  216. data/lib/sequel/extensions/null_dataset.rb +8 -8
  217. data/lib/sequel/extensions/pagination.rb +32 -29
  218. data/lib/sequel/extensions/pg_array.rb +221 -287
  219. data/lib/sequel/extensions/pg_array_ops.rb +17 -9
  220. data/lib/sequel/extensions/pg_enum.rb +63 -23
  221. data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
  222. data/lib/sequel/extensions/pg_hstore.rb +45 -54
  223. data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
  224. data/lib/sequel/extensions/pg_inet.rb +31 -12
  225. data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
  226. data/lib/sequel/extensions/pg_interval.rb +56 -29
  227. data/lib/sequel/extensions/pg_json.rb +417 -140
  228. data/lib/sequel/extensions/pg_json_ops.rb +270 -18
  229. data/lib/sequel/extensions/pg_loose_count.rb +4 -2
  230. data/lib/sequel/extensions/pg_multirange.rb +372 -0
  231. data/lib/sequel/extensions/pg_range.rb +131 -191
  232. data/lib/sequel/extensions/pg_range_ops.rb +42 -13
  233. data/lib/sequel/extensions/pg_row.rb +48 -81
  234. data/lib/sequel/extensions/pg_row_ops.rb +33 -14
  235. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  236. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  237. data/lib/sequel/extensions/query.rb +9 -7
  238. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  239. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  240. data/lib/sequel/extensions/s.rb +60 -0
  241. data/lib/sequel/extensions/schema_caching.rb +10 -1
  242. data/lib/sequel/extensions/schema_dumper.rb +71 -48
  243. data/lib/sequel/extensions/select_remove.rb +4 -4
  244. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  245. data/lib/sequel/extensions/server_block.rb +51 -27
  246. data/lib/sequel/extensions/split_array_nil.rb +4 -4
  247. data/lib/sequel/extensions/sql_comments.rb +119 -7
  248. data/lib/sequel/extensions/sql_expr.rb +2 -1
  249. data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
  250. data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
  251. data/lib/sequel/extensions/string_agg.rb +11 -8
  252. data/lib/sequel/extensions/string_date_time.rb +19 -23
  253. data/lib/sequel/extensions/symbol_aref.rb +55 -0
  254. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  255. data/lib/sequel/extensions/symbol_as.rb +23 -0
  256. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  257. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  258. data/lib/sequel/extensions/to_dot.rb +10 -4
  259. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  260. data/lib/sequel/model/associations.rb +1006 -284
  261. data/lib/sequel/model/base.rb +560 -805
  262. data/lib/sequel/model/dataset_module.rb +11 -10
  263. data/lib/sequel/model/default_inflections.rb +1 -1
  264. data/lib/sequel/model/errors.rb +10 -3
  265. data/lib/sequel/model/exceptions.rb +8 -10
  266. data/lib/sequel/model/inflections.rb +7 -20
  267. data/lib/sequel/model/plugins.rb +114 -0
  268. data/lib/sequel/model.rb +32 -82
  269. data/lib/sequel/plugins/active_model.rb +30 -14
  270. data/lib/sequel/plugins/after_initialize.rb +1 -1
  271. data/lib/sequel/plugins/association_dependencies.rb +25 -18
  272. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  273. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  274. data/lib/sequel/plugins/association_pks.rb +147 -70
  275. data/lib/sequel/plugins/association_proxies.rb +33 -9
  276. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  277. data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
  278. data/lib/sequel/plugins/auto_validations.rb +95 -28
  279. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  280. data/lib/sequel/plugins/before_after_save.rb +0 -42
  281. data/lib/sequel/plugins/blacklist_security.rb +21 -12
  282. data/lib/sequel/plugins/boolean_readers.rb +5 -5
  283. data/lib/sequel/plugins/boolean_subsets.rb +13 -8
  284. data/lib/sequel/plugins/caching.rb +25 -16
  285. data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
  286. data/lib/sequel/plugins/column_conflicts.rb +16 -3
  287. data/lib/sequel/plugins/column_encryption.rb +728 -0
  288. data/lib/sequel/plugins/column_select.rb +7 -5
  289. data/lib/sequel/plugins/columns_updated.rb +42 -0
  290. data/lib/sequel/plugins/composition.rb +42 -26
  291. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  292. data/lib/sequel/plugins/constraint_validations.rb +20 -14
  293. data/lib/sequel/plugins/csv_serializer.rb +56 -35
  294. data/lib/sequel/plugins/dataset_associations.rb +40 -17
  295. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  296. data/lib/sequel/plugins/defaults_setter.rb +65 -10
  297. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  298. data/lib/sequel/plugins/dirty.rb +62 -24
  299. data/lib/sequel/plugins/eager_each.rb +3 -3
  300. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  301. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  302. data/lib/sequel/plugins/enum.rb +124 -0
  303. data/lib/sequel/plugins/error_splitter.rb +17 -12
  304. data/lib/sequel/plugins/finder.rb +246 -0
  305. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  306. data/lib/sequel/plugins/force_encoding.rb +7 -12
  307. data/lib/sequel/plugins/hook_class_methods.rb +37 -54
  308. data/lib/sequel/plugins/input_transformer.rb +18 -10
  309. data/lib/sequel/plugins/insert_conflict.rb +76 -0
  310. data/lib/sequel/plugins/insert_returning_select.rb +2 -2
  311. data/lib/sequel/plugins/instance_filters.rb +10 -8
  312. data/lib/sequel/plugins/instance_hooks.rb +34 -17
  313. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  314. data/lib/sequel/plugins/inverted_subsets.rb +22 -13
  315. data/lib/sequel/plugins/json_serializer.rb +124 -64
  316. data/lib/sequel/plugins/lazy_attributes.rb +21 -14
  317. data/lib/sequel/plugins/list.rb +35 -21
  318. data/lib/sequel/plugins/many_through_many.rb +134 -21
  319. data/lib/sequel/plugins/modification_detection.rb +15 -5
  320. data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
  321. data/lib/sequel/plugins/nested_attributes.rb +61 -31
  322. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  323. data/lib/sequel/plugins/pg_array_associations.rb +103 -53
  324. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
  325. data/lib/sequel/plugins/pg_row.rb +5 -51
  326. data/lib/sequel/plugins/prepared_statements.rb +60 -72
  327. data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
  328. data/lib/sequel/plugins/rcte_tree.rb +68 -82
  329. data/lib/sequel/plugins/require_valid_schema.rb +67 -0
  330. data/lib/sequel/plugins/serialization.rb +43 -46
  331. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
  332. data/lib/sequel/plugins/sharding.rb +15 -10
  333. data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
  334. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  335. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  336. data/lib/sequel/plugins/split_values.rb +11 -6
  337. data/lib/sequel/plugins/sql_comments.rb +189 -0
  338. data/lib/sequel/plugins/static_cache.rb +77 -53
  339. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  340. data/lib/sequel/plugins/string_stripper.rb +3 -3
  341. data/lib/sequel/plugins/subclasses.rb +43 -10
  342. data/lib/sequel/plugins/subset_conditions.rb +15 -5
  343. data/lib/sequel/plugins/table_select.rb +2 -2
  344. data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
  345. data/lib/sequel/plugins/throw_failures.rb +110 -0
  346. data/lib/sequel/plugins/timestamps.rb +20 -8
  347. data/lib/sequel/plugins/touch.rb +19 -8
  348. data/lib/sequel/plugins/tree.rb +62 -32
  349. data/lib/sequel/plugins/typecast_on_load.rb +12 -4
  350. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  351. data/lib/sequel/plugins/unused_associations.rb +521 -0
  352. data/lib/sequel/plugins/update_or_create.rb +4 -4
  353. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  354. data/lib/sequel/plugins/update_refresh.rb +26 -15
  355. data/lib/sequel/plugins/uuid.rb +7 -11
  356. data/lib/sequel/plugins/validate_associated.rb +18 -0
  357. data/lib/sequel/plugins/validation_class_methods.rb +38 -19
  358. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  359. data/lib/sequel/plugins/validation_helpers.rb +57 -41
  360. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  361. data/lib/sequel/plugins/xml_serializer.rb +30 -31
  362. data/lib/sequel/sql.rb +471 -331
  363. data/lib/sequel/timezones.rb +78 -47
  364. data/lib/sequel/version.rb +7 -2
  365. data/lib/sequel.rb +1 -1
  366. metadata +217 -521
  367. data/Rakefile +0 -164
  368. data/doc/active_record.rdoc +0 -928
  369. data/doc/release_notes/1.0.txt +0 -38
  370. data/doc/release_notes/1.1.txt +0 -143
  371. data/doc/release_notes/1.3.txt +0 -101
  372. data/doc/release_notes/1.4.0.txt +0 -53
  373. data/doc/release_notes/1.5.0.txt +0 -155
  374. data/doc/release_notes/2.0.0.txt +0 -298
  375. data/doc/release_notes/2.1.0.txt +0 -271
  376. data/doc/release_notes/2.10.0.txt +0 -328
  377. data/doc/release_notes/2.11.0.txt +0 -215
  378. data/doc/release_notes/2.12.0.txt +0 -534
  379. data/doc/release_notes/2.2.0.txt +0 -253
  380. data/doc/release_notes/2.3.0.txt +0 -88
  381. data/doc/release_notes/2.4.0.txt +0 -106
  382. data/doc/release_notes/2.5.0.txt +0 -137
  383. data/doc/release_notes/2.6.0.txt +0 -157
  384. data/doc/release_notes/2.7.0.txt +0 -166
  385. data/doc/release_notes/2.8.0.txt +0 -171
  386. data/doc/release_notes/2.9.0.txt +0 -97
  387. data/doc/release_notes/3.0.0.txt +0 -221
  388. data/doc/release_notes/3.1.0.txt +0 -406
  389. data/doc/release_notes/3.10.0.txt +0 -286
  390. data/doc/release_notes/3.11.0.txt +0 -254
  391. data/doc/release_notes/3.12.0.txt +0 -304
  392. data/doc/release_notes/3.13.0.txt +0 -210
  393. data/doc/release_notes/3.14.0.txt +0 -118
  394. data/doc/release_notes/3.15.0.txt +0 -78
  395. data/doc/release_notes/3.16.0.txt +0 -45
  396. data/doc/release_notes/3.17.0.txt +0 -58
  397. data/doc/release_notes/3.18.0.txt +0 -120
  398. data/doc/release_notes/3.19.0.txt +0 -67
  399. data/doc/release_notes/3.2.0.txt +0 -268
  400. data/doc/release_notes/3.20.0.txt +0 -41
  401. data/doc/release_notes/3.21.0.txt +0 -87
  402. data/doc/release_notes/3.22.0.txt +0 -39
  403. data/doc/release_notes/3.23.0.txt +0 -172
  404. data/doc/release_notes/3.24.0.txt +0 -420
  405. data/doc/release_notes/3.25.0.txt +0 -88
  406. data/doc/release_notes/3.26.0.txt +0 -88
  407. data/doc/release_notes/3.27.0.txt +0 -82
  408. data/doc/release_notes/3.28.0.txt +0 -304
  409. data/doc/release_notes/3.29.0.txt +0 -459
  410. data/doc/release_notes/3.3.0.txt +0 -192
  411. data/doc/release_notes/3.30.0.txt +0 -135
  412. data/doc/release_notes/3.31.0.txt +0 -146
  413. data/doc/release_notes/3.32.0.txt +0 -202
  414. data/doc/release_notes/3.33.0.txt +0 -157
  415. data/doc/release_notes/3.34.0.txt +0 -671
  416. data/doc/release_notes/3.35.0.txt +0 -144
  417. data/doc/release_notes/3.36.0.txt +0 -245
  418. data/doc/release_notes/3.37.0.txt +0 -338
  419. data/doc/release_notes/3.38.0.txt +0 -234
  420. data/doc/release_notes/3.39.0.txt +0 -237
  421. data/doc/release_notes/3.4.0.txt +0 -325
  422. data/doc/release_notes/3.40.0.txt +0 -73
  423. data/doc/release_notes/3.41.0.txt +0 -155
  424. data/doc/release_notes/3.42.0.txt +0 -74
  425. data/doc/release_notes/3.43.0.txt +0 -105
  426. data/doc/release_notes/3.44.0.txt +0 -152
  427. data/doc/release_notes/3.45.0.txt +0 -179
  428. data/doc/release_notes/3.46.0.txt +0 -122
  429. data/doc/release_notes/3.47.0.txt +0 -270
  430. data/doc/release_notes/3.48.0.txt +0 -477
  431. data/doc/release_notes/3.5.0.txt +0 -510
  432. data/doc/release_notes/3.6.0.txt +0 -366
  433. data/doc/release_notes/3.7.0.txt +0 -179
  434. data/doc/release_notes/3.8.0.txt +0 -151
  435. data/doc/release_notes/3.9.0.txt +0 -233
  436. data/doc/release_notes/4.0.0.txt +0 -262
  437. data/doc/release_notes/4.1.0.txt +0 -85
  438. data/doc/release_notes/4.10.0.txt +0 -226
  439. data/doc/release_notes/4.11.0.txt +0 -147
  440. data/doc/release_notes/4.12.0.txt +0 -105
  441. data/doc/release_notes/4.13.0.txt +0 -169
  442. data/doc/release_notes/4.14.0.txt +0 -68
  443. data/doc/release_notes/4.15.0.txt +0 -56
  444. data/doc/release_notes/4.16.0.txt +0 -36
  445. data/doc/release_notes/4.17.0.txt +0 -38
  446. data/doc/release_notes/4.18.0.txt +0 -36
  447. data/doc/release_notes/4.19.0.txt +0 -45
  448. data/doc/release_notes/4.2.0.txt +0 -129
  449. data/doc/release_notes/4.20.0.txt +0 -79
  450. data/doc/release_notes/4.21.0.txt +0 -94
  451. data/doc/release_notes/4.22.0.txt +0 -72
  452. data/doc/release_notes/4.23.0.txt +0 -65
  453. data/doc/release_notes/4.24.0.txt +0 -99
  454. data/doc/release_notes/4.25.0.txt +0 -181
  455. data/doc/release_notes/4.26.0.txt +0 -44
  456. data/doc/release_notes/4.27.0.txt +0 -78
  457. data/doc/release_notes/4.28.0.txt +0 -57
  458. data/doc/release_notes/4.29.0.txt +0 -41
  459. data/doc/release_notes/4.3.0.txt +0 -40
  460. data/doc/release_notes/4.30.0.txt +0 -37
  461. data/doc/release_notes/4.31.0.txt +0 -57
  462. data/doc/release_notes/4.32.0.txt +0 -132
  463. data/doc/release_notes/4.33.0.txt +0 -88
  464. data/doc/release_notes/4.34.0.txt +0 -86
  465. data/doc/release_notes/4.35.0.txt +0 -130
  466. data/doc/release_notes/4.36.0.txt +0 -116
  467. data/doc/release_notes/4.4.0.txt +0 -92
  468. data/doc/release_notes/4.5.0.txt +0 -34
  469. data/doc/release_notes/4.6.0.txt +0 -30
  470. data/doc/release_notes/4.7.0.txt +0 -103
  471. data/doc/release_notes/4.8.0.txt +0 -175
  472. data/doc/release_notes/4.9.0.txt +0 -190
  473. data/lib/sequel/adapters/cubrid.rb +0 -144
  474. data/lib/sequel/adapters/do/mysql.rb +0 -66
  475. data/lib/sequel/adapters/do/postgres.rb +0 -44
  476. data/lib/sequel/adapters/do/sqlite3.rb +0 -42
  477. data/lib/sequel/adapters/do.rb +0 -158
  478. data/lib/sequel/adapters/jdbc/as400.rb +0 -84
  479. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
  480. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
  481. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
  482. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
  483. data/lib/sequel/adapters/odbc/progress.rb +0 -10
  484. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  485. data/lib/sequel/adapters/shared/firebird.rb +0 -247
  486. data/lib/sequel/adapters/shared/informix.rb +0 -54
  487. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
  488. data/lib/sequel/adapters/shared/progress.rb +0 -40
  489. data/lib/sequel/adapters/swift/mysql.rb +0 -49
  490. data/lib/sequel/adapters/swift/postgres.rb +0 -47
  491. data/lib/sequel/adapters/swift/sqlite.rb +0 -49
  492. data/lib/sequel/adapters/swift.rb +0 -160
  493. data/lib/sequel/adapters/utils/pg_types.rb +0 -70
  494. data/lib/sequel/dataset/mutation.rb +0 -111
  495. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
  496. data/lib/sequel/extensions/filter_having.rb +0 -63
  497. data/lib/sequel/extensions/hash_aliases.rb +0 -49
  498. data/lib/sequel/extensions/meta_def.rb +0 -35
  499. data/lib/sequel/extensions/query_literals.rb +0 -84
  500. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
  501. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
  502. data/lib/sequel/extensions/set_overrides.rb +0 -76
  503. data/lib/sequel/no_core_ext.rb +0 -3
  504. data/lib/sequel/plugins/association_autoreloading.rb +0 -9
  505. data/lib/sequel/plugins/identifier_columns.rb +0 -47
  506. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
  507. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
  508. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
  509. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
  510. data/lib/sequel/plugins/schema.rb +0 -82
  511. data/lib/sequel/plugins/scissors.rb +0 -35
  512. data/spec/adapter_spec.rb +0 -4
  513. data/spec/adapters/db2_spec.rb +0 -160
  514. data/spec/adapters/firebird_spec.rb +0 -411
  515. data/spec/adapters/informix_spec.rb +0 -100
  516. data/spec/adapters/mssql_spec.rb +0 -733
  517. data/spec/adapters/mysql_spec.rb +0 -1319
  518. data/spec/adapters/oracle_spec.rb +0 -313
  519. data/spec/adapters/postgres_spec.rb +0 -3790
  520. data/spec/adapters/spec_helper.rb +0 -49
  521. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  522. data/spec/adapters/sqlite_spec.rb +0 -688
  523. data/spec/bin_spec.rb +0 -258
  524. data/spec/core/connection_pool_spec.rb +0 -1045
  525. data/spec/core/database_spec.rb +0 -2636
  526. data/spec/core/dataset_spec.rb +0 -5175
  527. data/spec/core/deprecated_spec.rb +0 -70
  528. data/spec/core/expression_filters_spec.rb +0 -1247
  529. data/spec/core/mock_adapter_spec.rb +0 -464
  530. data/spec/core/object_graph_spec.rb +0 -303
  531. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  532. data/spec/core/schema_generator_spec.rb +0 -203
  533. data/spec/core/schema_spec.rb +0 -1676
  534. data/spec/core/spec_helper.rb +0 -34
  535. data/spec/core/version_spec.rb +0 -7
  536. data/spec/core_extensions_spec.rb +0 -699
  537. data/spec/core_model_spec.rb +0 -2
  538. data/spec/core_spec.rb +0 -1
  539. data/spec/extensions/accessed_columns_spec.rb +0 -51
  540. data/spec/extensions/active_model_spec.rb +0 -85
  541. data/spec/extensions/after_initialize_spec.rb +0 -24
  542. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  543. data/spec/extensions/association_dependencies_spec.rb +0 -117
  544. data/spec/extensions/association_pks_spec.rb +0 -405
  545. data/spec/extensions/association_proxies_spec.rb +0 -86
  546. data/spec/extensions/auto_validations_spec.rb +0 -192
  547. data/spec/extensions/before_after_save_spec.rb +0 -40
  548. data/spec/extensions/blacklist_security_spec.rb +0 -88
  549. data/spec/extensions/blank_spec.rb +0 -69
  550. data/spec/extensions/boolean_readers_spec.rb +0 -93
  551. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  552. data/spec/extensions/caching_spec.rb +0 -270
  553. data/spec/extensions/class_table_inheritance_spec.rb +0 -444
  554. data/spec/extensions/column_conflicts_spec.rb +0 -60
  555. data/spec/extensions/column_select_spec.rb +0 -108
  556. data/spec/extensions/columns_introspection_spec.rb +0 -91
  557. data/spec/extensions/composition_spec.rb +0 -242
  558. data/spec/extensions/connection_expiration_spec.rb +0 -121
  559. data/spec/extensions/connection_validator_spec.rb +0 -127
  560. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
  561. data/spec/extensions/constraint_validations_spec.rb +0 -389
  562. data/spec/extensions/core_refinements_spec.rb +0 -519
  563. data/spec/extensions/csv_serializer_spec.rb +0 -180
  564. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  565. data/spec/extensions/dataset_associations_spec.rb +0 -343
  566. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  567. data/spec/extensions/date_arithmetic_spec.rb +0 -167
  568. data/spec/extensions/defaults_setter_spec.rb +0 -102
  569. data/spec/extensions/delay_add_association_spec.rb +0 -74
  570. data/spec/extensions/dirty_spec.rb +0 -180
  571. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
  572. data/spec/extensions/eager_each_spec.rb +0 -66
  573. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  574. data/spec/extensions/error_splitter_spec.rb +0 -18
  575. data/spec/extensions/error_sql_spec.rb +0 -20
  576. data/spec/extensions/eval_inspect_spec.rb +0 -73
  577. data/spec/extensions/filter_having_spec.rb +0 -40
  578. data/spec/extensions/force_encoding_spec.rb +0 -114
  579. data/spec/extensions/from_block_spec.rb +0 -21
  580. data/spec/extensions/graph_each_spec.rb +0 -119
  581. data/spec/extensions/hash_aliases_spec.rb +0 -24
  582. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  583. data/spec/extensions/identifier_columns_spec.rb +0 -17
  584. data/spec/extensions/inflector_spec.rb +0 -183
  585. data/spec/extensions/input_transformer_spec.rb +0 -54
  586. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  587. data/spec/extensions/instance_filters_spec.rb +0 -79
  588. data/spec/extensions/instance_hooks_spec.rb +0 -276
  589. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  590. data/spec/extensions/json_serializer_spec.rb +0 -304
  591. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  592. data/spec/extensions/list_spec.rb +0 -278
  593. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  594. data/spec/extensions/many_through_many_spec.rb +0 -2172
  595. data/spec/extensions/meta_def_spec.rb +0 -21
  596. data/spec/extensions/migration_spec.rb +0 -728
  597. data/spec/extensions/modification_detection_spec.rb +0 -80
  598. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  599. data/spec/extensions/named_timezones_spec.rb +0 -108
  600. data/spec/extensions/nested_attributes_spec.rb +0 -697
  601. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -65
  602. data/spec/extensions/null_dataset_spec.rb +0 -85
  603. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  604. data/spec/extensions/pagination_spec.rb +0 -118
  605. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  606. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  607. data/spec/extensions/pg_array_spec.rb +0 -390
  608. data/spec/extensions/pg_enum_spec.rb +0 -92
  609. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  610. data/spec/extensions/pg_hstore_spec.rb +0 -206
  611. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  612. data/spec/extensions/pg_inet_spec.rb +0 -52
  613. data/spec/extensions/pg_interval_spec.rb +0 -76
  614. data/spec/extensions/pg_json_ops_spec.rb +0 -275
  615. data/spec/extensions/pg_json_spec.rb +0 -218
  616. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  617. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  618. data/spec/extensions/pg_range_spec.rb +0 -473
  619. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  620. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  621. data/spec/extensions/pg_row_spec.rb +0 -360
  622. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  623. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  624. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  625. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  626. data/spec/extensions/prepared_statements_spec.rb +0 -103
  627. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  628. data/spec/extensions/pretty_table_spec.rb +0 -92
  629. data/spec/extensions/query_literals_spec.rb +0 -183
  630. data/spec/extensions/query_spec.rb +0 -102
  631. data/spec/extensions/rcte_tree_spec.rb +0 -392
  632. data/spec/extensions/round_timestamps_spec.rb +0 -43
  633. data/spec/extensions/schema_caching_spec.rb +0 -41
  634. data/spec/extensions/schema_dumper_spec.rb +0 -814
  635. data/spec/extensions/schema_spec.rb +0 -117
  636. data/spec/extensions/scissors_spec.rb +0 -26
  637. data/spec/extensions/select_remove_spec.rb +0 -38
  638. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  639. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  640. data/spec/extensions/serialization_spec.rb +0 -362
  641. data/spec/extensions/server_block_spec.rb +0 -90
  642. data/spec/extensions/server_logging_spec.rb +0 -45
  643. data/spec/extensions/set_overrides_spec.rb +0 -61
  644. data/spec/extensions/sharding_spec.rb +0 -198
  645. data/spec/extensions/shared_caching_spec.rb +0 -175
  646. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  647. data/spec/extensions/singular_table_names_spec.rb +0 -22
  648. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  649. data/spec/extensions/spec_helper.rb +0 -71
  650. data/spec/extensions/split_array_nil_spec.rb +0 -24
  651. data/spec/extensions/split_values_spec.rb +0 -22
  652. data/spec/extensions/sql_comments_spec.rb +0 -27
  653. data/spec/extensions/sql_expr_spec.rb +0 -60
  654. data/spec/extensions/static_cache_spec.rb +0 -361
  655. data/spec/extensions/string_agg_spec.rb +0 -85
  656. data/spec/extensions/string_date_time_spec.rb +0 -95
  657. data/spec/extensions/string_stripper_spec.rb +0 -68
  658. data/spec/extensions/subclasses_spec.rb +0 -66
  659. data/spec/extensions/subset_conditions_spec.rb +0 -38
  660. data/spec/extensions/table_select_spec.rb +0 -71
  661. data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
  662. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  663. data/spec/extensions/timestamps_spec.rb +0 -175
  664. data/spec/extensions/to_dot_spec.rb +0 -154
  665. data/spec/extensions/touch_spec.rb +0 -203
  666. data/spec/extensions/tree_spec.rb +0 -274
  667. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  668. data/spec/extensions/unlimited_update_spec.rb +0 -20
  669. data/spec/extensions/update_or_create_spec.rb +0 -87
  670. data/spec/extensions/update_primary_key_spec.rb +0 -100
  671. data/spec/extensions/update_refresh_spec.rb +0 -53
  672. data/spec/extensions/uuid_spec.rb +0 -106
  673. data/spec/extensions/validate_associated_spec.rb +0 -52
  674. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  675. data/spec/extensions/validation_helpers_spec.rb +0 -554
  676. data/spec/extensions/xml_serializer_spec.rb +0 -207
  677. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  678. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  679. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  680. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  681. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  682. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  683. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  684. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  685. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  686. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  687. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  688. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  689. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  690. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  691. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  692. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  693. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  694. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  695. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  696. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  697. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  698. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  699. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  700. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  701. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  702. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  703. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  704. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  705. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  706. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  707. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  708. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  709. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  710. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  711. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  712. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  713. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  714. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  715. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  716. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  717. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  718. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  719. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  720. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  721. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  722. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  723. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  724. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  725. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  726. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  727. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  728. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  729. data/spec/guards_helper.rb +0 -55
  730. data/spec/integration/associations_test.rb +0 -2506
  731. data/spec/integration/database_test.rb +0 -113
  732. data/spec/integration/dataset_test.rb +0 -1858
  733. data/spec/integration/eager_loader_test.rb +0 -687
  734. data/spec/integration/migrator_test.rb +0 -262
  735. data/spec/integration/model_test.rb +0 -230
  736. data/spec/integration/plugin_test.rb +0 -2297
  737. data/spec/integration/prepared_statement_test.rb +0 -467
  738. data/spec/integration/schema_test.rb +0 -815
  739. data/spec/integration/spec_helper.rb +0 -56
  740. data/spec/integration/timezone_test.rb +0 -86
  741. data/spec/integration/transaction_test.rb +0 -406
  742. data/spec/integration/type_test.rb +0 -133
  743. data/spec/model/association_reflection_spec.rb +0 -565
  744. data/spec/model/associations_spec.rb +0 -4589
  745. data/spec/model/base_spec.rb +0 -759
  746. data/spec/model/class_dataset_methods_spec.rb +0 -150
  747. data/spec/model/dataset_methods_spec.rb +0 -149
  748. data/spec/model/eager_loading_spec.rb +0 -2197
  749. data/spec/model/hooks_spec.rb +0 -604
  750. data/spec/model/inflector_spec.rb +0 -26
  751. data/spec/model/model_spec.rb +0 -1097
  752. data/spec/model/plugins_spec.rb +0 -299
  753. data/spec/model/record_spec.rb +0 -2162
  754. data/spec/model/spec_helper.rb +0 -46
  755. data/spec/model/validations_spec.rb +0 -193
  756. data/spec/model_no_assoc_spec.rb +0 -1
  757. data/spec/model_spec.rb +0 -1
  758. data/spec/plugin_spec.rb +0 -1
  759. data/spec/sequel_coverage.rb +0 -15
  760. data/spec/spec_config.rb +0 -10
@@ -17,38 +17,19 @@ module Sequel
17
17
 
18
18
  # Returns an INSERT SQL query string. See +insert+.
19
19
  #
20
- # DB[:items].insert_sql(:a=>1)
20
+ # DB[:items].insert_sql(a: 1)
21
21
  # # => "INSERT INTO items (a) VALUES (1)"
22
22
  def insert_sql(*values)
23
23
  return static_sql(@opts[:sql]) if @opts[:sql]
24
24
 
25
- check_modification_allowed!
26
-
27
- columns = []
28
-
29
- case values.size
30
- when 0
31
- return insert_sql({})
32
- when 1
33
- case vals = values.at(0)
34
- when Hash
35
- values = []
36
- vals.each do |k,v|
37
- columns << k
38
- values << v
39
- end
40
- when Dataset, Array, LiteralString
41
- values = vals
42
- end
43
- when 2
44
- if (v0 = values.at(0)).is_a?(Array) && ((v1 = values.at(1)).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
45
- columns, values = v0, v1
46
- raise(Error, "Different number of values and columns given to insert_sql") if values.is_a?(Array) and columns.length != values.length
47
- end
48
- end
25
+ check_insert_allowed!
49
26
 
27
+ columns, values = _parse_insert_sql_args(values)
50
28
  if values.is_a?(Array) && values.empty? && !insert_supports_empty_values?
51
29
  columns, values = insert_empty_columns_values
30
+ elsif values.is_a?(Dataset) && hoist_cte?(values) && supports_cte?(:insert)
31
+ ds, values = hoist_cte(values)
32
+ return ds.clone(:columns=>columns, :values=>values).send(:_insert_sql)
52
33
  end
53
34
  clone(:columns=>columns, :values=>values).send(:_insert_sql)
54
35
  end
@@ -109,12 +90,34 @@ module Sequel
109
90
  end
110
91
  end
111
92
 
93
+ # The SQL to use for the MERGE statement.
94
+ def merge_sql
95
+ raise Error, "This database doesn't support MERGE" unless supports_merge?
96
+ if sql = opts[:sql]
97
+ return static_sql(sql)
98
+ end
99
+ if sql = cache_get(:_merge_sql)
100
+ return sql
101
+ end
102
+ source, join_condition = @opts[:merge_using]
103
+ raise Error, "No USING clause for MERGE" unless source
104
+ sql = @opts[:append_sql] || sql_string_origin
105
+
106
+ select_with_sql(sql)
107
+ sql << "MERGE INTO "
108
+ source_list_append(sql, @opts[:from])
109
+ sql << " USING "
110
+ identifier_append(sql, source)
111
+ sql << " ON "
112
+ literal_append(sql, join_condition)
113
+ _merge_when_sql(sql)
114
+ cache_set(:_merge_sql, sql) if cache_sql?
115
+ sql
116
+ end
117
+
112
118
  # Returns an array of insert statements for inserting multiple records.
113
119
  # This method is used by +multi_insert+ to format insert statements and
114
120
  # expects a keys array and and an array of value arrays.
115
- #
116
- # This method should be overridden by descendants if the support
117
- # inserting multiple records in a single SQL statement.
118
121
  def multi_insert_sql(columns, values)
119
122
  case multi_insert_sql_strategy
120
123
  when :values
@@ -124,13 +127,13 @@ module Sequel
124
127
  when :union
125
128
  c = false
126
129
  sql = LiteralString.new
127
- u = UNION_ALL_SELECT
130
+ u = ' UNION ALL SELECT '
128
131
  f = empty_from_sql
129
132
  values.each do |v|
130
133
  if c
131
134
  sql << u
132
135
  else
133
- sql << SELECT << SPACE
136
+ sql << 'SELECT '
134
137
  c = true
135
138
  end
136
139
  expression_list_append(sql, v)
@@ -155,6 +158,7 @@ module Sequel
155
158
  static_sql(opts[:sql])
156
159
  else
157
160
  check_truncation_allowed!
161
+ check_not_limited!(:truncate)
158
162
  raise(InvalidOperation, "Can't truncate filtered datasets") if opts[:where] || opts[:having]
159
163
  t = String.new
160
164
  source_list_append(t, opts[:from])
@@ -164,14 +168,23 @@ module Sequel
164
168
 
165
169
  # Formats an UPDATE statement using the given values. See +update+.
166
170
  #
167
- # DB[:items].update_sql(:price => 100, :category => 'software')
171
+ # DB[:items].update_sql(price: 100, category: 'software')
168
172
  # # => "UPDATE items SET price = 100, category = 'software'
169
173
  #
170
174
  # Raises an +Error+ if the dataset is grouped or includes more
171
175
  # than one table.
172
176
  def update_sql(values = OPTS)
173
177
  return static_sql(opts[:sql]) if opts[:sql]
174
- check_modification_allowed!
178
+ check_update_allowed!
179
+ check_not_limited!(:update)
180
+
181
+ case values
182
+ when LiteralString
183
+ # nothing
184
+ when String
185
+ raise Error, "plain string passed to Dataset#update is not supported, use Sequel.lit to use a literal string"
186
+ end
187
+
175
188
  clone(:values=>values).send(:_update_sql)
176
189
  end
177
190
 
@@ -198,12 +211,14 @@ module Sequel
198
211
  # being an array of symbol/strings for the appropriate branch.
199
212
  def self.def_sql_method(mod, type, clauses)
200
213
  priv = type == :update || type == :insert
214
+ cacheable = type == :select || type == :delete
201
215
 
202
216
  lines = []
203
217
  lines << 'private' if priv
204
218
  lines << "def #{'_' if priv}#{type}_sql"
205
219
  lines << 'if sql = opts[:sql]; return static_sql(sql) end' unless priv
206
- lines << 'check_modification_allowed!' if type == :delete
220
+ lines << "if sql = cache_get(:_#{type}_sql); return sql end" if cacheable
221
+ lines << 'check_delete_allowed!' << 'check_not_limited!(:delete)' if type == :delete
207
222
  lines << 'sql = @opts[:append_sql] || sql_string_origin'
208
223
 
209
224
  if clauses.all?{|c| c.is_a?(Array)}
@@ -216,6 +231,7 @@ module Sequel
216
231
  lines.concat(clause_methods(type, clauses).map{|x| "#{x}(sql)"})
217
232
  end
218
233
 
234
+ lines << "cache_set(:_#{type}_sql, sql) if cache_sql?" if cacheable
219
235
  lines << 'sql'
220
236
  lines << 'end'
221
237
 
@@ -227,116 +243,21 @@ module Sequel
227
243
  def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order limit lock')
228
244
  def_sql_method(self, :update, %w'update table set where')
229
245
 
230
- # Map of emulated function names to native function names.
231
- EMULATED_FUNCTION_MAP = {}
232
-
233
246
  WILDCARD = LiteralString.new('*').freeze
234
- ALL = ' ALL'.freeze
235
- AND_SEPARATOR = " AND ".freeze
236
- APOS = "'".freeze
237
- APOS_RE = /'/.freeze
238
- ARRAY_EMPTY = '(NULL)'.freeze
239
- AS = ' AS '.freeze
240
- ASC = ' ASC'.freeze
241
- BACKSLASH = "\\".freeze
242
- BITCOMP_CLOSE = ") - 1)".freeze
243
- BITCOMP_OPEN = "((0 - ".freeze
244
- BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
245
- BOOL_FALSE = "'f'".freeze
246
- BOOL_TRUE = "'t'".freeze
247
- BRACKET_CLOSE = ']'.freeze
248
- BRACKET_OPEN = '['.freeze
249
- CASE_ELSE = " ELSE ".freeze
250
- CASE_END = " END)".freeze
251
- CASE_OPEN = '(CASE'.freeze
252
- CASE_THEN = " THEN ".freeze
253
- CASE_WHEN = " WHEN ".freeze
254
- CAST_OPEN = 'CAST('.freeze
255
- COLON = ':'.freeze
256
- COLUMN_REF_RE1 = Sequel::COLUMN_REF_RE1
257
- COLUMN_REF_RE2 = Sequel::COLUMN_REF_RE2
258
- COLUMN_REF_RE3 = Sequel::COLUMN_REF_RE3
259
- COMMA = ', '.freeze
260
- COMMA_SEPARATOR = COMMA
261
- CONDITION_FALSE = '(1 = 0)'.freeze
262
- CONDITION_TRUE = '(1 = 1)'.freeze
263
- COUNT_FROM_SELF_OPTS = [:distinct, :group, :sql, :limit, :offset, :compounds]
264
247
  COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count, WILDCARD).as(:count)
265
- DATASET_ALIAS_BASE_NAME = 't'.freeze
266
248
  DEFAULT = LiteralString.new('DEFAULT').freeze
267
- DEFAULT_VALUES = " DEFAULT VALUES".freeze
268
- DELETE = 'DELETE'.freeze
269
- DESC = ' DESC'.freeze
270
- DISTINCT = " DISTINCT".freeze
271
- DOT = '.'.freeze
272
- DOUBLE_APOS = "''".freeze
273
- DOUBLE_QUOTE = '""'.freeze
274
- EQUAL = ' = '.freeze
275
- EMPTY_PARENS = '()'.freeze
276
- ESCAPE = " ESCAPE ".freeze
277
- EXTRACT = 'extract('.freeze
249
+
278
250
  EXISTS = ['EXISTS '.freeze].freeze
279
- FILTER = " FILTER (WHERE ".freeze
280
- FOR_UPDATE = ' FOR UPDATE'.freeze
281
- FORMAT_DATE = "'%Y-%m-%d'".freeze
282
- FORMAT_DATE_STANDARD = "DATE '%Y-%m-%d'".freeze
283
- FORMAT_OFFSET = "%+03i%02i".freeze
284
- FORMAT_TIMESTAMP_RE = /%[Nz]/.freeze
285
- FORMAT_USEC = '%N'.freeze
286
- FRAME_ALL = "ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING".freeze
287
- FRAME_ROWS = "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW".freeze
288
- FROM = ' FROM '.freeze
289
- FUNCTION_DISTINCT = "DISTINCT ".freeze
290
- GROUP_BY = " GROUP BY ".freeze
291
- HAVING = " HAVING ".freeze
292
- INSERT = "INSERT".freeze
293
- INTO = " INTO ".freeze
251
+ BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}.freeze
252
+ COUNT_FROM_SELF_OPTS = [:distinct, :group, :sql, :limit, :offset, :compounds].freeze
294
253
  IS_LITERALS = {nil=>'NULL'.freeze, true=>'TRUE'.freeze, false=>'FALSE'.freeze}.freeze
254
+ QUALIFY_KEYS = [:select, :where, :having, :order, :group].freeze
255
+
295
256
  IS_OPERATORS = ::Sequel::SQL::ComplexExpression::IS_OPERATORS
296
- LATERAL = 'LATERAL '.freeze
297
257
  LIKE_OPERATORS = ::Sequel::SQL::ComplexExpression::LIKE_OPERATORS
298
- LIMIT = " LIMIT ".freeze
299
258
  N_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::N_ARITY_OPERATORS
300
- NOT_SPACE = 'NOT '.freeze
301
- NULL = "NULL".freeze
302
- NULLS_FIRST = " NULLS FIRST".freeze
303
- NULLS_LAST = " NULLS LAST".freeze
304
- OFFSET = " OFFSET ".freeze
305
- ON = ' ON '.freeze
306
- ON_PAREN = " ON (".freeze
307
- ORDER_BY = " ORDER BY ".freeze
308
- ORDER_BY_NS = "ORDER BY ".freeze
309
- OVER = ' OVER '.freeze
310
- PAREN_CLOSE = ')'.freeze
311
- PAREN_OPEN = '('.freeze
312
- PAREN_SPACE_OPEN = ' ('.freeze
313
- PARTITION_BY = "PARTITION BY ".freeze
314
- QUALIFY_KEYS = [:select, :where, :having, :order, :group]
315
- QUESTION_MARK = '?'.freeze
316
- QUESTION_MARK_RE = /\?/.freeze
317
- QUOTE = '"'.freeze
318
- QUOTE_RE = /"/.freeze
319
- RETURNING = " RETURNING ".freeze
320
- SELECT = 'SELECT'.freeze
321
- SET = ' SET '.freeze
322
- SPACE = ' '.freeze
323
- SQL_WITH = "WITH ".freeze
324
- SPACE_WITH = " WITH ".freeze
325
- TILDE = '~'.freeze
326
- TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S%N%z'".freeze
327
- STANDARD_TIMESTAMP_FORMAT = "TIMESTAMP #{TIMESTAMP_FORMAT}".freeze
328
259
  TWO_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::TWO_ARITY_OPERATORS
329
260
  REGEXP_OPERATORS = ::Sequel::SQL::ComplexExpression::REGEXP_OPERATORS
330
- UNDERSCORE = '_'.freeze
331
- UPDATE = 'UPDATE'.freeze
332
- USING = ' USING ('.freeze
333
- UNION_ALL_SELECT = ' UNION ALL SELECT '.freeze
334
- VALUES = " VALUES ".freeze
335
- WHERE = " WHERE ".freeze
336
- WITH_ORDINALITY = " WITH ORDINALITY".freeze
337
- WITHIN_GROUP = " WITHIN GROUP (ORDER BY ".freeze
338
-
339
- DATETIME_SECFRACTION_ARG = RUBY_VERSION >= '1.9.0' ? 1000000 : 86400000000
340
261
 
341
262
  [:literal, :quote_identifier, :quote_schema_table].each do |meth|
342
263
  class_eval(<<-END, __FILE__, __LINE__ + 1)
@@ -357,18 +278,18 @@ module Sequel
357
278
  # Append literalization of array to SQL string.
358
279
  def array_sql_append(sql, a)
359
280
  if a.empty?
360
- sql << ARRAY_EMPTY
281
+ sql << '(NULL)'
361
282
  else
362
- sql << PAREN_OPEN
283
+ sql << '('
363
284
  expression_list_append(sql, a)
364
- sql << PAREN_CLOSE
285
+ sql << ')'
365
286
  end
366
287
  end
367
288
 
368
289
  # Append literalization of boolean constant to SQL string.
369
290
  def boolean_constant_sql_append(sql, constant)
370
291
  if (constant == true || constant == false) && !supports_where_true?
371
- sql << (constant == true ? CONDITION_TRUE : CONDITION_FALSE)
292
+ sql << (constant == true ? '(1 = 1)' : '(1 = 0)')
372
293
  else
373
294
  literal_append(sql, constant)
374
295
  end
@@ -376,30 +297,30 @@ module Sequel
376
297
 
377
298
  # Append literalization of case expression to SQL string.
378
299
  def case_expression_sql_append(sql, ce)
379
- sql << CASE_OPEN
300
+ sql << '(CASE'
380
301
  if ce.expression?
381
- sql << SPACE
302
+ sql << ' '
382
303
  literal_append(sql, ce.expression)
383
304
  end
384
- w = CASE_WHEN
385
- t = CASE_THEN
305
+ w = " WHEN "
306
+ t = " THEN "
386
307
  ce.conditions.each do |c,r|
387
308
  sql << w
388
309
  literal_append(sql, c)
389
310
  sql << t
390
311
  literal_append(sql, r)
391
312
  end
392
- sql << CASE_ELSE
313
+ sql << " ELSE "
393
314
  literal_append(sql, ce.default)
394
- sql << CASE_END
315
+ sql << " END)"
395
316
  end
396
317
 
397
318
  # Append literalization of cast expression to SQL string.
398
319
  def cast_sql_append(sql, expr, type)
399
- sql << CAST_OPEN
320
+ sql << 'CAST('
400
321
  literal_append(sql, expr)
401
- sql << AS << db.cast_type_literal(type).to_s
402
- sql << PAREN_CLOSE
322
+ sql << ' AS ' << db.cast_type_literal(type).to_s
323
+ sql << ')'
403
324
  end
404
325
 
405
326
  # Append literalization of column all selection to SQL string.
@@ -411,21 +332,21 @@ module Sequel
411
332
  def complex_expression_sql_append(sql, op, args)
412
333
  case op
413
334
  when *IS_OPERATORS
414
- r = args.at(1)
335
+ r = args[1]
415
336
  if r.nil? || supports_is_true?
416
337
  raise(InvalidOperation, 'Invalid argument used for IS operator') unless val = IS_LITERALS[r]
417
- sql << PAREN_OPEN
418
- literal_append(sql, args.at(0))
419
- sql << SPACE << op.to_s << SPACE
420
- sql << val << PAREN_CLOSE
338
+ sql << '('
339
+ literal_append(sql, args[0])
340
+ sql << ' ' << op.to_s << ' '
341
+ sql << val << ')'
421
342
  elsif op == :IS
422
343
  complex_expression_sql_append(sql, :"=", args)
423
344
  else
424
- complex_expression_sql_append(sql, :OR, [SQL::BooleanExpression.new(:"!=", *args), SQL::BooleanExpression.new(:IS, args.at(0), nil)])
345
+ complex_expression_sql_append(sql, :OR, [SQL::BooleanExpression.new(:"!=", *args), SQL::BooleanExpression.new(:IS, args[0], nil)])
425
346
  end
426
347
  when :IN, :"NOT IN"
427
- cols = args.at(0)
428
- vals = args.at(1)
348
+ cols = args[0]
349
+ vals = args[1]
429
350
  col_array = true if cols.is_a?(Array)
430
351
  if vals.is_a?(Array)
431
352
  val_array = true
@@ -449,44 +370,48 @@ module Sequel
449
370
  # If the columns and values are both arrays, use array_sql instead of
450
371
  # literal so that if values is an array of two element arrays, it
451
372
  # will be treated as a value list instead of a condition specifier.
452
- sql << PAREN_OPEN
373
+ sql << '('
453
374
  literal_append(sql, cols)
454
- sql << SPACE << op.to_s << SPACE
375
+ sql << ' ' << op.to_s << ' '
455
376
  if val_array
456
377
  array_sql_append(sql, vals)
457
378
  else
458
379
  literal_append(sql, vals)
459
380
  end
460
- sql << PAREN_CLOSE
381
+ sql << ')'
461
382
  end
462
383
  else
463
- sql << PAREN_OPEN
384
+ sql << '('
464
385
  literal_append(sql, cols)
465
- sql << SPACE << op.to_s << SPACE
386
+ sql << ' ' << op.to_s << ' '
466
387
  literal_append(sql, vals)
467
- sql << PAREN_CLOSE
388
+ sql << ')'
468
389
  end
469
390
  when :LIKE, :'NOT LIKE'
470
- sql << PAREN_OPEN
471
- literal_append(sql, args.at(0))
472
- sql << SPACE << op.to_s << SPACE
473
- literal_append(sql, args.at(1))
474
- sql << ESCAPE
475
- literal_append(sql, BACKSLASH)
476
- sql << PAREN_CLOSE
391
+ sql << '('
392
+ literal_append(sql, args[0])
393
+ sql << ' ' << op.to_s << ' '
394
+ literal_append(sql, args[1])
395
+ if requires_like_escape?
396
+ sql << " ESCAPE "
397
+ literal_append(sql, "\\")
398
+ end
399
+ sql << ')'
477
400
  when :ILIKE, :'NOT ILIKE'
478
401
  complex_expression_sql_append(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|v| Sequel.function(:UPPER, v)})
402
+ when :**
403
+ function_sql_append(sql, Sequel.function(:power, *args))
479
404
  when *TWO_ARITY_OPERATORS
480
405
  if REGEXP_OPERATORS.include?(op) && !supports_regexp?
481
406
  raise InvalidOperation, "Pattern matching via regular expressions is not supported on #{db.database_type}"
482
407
  end
483
- sql << PAREN_OPEN
484
- literal_append(sql, args.at(0))
485
- sql << SPACE << op.to_s << SPACE
486
- literal_append(sql, args.at(1))
487
- sql << PAREN_CLOSE
408
+ sql << '('
409
+ literal_append(sql, args[0])
410
+ sql << ' ' << op.to_s << ' '
411
+ literal_append(sql, args[1])
412
+ sql << ')'
488
413
  when *N_ARITY_OPERATORS
489
- sql << PAREN_OPEN
414
+ sql << '('
490
415
  c = false
491
416
  op_str = " #{op} "
492
417
  args.each do |a|
@@ -494,19 +419,19 @@ module Sequel
494
419
  literal_append(sql, a)
495
420
  c ||= true
496
421
  end
497
- sql << PAREN_CLOSE
422
+ sql << ')'
498
423
  when :NOT
499
- sql << NOT_SPACE
500
- literal_append(sql, args.at(0))
424
+ sql << 'NOT '
425
+ literal_append(sql, args[0])
501
426
  when :NOOP
502
- literal_append(sql, args.at(0))
427
+ literal_append(sql, args[0])
503
428
  when :'B~'
504
- sql << TILDE
505
- literal_append(sql, args.at(0))
429
+ sql << '~'
430
+ literal_append(sql, args[0])
506
431
  when :extract
507
- sql << EXTRACT << args.at(0).to_s << FROM
508
- literal_append(sql, args.at(1))
509
- sql << PAREN_CLOSE
432
+ sql << 'extract(' << args[0].to_s << ' FROM '
433
+ literal_append(sql, args[1])
434
+ sql << ')'
510
435
  else
511
436
  raise(InvalidOperation, "invalid operator #{op}")
512
437
  end
@@ -520,6 +445,11 @@ module Sequel
520
445
  # Append literalization of delayed evaluation to SQL string,
521
446
  # causing the delayed evaluation proc to be evaluated.
522
447
  def delayed_evaluation_sql_append(sql, delay)
448
+ # Delayed evaluations are used specifically so the SQL
449
+ # can differ in subsequent calls, so we definitely don't
450
+ # want to cache the sql in this case.
451
+ disable_sql_caching!
452
+
523
453
  if recorder = @opts[:placeholder_literalizer]
524
454
  recorder.use(sql, lambda{delay.call(self)}, nil)
525
455
  else
@@ -541,11 +471,11 @@ module Sequel
541
471
  name = native_function_name(name)
542
472
  end
543
473
 
544
- sql << LATERAL if opts[:lateral]
474
+ sql << 'LATERAL ' if opts[:lateral]
545
475
 
546
476
  case name
547
477
  when SQL::Identifier
548
- if supports_quoted_function_names? && opts[:quoted] != false
478
+ if supports_quoted_function_names? && opts[:quoted]
549
479
  literal_append(sql, name)
550
480
  else
551
481
  sql << name.value.to_s
@@ -554,7 +484,7 @@ module Sequel
554
484
  if supports_quoted_function_names? && opts[:quoted] != false
555
485
  literal_append(sql, name)
556
486
  else
557
- sql << split_qualifiers(name).join(DOT)
487
+ sql << split_qualifiers(name).join('.')
558
488
  end
559
489
  else
560
490
  if supports_quoted_function_names? && opts[:quoted]
@@ -564,38 +494,51 @@ module Sequel
564
494
  end
565
495
  end
566
496
 
567
- sql << PAREN_OPEN
497
+ sql << '('
498
+ if filter = opts[:filter]
499
+ filter = filter_expr(filter, &opts[:filter_block])
500
+ end
568
501
  if opts[:*]
569
- sql << WILDCARD
502
+ if filter && !supports_filtered_aggregates?
503
+ literal_append(sql, Sequel.case({filter=>1}, nil))
504
+ filter = nil
505
+ else
506
+ sql << '*'
507
+ end
570
508
  else
571
- sql << FUNCTION_DISTINCT if opts[:distinct]
572
- expression_list_append(sql, f.args)
509
+ sql << "DISTINCT " if opts[:distinct]
510
+ if filter && !supports_filtered_aggregates?
511
+ expression_list_append(sql, f.args.map{|arg| Sequel.case({filter=>arg}, nil)})
512
+ filter = nil
513
+ else
514
+ expression_list_append(sql, f.args)
515
+ end
573
516
  if order = opts[:order]
574
- sql << ORDER_BY
517
+ sql << " ORDER BY "
575
518
  expression_list_append(sql, order)
576
519
  end
577
520
  end
578
- sql << PAREN_CLOSE
521
+ sql << ')'
579
522
 
580
523
  if group = opts[:within_group]
581
- sql << WITHIN_GROUP
524
+ sql << " WITHIN GROUP (ORDER BY "
582
525
  expression_list_append(sql, group)
583
- sql << PAREN_CLOSE
526
+ sql << ')'
584
527
  end
585
528
 
586
- if filter = opts[:filter]
587
- sql << FILTER
588
- literal_append(sql, filter_expr(filter, &opts[:filter_block]))
589
- sql << PAREN_CLOSE
529
+ if filter
530
+ sql << " FILTER (WHERE "
531
+ literal_append(sql, filter)
532
+ sql << ')'
590
533
  end
591
534
 
592
535
  if window = opts[:over]
593
- sql << OVER
536
+ sql << ' OVER '
594
537
  window_sql_append(sql, window.opts)
595
538
  end
596
539
 
597
540
  if opts[:with_ordinality]
598
- sql << WITH_ORDINALITY
541
+ sql << " WITH ORDINALITY"
599
542
  end
600
543
  end
601
544
 
@@ -604,7 +547,7 @@ module Sequel
604
547
  table = jc.table
605
548
  table_alias = jc.table_alias
606
549
  table_alias = nil if table == table_alias && !jc.column_aliases
607
- sql << SPACE << join_type_sql(jc.join_type) << SPACE
550
+ sql << ' ' << join_type_sql(jc.join_type) << ' '
608
551
  identifier_append(sql, table)
609
552
  as_sql_append(sql, table_alias, jc.column_aliases) if table_alias
610
553
  end
@@ -612,33 +555,48 @@ module Sequel
612
555
  # Append literalization of JOIN ON clause to SQL string.
613
556
  def join_on_clause_sql_append(sql, jc)
614
557
  join_clause_sql_append(sql, jc)
615
- sql << ON
558
+ sql << ' ON '
616
559
  literal_append(sql, filter_expr(jc.on))
617
560
  end
618
561
 
619
562
  # Append literalization of JOIN USING clause to SQL string.
620
563
  def join_using_clause_sql_append(sql, jc)
621
564
  join_clause_sql_append(sql, jc)
622
- sql << USING
623
- column_list_append(sql, jc.using)
624
- sql << PAREN_CLOSE
565
+ join_using_clause_using_sql_append(sql, jc.using)
625
566
  end
626
-
567
+
627
568
  # Append literalization of negative boolean constant to SQL string.
628
569
  def negative_boolean_constant_sql_append(sql, constant)
629
- sql << NOT_SPACE
570
+ sql << 'NOT '
630
571
  boolean_constant_sql_append(sql, constant)
631
572
  end
632
573
 
633
574
  # Append literalization of ordered expression to SQL string.
634
575
  def ordered_expression_sql_append(sql, oe)
576
+ if emulate = requires_emulating_nulls_first?
577
+ case oe.nulls
578
+ when :first
579
+ null_order = 0
580
+ when :last
581
+ null_order = 2
582
+ end
583
+
584
+ if null_order
585
+ literal_append(sql, Sequel.case({{oe.expression=>nil}=>null_order}, 1))
586
+ sql << ", "
587
+ end
588
+ end
589
+
635
590
  literal_append(sql, oe.expression)
636
- sql << (oe.descending ? DESC : ASC)
637
- case oe.nulls
638
- when :first
639
- sql << NULLS_FIRST
640
- when :last
641
- sql << NULLS_LAST
591
+ sql << (oe.descending ? ' DESC' : ' ASC')
592
+
593
+ unless emulate
594
+ case oe.nulls
595
+ when :first
596
+ sql << " NULLS FIRST"
597
+ when :last
598
+ sql << " NULLS LAST"
599
+ end
642
600
  end
643
601
  end
644
602
 
@@ -646,13 +604,13 @@ module Sequel
646
604
  def placeholder_literal_string_sql_append(sql, pls)
647
605
  args = pls.args
648
606
  str = pls.str
649
- sql << PAREN_OPEN if pls.parens
607
+ sql << '(' if pls.parens
650
608
  if args.is_a?(Hash)
651
609
  if args.empty?
652
610
  sql << str
653
611
  else
654
612
  re = /:(#{args.keys.map{|k| Regexp.escape(k.to_s)}.join('|')})\b/
655
- loop do
613
+ while true
656
614
  previous, q, str = str.partition(re)
657
615
  sql << previous
658
616
  literal_append(sql, args[($1||q[1..-1].to_s).to_sym]) unless q.empty?
@@ -671,19 +629,19 @@ module Sequel
671
629
  else
672
630
  i = -1
673
631
  match_len = args.length - 1
674
- loop do
675
- previous, q, str = str.partition(QUESTION_MARK)
632
+ while true
633
+ previous, q, str = str.partition('?')
676
634
  sql << previous
677
635
  literal_append(sql, args.at(i+=1)) unless q.empty?
678
636
  if str.empty?
679
637
  unless i == match_len
680
- raise Error, "Mismatched number of placeholders (#{i+1}) and placeholder arguments (#{args.length}) when using placeholder array"
638
+ raise Error, "Mismatched number of placeholders (#{i+1}) and placeholder arguments (#{args.length}) when using placeholder string"
681
639
  end
682
640
  break
683
641
  end
684
642
  end
685
643
  end
686
- sql << PAREN_CLOSE if pls.parens
644
+ sql << ')' if pls.parens
687
645
  end
688
646
 
689
647
  # Append literalization of qualified identifier to SQL string.
@@ -691,7 +649,7 @@ module Sequel
691
649
  # column/qualified. If 2 arguments are given, the 2nd should be an SQL::QualifiedIdentifier.
692
650
  def qualified_identifier_sql_append(sql, table, column=(c = table.column; table = table.table; c))
693
651
  identifier_append(sql, table)
694
- sql << DOT
652
+ sql << '.'
695
653
  identifier_append(sql, column)
696
654
  end
697
655
 
@@ -718,7 +676,7 @@ module Sequel
718
676
  schema, table = schema_and_table(table)
719
677
  if schema
720
678
  quote_identifier_append(sql, schema)
721
- sql << DOT
679
+ sql << '.'
722
680
  end
723
681
  quote_identifier_append(sql, table)
724
682
  end
@@ -728,7 +686,7 @@ module Sequel
728
686
  # should be overridden by subclasses to provide quoting not matching the
729
687
  # SQL standard, such as backtick (used by MySQL and SQLite).
730
688
  def quoted_identifier_append(sql, name)
731
- sql << QUOTE << name.to_s.gsub(QUOTE_RE, DOUBLE_QUOTE) << QUOTE
689
+ sql << '"' << name.to_s.gsub('"', '""') << '"'
732
690
  end
733
691
 
734
692
  # Split the schema information from the table, returning two strings,
@@ -758,9 +716,9 @@ module Sequel
758
716
  # Splits table_name into an array of strings.
759
717
  #
760
718
  # ds.split_qualifiers(:s) # ['s']
761
- # ds.split_qualifiers(:t__s) # ['t', 's']
762
- # ds.split_qualifiers(Sequel.qualify(:d, :t__s)) # ['d', 't', 's']
763
- # ds.split_qualifiers(Sequel.qualify(:h__d, :t__s)) # ['h', 'd', 't', 's']
719
+ # ds.split_qualifiers(Sequel[:t][:s]) # ['t', 's']
720
+ # ds.split_qualifiers(Sequel[:d][:t][:s]) # ['d', 't', 's']
721
+ # ds.split_qualifiers(Sequel.qualify(Sequel[:h][:d], Sequel[:t][:s])) # ['h', 'd', 't', 's']
764
722
  def split_qualifiers(table_name, *args)
765
723
  case table_name
766
724
  when SQL::QualifiedIdentifier
@@ -773,59 +731,116 @@ module Sequel
773
731
 
774
732
  # Append literalization of subscripts (SQL array accesses) to SQL string.
775
733
  def subscript_sql_append(sql, s)
776
- literal_append(sql, s.f)
777
- sql << BRACKET_OPEN
778
- if s.sub.length == 1 && (range = s.sub.first).is_a?(Range)
734
+ case s.expression
735
+ when Symbol, SQL::Subscript, SQL::Identifier, SQL::QualifiedIdentifier
736
+ # nothing
737
+ else
738
+ wrap_expression = true
739
+ sql << '('
740
+ end
741
+ literal_append(sql, s.expression)
742
+ if wrap_expression
743
+ sql << ')['
744
+ else
745
+ sql << '['
746
+ end
747
+ sub = s.sub
748
+ if sub.length == 1 && (range = sub.first).is_a?(Range)
779
749
  literal_append(sql, range.begin)
780
- sql << COLON
750
+ sql << ':'
781
751
  e = range.end
782
752
  e -= 1 if range.exclude_end? && e.is_a?(Integer)
783
753
  literal_append(sql, e)
784
754
  else
785
755
  expression_list_append(sql, s.sub)
786
756
  end
787
- sql << BRACKET_CLOSE
757
+ sql << ']'
788
758
  end
789
759
 
790
760
  # Append literalization of windows (for window functions) to SQL string.
791
761
  def window_sql_append(sql, opts)
792
762
  raise(Error, 'This dataset does not support window functions') unless supports_window_functions?
793
- sql << PAREN_OPEN
794
- window, part, order, frame = opts.values_at(:window, :partition, :order, :frame)
795
763
  space = false
796
- space_s = SPACE
797
- if window
764
+ space_s = ' '
765
+
766
+ sql << '('
767
+
768
+ if window = opts[:window]
798
769
  literal_append(sql, window)
799
770
  space = true
800
771
  end
801
- if part
772
+
773
+ if part = opts[:partition]
802
774
  sql << space_s if space
803
- sql << PARTITION_BY
775
+ sql << "PARTITION BY "
804
776
  expression_list_append(sql, Array(part))
805
777
  space = true
806
778
  end
807
- if order
779
+
780
+ if order = opts[:order]
808
781
  sql << space_s if space
809
- sql << ORDER_BY_NS
782
+ sql << "ORDER BY "
810
783
  expression_list_append(sql, Array(order))
811
784
  space = true
812
785
  end
813
- case frame
814
- when nil
815
- # nothing
816
- when :all
817
- sql << space_s if space
818
- sql << FRAME_ALL
819
- when :rows
820
- sql << space_s if space
821
- sql << FRAME_ROWS
822
- when String
823
- sql << space_s if space
786
+
787
+ if frame = opts[:frame]
788
+ sql << space_s if space
789
+
790
+ if frame.is_a?(String)
824
791
  sql << frame
825
792
  else
826
- raise Error, "invalid window frame clause, should be :all, :rows, a string, or nil"
793
+ case frame
794
+ when :all
795
+ frame_type = :rows
796
+ frame_start = :preceding
797
+ frame_end = :following
798
+ when :rows, :range, :groups
799
+ frame_type = frame
800
+ frame_start = :preceding
801
+ frame_end = :current
802
+ when Hash
803
+ frame_type = frame[:type]
804
+ unless frame_type == :rows || frame_type == :range || frame_type == :groups
805
+ raise Error, "invalid window :frame :type option: #{frame_type.inspect}"
806
+ end
807
+ unless frame_start = frame[:start]
808
+ raise Error, "invalid window :frame :start option: #{frame_start.inspect}"
809
+ end
810
+ frame_end = frame[:end]
811
+ frame_exclude = frame[:exclude]
812
+ else
813
+ raise Error, "invalid window :frame option: #{frame.inspect}"
814
+ end
815
+
816
+ sql << frame_type.to_s.upcase << " "
817
+ sql << 'BETWEEN ' if frame_end
818
+ window_frame_boundary_sql_append(sql, frame_start, :preceding)
819
+ if frame_end
820
+ sql << " AND "
821
+ window_frame_boundary_sql_append(sql, frame_end, :following)
822
+ end
823
+
824
+ if frame_exclude
825
+ sql << " EXCLUDE "
826
+
827
+ case frame_exclude
828
+ when :current
829
+ sql << "CURRENT ROW"
830
+ when :group
831
+ sql << "GROUP"
832
+ when :ties
833
+ sql << "TIES"
834
+ when :no_others
835
+ sql << "NO OTHERS"
836
+ else
837
+ raise Error, "invalid window :frame :exclude option: #{frame_exclude.inspect}"
838
+ end
839
+ end
840
+ end
827
841
  end
828
- sql << PAREN_CLOSE
842
+
843
+ sql << ')'
829
844
  end
830
845
 
831
846
  protected
@@ -833,11 +848,88 @@ module Sequel
833
848
  # Return a from_self dataset if an order or limit is specified, so it works as expected
834
849
  # with UNION, EXCEPT, and INTERSECT clauses.
835
850
  def compound_from_self
836
- (@opts[:sql] || @opts[:limit] || @opts[:order]) ? from_self : self
851
+ (@opts[:sql] || @opts[:limit] || @opts[:order] || @opts[:offset]) ? from_self : self
837
852
  end
838
853
 
839
854
  private
840
855
 
856
+ # Append the INSERT sql used in a MERGE
857
+ def _merge_insert_sql(sql, data)
858
+ sql << " THEN INSERT"
859
+ columns, values = _parse_insert_sql_args(data[:values])
860
+ _insert_columns_sql(sql, columns)
861
+ _insert_values_sql(sql, values)
862
+ end
863
+
864
+ def _merge_update_sql(sql, data)
865
+ sql << " THEN UPDATE SET "
866
+ update_sql_values_hash(sql, data[:values])
867
+ end
868
+
869
+ def _merge_delete_sql(sql, data)
870
+ sql << " THEN DELETE"
871
+ end
872
+
873
+ # Mapping of merge types to related SQL
874
+ MERGE_TYPE_SQL = {
875
+ :insert => ' WHEN NOT MATCHED',
876
+ :delete => ' WHEN MATCHED',
877
+ :update => ' WHEN MATCHED',
878
+ :matched => ' WHEN MATCHED',
879
+ :not_matched => ' WHEN NOT MATCHED',
880
+ }.freeze
881
+ private_constant :MERGE_TYPE_SQL
882
+
883
+ # Add the WHEN clauses to the MERGE SQL
884
+ def _merge_when_sql(sql)
885
+ raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
886
+ merge_when.each do |data|
887
+ type = data[:type]
888
+ sql << MERGE_TYPE_SQL[type]
889
+ _merge_when_conditions_sql(sql, data)
890
+ send(:"_merge_#{type}_sql", sql, data)
891
+ end
892
+ end
893
+
894
+ # Append MERGE WHEN conditions, if there are conditions provided.
895
+ def _merge_when_conditions_sql(sql, data)
896
+ if data.has_key?(:conditions)
897
+ sql << " AND "
898
+ literal_append(sql, data[:conditions])
899
+ end
900
+ end
901
+
902
+ # Parse the values passed to insert_sql, returning columns and values
903
+ # to use for the INSERT. Returned columns is always an array, but can be empty
904
+ # for an INSERT without explicit column references. Returned values can be an
905
+ # array, dataset, or literal string.
906
+ def _parse_insert_sql_args(values)
907
+ columns = []
908
+
909
+ case values.size
910
+ when 0
911
+ values = []
912
+ when 1
913
+ case vals = values[0]
914
+ when Hash
915
+ values = []
916
+ vals.each do |k,v|
917
+ columns << k
918
+ values << v
919
+ end
920
+ when Dataset, Array, LiteralString
921
+ values = vals
922
+ end
923
+ when 2
924
+ if (v0 = values[0]).is_a?(Array) && ((v1 = values[1]).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
925
+ columns, values = v0, v1
926
+ raise(Error, "Different number of values and columns given to insert_sql") if values.is_a?(Array) and columns.length != values.length
927
+ end
928
+ end
929
+
930
+ [columns, values]
931
+ end
932
+
841
933
  # Formats the truncate statement. Assumes the table given has already been
842
934
  # literalized.
843
935
  def _truncate_sql(table)
@@ -882,41 +974,71 @@ module Sequel
882
974
  # Clone of this dataset usable in aggregate operations. Does
883
975
  # a from_self if dataset contains any parameters that would
884
976
  # affect normal aggregation, or just removes an existing
885
- # order if not.
977
+ # order if not. Also removes the row_proc, which isn't needed
978
+ # for aggregate calculations.
886
979
  def aggregate_dataset
887
- options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered
980
+ (options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered).naked
888
981
  end
889
982
 
890
983
  # Append aliasing expression to SQL string.
891
984
  def as_sql_append(sql, aliaz, column_aliases=nil)
892
- sql << AS
985
+ sql << ' AS '
893
986
  quote_identifier_append(sql, aliaz)
894
987
  if column_aliases
895
988
  raise Error, "#{db.database_type} does not support derived column lists" unless supports_derived_column_lists?
896
- sql << PAREN_OPEN
989
+ sql << '('
897
990
  identifier_list_append(sql, column_aliases)
898
- sql << PAREN_CLOSE
991
+ sql << ')'
899
992
  end
900
993
  end
901
994
 
902
- # Raise an InvalidOperation exception if deletion is not allowed
903
- # for this dataset
995
+ # Don't allow caching SQL if specifically marked not to.
996
+ def cache_sql?
997
+ !@opts[:no_cache_sql] && !cache_get(:_no_cache_sql)
998
+ end
999
+
1000
+ # Raise an InvalidOperation exception if modification is not allowed for this dataset.
1001
+ # Check whether it is allowed to insert into this dataset.
1002
+ # Only for backwards compatibility with older external adapters.
904
1003
  def check_modification_allowed!
1004
+ # SEQUEL6: Remove
1005
+ Sequel::Deprecation.deprecate("Dataset#check_modification_allowed!", "Use check_{insert,delete,update,truncation}_allowed! instead")
1006
+ _check_modification_allowed!(supports_modifying_joins?)
1007
+ end
1008
+
1009
+ # Check whether it is allowed to insert into this dataset.
1010
+ def check_insert_allowed!
1011
+ _check_modification_allowed!(false)
1012
+ end
1013
+ alias check_truncation_allowed! check_insert_allowed!
1014
+
1015
+ # Check whether it is allowed to delete from this dataset.
1016
+ def check_delete_allowed!
1017
+ _check_modification_allowed!(supports_deleting_joins?)
1018
+ end
1019
+
1020
+ # Check whether it is allowed to update this dataset.
1021
+ def check_update_allowed!
1022
+ _check_modification_allowed!(supports_updating_joins?)
1023
+ end
1024
+
1025
+ # Internals of the check_*_allowed! methods
1026
+ def _check_modification_allowed!(modifying_joins_supported)
905
1027
  raise(InvalidOperation, "Grouped datasets cannot be modified") if opts[:group]
906
- raise(InvalidOperation, "Joined datasets cannot be modified") if !supports_modifying_joins? && joined_dataset?
1028
+ raise(InvalidOperation, "Joined datasets cannot be modified") if !modifying_joins_supported && joined_dataset?
907
1029
  end
908
1030
 
909
- # Alias of check_modification_allowed!
910
- def check_truncation_allowed!
911
- check_modification_allowed!
1031
+ # Raise error if the dataset uses limits or offsets.
1032
+ def check_not_limited!(type)
1033
+ return if @opts[:skip_limit_check] && type != :truncate
1034
+ raise InvalidOperation, "Dataset##{type} not supported on datasets with limits or offsets" if opts[:limit] || opts[:offset]
912
1035
  end
913
1036
 
914
1037
  # Append column list to SQL string.
915
- # Converts an array of column names into a comma seperated string of
916
- # column names. If the array is empty, a wildcard (*) is returned.
1038
+ # If the column list is empty, a wildcard (*) is appended.
917
1039
  def column_list_append(sql, columns)
918
1040
  if (columns.nil? || columns.empty?)
919
- sql << WILDCARD
1041
+ sql << '*'
920
1042
  else
921
1043
  expression_list_append(sql, columns)
922
1044
  end
@@ -929,9 +1051,9 @@ module Sequel
929
1051
  def complex_expression_arg_pairs(args)
930
1052
  case args.length
931
1053
  when 1
932
- args.at(0)
1054
+ args[0]
933
1055
  when 2
934
- yield args.at(0), args.at(1)
1056
+ yield args[0], args[1]
935
1057
  else
936
1058
  args.inject{|m, a| yield(m, a)}
937
1059
  end
@@ -948,7 +1070,9 @@ module Sequel
948
1070
  # operators unsupported by some databases. Used by adapters for databases
949
1071
  # that don't support the operators natively.
950
1072
  def complex_expression_emulate_append(sql, op, args)
1073
+ # :nocov:
951
1074
  case op
1075
+ # :nocov:
952
1076
  when :%
953
1077
  complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(:MOD, a, b)}
954
1078
  when :>>
@@ -959,9 +1083,9 @@ module Sequel
959
1083
  f = BITWISE_METHOD_MAP[op]
960
1084
  complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(f, a, b)}
961
1085
  when :'B~'
962
- sql << BITCOMP_OPEN
963
- literal_append(sql, args.at(0))
964
- sql << BITCOMP_CLOSE
1086
+ sql << "((0 - "
1087
+ literal_append(sql, args[0])
1088
+ sql << ") - 1)"
965
1089
  end
966
1090
  end
967
1091
 
@@ -972,25 +1096,30 @@ module Sequel
972
1096
 
973
1097
  # The alias to use for datasets, takes a number to make sure the name is unique.
974
1098
  def dataset_alias(number)
975
- :"#{DATASET_ALIAS_BASE_NAME}#{number}"
1099
+ :"t#{number}"
976
1100
  end
977
1101
 
978
1102
  # The strftime format to use when literalizing the time.
979
1103
  def default_timestamp_format
980
- requires_sql_standard_datetimes? ? STANDARD_TIMESTAMP_FORMAT : TIMESTAMP_FORMAT
1104
+ requires_sql_standard_datetimes? ? "TIMESTAMP '%Y-%m-%d %H:%M:%S%N%z'" : "'%Y-%m-%d %H:%M:%S%N%z'"
981
1105
  end
982
1106
 
983
1107
  def delete_delete_sql(sql)
984
- sql << DELETE
1108
+ sql << 'DELETE'
985
1109
  end
986
1110
 
987
1111
  def delete_from_sql(sql)
988
1112
  if f = @opts[:from]
989
- sql << FROM
1113
+ sql << ' FROM '
990
1114
  source_list_append(sql, f)
991
1115
  end
992
1116
  end
993
1117
 
1118
+ # Disable caching of SQL for the current dataset
1119
+ def disable_sql_caching!
1120
+ cache_set(:_no_cache_sql, true)
1121
+ end
1122
+
994
1123
  # An SQL FROM clause to use in SELECT statements where the dataset has
995
1124
  # no from tables.
996
1125
  def empty_from_sql
@@ -1003,10 +1132,11 @@ module Sequel
1003
1132
  false
1004
1133
  end
1005
1134
 
1006
- # Append literalization of array of expressions to SQL string.
1135
+ # Append literalization of array of expressions to SQL string, separating them
1136
+ # with commas.
1007
1137
  def expression_list_append(sql, columns)
1008
1138
  c = false
1009
- co = COMMA
1139
+ co = ', '
1010
1140
  columns.each do |col|
1011
1141
  sql << co if c
1012
1142
  literal_append(sql, col)
@@ -1014,14 +1144,14 @@ module Sequel
1014
1144
  end
1015
1145
  end
1016
1146
 
1017
- # Append literalization of array of grouping elements to SQL string.
1147
+ # Append literalization of array of grouping elements to SQL string, seperating them with commas.
1018
1148
  def grouping_element_list_append(sql, columns)
1019
1149
  c = false
1020
- co = COMMA
1150
+ co = ', '
1021
1151
  columns.each do |col|
1022
1152
  sql << co if c
1023
1153
  if col.is_a?(Array) && col.empty?
1024
- sql << EMPTY_PARENS
1154
+ sql << '()'
1025
1155
  else
1026
1156
  literal_append(sql, Array(col))
1027
1157
  end
@@ -1040,9 +1170,12 @@ module Sequel
1040
1170
  # of hours and minutes.
1041
1171
  def format_timestamp(v)
1042
1172
  v2 = db.from_application_timestamp(v)
1043
- fmt = default_timestamp_format.gsub(FORMAT_TIMESTAMP_RE) do |m|
1044
- if m == FORMAT_USEC
1045
- format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(DATETIME_SECFRACTION_ARG) : v.usec) if supports_timestamp_usecs?
1173
+ fmt = default_timestamp_format.gsub(/%[Nz]/) do |m|
1174
+ if m == '%N'
1175
+ # Ruby 1.9 supports %N in timestamp formats, but Sequel has supported %N
1176
+ # for longer in a different way, where the . is already appended and only 6
1177
+ # decimal places are used by default.
1178
+ format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(1000000) : v.usec) if supports_timestamp_usecs?
1046
1179
  else
1047
1180
  if supports_timestamp_timezones?
1048
1181
  # Would like to just use %z format, but it doesn't appear to work on Windows
@@ -1057,13 +1190,13 @@ module Sequel
1057
1190
 
1058
1191
  # Return the SQL timestamp fragment to use for the timezone offset.
1059
1192
  def format_timestamp_offset(hour, minute)
1060
- sprintf(FORMAT_OFFSET, hour, minute)
1193
+ sprintf("%+03i%02i", hour, minute)
1061
1194
  end
1062
1195
 
1063
1196
  # Return the SQL timestamp fragment to use for the fractional time part.
1064
1197
  # Should start with the decimal point. Uses 6 decimal places by default.
1065
- def format_timestamp_usec(usec)
1066
- unless (ts = timestamp_precision) == 6
1198
+ def format_timestamp_usec(usec, ts=timestamp_precision)
1199
+ unless ts == 6
1067
1200
  usec = usec/(10 ** (6 - ts))
1068
1201
  end
1069
1202
  sprintf(".%0#{ts}d", usec)
@@ -1089,7 +1222,7 @@ module Sequel
1089
1222
  # Append literalization of array of identifiers to SQL string.
1090
1223
  def identifier_list_append(sql, args)
1091
1224
  c = false
1092
- comma = COMMA
1225
+ comma = ', '
1093
1226
  args.each do |a|
1094
1227
  sql << comma if c
1095
1228
  identifier_append(sql, a)
@@ -1097,14 +1230,13 @@ module Sequel
1097
1230
  end
1098
1231
  end
1099
1232
 
1100
- # Modify the identifier returned from the database based on the
1101
- # identifier_output_method.
1233
+ # Upcase identifiers by default when inputting them into the database.
1102
1234
  def input_identifier(v)
1103
- (i = identifier_input_method) ? v.to_s.send(i) : v.to_s
1235
+ v.to_s.upcase
1104
1236
  end
1105
1237
 
1106
1238
  def insert_into_sql(sql)
1107
- sql << INTO
1239
+ sql << " INTO "
1108
1240
  if (f = @opts[:from]) && f.length == 1
1109
1241
  identifier_append(sql, unaliased_identifier(f.first))
1110
1242
  else
@@ -1113,11 +1245,14 @@ module Sequel
1113
1245
  end
1114
1246
 
1115
1247
  def insert_columns_sql(sql)
1116
- columns = opts[:columns]
1248
+ _insert_columns_sql(sql, opts[:columns])
1249
+ end
1250
+
1251
+ def _insert_columns_sql(sql, columns)
1117
1252
  if columns && !columns.empty?
1118
- sql << PAREN_SPACE_OPEN
1253
+ sql << ' ('
1119
1254
  identifier_list_append(sql, columns)
1120
- sql << PAREN_CLOSE
1255
+ sql << ')'
1121
1256
  end
1122
1257
  end
1123
1258
 
@@ -1128,23 +1263,27 @@ module Sequel
1128
1263
  end
1129
1264
 
1130
1265
  def insert_insert_sql(sql)
1131
- sql << INSERT
1266
+ sql << "INSERT"
1132
1267
  end
1133
1268
 
1134
1269
  def insert_values_sql(sql)
1135
- case values = opts[:values]
1270
+ _insert_values_sql(sql, opts[:values])
1271
+ end
1272
+
1273
+ def _insert_values_sql(sql, values)
1274
+ case values
1136
1275
  when Array
1137
1276
  if values.empty?
1138
- sql << DEFAULT_VALUES
1277
+ sql << " DEFAULT VALUES"
1139
1278
  else
1140
- sql << VALUES
1279
+ sql << " VALUES "
1141
1280
  literal_append(sql, values)
1142
1281
  end
1143
1282
  when Dataset
1144
- sql << SPACE
1283
+ sql << ' '
1145
1284
  subselect_sql_append(sql, values)
1146
1285
  when LiteralString
1147
- sql << SPACE << values
1286
+ sql << ' ' << values
1148
1287
  else
1149
1288
  raise Error, "Unsupported INSERT values type, should be an Array or Dataset: #{values.inspect}"
1150
1289
  end
@@ -1152,7 +1291,7 @@ module Sequel
1152
1291
 
1153
1292
  def insert_returning_sql(sql)
1154
1293
  if opts.has_key?(:returning)
1155
- sql << RETURNING
1294
+ sql << " RETURNING "
1156
1295
  column_list_append(sql, Array(opts[:returning]))
1157
1296
  end
1158
1297
  end
@@ -1162,9 +1301,16 @@ module Sequel
1162
1301
  # SQL fragment specifying a JOIN type, converts underscores to
1163
1302
  # spaces and upcases.
1164
1303
  def join_type_sql(join_type)
1165
- "#{join_type.to_s.gsub(UNDERSCORE, SPACE).upcase} JOIN"
1304
+ "#{join_type.to_s.gsub('_', ' ').upcase} JOIN"
1166
1305
  end
1167
1306
 
1307
+ # Append USING clause for JOIN USING
1308
+ def join_using_clause_using_sql_append(sql, using_columns)
1309
+ sql << ' USING ('
1310
+ column_list_append(sql, using_columns)
1311
+ sql << ')'
1312
+ end
1313
+
1168
1314
  # Append a literalization of the array to SQL string.
1169
1315
  # Treats as an expression if an array of all two pairs, or as a SQL array otherwise.
1170
1316
  def literal_array_append(sql, v)
@@ -1188,18 +1334,18 @@ module Sequel
1188
1334
 
1189
1335
  # Append literalization of dataset to SQL string. Does a subselect inside parantheses.
1190
1336
  def literal_dataset_append(sql, v)
1191
- sql << LATERAL if v.opts[:lateral]
1192
- sql << PAREN_OPEN
1337
+ sql << 'LATERAL ' if v.opts[:lateral]
1338
+ sql << '('
1193
1339
  subselect_sql_append(sql, v)
1194
- sql << PAREN_CLOSE
1340
+ sql << ')'
1195
1341
  end
1196
1342
 
1197
1343
  # SQL fragment for Date, using the ISO8601 format.
1198
1344
  def literal_date(v)
1199
1345
  if requires_sql_standard_datetimes?
1200
- v.strftime(FORMAT_DATE_STANDARD)
1346
+ v.strftime("DATE '%Y-%m-%d'")
1201
1347
  else
1202
- v.strftime(FORMAT_DATE)
1348
+ v.strftime("'%Y-%m-%d'")
1203
1349
  end
1204
1350
  end
1205
1351
 
@@ -1220,7 +1366,7 @@ module Sequel
1220
1366
 
1221
1367
  # SQL fragment for false
1222
1368
  def literal_false
1223
- BOOL_FALSE
1369
+ "'f'"
1224
1370
  end
1225
1371
 
1226
1372
  # SQL fragment for Float
@@ -1240,7 +1386,7 @@ module Sequel
1240
1386
 
1241
1387
  # SQL fragment for nil
1242
1388
  def literal_nil
1243
- NULL
1389
+ "NULL"
1244
1390
  end
1245
1391
 
1246
1392
  # Append a literalization of the object to the given SQL string.
@@ -1248,6 +1394,10 @@ module Sequel
1248
1394
  # calls +sql_literal+ if object responds to it, otherwise raises an error.
1249
1395
  # If a database specific type is allowed, this should be overriden in a subclass.
1250
1396
  def literal_other_append(sql, v)
1397
+ # We can't be sure if v will always literalize to the same SQL, so
1398
+ # don't cache SQL for a dataset that uses this.
1399
+ disable_sql_caching!
1400
+
1251
1401
  if v.respond_to?(:sql_literal_append)
1252
1402
  v.sql_literal_append(self, sql)
1253
1403
  elsif v.respond_to?(:sql_literal)
@@ -1259,7 +1409,7 @@ module Sequel
1259
1409
 
1260
1410
  # SQL fragment for Sequel::SQLTime, containing just the time part
1261
1411
  def literal_sqltime(v)
1262
- v.strftime("'%H:%M:%S#{format_timestamp_usec(v.usec) if supports_timestamp_usecs?}'")
1412
+ v.strftime("'%H:%M:%S#{format_timestamp_usec(v.usec, sqltime_precision) if supports_timestamp_usecs?}'")
1263
1413
  end
1264
1414
 
1265
1415
  # Append literalization of Sequel::SQLTime to SQL string.
@@ -1269,7 +1419,7 @@ module Sequel
1269
1419
 
1270
1420
  # Append literalization of string to SQL string.
1271
1421
  def literal_string_append(sql, v)
1272
- sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
1422
+ sql << "'" << v.gsub("'", "''") << "'"
1273
1423
  end
1274
1424
 
1275
1425
  # Append literalization of symbol to SQL string.
@@ -1277,7 +1427,7 @@ module Sequel
1277
1427
  c_table, column, c_alias = split_symbol(v)
1278
1428
  if c_table
1279
1429
  quote_identifier_append(sql, c_table)
1280
- sql << DOT
1430
+ sql << '.'
1281
1431
  end
1282
1432
  quote_identifier_append(sql, column)
1283
1433
  as_sql_append(sql, c_alias) if c_alias
@@ -1295,7 +1445,7 @@ module Sequel
1295
1445
 
1296
1446
  # SQL fragment for true
1297
1447
  def literal_true
1298
- BOOL_TRUE
1448
+ "'t'"
1299
1449
  end
1300
1450
 
1301
1451
  # What strategy to use for import/multi_insert. While SQL-92 defaults
@@ -1306,9 +1456,10 @@ module Sequel
1306
1456
  :separate
1307
1457
  end
1308
1458
 
1459
+
1309
1460
  # Get the native function name given the emulated function name.
1310
1461
  def native_function_name(emulated_function)
1311
- self.class.const_get(:EMULATED_FUNCTION_MAP).fetch(emulated_function, emulated_function)
1462
+ emulated_function
1312
1463
  end
1313
1464
 
1314
1465
  # Returns a qualified column name (including a table name) if the column
@@ -1332,43 +1483,43 @@ module Sequel
1332
1483
  end
1333
1484
  end
1334
1485
 
1335
- # Qualify the given expression e to the given table.
1486
+ # Qualify the given expression to the given table.
1336
1487
  def qualified_expression(e, table)
1337
- Qualifier.new(self, table).transform(e)
1488
+ Qualifier.new(table).transform(e)
1338
1489
  end
1339
1490
 
1340
1491
  def select_columns_sql(sql)
1341
- sql << SPACE
1492
+ sql << ' '
1342
1493
  column_list_append(sql, @opts[:select])
1343
1494
  end
1344
1495
 
1345
1496
  def select_distinct_sql(sql)
1346
1497
  if distinct = @opts[:distinct]
1347
- sql << DISTINCT
1498
+ sql << " DISTINCT"
1348
1499
  unless distinct.empty?
1349
- sql << ON_PAREN
1500
+ sql << " ON ("
1350
1501
  expression_list_append(sql, distinct)
1351
- sql << PAREN_CLOSE
1502
+ sql << ')'
1352
1503
  end
1353
1504
  end
1354
1505
  end
1355
1506
 
1356
1507
  # Modify the sql to add a dataset to the via an EXCEPT, INTERSECT, or UNION clause.
1357
1508
  # This uses a subselect for the compound datasets used, because using parantheses doesn't
1358
- # work on all databases. I consider this an ugly hack, but can't I think of a better default.
1509
+ # work on all databases.
1359
1510
  def select_compounds_sql(sql)
1360
1511
  return unless c = @opts[:compounds]
1361
1512
  c.each do |type, dataset, all|
1362
- sql << SPACE << type.to_s.upcase
1363
- sql << ALL if all
1364
- sql << SPACE
1513
+ sql << ' ' << type.to_s.upcase
1514
+ sql << ' ALL' if all
1515
+ sql << ' '
1365
1516
  compound_dataset_sql_append(sql, dataset)
1366
1517
  end
1367
1518
  end
1368
1519
 
1369
1520
  def select_from_sql(sql)
1370
1521
  if f = @opts[:from]
1371
- sql << FROM
1522
+ sql << ' FROM '
1372
1523
  source_list_append(sql, f)
1373
1524
  elsif f = empty_from_sql
1374
1525
  sql << f
@@ -1377,19 +1528,19 @@ module Sequel
1377
1528
 
1378
1529
  def select_group_sql(sql)
1379
1530
  if group = @opts[:group]
1380
- sql << GROUP_BY
1531
+ sql << " GROUP BY "
1381
1532
  if go = @opts[:group_options]
1382
1533
  if go == :"grouping sets"
1383
- sql << go.to_s.upcase << PAREN_OPEN
1534
+ sql << go.to_s.upcase << '('
1384
1535
  grouping_element_list_append(sql, group)
1385
- sql << PAREN_CLOSE
1536
+ sql << ')'
1386
1537
  elsif uses_with_rollup?
1387
1538
  expression_list_append(sql, group)
1388
- sql << SPACE_WITH << go.to_s.upcase
1539
+ sql << " WITH " << go.to_s.upcase
1389
1540
  else
1390
- sql << go.to_s.upcase << PAREN_OPEN
1541
+ sql << go.to_s.upcase << '('
1391
1542
  expression_list_append(sql, group)
1392
- sql << PAREN_CLOSE
1543
+ sql << ')'
1393
1544
  end
1394
1545
  else
1395
1546
  expression_list_append(sql, group)
@@ -1399,7 +1550,7 @@ module Sequel
1399
1550
 
1400
1551
  def select_having_sql(sql)
1401
1552
  if having = @opts[:having]
1402
- sql << HAVING
1553
+ sql << " HAVING "
1403
1554
  literal_append(sql, having)
1404
1555
  end
1405
1556
  end
@@ -1412,10 +1563,10 @@ module Sequel
1412
1563
 
1413
1564
  def select_limit_sql(sql)
1414
1565
  if l = @opts[:limit]
1415
- sql << LIMIT
1566
+ sql << " LIMIT "
1416
1567
  literal_append(sql, l)
1417
1568
  if o = @opts[:offset]
1418
- sql << OFFSET
1569
+ sql << " OFFSET "
1419
1570
  literal_append(sql, o)
1420
1571
  end
1421
1572
  elsif @opts[:offset]
@@ -1426,9 +1577,9 @@ module Sequel
1426
1577
  def select_lock_sql(sql)
1427
1578
  case l = @opts[:lock]
1428
1579
  when :update
1429
- sql << FOR_UPDATE
1580
+ sql << ' FOR UPDATE'
1430
1581
  when String
1431
- sql << SPACE << l
1582
+ sql << ' ' << l
1432
1583
  end
1433
1584
  end
1434
1585
 
@@ -1436,13 +1587,13 @@ module Sequel
1436
1587
  # in the adapter, as many databases do not support just a plain offset with
1437
1588
  # no limit.
1438
1589
  def select_only_offset_sql(sql)
1439
- sql << OFFSET
1590
+ sql << " OFFSET "
1440
1591
  literal_append(sql, @opts[:offset])
1441
1592
  end
1442
1593
 
1443
1594
  def select_order_sql(sql)
1444
1595
  if o = @opts[:order]
1445
- sql << ORDER_BY
1596
+ sql << " ORDER BY "
1446
1597
  expression_list_append(sql, o)
1447
1598
  end
1448
1599
  end
@@ -1450,56 +1601,81 @@ module Sequel
1450
1601
  alias update_order_sql select_order_sql
1451
1602
 
1452
1603
  def select_select_sql(sql)
1453
- sql << SELECT
1604
+ sql << 'SELECT'
1454
1605
  end
1455
1606
 
1456
1607
  def select_where_sql(sql)
1457
1608
  if w = @opts[:where]
1458
- sql << WHERE
1609
+ sql << " WHERE "
1459
1610
  literal_append(sql, w)
1460
1611
  end
1461
1612
  end
1462
1613
  alias delete_where_sql select_where_sql
1463
1614
  alias update_where_sql select_where_sql
1464
1615
 
1616
+ def select_window_sql(sql)
1617
+ if ws = @opts[:window]
1618
+ sql << " WINDOW "
1619
+ c = false
1620
+ co = ', '
1621
+ as = ' AS '
1622
+ ws.map do |name, window|
1623
+ sql << co if c
1624
+ literal_append(sql, name)
1625
+ sql << as
1626
+ literal_append(sql, window)
1627
+ c ||= true
1628
+ end
1629
+ end
1630
+ end
1631
+
1465
1632
  def select_with_sql(sql)
1466
1633
  return unless supports_cte?
1467
- ws = opts[:with]
1468
- return if !ws || ws.empty?
1634
+ ctes = opts[:with]
1635
+ return if !ctes || ctes.empty?
1469
1636
  sql << select_with_sql_base
1470
1637
  c = false
1471
- comma = COMMA
1472
- ws.each do |w|
1638
+ comma = ', '
1639
+ ctes.each do |cte|
1473
1640
  sql << comma if c
1474
- quote_identifier_append(sql, w[:name])
1475
- if args = w[:args]
1476
- sql << PAREN_OPEN
1477
- identifier_list_append(sql, args)
1478
- sql << PAREN_CLOSE
1479
- end
1480
- sql << AS
1481
- literal_dataset_append(sql, w[:dataset])
1641
+ select_with_sql_cte(sql, cte)
1482
1642
  c ||= true
1483
1643
  end
1484
- sql << SPACE
1644
+ sql << ' '
1485
1645
  end
1486
1646
  alias delete_with_sql select_with_sql
1487
1647
  alias insert_with_sql select_with_sql
1488
1648
  alias update_with_sql select_with_sql
1489
1649
 
1490
- # The base keyword to use for the SQL WITH clause
1491
1650
  def select_with_sql_base
1492
- SQL_WITH
1651
+ "WITH "
1493
1652
  end
1494
1653
 
1495
- # Whether the symbol cache should be skipped when literalizing the dataset
1496
- def skip_symbol_cache?
1497
- @skip_symbol_cache
1654
+ def select_with_sql_cte(sql, cte)
1655
+ select_with_sql_prefix(sql, cte)
1656
+ literal_dataset_append(sql, cte[:dataset])
1657
+ end
1658
+
1659
+ def select_with_sql_prefix(sql, w)
1660
+ quote_identifier_append(sql, w[:name])
1661
+ if args = w[:args]
1662
+ sql << '('
1663
+ identifier_list_append(sql, args)
1664
+ sql << ')'
1665
+ end
1666
+ sql << ' AS '
1667
+
1668
+ case w[:materialized]
1669
+ when true
1670
+ sql << "MATERIALIZED "
1671
+ when false
1672
+ sql << "NOT MATERIALIZED "
1673
+ end
1498
1674
  end
1499
1675
 
1500
- # Set the dataset to skip the symbol cache
1501
- def skip_symbol_cache!
1502
- @skip_symbol_cache = true
1676
+ # Whether the symbol cache should be skipped when literalizing the dataset
1677
+ def skip_symbol_cache?
1678
+ @opts[:skip_symbol_cache]
1503
1679
  end
1504
1680
 
1505
1681
  # Append literalization of array of sources/tables to SQL string, raising an Error if there
@@ -1515,11 +1691,17 @@ module Sequel
1515
1691
  end
1516
1692
 
1517
1693
  # The string that is appended to to create the SQL query, the empty
1518
- # string by default
1694
+ # string by default.
1519
1695
  def sql_string_origin
1520
1696
  String.new
1521
1697
  end
1522
1698
 
1699
+ # The precision to use for SQLTime instances (time column values without dates).
1700
+ # Defaults to timestamp_precision.
1701
+ def sqltime_precision
1702
+ timestamp_precision
1703
+ end
1704
+
1523
1705
  # SQL to use if this dataset uses static SQL. Since static SQL
1524
1706
  # can be a PlaceholderLiteralString in addition to a String,
1525
1707
  # we literalize nonstrings. If there is an append_sql for this
@@ -1540,9 +1722,19 @@ module Sequel
1540
1722
  end
1541
1723
  end
1542
1724
 
1543
- # Append literalization of the subselect to SQL String.
1725
+ # Append literalization of the subselect to SQL string.
1544
1726
  def subselect_sql_append(sql, ds)
1545
- ds.clone(:append_sql=>sql).sql
1727
+ sds = subselect_sql_dataset(sql, ds)
1728
+ sds.sql
1729
+ unless sds.send(:cache_sql?)
1730
+ # If subquery dataset does not allow caching SQL,
1731
+ # then this dataset should not allow caching SQL.
1732
+ disable_sql_caching!
1733
+ end
1734
+ end
1735
+
1736
+ def subselect_sql_dataset(sql, ds)
1737
+ ds.clone(:append_sql=>sql)
1546
1738
  end
1547
1739
 
1548
1740
  # The number of decimal digits of precision to use in timestamps.
@@ -1551,13 +1743,13 @@ module Sequel
1551
1743
  end
1552
1744
 
1553
1745
  def update_table_sql(sql)
1554
- sql << SPACE
1746
+ sql << ' '
1555
1747
  source_list_append(sql, @opts[:from])
1556
1748
  select_join_sql(sql) if supports_modifying_joins?
1557
1749
  end
1558
1750
 
1559
1751
  def update_set_sql(sql)
1560
- sql << SET
1752
+ sql << ' SET '
1561
1753
  values = @opts[:values]
1562
1754
  if values.is_a?(Hash)
1563
1755
  update_sql_values_hash(sql, values)
@@ -1568,9 +1760,9 @@ module Sequel
1568
1760
 
1569
1761
  def update_sql_values_hash(sql, values)
1570
1762
  c = false
1571
- eq = EQUAL
1763
+ eq = ' = '
1572
1764
  values.each do |k, v|
1573
- sql << COMMA if c
1765
+ sql << ', ' if c
1574
1766
  if k.is_a?(String) && !k.is_a?(LiteralString)
1575
1767
  quote_identifier_append(sql, k)
1576
1768
  else
@@ -1583,7 +1775,37 @@ module Sequel
1583
1775
  end
1584
1776
 
1585
1777
  def update_update_sql(sql)
1586
- sql << UPDATE
1778
+ sql << 'UPDATE'
1779
+ end
1780
+
1781
+ def window_frame_boundary_sql_append(sql, boundary, direction)
1782
+ case boundary
1783
+ when :current
1784
+ sql << "CURRENT ROW"
1785
+ when :preceding
1786
+ sql << "UNBOUNDED PRECEDING"
1787
+ when :following
1788
+ sql << "UNBOUNDED FOLLOWING"
1789
+ else
1790
+ if boundary.is_a?(Array)
1791
+ offset, direction = boundary
1792
+ unless boundary.length == 2 && (direction == :preceding || direction == :following)
1793
+ raise Error, "invalid window :frame boundary (:start or :end) option: #{boundary.inspect}"
1794
+ end
1795
+ else
1796
+ offset = boundary
1797
+ end
1798
+
1799
+ case offset
1800
+ when Numeric, String, SQL::Cast
1801
+ # nothing
1802
+ else
1803
+ raise Error, "invalid window :frame boundary (:start or :end) option: #{boundary.inspect}"
1804
+ end
1805
+
1806
+ literal_append(sql, offset)
1807
+ sql << (direction == :preceding ? " PRECEDING" : " FOLLOWING")
1808
+ end
1587
1809
  end
1588
1810
  end
1589
1811
  end