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
@@ -0,0 +1,350 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Sequel
4
+ module Plugins
5
+ # The pg_auto_constraint_validations plugin automatically converts some constraint
6
+ # violation exceptions that are raised by INSERT/UPDATE queries into validation
7
+ # failures. This can allow for using the same error handling code for both
8
+ # regular validation errors (checked before attempting the INSERT/UPDATE), and
9
+ # constraint violations (raised during the INSERT/UPDATE).
10
+ #
11
+ # This handles the following constraint violations:
12
+ #
13
+ # * NOT NULL
14
+ # * CHECK
15
+ # * UNIQUE (except expression/functional indexes)
16
+ # * FOREIGN KEY (both referencing and referenced by)
17
+ #
18
+ # If the plugin cannot convert the constraint violation error to a validation
19
+ # error, it just reraises the initial exception, so this should not cause
20
+ # problems if the plugin doesn't know how to convert the exception.
21
+ #
22
+ # This plugin is not intended as a replacement for other validations,
23
+ # it is intended as a last resort. The purpose of validations is to provide nice
24
+ # error messages for the user, and the error messages generated by this plugin are
25
+ # fairly generic by default. The error messages can be customized per constraint type
26
+ # using the :messages plugin option, and individually per constraint using
27
+ # +pg_auto_constraint_validation_override+ (see below).
28
+ #
29
+ # This plugin only works on the postgres adapter when using the pg 0.16+ driver,
30
+ # PostgreSQL 9.3+ server, and PostgreSQL 9.3+ client library (libpq). In other cases
31
+ # it will be a no-op.
32
+ #
33
+ # Example:
34
+ #
35
+ # album = Album.new(:artist_id=>1) # Assume no such artist exists
36
+ # begin
37
+ # album.save
38
+ # rescue Sequel::ValidationFailed
39
+ # album.errors.on(:artist_id) # ['is invalid']
40
+ # end
41
+ #
42
+ # While the database usually provides enough information to correctly associated
43
+ # constraint violations with model columns, there are cases where it does not.
44
+ # In those cases, you can override the handling of specific constraint violations
45
+ # to be associated to particular column(s), and use a specific error message:
46
+ #
47
+ # Album.pg_auto_constraint_validation_override(:constraint_name, [:column1], "validation error message")
48
+ #
49
+ # Using the pg_auto_constraint_validations plugin requires 5 queries per
50
+ # model at load time in order to gather the necessary metadata. For applications
51
+ # with a large number of models, this can result in a noticeable delay during model
52
+ # initialization. To mitigate this issue, you can cache the necessary metadata in
53
+ # a file with the :cache_file option:
54
+ #
55
+ # Sequel::Model.plugin :pg_auto_constraint_validations, cache_file: 'db/pgacv.cache'
56
+ #
57
+ # The file does not have to exist when loading the plugin. If it exists, the plugin
58
+ # will load the cache and use the cached results instead of issuing queries if there
59
+ # is an entry in the cache. If there is no entry in the cache, it will update the
60
+ # in-memory cache with the metadata results. To save the in in-memory cache back to
61
+ # the cache file, run:
62
+ #
63
+ # Sequel::Model.dump_pg_auto_constraint_validations_cache
64
+ #
65
+ # Note that when using the :cache_file option, it is up to the application to ensure
66
+ # that the dumped cached metadata reflects the current state of the database. Sequel
67
+ # does no checking to ensure this, as checking would take time and the
68
+ # purpose of this code is to take a shortcut.
69
+ #
70
+ # The cached schema is dumped in Marshal format, since it is the fastest
71
+ # and it handles all ruby objects used in the metadata. Because of this,
72
+ # you should not attempt to load the metadata from a untrusted file.
73
+ #
74
+ # Usage:
75
+ #
76
+ # # Make all model subclasses automatically convert constraint violations
77
+ # # to validation failures (called before loading subclasses)
78
+ # Sequel::Model.plugin :pg_auto_constraint_validations
79
+ #
80
+ # # Make the Album class automatically convert constraint violations
81
+ # # to validation failures
82
+ # Album.plugin :pg_auto_constraint_validations
83
+ module PgAutoConstraintValidations
84
+ (
85
+ # The default error messages for each constraint violation type.
86
+ DEFAULT_ERROR_MESSAGES = {
87
+ :not_null=>"is not present",
88
+ :check=>"is invalid",
89
+ :unique=>'is already taken',
90
+ :foreign_key=>'is invalid',
91
+ :referenced_by=>'cannot be changed currently'
92
+ }.freeze).each_value(&:freeze)
93
+
94
+ # Setup the constraint violation metadata. Options:
95
+ # :cache_file :: File storing cached metadata, to avoid queries for each model
96
+ # :messages :: Override the default error messages for each constraint
97
+ # violation type (:not_null, :check, :unique, :foreign_key, :referenced_by)
98
+ def self.configure(model, opts=OPTS)
99
+ model.instance_exec do
100
+ if @pg_auto_constraint_validations_cache_file = opts[:cache_file]
101
+ @pg_auto_constraint_validations_cache = if ::File.file?(@pg_auto_constraint_validations_cache_file)
102
+ cache = Marshal.load(File.read(@pg_auto_constraint_validations_cache_file))
103
+ cache.each_value do |hash|
104
+ hash.freeze.each_value(&:freeze)
105
+ end
106
+ else
107
+ {}
108
+ end
109
+ else
110
+ @pg_auto_constraint_validations_cache = nil
111
+ end
112
+
113
+ setup_pg_auto_constraint_validations
114
+ @pg_auto_constraint_validations_messages = (@pg_auto_constraint_validations_messages || DEFAULT_ERROR_MESSAGES).merge(opts[:messages] || OPTS).freeze
115
+ end
116
+ nil
117
+ end
118
+
119
+ module ClassMethods
120
+ # Hash of metadata checked when an instance attempts to convert a constraint
121
+ # violation into a validation failure.
122
+ attr_reader :pg_auto_constraint_validations
123
+
124
+ # Hash of error messages keyed by constraint type symbol to use in the
125
+ # generated validation failures.
126
+ attr_reader :pg_auto_constraint_validations_messages
127
+
128
+ Plugins.inherited_instance_variables(self, :@pg_auto_constraint_validations=>nil, :@pg_auto_constraint_validations_messages=>nil, :@pg_auto_constraint_validations_cache=>nil, :@pg_auto_constraint_validations_cache_file=>nil)
129
+ Plugins.after_set_dataset(self, :setup_pg_auto_constraint_validations)
130
+
131
+ # Dump the in-memory cached metadata to the cache file.
132
+ def dump_pg_auto_constraint_validations_cache
133
+ raise Error, "No pg_auto_constraint_validations setup" unless file = @pg_auto_constraint_validations_cache_file
134
+ File.open(file, 'wb'){|f| f.write(Marshal.dump(@pg_auto_constraint_validations_cache))}
135
+ nil
136
+ end
137
+
138
+ # Override the constraint validation columns and message for a given constraint
139
+ def pg_auto_constraint_validation_override(constraint, columns, message)
140
+ pgacv = Hash[@pg_auto_constraint_validations]
141
+ overrides = pgacv[:overrides] = Hash[pgacv[:overrides]]
142
+ overrides[constraint] = [Array(columns), message].freeze
143
+ overrides.freeze
144
+ @pg_auto_constraint_validations = pgacv.freeze
145
+ nil
146
+ end
147
+
148
+ private
149
+
150
+ # Get the list of constraints, unique indexes, foreign keys in the current
151
+ # table, and keys in the current table referenced by foreign keys in other
152
+ # tables. Store this information so that if a constraint violation occurs,
153
+ # all necessary metadata is already available in the model, so a query is
154
+ # not required at runtime. This is both for performance and because in
155
+ # general after the constraint violation failure you will be inside a
156
+ # failed transaction and not able to execute queries.
157
+ def setup_pg_auto_constraint_validations
158
+ return unless @dataset
159
+
160
+ case @dataset.first_source_table
161
+ when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
162
+ convert_errors = db.respond_to?(:error_info)
163
+ end
164
+
165
+ unless convert_errors
166
+ # Might be a table returning function or subquery, skip handling those.
167
+ # Might have db not support error_info, skip handling that.
168
+ @pg_auto_constraint_validations = nil
169
+ return
170
+ end
171
+
172
+ cache = @pg_auto_constraint_validations_cache
173
+ literal_table_name = dataset.literal(table_name)
174
+ unless cache && (metadata = cache[literal_table_name])
175
+ checks = {}
176
+ indexes = {}
177
+ foreign_keys = {}
178
+ referenced_by = {}
179
+
180
+ db.check_constraints(table_name).each do |k, v|
181
+ checks[k] = v[:columns].dup.freeze unless v[:columns].empty?
182
+ end
183
+ db.indexes(table_name, :include_partial=>true).each do |k, v|
184
+ if v[:unique]
185
+ indexes[k] = v[:columns].dup.freeze
186
+ end
187
+ end
188
+ db.foreign_key_list(table_name, :schema=>false).each do |fk|
189
+ foreign_keys[fk[:name]] = fk[:columns].dup.freeze
190
+ end
191
+ db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk|
192
+ referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze
193
+ end
194
+
195
+ schema, table = db[:pg_class].
196
+ join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid).
197
+ get([:nspname, :relname])
198
+
199
+ metadata = {
200
+ :schema=>schema,
201
+ :table=>table,
202
+ :check=>checks,
203
+ :unique=>indexes,
204
+ :foreign_key=>foreign_keys,
205
+ :referenced_by=>referenced_by,
206
+ :overrides=>OPTS
207
+ }.freeze
208
+ metadata.each_value(&:freeze)
209
+
210
+ if cache
211
+ cache[literal_table_name] = metadata
212
+ end
213
+ end
214
+
215
+ @pg_auto_constraint_validations = metadata
216
+ nil
217
+ end
218
+ end
219
+
220
+ module InstanceMethods
221
+ private
222
+
223
+ # Yield to the given block, and if a Sequel::ConstraintViolation is raised, try
224
+ # to convert it to a Sequel::ValidationFailed error using the PostgreSQL error
225
+ # metadata.
226
+ def check_pg_constraint_error(ds)
227
+ yield
228
+ rescue Sequel::ConstraintViolation => e
229
+ begin
230
+ unless cv_info = model.pg_auto_constraint_validations
231
+ # Necessary metadata does not exist, just reraise the exception.
232
+ raise e
233
+ end
234
+
235
+ info = ds.db.error_info(e)
236
+ m = ds.method(:output_identifier)
237
+ schema = info[:schema]
238
+ table = info[:table]
239
+
240
+ if constraint = info[:constraint]
241
+ constraint = m.call(constraint)
242
+
243
+ columns, message = cv_info[:overrides][constraint]
244
+ if columns
245
+ override = true
246
+ add_pg_constraint_validation_error(columns, message)
247
+ end
248
+ end
249
+
250
+ messages = model.pg_auto_constraint_validations_messages
251
+
252
+ unless override
253
+ # :nocov:
254
+ case e
255
+ # :nocov:
256
+ when Sequel::NotNullConstraintViolation
257
+ if column = info[:column]
258
+ add_pg_constraint_validation_error([m.call(column)], messages[:not_null])
259
+ end
260
+ when Sequel::CheckConstraintViolation
261
+ if columns = cv_info[:check][constraint]
262
+ add_pg_constraint_validation_error(columns, messages[:check])
263
+ end
264
+ when Sequel::UniqueConstraintViolation
265
+ if columns = cv_info[:unique][constraint]
266
+ add_pg_constraint_validation_error(columns, messages[:unique])
267
+ end
268
+ when Sequel::ForeignKeyConstraintViolation
269
+ message_primary = info[:message_primary]
270
+ if message_primary.start_with?('update')
271
+ # This constraint violation is different from the others, because the constraint
272
+ # referenced is a constraint for a different table, not for this table. This
273
+ # happens when another table references the current table, and the referenced
274
+ # column in the current update is modified such that referential integrity
275
+ # would be broken. Use the reverse foreign key information to figure out
276
+ # which column is affected in that case.
277
+ skip_schema_table_check = true
278
+ if columns = cv_info[:referenced_by][[m.call(schema), m.call(table), constraint]]
279
+ add_pg_constraint_validation_error(columns, messages[:referenced_by])
280
+ end
281
+ elsif message_primary.start_with?('insert')
282
+ if columns = cv_info[:foreign_key][constraint]
283
+ add_pg_constraint_validation_error(columns, messages[:foreign_key])
284
+ end
285
+ end
286
+ end
287
+ end
288
+ rescue
289
+ # If there is an error trying to conver the constraint violation
290
+ # into a validation failure, it's best to just raise the constraint
291
+ # violation. This can make debugging the above block of code more
292
+ # difficult.
293
+ raise e
294
+ else
295
+ unless skip_schema_table_check
296
+ # The constraint violation could be caused by a trigger modifying
297
+ # a different table. Check that the error schema and table
298
+ # match the model's schema and table, or clear the validation error
299
+ # that was set above.
300
+ if schema != cv_info[:schema] || table != cv_info[:table]
301
+ errors.clear
302
+ end
303
+ end
304
+
305
+ if errors.empty?
306
+ # If we weren't able to parse the constraint violation metadata and
307
+ # convert it to an appropriate validation failure, or the schema/table
308
+ # didn't match, then raise the constraint violation.
309
+ raise e
310
+ end
311
+
312
+ # Integrate with error_splitter plugin to split any multi-column errors
313
+ # and add them as separate single column errors
314
+ if respond_to?(:split_validation_errors, true)
315
+ split_validation_errors(errors)
316
+ end
317
+
318
+ vf = ValidationFailed.new(self)
319
+ vf.set_backtrace(e.backtrace)
320
+ vf.wrapped_exception = e
321
+ raise vf
322
+ end
323
+ end
324
+
325
+ # If there is a single column instead of an array of columns, add the error
326
+ # for the column, otherwise add the error for the array of columns.
327
+ def add_pg_constraint_validation_error(column, message)
328
+ column = column.first if column.length == 1
329
+ errors.add(column, message)
330
+ end
331
+
332
+ # Convert PostgreSQL constraint errors when inserting.
333
+ def _insert_raw(ds)
334
+ check_pg_constraint_error(ds){super}
335
+ end
336
+
337
+ # Convert PostgreSQL constraint errors when inserting.
338
+ def _insert_select_raw(ds)
339
+ check_pg_constraint_error(ds){super}
340
+ end
341
+
342
+ # Convert PostgreSQL constraint errors when updating.
343
+ def _update_without_checking(_)
344
+ check_pg_constraint_error(_update_dataset){super}
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+
@@ -41,64 +41,21 @@ module Sequel
41
41
  #
