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
@@ -1,51 +1,46 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- Sequel.require 'adapters/utils/replace'
3
+ require_relative '../utils/replace'
4
+ require_relative '../utils/unmodified_identifiers'
4
5
 
5
6
  module Sequel
6
7
  module SQLite
8
+ Sequel::Database.set_shared_adapter_scheme(:sqlite, self)
9
+
10
+ def self.mock_adapter_setup(db)
11
+ db.instance_exec do
12
+ @sqlite_version = 30903
13
+
14
+ def schema_parse_table(*)
15
+ []
16
+ end
17
+ singleton_class.send(:private, :schema_parse_table)
18
+ end
19
+ end
20
+
7
21
  # No matter how you connect to SQLite, the following Database options
8
22
  # can be used to set PRAGMAs on connections in a thread-safe manner:
9
23
  # :auto_vacuum, :foreign_keys, :synchronous, and :temp_store.
10
24
  module DatabaseMethods
11
- extend Sequel::Database::ResetIdentifierMangling
25
+ include UnmodifiedIdentifiers::DatabaseMethods
12
26
 
13
27
  AUTO_VACUUM = [:none, :full, :incremental].freeze
14
- PRIMARY_KEY_INDEX_RE = /\Asqlite_autoindex_/.freeze
15
28
  SYNCHRONOUS = [:off, :normal, :full].freeze
16
- TABLES_FILTER = Sequel.~(:name=>'sqlite_sequence'.freeze) & {:type => 'table'.freeze}
17
29
  TEMP_STORE = [:default, :file, :memory].freeze
18
- VIEWS_FILTER = {:type => 'view'.freeze}.freeze
19
30
  TRANSACTION_MODE = {
20
31
  :deferred => "BEGIN DEFERRED TRANSACTION".freeze,
21
32
  :immediate => "BEGIN IMMEDIATE TRANSACTION".freeze,
22
33
  :exclusive => "BEGIN EXCLUSIVE TRANSACTION".freeze,
23
- nil => Sequel::Database::SQL_BEGIN,
34
+ nil => "BEGIN".freeze
24
35
  }.freeze
25
36
 
26
37
  # Whether to use integers for booleans in the database. SQLite recommends
27
38
  # booleans be stored as integers, but historically Sequel has used 't'/'f'.
28
39
  attr_accessor :integer_booleans
29
40
 
30
- # A symbol signifying the value of the auto_vacuum PRAGMA.
31
- def auto_vacuum
32
- AUTO_VACUUM[pragma_get(:auto_vacuum).to_i]
33
- end
34
-
35
- # Set the auto_vacuum PRAGMA using the given symbol (:none, :full, or
36
- # :incremental). See pragma_set. Consider using the :auto_vacuum
37
- # Database option instead.
38
- def auto_vacuum=(value)
39
- value = AUTO_VACUUM.index(value) || (raise Error, "Invalid value for auto_vacuum option. Please specify one of :none, :full, :incremental.")
40
- pragma_set(:auto_vacuum, value)
41
- end
42
-
43
- # Set the case_sensitive_like PRAGMA using the given boolean value, if using
44
- # SQLite 3.2.3+. If not using 3.2.3+, no error is raised. See pragma_set.
45
- # Consider using the :case_sensitive_like Database option instead.
46
- def case_sensitive_like=(value)
47
- pragma_set(:case_sensitive_like, !!value ? 'on' : 'off') if sqlite_version >= 30203
48
- end
41
+ # Whether to keep CURRENT_TIMESTAMP and similar expressions in UTC. By
42
+ # default, the expressions are converted to localtime.
43
+ attr_accessor :current_timestamp_utc
49
44
 
50
45
  # A symbol signifying the value of the default transaction mode
51
46
  attr_reader :transaction_mode
@@ -64,17 +59,9 @@ module Sequel
64
59
  :sqlite
65
60
  end
66
61
 
67
- # Boolean signifying the value of the foreign_keys PRAGMA, or nil
68
- # if not using SQLite 3.6.19+.
69
- def foreign_keys
70
- pragma_get(:foreign_keys).to_i == 1 if sqlite_version >= 30619
71
- end
72
-
73
- # Set the foreign_keys PRAGMA using the given boolean value, if using
74
- # SQLite 3.6.19+. If not using 3.6.19+, no error is raised. See pragma_set.
75
- # Consider using the :foreign_keys Database option instead.
76
- def foreign_keys=(value)
77
- pragma_set(:foreign_keys, !!value ? 'on' : 'off') if sqlite_version >= 30619
62
+ # Set the integer_booleans option using the passed in :integer_boolean option.
63
+ def set_integer_booleans
64
+ @integer_booleans = @opts.has_key?(:integer_booleans) ? typecast_value_boolean(@opts[:integer_booleans]) : true
78
65
  end
79
66
 
80
67
  # Return the array of foreign key info hashes using the foreign_key_list PRAGMA,
@@ -82,7 +69,7 @@ module Sequel
82
69
  def foreign_key_list(table, opts=OPTS)
83
70
  m = output_identifier_meth
84
71
  h = {}
85
- metadata_dataset.with_sql("PRAGMA foreign_key_list(?)", input_identifier_meth.call(table)).each do |row|
72
+ _foreign_key_list_ds(table).each do |row|
86
73
  if r = h[row[:id]]
87
74
  r[:columns] << m.call(row[:from])
88
75
  r[:key] << m.call(row[:to]) if r[:key]
@@ -93,14 +80,31 @@ module Sequel
93
80
  h.values
94
81
  end
95
82
 
83
+ def freeze
84
+ sqlite_version
85
+ use_timestamp_timezones?
86
+ super
87
+ end
88
+
96
89
  # Use the index_list and index_info PRAGMAs to determine the indexes on the table.
97
90
  def indexes(table, opts=OPTS)
98
91
  m = output_identifier_meth
99
92
  im = input_identifier_meth
100
93
  indexes = {}
94
+ table = table.value if table.is_a?(Sequel::SQL::Identifier)
101
95
  metadata_dataset.with_sql("PRAGMA index_list(?)", im.call(table)).each do |r|
102
- # :only_autocreated internal option can be used to get only autocreated indexes
103
- next if (!!(r[:name] =~ PRIMARY_KEY_INDEX_RE) ^ !!opts[:only_autocreated])
96
+ if opts[:only_autocreated]
97
+ # If specifically asked for only autocreated indexes, then return those an only those
98
+ next unless r[:name] =~ /\Asqlite_autoindex_/
99
+ elsif r.has_key?(:origin)
100
+ # If origin is set, then only exclude primary key indexes and partial indexes
101
+ next if r[:origin] == 'pk'
102
+ next if r[:partial].to_i == 1
103
+ else
104
+ # When :origin key not present, assume any autoindex could be a primary key one and exclude it
105
+ next if r[:name] =~ /\Asqlite_autoindex_/
106
+ end
107
+
104
108
  indexes[m.call(r[:name])] = {:unique=>r[:unique].to_i==1}
105
109
  end
106
110
  indexes.each do |k, v|
@@ -109,26 +113,6 @@ module Sequel
109
113
  indexes
110
114
  end
111
115
 
112
- # Get the value of the given PRAGMA.
113
- def pragma_get(name)
114
- self["PRAGMA #{name}"].single_value
115
- end
116
-
117
- # Set the value of the given PRAGMA to value.
118
- #
119
- # This method is not thread safe, and will not work correctly if there
120
- # are multiple connections in the Database's connection pool. PRAGMA
121
- # modifications should be done when the connection is created, using
122
- # an option provided when creating the Database object.
123
- def pragma_set(name, value)
124
- execute_ddl("PRAGMA #{name} = #{value}")
125
- end
126
-
127
- # Set the integer_booleans option using the passed in :integer_boolean option.
128
- def set_integer_booleans
129
- @integer_booleans = @opts.has_key?(:integer_booleans) ? typecast_value_boolean(@opts[:integer_booleans]) : true
130
- end
131
-
132
116
  # The version of the server as an integer, where 3.6.19 = 30619.
133
117
  # If the server version can't be determined, 0 is used.
134
118
  def sqlite_version
@@ -172,55 +156,57 @@ module Sequel
172
156
  defined?(@use_timestamp_timezones) ? @use_timestamp_timezones : (@use_timestamp_timezones = false)
173
157
  end
174
158
 
175
- # A symbol signifying the value of the synchronous PRAGMA.
176
- def synchronous
177
- SYNCHRONOUS[pragma_get(:synchronous).to_i]
178
- end
179
-
180
- # Set the synchronous PRAGMA using the given symbol (:off, :normal, or :full). See pragma_set.
181
- # Consider using the :synchronous Database option instead.
182
- def synchronous=(value)
183
- value = SYNCHRONOUS.index(value) || (raise Error, "Invalid value for synchronous option. Please specify one of :off, :normal, :full.")
184
- pragma_set(:synchronous, value)
185
- end
186
-
187
159
  # Array of symbols specifying the table names in the current database.
188
160
  #
189
161
  # Options:
190
162
  # :server :: Set the server to use.
191
163
  def tables(opts=OPTS)
192
- tables_and_views(TABLES_FILTER, opts)
164
+ tables_and_views(Sequel.~(:name=>'sqlite_sequence') & {:type => 'table'}, opts)
193
165
  end
194
166
 
195
- # A symbol signifying the value of the temp_store PRAGMA.
196
- def temp_store
197
- TEMP_STORE[pragma_get(:temp_store).to_i]
198
- end
199
-
200
- # Set the temp_store PRAGMA using the given symbol (:default, :file, or :memory). See pragma_set.
201
- # Consider using the :temp_store Database option instead.
202
- def temp_store=(value)
203
- value = TEMP_STORE.index(value) || (raise Error, "Invalid value for temp_store option. Please specify one of :default, :file, :memory.")
204
- pragma_set(:temp_store, value)
167
+ # Creates a dataset that uses the VALUES clause:
168
+ #
169
+ # DB.values([[1, 2], [3, 4]])
170
+ # # VALUES ((1, 2), (3, 4))
171
+ def values(v)
172
+ @default_dataset.clone(:values=>v)
205
173
  end
206
-
174
+
207
175
  # Array of symbols specifying the view names in the current database.
208
176
  #
209
177
  # Options:
210
178
  # :server :: Set the server to use.
211
179
  def views(opts=OPTS)
212
- tables_and_views(VIEWS_FILTER, opts)
180
+ tables_and_views({:type => 'view'}, opts)
213
181
  end
214
182
 
215
183
  private
216
184
 
185
+ # Dataset used for parsing foreign key lists
186
+ def _foreign_key_list_ds(table)
187
+ metadata_dataset.with_sql("PRAGMA foreign_key_list(?)", input_identifier_meth.call(table))
188
+ end
189
+
190
+ # Dataset used for parsing schema
191
+ def _parse_pragma_ds(table_name, opts)
192
+ metadata_dataset.with_sql("PRAGMA table_#{'x' if sqlite_version > 33100}info(?)", input_identifier_meth(opts[:dataset]).call(table_name))
193
+ end
194
+
217
195
  # Run all alter_table commands in a transaction. This is technically only
218
196
  # needed for drop column.
219
197
  def apply_alter_table(table, ops)
220
- fks = foreign_keys
221
- self.foreign_keys = false if fks
198
+ fks = fetch("PRAGMA foreign_keys")
199
+ if fks
200
+ run "PRAGMA foreign_keys = 0"
201
+ run "PRAGMA legacy_alter_table = 1" if sqlite_version >= 32600
202
+ end
222
203
  transaction do
223
- if ops.length > 1 && ops.all?{|op| op[:op] == :add_constraint}
204
+ if ops.length > 1 && ops.all?{|op| op[:op] == :add_constraint || op[:op] == :set_column_null}
205
+ null_ops, ops = ops.partition{|op| op[:op] == :set_column_null}
206
+
207
+ # Apply NULL/NOT NULL ops first, since those should be purely idependent of the constraints.
208
+ null_ops.each{|op| alter_table_sql_list(table, [op]).flatten.each{|sql| execute_ddl(sql)}}
209
+
224
210
  # If you are just doing constraints, apply all of them at the same time,