42
42
  # Address.register_row_type
43
43
  #
44
- # Note that automatic conversion only works with the native postgres adapter.
45
- # For other adapters that connect to PostgreSQL, you need to call the conversion
46
- # proc manually.
47
- #
48
44
  # In addition to returning row-valued/composite types as instances of Sequel::Model,
49
45
  # this also lets you use model instances in datasets when inserting, updating, and
50
46
  # filtering:
51
47
  #
52
- # DB[:company].insert(:name=>'MS', :address=>
53
- # Address.load(:street=>'123 Foo St', :city=>'Bar Town', :zip=>'12345'))
48
+ # DB[:company].insert(name: 'MS', address:
49
+ # Address.load(street: '123 Foo St', city: 'Bar Town', zip: '12345'))
54
50
  module PgRow
55
51
  # When loading the extension, make sure the database has the pg_row extension
56
52
  # loaded, load the custom database extensions, and automatically register the
57
53
  # row type if the model has a dataset.
58
54
  def self.configure(model)
59
- model.db.extension(:pg_row)
60
- model.db.extend(DatabaseMethods)
55
+ model.db.extension(:pg_row, :_model_pg_row)
61
56
  model.register_row_type if model.instance_variable_get(:@dataset)
62
57
  end
63
58
 
64
- module DatabaseMethods
65
- ESCAPE_RE = /("|\\)/.freeze
66
- ESCAPE_REPLACEMENT = '\\\\\1'.freeze
67
- COMMA = ','
68
-
69
- # Handle Sequel::Model instances in bound variables.
70
- def bound_variable_arg(arg, conn)
71
- case arg
72
- when Sequel::Model
73
- "(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(COMMA)})"
74
- else
75
- super
76
- end
77
- end
78
-
79
- # If a Sequel::Model instance is given, return it as-is
80
- # instead of attempting to convert it.
81
- def row_type(db_type, v)
82
- if v.is_a?(Sequel::Model)
83
- v
84
- else
85
- super
86
- end
87
- end
88
-
89
- private
90
-
91
- # Handle Sequel::Model instances in bound variable arrays.
92
- def bound_variable_array(arg)
93
- case arg
94
- when Sequel::Model
95
- "\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(COMMA).gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)})\""
96
- else
97
- super
98
- end
99
- end
100
- end
101
-
102
59
  module ClassMethods
103
60
  # Register the model's row type with the database.
104
61
  def register_row_type
@@ -109,14 +66,11 @@ module Sequel
109
66
  end
110
67
 
111
68
  module InstanceMethods
112
- ROW = 'ROW'.freeze
113
- CAST = '::'.freeze
114
-
115
69
  # Literalize the model instance and append it to the sql.
116
70
  def sql_literal_append(ds, sql)
117
- sql << ROW
71
+ sql << 'ROW'
118
72
  ds.literal_append(sql, values.values_at(*columns))
119
- sql << CAST
73
+ sql << '::'
120
74
  ds.quote_schema_table_append(sql, model.dataset.first_source_table)
121
75
  end
122
76
  end
@@ -1,26 +1,13 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Sequel
4
- class Model
5
- module InstanceMethods
6
- # Whether prepared statements should be used for the given type of query
7
- # (:insert, :insert_select, :refresh, :update, or :delete). True by default,
8
- # can be overridden in other plugins to disallow prepared statements for
9
- # specific types of queries.
10
- def use_prepared_statements_for?(type)
11
- true
12
- end
13
- end
14
- end
15
-
16
4
  module Plugins
17
5
  # The prepared_statements plugin modifies the model to use prepared statements for
18
- # instance level deletes and saves, as well as class level lookups by
19
- # primary key.
6
+ # instance level inserts and updates.
20
7
  #
21
8
  # Note that this plugin is unsafe in some circumstances, as it can allow up to
22
9
  # 2^N prepared statements to be created for each type of insert and update query, where
23
- # N is the number of colums in the table. It is recommended that you use the
10
+ # N is the number of columns in the table. It is recommended that you use the
24
11
  # +prepared_statements_safe+ plugin in addition to this plugin to reduce the number
25
12
  # of prepared statements that can be created, unless you tightly control how your
26
13
  # model instances are saved.
@@ -43,22 +30,20 @@ module Sequel
43
30
 
44
31
  # Setup the datastructure used to hold the prepared statements in the model.
45
32
  def self.apply(model)
46
- model.instance_variable_set(:@prepared_statements, :insert=>{}, :insert_select=>{}, :update=>{}, :lookup_sql=>{}, :fixed=>{})
33
+ model.instance_variable_set(:@prepared_statements, {:insert=>{}, :insert_select=>{}, :update=>{}}.freeze)
47
34
  end
48
35
 
49
36
  module ClassMethods
50
- Plugins.inherited_instance_variables(self, :@prepared_statements=>lambda{|v| {:insert=>{}, :insert_select=>{}, :update=>{}, :lookup_sql=>{}, :fixed=>{}}})
37
+ Plugins.inherited_instance_variables(self, :@prepared_statements=>lambda{|v| {:insert=>{}, :insert_select=>{}, :update=>{}}.freeze})
51
38
 
52
39
  private
53
40
 
54
41
  # Create a prepared statement, but modify the SQL used so that the model's columns are explicitly
55
42
  # selected instead of using *, assuming that the dataset selects from a single table.
56
43
  def prepare_explicit_statement(ds, type, vals=OPTS)
57
- f = ds.opts[:from]
58
- meth = type == :insert_select ? :returning : :select
59
- s = ds.opts[meth]
60
- if f && f.length == 1 && !ds.opts[:join] && (!s || s.empty?)
61
- ds = ds.send(meth, *columns.map{|c| Sequel.identifier(c)})
44
+ s = ds.opts[:returning]
45
+ if !s || s.empty?
46
+ ds = ds.returning(*columns.map{|c| Sequel.identifier(c)})
62
47
  end
63
48
 
64
49
  prepare_statement(ds, type, vals)
@@ -67,19 +52,12 @@ module Sequel
67
52
  # Create a prepared statement based on the given dataset with a unique name for the given
68
53
  # type of query and values.
69
54
  def prepare_statement(ds, type, vals=OPTS)
70
- ps = ds.prepare(type, :"smpsp_#{NEXT.call}", vals)
71
- ps.log_sql = true
72
- ps
55
+ ds.clone(:log_sql=>true).prepare(type, :"smpsp_#{NEXT.call}", vals)
73
56
  end
74
57
 
75
58
  # Return a sorted array of columns for use as a hash key.
76
59
  def prepared_columns(cols)
77
- RUBY_VERSION >= '1.9' ? cols.sort : cols.sort_by(&:to_s)
78
- end
79
-
80
- # Return a prepared statement that can be used to delete a row from this model's dataset.
81
- def prepared_delete
82
- cached_prepared_statement(:fixed, :delete){prepare_statement(filter(prepared_statement_key_array(primary_key)), :delete)}
60
+ cols.sort
83
61
  end
84
62
 
85
63
  # Return a prepared statement that can be used to insert a row using the given columns.
@@ -90,19 +68,7 @@ module Sequel
90
68
  # Return a prepared statement that can be used to insert a row using the given columns
91
69
  # and return that column values for the row created.
92
70
  def prepared_insert_select(cols)
93
- if dataset.supports_insert_select?
94
- cached_prepared_statement(:insert_select, prepared_columns(cols)){prepare_explicit_statement(naked.clone(:server=>dataset.opts.fetch(:server, :default)), :insert_select, prepared_statement_key_hash(cols))}
95
- end
96
- end
97
-
98
- # Return a prepared statement that can be used to lookup a row solely based on the primary key.
99
- def prepared_lookup
100
- cached_prepared_statement(:fixed, :lookup){prepare_explicit_statement(filter(prepared_statement_key_array(primary_key)), :first)}
101
- end
102
-
103
- # Return a prepared statement that can be used to refresh a row to get new column values after insertion.
104
- def prepared_refresh
105
- cached_prepared_statement(:fixed, :refresh){prepare_explicit_statement(naked.clone(:server=>dataset.opts.fetch(:server, :default)).filter(prepared_statement_key_array(primary_key)), :first)}
71
+ cached_prepared_statement(:insert_select, prepared_columns(cols)){prepare_explicit_statement(naked.clone(:server=>dataset.opts.fetch(:server, :default)), :insert_select, prepared_statement_key_hash(cols))}
106
72
  end
107
73
 
108
74
  # Return an array of two element arrays with the column symbol as the first entry and the
@@ -129,12 +95,7 @@ module Sequel
129
95
 
130
96
  # Return a prepared statement that can be used to update row using the given columns.
131
97
  def prepared_update(cols)
132
- cached_prepared_statement(:update, prepared_columns(cols)){prepare_statement(filter(prepared_statement_key_array(primary_key)), :update, prepared_statement_key_hash(cols))}
133
- end
134
-
135
- # Use a prepared statement to query the database for the row matching the given primary key.
136
- def primary_key_lookup(pk)
137
- prepared_lookup.call(primary_key_hash(pk))
98
+ cached_prepared_statement(:update, prepared_columns(cols)){prepare_statement(where(prepared_statement_key_array(primary_key)), :update, prepared_statement_key_hash(cols))}
138
99
  end
139
100
 
140
101
  # If a prepared statement has already been cached for the given type and subtype,
@@ -149,24 +110,21 @@ module Sequel
149
110
  ps = yield
150
111
  Sequel.synchronize{h[subtype] = ps}
151
112
  end
113
+
114
+ # Whether to use prepared statements for lookups by primary key. True if the default
115
+ # primary key lookup isn't optimized.
116
+ def use_prepared_statements_for_pk_lookup?
117
+ !@fast_pk_lookup_sql && !dataset.joined_dataset?
118
+ end
152
119
  end
153
120
 
154
121
  module InstanceMethods
155
122
  private
156
123
 
157
- # Use a prepared statement to delete the row.
158
- def _delete_without_checking
159
- if use_prepared_statements_for?(:delete)
160
- model.send(:prepared_delete).call(pk_hash)
161
- else
162
- super
163
- end
164
- end
165
-
166
124
  # Use a prepared statement to insert the values into the model's dataset.
167
125
  def _insert_raw(ds)
168
126
  if use_prepared_statements_for?(:insert)
169
- model.send(:prepared_insert, @values.keys).call(@values)
127
+ _set_prepared_statement_server(model.send(:prepared_insert, @values.keys)).call(@values)
170
128
  else
171
129
  super
172
130
  end
@@ -176,29 +134,59 @@ module Sequel
176
134
  # and return the new column values.
177
135
  def _insert_select_raw(ds)
178
136
  if use_prepared_statements_for?(:insert_select)
179
- if ps = model.send(:prepared_insert_select, @values.keys)
180
- ps.call(@values)
181
- end
137
+ _set_prepared_statement_server(model.send(:prepared_insert_select, @values.keys)).call(@values)
182
138
  else
183
139
  super
184
140
  end
185
141
  end
186
142
 
187
- # Use a prepared statement to refresh this model's column values.
188
- def _refresh_get(ds)
189
- if use_prepared_statements_for?(:refresh)
190
- model.send(:prepared_refresh).call(pk_hash)
143
+ # Use a prepared statement to update this model's columns in the database.
144
+ def _update_without_checking(columns)
145
+ if use_prepared_statements_for?(:update)
146
+ _set_prepared_statement_server(model.send(:prepared_update, columns.keys)).call(columns.merge(pk_hash))
191
147
  else
192
148
  super
193
149
  end
194
150
  end
195
151
 
196
- # Use a prepared statement to update this model's columns in the database.
197
- def _update_without_checking(columns)
198
- if use_prepared_statements_for?(:update)
199
- model.send(:prepared_update, columns.keys).call(Hash[columns].merge!(pk_hash))
152
+ # If a server is set for the instance, return a prepared statement that will use that server.
153
+ def _set_prepared_statement_server(ps)
154
+ if @server
155
+ ps.server(@server)
200
156
  else
201
- super
157
+ ps
158
+ end
159
+ end
160
+
161
+ # Whether prepared statements should be used for the given type of query
162
+ # (:insert, :insert_select, :update). True by default,
163
+ # can be overridden in other plugins to disallow prepared statements for
164
+ # specific types of queries.
165
+ def use_prepared_statements_for?(type)
166
+ if defined?(super)
167
+ result = super
168
+ return result unless result.nil?
169
+ end
170
+
171
+ case type
172
+ when :insert, :update
173
+ true
174
+ when :insert_select
175
+ # SQLite RETURNING support has a bug that doesn't allow for committing transactions
176
+ # when a prepared statement with RETURNING has been used on the connection:
177
+ #
178
+ # SQLite3::BusyException: cannot commit transaction - SQL statements in progress: COMMIT
179
+ #
180
+ # Disabling usage of prepared statements for insert_select on SQLite seems to be the
181
+ # simplest way to workaround the problem.
182
+ db.database_type != :sqlite
183
+ # :nocov:
184
+ when :delete, :refresh
185
+ Sequel::Deprecation.deprecate("The :delete and :refresh prepared statement types", "There should be no need to check if these types are supported")
186
+ false
187
+ # :nocov:
188
+ else
189
+ raise Error, "unsupported type used: #{type.inspect}"
202
190
  end
203
191
  end
204
192
  end
@@ -28,7 +28,7 @@ module Sequel
28
28
  end
29
29
 
30
30
  module ClassMethods
31
- # A hash with column symbol keys and default values. Instance's
31
+ # A hash with column symbol keys and default values. Instance
32
32
  # values are merged into this hash before creating to reduce the
33
33
  # number of free columns (columns that may or may not be present
34
34
  # in the INSERT statement), as the number of prepared statements
@@ -38,6 +38,13 @@ module Sequel
38
38
  Plugins.inherited_instance_variables(self, :@prepared_statements_column_defaults=>:dup)
39
39
  Plugins.after_set_dataset(self, :set_prepared_statements_column_defaults)
40
40
 
41
+ # Freeze the prepared statements column defaults when freezing the model class.
42
+ def freeze
43
+ @prepared_statements_column_defaults.freeze if @prepared_statements_column_defaults
44
+
45
+ super
46
+ end
47
+
41
48
  private
42
49
 
43
50
  # Set the column defaults based on the database schema. All columns
@@ -59,9 +66,7 @@ module Sequel
59
66
  # Merge the current values into the default values to reduce the number
60
67
  # of free columns.
61
68
  def before_create
62
- if v = model.prepared_statements_column_defaults
63
- @values = Hash[v].merge!(values)
64
- end
69
+ @values = model.prepared_statements_column_defaults.merge(@values)
65
70
  super
66
71
  end
67
72