225
211
  # as otherwise all but the last one get lost.
226
212
  alter_table_sql_list(table, [{:op=>:add_constraints, :ops=>ops}]).flatten.each{|sql| execute_ddl(sql)}
@@ -230,8 +216,12 @@ module Sequel
230
216
  ops.each{|op| alter_table_sql_list(table, [op]).flatten.each{|sql| execute_ddl(sql)}}
231
217
  end
232
218
  end
219
+ remove_cached_schema(table)
233
220
  ensure
234
- self.foreign_keys = true if fks
221
+ if fks
222
+ run "PRAGMA foreign_keys = 1"
223
+ run "PRAGMA legacy_alter_table = 0" if sqlite_version >= 32600
224
+ end
235
225
  end
236
226
 
237
227
  # SQLite supports limited table modification. You can add a column
@@ -249,11 +239,19 @@ module Sequel
249
239
  super
250
240
  end
251
241
  when :drop_column
252
- ocp = lambda{|oc| oc.delete_if{|c| c.to_s == op[:name].to_s}}
253
- duplicate_table(table, :old_columns_proc=>ocp){|columns| columns.delete_if{|s| s[:name].to_s == op[:name].to_s}}
242
+ if sqlite_version >= 33500
243
+ super
244
+ else
245
+ ocp = lambda{|oc| oc.delete_if{|c| c.to_s == op[:name].to_s}}
246
+ duplicate_table(table, :old_columns_proc=>ocp){|columns| columns.delete_if{|s| s[:name].to_s == op[:name].to_s}}
247
+ end
254
248
  when :rename_column
255
- ncp = lambda{|nc| nc.map!{|c| c.to_s == op[:name].to_s ? op[:new_name] : c}}
256
- duplicate_table(table, :new_columns_proc=>ncp){|columns| columns.each{|s| s[:name] = op[:new_name] if s[:name].to_s == op[:name].to_s}}
249
+ if sqlite_version >= 32500
250
+ super
251
+ else
252
+ ncp = lambda{|nc| nc.map!{|c| c.to_s == op[:name].to_s ? op[:new_name] : c}}
253
+ duplicate_table(table, :new_columns_proc=>ncp){|columns| columns.each{|s| s[:name] = op[:new_name] if s[:name].to_s == op[:name].to_s}}
254
+ end
257
255
  when :set_column_default
258
256
  duplicate_table(table){|columns| columns.each{|s| s[:default] = op[:default] if s[:name].to_s == op[:name].to_s}}
259
257
  when :set_column_null
@@ -263,13 +261,20 @@ module Sequel
263
261
  when :drop_constraint
264
262
  case op[:type]
265
263
  when :primary_key
266
- duplicate_table(table){|columns| columns.each{|s| s[:primary_key] = nil}}
264
+ duplicate_table(table) do |columns|
265
+ columns.each do |s|
266
+ s[:unique] = false if s[:primary_key]
267
+ s[:primary_key] = s[:auto_increment] = nil
268
+ end
269
+ end
267
270
  when :foreign_key
268
271
  if op[:columns]
269
272
  duplicate_table(table, :skip_foreign_key_columns=>op[:columns])
270
273
  else
271
274
  duplicate_table(table, :no_foreign_keys=>true)
272
275
  end
276
+ when :unique
277
+ duplicate_table(table, :no_unique=>true)
273
278
  else
274
279
  duplicate_table(table)
275
280
  end
@@ -298,15 +303,21 @@ module Sequel
298
303
  end
299
304
  end
300
305
 
301
- # Surround default with parens to appease SQLite
306
+ # SQLite allows adding primary key constraints on NULLABLE columns, but then
307
+ # does not enforce NOT NULL for such columns, so force setting the columns NOT NULL.
308
+ def can_add_primary_key_constraint_on_nullable_columns?
309
+ false
310
+ end
311
+
312
+ # Surround default with parens to appease SQLite. Add support for GENERATED ALWAYS AS.
302
313
  def column_definition_default_sql(sql, column)
303
314
  sql << " DEFAULT (#{literal(column[:default])})" if column.include?(:default)
304
- end
305
-
306
- # Add null/not null SQL fragment to column creation SQL.
307
- def column_definition_null_sql(sql, column)
308
- column = column.merge(:null=>false) if column[:primary_key]
309
- super(sql, column)
315
+ if (generated = column[:generated_always_as])
316
+ if (generated_type = column[:generated_type]) && (generated_type == :stored || generated_type == :virtual)
317
+ generated_type = generated_type.to_s.upcase
318
+ end
319
+ sql << " GENERATED ALWAYS AS (#{literal(generated)}) #{generated_type}"
320
+ end
310
321
  end
311
322
 
312
323
  # Array of PRAGMA SQL statements based on the Database options that should be applied to
@@ -326,16 +337,22 @@ module Sequel
326
337
  ps
327
338
  end
328
339
 
340
+ # Support creating STRICT tables via :strict option
341
+ def create_table_sql(name, generator, options)
342
+ "#{super}#{' STRICT' if options[:strict]}"
343
+ end
344
+
329
345
  # SQLite support creating temporary views.
330
346
  def create_view_prefix_sql(name, options)
331
- "CREATE #{'TEMPORARY 'if options[:temp]}VIEW #{quote_schema_table(name)}"
347
+ create_view_sql_append_columns("CREATE #{'TEMPORARY 'if options[:temp]}VIEW #{quote_schema_table(name)}", options[:columns])
332
348
  end
333
349
 
334
350
  DATABASE_ERROR_REGEXPS = {
335
351
  /(is|are) not unique\z|PRIMARY KEY must be unique\z|UNIQUE constraint failed: .+\z/ => UniqueConstraintViolation,
336
352
  /foreign key constraint failed\z/i => ForeignKeyConstraintViolation,
337
- /\ACHECK constraint failed/ => CheckConstraintViolation,
353
+ /\A(SQLITE ERROR 275 \(CONSTRAINT_CHECK\) : )?CHECK constraint failed/ => CheckConstraintViolation,
338
354
  /\A(SQLITE ERROR 19 \(CONSTRAINT\) : )?constraint failed\z/ => ConstraintViolation,
355
+ /\Acannot store [A-Z]+ value in [A-Z]+ column / => ConstraintViolation,
339
356
  /may not be NULL\z|NOT NULL constraint failed: .+\z/ => NotNullConstraintViolation,
340
357
  /\ASQLITE ERROR \d+ \(\) : CHECK constraint failed: / => CheckConstraintViolation
341
358
  }.freeze
@@ -343,13 +360,32 @@ module Sequel
343
360
  DATABASE_ERROR_REGEXPS
344
361
  end
345
362
 
363
+ # Recognize SQLite error codes if the exception provides access to them.
364
+ def database_specific_error_class(exception, opts)
365
+ case sqlite_error_code(exception)
366
+ when 1299
367
+ NotNullConstraintViolation
368
+ when 1555, 2067, 2579
369
+ UniqueConstraintViolation
370
+ when 787
371
+ ForeignKeyConstraintViolation
372
+ when 275
373
+ CheckConstraintViolation
374
+ when 19
375
+ ConstraintViolation
376
+ when 517
377
+ SerializationFailure
378
+ else
379
+ super
380
+ end
381
+ end
382
+
346
383
  # The array of column schema hashes for the current columns in the table
347
384
  def defined_columns_for(table)
348
- cols = parse_pragma(table, {})
385
+ cols = parse_pragma(table, OPTS)
349
386
  cols.each do |c|
350
387
  c[:default] = LiteralString.new(c[:default]) if c[:default]
351
388
  c[:type] = c[:db_type]
352
- c.delete(:auto_increment)
353
389
  end
354
390
  cols
355
391
  end
@@ -363,7 +399,7 @@ module Sequel
363
399
  old_columns = def_columns.map{|c| c[:name]}
364
400
  opts[:old_columns_proc].call(old_columns) if opts[:old_columns_proc]
365
401
 
366
- yield def_columns if block_given?
402
+ yield def_columns if defined?(yield)
367
403
 
368
404
  constraints = (opts[:constraints] || []).dup
369
405
  pks = []
@@ -395,14 +431,22 @@ module Sequel
395
431
 
396
432
  # Determine unique constraints and make sure the new columns have them
397
433
  unique_columns = []
398
- indexes(table, :only_autocreated=>true).each_value do |h|
399
- unique_columns.concat(h[:columns]) if h[:columns].length == 1 && h[:unique]
434
+ skip_indexes = []
435
+ indexes(table, :only_autocreated=>true).each do |name, h|
436
+ skip_indexes << name
437
+ if h[:unique] && !opts[:no_unique]
438
+ if h[:columns].length == 1
439
+ unique_columns.concat(h[:columns])
440
+ elsif h[:columns].map(&:to_s) != pks
441
+ constraints << {:type=>:unique, :columns=>h[:columns]}
442
+ end
443
+ end
400
444
  end
401
445
  unique_columns -= pks
402
446
  unless unique_columns.empty?
403
447
  unique_columns.map!{|c| quote_identifier(c)}
404
448
  def_columns.each do |c|
405
- c[:unique] = true if unique_columns.include?(quote_identifier(c[:name]))
449
+ c[:unique] = true if unique_columns.include?(quote_identifier(c[:name])) && c[:unique] != false
406
450
  end
407
451
  end
408
452
 
@@ -419,6 +463,7 @@ module Sequel
419
463
  "DROP TABLE #{bt}"
420
464
  ]
421
465
  indexes(table).each do |name, h|
466
+ next if skip_indexes.include?(name)
422
467
  if (h[:columns].map(&:to_s) - new_columns).empty?
423
468
  a << alter_table_sql(table, h.merge(:op=>:add_index, :name=>name))
424
469
  end
@@ -426,19 +471,9 @@ module Sequel
426
471
  a
427
472
  end
428
473
 
429
- # SQLite folds unquoted identifiers to lowercase, so it shouldn't need to upcase identifiers on input.
430
- def identifier_input_method_default
431
- nil
432
- end
433
-
434
- # SQLite folds unquoted identifiers to lowercase, so it shouldn't need to upcase identifiers on output.
435
- def identifier_output_method_default
436
- nil
437
- end
438
-
439
474
  # Does the reverse of on_delete_clause, eg. converts strings like +'SET NULL'+
440
475
  # to symbols +:set_null+.
441
- def on_delete_sql_to_sym str
476
+ def on_delete_sql_to_sym(str)
442
477
  case str
443
478
  when 'RESTRICT'
444
479
  :restrict
@@ -455,18 +490,43 @@ module Sequel
455
490
 
456
491
  # Parse the output of the table_info pragma
457
492
  def parse_pragma(table_name, opts)
458
- metadata_dataset.with_sql("PRAGMA table_info(?)", input_identifier_meth(opts[:dataset]).call(table_name)).map do |row|
493
+ pks = 0
494
+ sch = _parse_pragma_ds(table_name, opts).map do |row|
495
+ if sqlite_version > 33100
496
+ # table_xinfo PRAGMA used, remove hidden columns
497
+ # that are not generated columns
498
+ if row[:generated] = (row.delete(:hidden) != 0)
499
+ next unless row[:type].end_with?(' GENERATED ALWAYS')
500
+ row[:type] = row[:type].sub(' GENERATED ALWAYS', '')
501
+ end
502
+ end
503
+
459
504
  row.delete(:cid)
460
505
  row[:allow_null] = row.delete(:notnull).to_i == 0
461
506
  row[:default] = row.delete(:dflt_value)
462
507
  row[:default] = nil if blank_object?(row[:default]) || row[:default] == 'NULL'
463
508
  row[:db_type] = row.delete(:type)
464
509
  if row[:primary_key] = row.delete(:pk).to_i > 0
510
+ pks += 1
511
+ # Guess that an integer primary key uses auto increment,
512
+ # since that is Sequel's default and SQLite does not provide
513
+ # a way to introspect whether it is actually autoincrementing.
465
514
  row[:auto_increment] = row[:db_type].downcase == 'integer'
466
515
  end
467
516
  row[:type] = schema_column_type(row[:db_type])
468
517
  row
469
518
  end
519
+
520
+ sch.compact!
521
+
522
+ if pks > 1
523
+ # SQLite does not allow use of auto increment for tables
524
+ # with composite primary keys, so remove auto_increment
525
+ # if composite primary keys are detected.
526
+ sch.each{|r| r.delete(:auto_increment)}
527
+ end
528
+
529
+ sch
470
530
  end
471
531
 
472
532
  # SQLite supports schema parsing using the table_info PRAGMA, so
@@ -478,10 +538,15 @@ module Sequel
478
538
  end
479
539
  end
480
540
 
541
+ # Don't support SQLite error codes for exceptions by default.
542
+ def sqlite_error_code(exception)
543
+ nil
544
+ end
545
+
481
546
  # Backbone of the tables and views support.
482
547
  def tables_and_views(filter, opts)
483
548
  m = output_identifier_meth
484
- metadata_dataset.from(:sqlite_master).server(opts[:server]).filter(filter).map{|r| m.call(r[:name])}
549
+ metadata_dataset.from(:sqlite_master).server(opts[:server]).where(filter).map{|r| m.call(r[:name])}
485
550
  end
486
551
 
487
552
  # SQLite only supports AUTOINCREMENT on integer columns, not
@@ -492,65 +557,76 @@ module Sequel
492
557
  end
493
558
  end
494
559
 
495
- # Instance methods for datasets that connect to an SQLite database
496
560
  module DatasetMethods
497
561
  include Dataset::Replace
562
+ include UnmodifiedIdentifiers::DatasetMethods
563
+
564
+ # The allowed values for insert_conflict
565
+ INSERT_CONFLICT_RESOLUTIONS = %w'ROLLBACK ABORT FAIL IGNORE REPLACE'.each(&:freeze).freeze
498
566
 
499
- CONSTANT_MAP = {:CURRENT_DATE=>"date(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIMESTAMP=>"datetime(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIME=>"time(CURRENT_TIMESTAMP, 'localtime')".freeze}
500
- EMULATED_FUNCTION_MAP = {:char_length=>'length'.freeze}
501
- EXTRACT_MAP = {:year=>"'%Y'", :month=>"'%m'", :day=>"'%d'", :hour=>"'%H'", :minute=>"'%M'", :second=>"'%f'"}
502
- NOT_SPACE = Dataset::NOT_SPACE
503
- COMMA = Dataset::COMMA
504
- PAREN_CLOSE = Dataset::PAREN_CLOSE
505
- AS = Dataset::AS
506
- APOS = Dataset::APOS
507
- EXTRACT_OPEN = "CAST(strftime(".freeze
508
- EXTRACT_CLOSE = ') AS '.freeze
509
- NUMERIC = 'NUMERIC'.freeze
510
- INTEGER = 'INTEGER'.freeze
511
- BACKTICK = '`'.freeze
512
- BACKTICK_RE = /`/.freeze
513
- DOUBLE_BACKTICK = '``'.freeze
514
- BLOB_START = "X'".freeze
515
- HSTAR = "H*".freeze
516
- DATE_OPEN = "date(".freeze
517
- DATETIME_OPEN = "datetime(".freeze
518
- ONLY_OFFSET = " LIMIT -1 OFFSET ".freeze
519
- OR = " OR ".freeze
520
-
521
- Dataset.def_sql_method(self, :delete, [['if db.sqlite_version >= 30803', %w'with delete from where'], ["else", %w'delete from where']])
522
- Dataset.def_sql_method(self, :insert, [['if db.sqlite_version >= 30803', %w'with insert conflict into columns values'], ["else", %w'insert conflict into columns values']])
523
- Dataset.def_sql_method(self, :update, [['if db.sqlite_version >= 30803', %w'with update table set where'], ["else", %w'update table set where']])
567
+ CONSTANT_MAP = {:CURRENT_DATE=>"date(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIMESTAMP=>"datetime(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIME=>"time(CURRENT_TIMESTAMP, 'localtime')".freeze}.freeze
568
+ EXTRACT_MAP = {:year=>"'%Y'", :month=>"'%m'", :day=>"'%d'", :hour=>"'%H'", :minute=>"'%M'", :second=>"'%f'"}.freeze
569
+ EXTRACT_MAP.each_value(&:freeze)
570
+
571
+ Dataset.def_sql_method(self, :delete, [['if db.sqlite_version >= 33500', %w'with delete from where returning'], ['elsif db.sqlite_version >= 30803', %w'with delete from where'], ["else", %w'delete from where']])
572
+ Dataset.def_sql_method(self, :insert, [['if db.sqlite_version >= 33500', %w'with insert conflict into columns values on_conflict returning'], ['elsif db.sqlite_version >= 30803', %w'with insert conflict into columns values on_conflict'], ["else", %w'insert conflict into columns values']])
573
+ Dataset.def_sql_method(self, :select, [['if opts[:values]', %w'with values compounds'], ['else', %w'with select distinct columns from join where group having window compounds order limit lock']])
574
+ Dataset.def_sql_method(self, :update, [['if db.sqlite_version >= 33500', %w'with update table set from where returning'], ['elsif db.sqlite_version >= 33300', %w'with update table set from where'], ['elsif db.sqlite_version >= 30803', %w'with update table set where'], ["else", %w'update table set where']])
524
575
 
525
576
  def cast_sql_append(sql, expr, type)
526
577
  if type == Time or type == DateTime
527
- sql << DATETIME_OPEN
578
+ sql << "datetime("
528
579
  literal_append(sql, expr)
529
- sql << PAREN_CLOSE
580
+ sql << ')'
530
581
  elsif type == Date
531
- sql << DATE_OPEN
582
+ sql << "date("
532
583
  literal_append(sql, expr)
533
- sql << PAREN_CLOSE
584
+ sql << ')'
534
585
  else
535
586
  super
536
587
  end
537
588
  end
538
589
 
539
590
  # SQLite doesn't support a NOT LIKE b, you need to use NOT (a LIKE b).
540
- # It doesn't support xor or the extract function natively, so those have to be emulated.
591
+ # It doesn't support xor, power, or the extract function natively, so those have to be emulated.
541
592
  def complex_expression_sql_append(sql, op, args)
542
593
  case op
543
594
  when :"NOT LIKE", :"NOT ILIKE"
544
- sql << NOT_SPACE
595
+ sql << 'NOT '
545
596
  complex_expression_sql_append(sql, (op == :"NOT ILIKE" ? :ILIKE : :LIKE), args)
546
597
  when :^
547
598
  complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.lit(["((~(", " & ", ")) & (", " | ", "))"], a, b, a, b)}
599
+ when :**
600
+ unless (exp = args[1]).is_a?(Integer)
601
+ raise(Sequel::Error, "can only emulate exponentiation on SQLite if exponent is an integer, given #{exp.inspect}")
602
+ end
603
+ case exp
604
+ when 0
605
+ sql << '1'
606
+ else
607
+ sql << '('
608
+ arg = args[0]
609
+ if exp < 0
610
+ invert = true
611
+ exp = exp.abs
612
+ sql << '(1.0 / ('
613
+ end
614
+ (exp - 1).times do
615
+ literal_append(sql, arg)
616
+ sql << " * "
617
+ end
618
+ literal_append(sql, arg)
619
+ sql << ')'
620
+ if invert
621
+ sql << "))"
622
+ end
623
+ end
548
624
  when :extract
549
- part = args.at(0)
625
+ part = args[0]
550
626
  raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
551
- sql << EXTRACT_OPEN << format << COMMA
552
- literal_append(sql, args.at(1))
553
- sql << EXTRACT_CLOSE << (part == :second ? NUMERIC : INTEGER) << PAREN_CLOSE
627
+ sql << "CAST(strftime(" << format << ', '
628
+ literal_append(sql, args[1])
629
+ sql << ') AS ' << (part == :second ? 'NUMERIC' : 'INTEGER') << ')'
554
630
  else
555
631
  super
556
632
  end
@@ -559,7 +635,7 @@ module Sequel
559
635
  # SQLite has CURRENT_TIMESTAMP and related constants in UTC instead
560
636
  # of in localtime, so convert those constants to local time.
561
637
  def constant_sql_append(sql, constant)
562
- if c = CONSTANT_MAP[constant]
638
+ if (c = CONSTANT_MAP[constant]) && !db.current_timestamp_utc
563
639
  sql << c
564
640
  else
565
641
  super
@@ -569,12 +645,12 @@ module Sequel
569
645
  # SQLite performs a TRUNCATE style DELETE if no filter is specified.
570
646
  # Since we want to always return the count of records, add a condition
571
647
  # that is always true and then delete.
572
- def delete
573
- @opts[:where] ? super : where(1=>1).delete
648
+ def delete(&block)
649
+ @opts[:where] ? super : where(1=>1).delete(&block)
574
650
  end
575
651
 
576
652
  # Return an array of strings specifying a query explanation for a SELECT of the
577
- # current dataset. Currently, the options are ignore, but it accepts options
653
+ # current dataset. Currently, the options are ignored, but it accepts options
578
654
  # to be compatible with other adapters.
579
655
  def explain(opts=nil)
580
656
  # Load the PrettyTable class, needed for explain output
@@ -587,13 +663,28 @@ module Sequel
587
663
 
588
664
  # HAVING requires GROUP BY on SQLite
589
665
  def having(*cond)
590
- raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") unless @opts[:group]
666
+ raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") if !@opts[:group] && db.sqlite_version < 33900
591
667
  super
592
668
  end
593
669
 
670
+ # Support insert select for associations, so that the model code can use
671
+ # returning instead of a separate query.
672
+ def insert_select(*values)
673
+ return unless supports_insert_select?
674
+ # Handle case where query does not return a row
675
+ server?(:default).with_sql_first(insert_select_sql(*values)) || false
676
+ end
677
+
678
+ # The SQL to use for an insert_select, adds a RETURNING clause to the insert
679
+ # unless the RETURNING clause is already present.
680
+ def insert_select_sql(*values)
681
+ ds = opts[:returning] ? self : returning
682
+ ds.insert_sql(*values)
683
+ end
684
+
594
685
  # SQLite uses the nonstandard ` (backtick) for quoting identifiers.
595
686
  def quoted_identifier_append(sql, c)
596
- sql << BACKTICK << c.to_s.gsub(BACKTICK_RE, DOUBLE_BACKTICK) << BACKTICK
687
+ sql << '`' << c.to_s.gsub('`', '``') << '`'
597
688
  end
598
689
 
599
690
  # When a qualified column is selected on SQLite and the qualifier
@@ -613,36 +704,92 @@ module Sequel
613
704
  # supports the following conflict resolution algoriths: ROLLBACK, ABORT,
614
705
  # FAIL, IGNORE and REPLACE.
615
706
  #
707
+ # On SQLite 3.24.0+, you can pass a hash to use an ON CONFLICT clause.
708
+ # With out :update option, uses ON CONFLICT DO NOTHING. Options:
709
+ #
710
+ # :conflict_where :: The index filter, when using a partial index to determine uniqueness.
711
+ # :target :: The column name or expression to handle uniqueness violations on.
712
+ # :update :: A hash of columns and values to set. Uses ON CONFLICT DO UPDATE.
713
+ # :update_where :: A WHERE condition to use for the update.
714
+ #
616
715
  # Examples:
617
716
  #
618
- # DB[:table].insert_conflict.insert(:a=>1, :b=>2)
717
+ # DB[:table].insert_conflict.insert(a: 1, b: 2)
619
718
  # # INSERT OR IGNORE INTO TABLE (a, b) VALUES (1, 2)
620
719
  #
621
- # DB[:table].insert_conflict(:replace).insert(:a=>1, :b=>2)
720
+ # DB[:table].insert_conflict(:replace).insert(a: 1, b: 2)
622
721
  # # INSERT OR REPLACE INTO TABLE (a, b) VALUES (1, 2)
623
- def insert_conflict(resolution = :ignore)
624
- clone(:insert_conflict => resolution)
722
+ #
723
+ # DB[:table].insert_conflict({}).insert(a: 1, b: 2)
724
+ # # INSERT INTO TABLE (a, b) VALUES (1, 2)
725
+ # # ON CONFLICT DO NOTHING
726
+ #
727
+ # DB[:table].insert_conflict(target: :a).insert(a: 1, b: 2)
728
+ # # INSERT INTO TABLE (a, b) VALUES (1, 2)
729
+ # # ON CONFLICT (a) DO NOTHING
730
+ #
731
+ # DB[:table].insert_conflict(target: :a, conflict_where: {c: true}).insert(a: 1, b: 2)
732
+ # # INSERT INTO TABLE (a, b) VALUES (1, 2)
733
+ # # ON CONFLICT (a) WHERE (c IS TRUE) DO NOTHING
734
+ #
735
+ # DB[:table].insert_conflict(target: :a, update: {b: Sequel[:excluded][:b]}).insert(a: 1, b: 2)
736
+ # # INSERT INTO TABLE (a, b) VALUES (1, 2)
737
+ # # ON CONFLICT (a) DO UPDATE SET b = excluded.b
738
+ #
739
+ # DB[:table].insert_conflict(target: :a,
740
+ # update: {b: Sequel[:excluded][:b]}, update_where: {Sequel[:table][:status_id] => 1}).insert(a: 1, b: 2)
741
+ # # INSERT INTO TABLE (a, b) VALUES (1, 2)
742
+ # # ON CONFLICT (a) DO UPDATE SET b = excluded.b WHERE (table.status_id = 1)
743
+ def insert_conflict(opts = :ignore)
744
+ case opts
745
+ when Symbol, String
746
+ unless INSERT_CONFLICT_RESOLUTIONS.include?(opts.to_s.upcase)
747
+ raise Error, "Invalid symbol or string passed to Dataset#insert_conflict: #{opts.inspect}. The allowed values are: :rollback, :abort, :fail, :ignore, or :replace"
748
+ end
749
+ clone(:insert_conflict => opts)
750
+ when Hash
751
+ clone(:insert_on_conflict => opts)
752
+ else
753
+ raise Error, "Invalid value passed to Dataset#insert_conflict: #{opts.inspect}, should use a symbol or a hash"
754
+ end
625
755
  end
626
756
 
627
757
  # Ignore uniqueness/exclusion violations when inserting, using INSERT OR IGNORE.
628
758
  # Exists mostly for compatibility to MySQL's insert_ignore. Example:
629
759
  #
630
- # DB[:table].insert_ignore.insert(:a=>1, :b=>2)
760
+ # DB[:table].insert_ignore.insert(a: 1, b: 2)
631
761
  # # INSERT OR IGNORE INTO TABLE (a, b) VALUES (1, 2)
632
762
  def insert_ignore
633
763
  insert_conflict(:ignore)
634
764
  end
635
765
 
766
+ # Automatically add aliases to RETURNING values to work around SQLite bug.
767
+ def returning(*values)
768
+ return super if values.empty?
769
+ raise Error, "RETURNING is not supported on #{db.database_type}" unless supports_returning?(:insert)
770
+ clone(:returning=>_returning_values(values).freeze)
771
+ end
772
+
636
773
  # SQLite 3.8.3+ supports common table expressions.
637
774
  def supports_cte?(type=:select)
638
775
  db.sqlite_version >= 30803
639
776
  end
640
777
 
778
+ # SQLite supports CTEs in subqueries if it supports CTEs.
779
+ def supports_cte_in_subqueries?
780
+ supports_cte?
781
+ end
782
+
641
783
  # SQLite does not support table aliases with column aliases
642
784
  def supports_derived_column_lists?
643
785
  false
644
786
  end
645
787
 
788
+ # SQLite does not support deleting from a joined dataset
789
+ def supports_deleting_joins?
790
+ false
791
+ end
792
+
646
793
  # SQLite does not support INTERSECT ALL or EXCEPT ALL
647
794
  def supports_intersect_except_all?
648
795
  false
@@ -653,11 +800,21 @@ module Sequel
653
800
  false
654
801
  end
655
802
 
803
+ # SQLite 3.33.0 supports modifying joined datasets
804
+ def supports_modifying_joins?
805
+ db.sqlite_version >= 33300
806
+ end
807
+
656
808
  # SQLite does not support multiple columns for the IN/NOT IN operators
657
809
  def supports_multiple_column_in?
658
810
  false
659
811
  end
660
812
 
813
+ # SQLite 3.35.0 supports RETURNING on INSERT/UPDATE/DELETE.
814
+ def supports_returning?(_)
815
+ db.sqlite_version >= 33500
816
+ end
817
+
661
818
  # SQLite supports timezones in literal timestamps, since it stores them
662
819
  # as text. But using timezones in timestamps breaks SQLite datetime
663
820
  # functions, so we allow the user to override the default per database.
@@ -669,14 +826,47 @@ module Sequel
669
826
  def supports_where_true?
670
827
  false
671
828
  end
829
+
830
+ # SQLite 3.28+ supports the WINDOW clause.
831
+ def supports_window_clause?
832
+ db.sqlite_version >= 32800
833
+ end
672
834
 
835
+ # SQLite 3.25+ supports window functions. However, support is only enabled
836
+ # on SQLite 3.26.0+ because internal Sequel usage of window functions
837
+ # to implement eager loading of limited associations triggers
838
+ # an SQLite crash bug in versions 3.25.0-3.25.3.
839
+ def supports_window_functions?
840
+ db.sqlite_version >= 32600
841
+ end
842
+
843
+ # SQLite 3.28.0+ supports all window frame options that Sequel supports
844
+ def supports_window_function_frame_option?(option)
845
+ db.sqlite_version >= 32800 ? true : super
846
+ end
847
+
673
848
  private
674
849
 
850
+ # Add aliases to symbols and identifiers to work around SQLite bug.
851
+ def _returning_values(values)
852
+ values.map do |v|
853
+ case v
854
+ when Symbol
855
+ _, c, a = split_symbol(v)
856
+ a ? v : Sequel.as(v, c)
857
+ when SQL::Identifier, SQL::QualifiedIdentifier
858
+ Sequel.as(v, unqualified_column_for(v))
859
+ else
860
+ v
861
+ end
862
+ end
863
+ end
864
+
675
865
  # SQLite uses string literals instead of identifiers in AS clauses.
676
866
  def as_sql_append(sql, aliaz, column_aliases=nil)
677
867
  raise Error, "sqlite does not support derived column lists" if column_aliases
678
868
  aliaz = aliaz.value if aliaz.is_a?(SQL::Identifier)
679
- sql << AS
869
+ sql << ' AS '
680
870
  literal_append(sql, aliaz.to_s)
681
871
  end
682
872
 
@@ -697,6 +887,13 @@ module Sequel
697
887
  end
698
888
  end
699
889
 
890
+ # Raise an InvalidOperation exception if insert is not allowed for this dataset.
891
+ def check_insert_allowed!
892
+ raise(InvalidOperation, "Grouped datasets cannot be modified") if opts[:group]
893
+ raise(InvalidOperation, "Joined datasets cannot be modified") if joined_dataset?
894
+ end
895
+ alias check_delete_allowed! check_insert_allowed!
896
+
700
897
  # SQLite supports a maximum of 500 rows in a VALUES clause.
701
898
  def default_import_slice
702
899
  500
@@ -704,19 +901,49 @@ module Sequel
704
901
 
705
902
  # SQL fragment specifying a list of identifiers
706
903
  def identifier_list(columns)
707
- columns.map{|i| quote_identifier(i)}.join(COMMA)
904
+ columns.map{|i| quote_identifier(i)}.join(', ')
708
905
  end
709
906
 
710
907
  # Add OR clauses to SQLite INSERT statements
711
908
  def insert_conflict_sql(sql)
712
909
  if resolution = @opts[:insert_conflict]
713
- sql << OR << resolution.to_s.upcase
910
+ sql << " OR " << resolution.to_s.upcase
911
+ end
912
+ end
913
+
914
+ # Add ON CONFLICT clause if it should be used
915
+ def insert_on_conflict_sql(sql)
916
+ if opts = @opts[:insert_on_conflict]
917
+ sql << " ON CONFLICT"
918
+
919
+ if target = opts[:constraint]
920
+ sql << " ON CONSTRAINT "
921
+ identifier_append(sql, target)
922
+ elsif target = opts[:target]
923
+ sql << ' '
924
+ identifier_append(sql, Array(target))
925
+ if conflict_where = opts[:conflict_where]
926
+ sql << " WHERE "
927
+ literal_append(sql, conflict_where)
928
+ end
929
+ end
930
+
931
+ if values = opts[:update]
932
+ sql << " DO UPDATE SET "
933
+ update_sql_values_hash(sql, values)
934
+ if update_where = opts[:update_where]
935
+ sql << " WHERE "
936
+ literal_append(sql, update_where)
937
+ end
938
+ else
939
+ sql << " DO NOTHING"
940
+ end
714
941
  end
715
942
  end
716
943
 
717
944
  # SQLite uses a preceding X for hex escaping strings
718
945
  def literal_blob_append(sql, v)
719
- sql << BLOB_START << v.unpack(HSTAR).first << APOS
946
+ sql << "X'" << v.unpack("H*").first << "'"
720
947
  end
721
948
 
722
949
  # Respect the database integer_booleans setting, using 0 or 'f'.
@@ -735,6 +962,20 @@ module Sequel
735
962
  db.sqlite_version >= 30711 ? :values : :union
736
963
  end
737
964
 
965
+ # Emulate the char_length function with length
966
+ def native_function_name(emulated_function)
967
+ if emulated_function == :char_length
968
+ 'length'
969
+ else
970
+ super
971
+ end
972
+ end
973
+
974
+ # SQLite supports NULLS FIRST/LAST natively in 3.30+.
975
+ def requires_emulating_nulls_first?
976
+ db.sqlite_version < 33000
977
+ end
978
+
738
979
  # SQLite does not support FOR UPDATE, but silently ignore it
739
980
  # instead of raising an error for compatibility with other
740
981
  # databases.
@@ -743,10 +984,26 @@ module Sequel
743
984
  end
744
985
 
745
986
  def select_only_offset_sql(sql)
746
- sql << ONLY_OFFSET
987
+ sql << " LIMIT -1 OFFSET "
747
988
  literal_append(sql, @opts[:offset])
748
989
  end
749
990
 
991
+ # Support VALUES clause instead of the SELECT clause to return rows.
992
+ def select_values_sql(sql)
993
+ sql << "VALUES "
994
+ expression_list_append(sql, opts[:values])
995
+ end
996
+
997
+ # SQLite does not support CTEs directly inside UNION/INTERSECT/EXCEPT.
998
+ def supports_cte_in_compounds?
999
+ false
1000
+ end
1001
+
1002
+ # SQLite 3.30 supports the FILTER clause for aggregate functions.
1003
+ def supports_filtered_aggregates?
1004
+ db.sqlite_version >= 33000
1005
+ end
1006
+
750
1007
  # SQLite supports quoted function names.
751
1008
  def supports_quoted_function_names?
752
1009
  true
@@ -756,6 +1013,23 @@ module Sequel
756
1013
  def _truncate_sql(table)
757
1014
  "DELETE FROM #{table}"
758
1015
  end
1016
+
1017
+ # Use FROM to specify additional tables in an update query
1018
+ def update_from_sql(sql)
1019
+ if(from = @opts[:from][1..-1]).empty?
1020
+ raise(Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs') if @opts[:join]
1021
+ else
1022
+ sql << ' FROM '
1023
+ source_list_append(sql, from)
1024
+ select_join_sql(sql)
1025
+ end
1026
+ end
1027
+
1028
+ # Only include the primary table in the main update clause
1029
+ def update_table_sql(sql)
1030
+ sql << ' '
1031
+ source_list_append(sql, @opts[:from][0..0])
1032
+ end
759
1033
  end
760
1034
  end
761
1035
  end