sequel 4.26.0 → 5.37.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (692) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +405 -5656
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +232 -157
  5. data/bin/sequel +32 -9
  6. data/doc/advanced_associations.rdoc +252 -188
  7. data/doc/association_basics.rdoc +231 -273
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +75 -48
  10. data/doc/code_order.rdoc +28 -10
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/mass_assignment.rdoc +74 -31
  16. data/doc/migration.rdoc +72 -46
  17. data/doc/model_dataset_method_design.rdoc +129 -0
  18. data/doc/model_hooks.rdoc +15 -25
  19. data/doc/model_plugins.rdoc +12 -12
  20. data/doc/mssql_stored_procedures.rdoc +3 -3
  21. data/doc/object_model.rdoc +59 -69
  22. data/doc/opening_databases.rdoc +84 -94
  23. data/doc/postgresql.rdoc +268 -38
  24. data/doc/prepared_statements.rdoc +29 -24
  25. data/doc/querying.rdoc +184 -164
  26. data/doc/reflection.rdoc +5 -6
  27. data/doc/release_notes/5.0.0.txt +159 -0
  28. data/doc/release_notes/5.1.0.txt +31 -0
  29. data/doc/release_notes/5.10.0.txt +84 -0
  30. data/doc/release_notes/5.11.0.txt +83 -0
  31. data/doc/release_notes/5.12.0.txt +141 -0
  32. data/doc/release_notes/5.13.0.txt +27 -0
  33. data/doc/release_notes/5.14.0.txt +63 -0
  34. data/doc/release_notes/5.15.0.txt +39 -0
  35. data/doc/release_notes/5.16.0.txt +110 -0
  36. data/doc/release_notes/5.17.0.txt +31 -0
  37. data/doc/release_notes/5.18.0.txt +69 -0
  38. data/doc/release_notes/5.19.0.txt +28 -0
  39. data/doc/release_notes/5.2.0.txt +33 -0
  40. data/doc/release_notes/5.20.0.txt +89 -0
  41. data/doc/release_notes/5.21.0.txt +87 -0
  42. data/doc/release_notes/5.22.0.txt +48 -0
  43. data/doc/release_notes/5.23.0.txt +56 -0
  44. data/doc/release_notes/5.24.0.txt +56 -0
  45. data/doc/release_notes/5.25.0.txt +32 -0
  46. data/doc/release_notes/5.26.0.txt +35 -0
  47. data/doc/release_notes/5.27.0.txt +21 -0
  48. data/doc/release_notes/5.28.0.txt +16 -0
  49. data/doc/release_notes/5.29.0.txt +22 -0
  50. data/doc/release_notes/5.3.0.txt +121 -0
  51. data/doc/release_notes/5.30.0.txt +20 -0
  52. data/doc/release_notes/5.31.0.txt +148 -0
  53. data/doc/release_notes/5.32.0.txt +46 -0
  54. data/doc/release_notes/5.33.0.txt +24 -0
  55. data/doc/release_notes/5.34.0.txt +40 -0
  56. data/doc/release_notes/5.35.0.txt +56 -0
  57. data/doc/release_notes/5.36.0.txt +60 -0
  58. data/doc/release_notes/5.37.0.txt +30 -0
  59. data/doc/release_notes/5.4.0.txt +80 -0
  60. data/doc/release_notes/5.5.0.txt +61 -0
  61. data/doc/release_notes/5.6.0.txt +31 -0
  62. data/doc/release_notes/5.7.0.txt +108 -0
  63. data/doc/release_notes/5.8.0.txt +170 -0
  64. data/doc/release_notes/5.9.0.txt +99 -0
  65. data/doc/schema_modification.rdoc +102 -77
  66. data/doc/security.rdoc +160 -87
  67. data/doc/sharding.rdoc +74 -47
  68. data/doc/sql.rdoc +135 -122
  69. data/doc/testing.rdoc +34 -18
  70. data/doc/thread_safety.rdoc +2 -4
  71. data/doc/transactions.rdoc +101 -19
  72. data/doc/validations.rdoc +64 -51
  73. data/doc/virtual_rows.rdoc +90 -109
  74. data/lib/sequel.rb +3 -1
  75. data/lib/sequel/adapters/ado.rb +154 -22
  76. data/lib/sequel/adapters/ado/access.rb +21 -21
  77. data/lib/sequel/adapters/ado/mssql.rb +8 -15
  78. data/lib/sequel/adapters/amalgalite.rb +17 -25
  79. data/lib/sequel/adapters/ibmdb.rb +52 -58
  80. data/lib/sequel/adapters/jdbc.rb +149 -127
  81. data/lib/sequel/adapters/jdbc/db2.rb +32 -40
  82. data/lib/sequel/adapters/jdbc/derby.rb +56 -58
  83. data/lib/sequel/adapters/jdbc/h2.rb +40 -30
  84. data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
  85. data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
  86. data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
  87. data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
  88. data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
  89. data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
  90. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
  91. data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
  92. data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
  93. data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
  94. data/lib/sequel/adapters/mock.rb +104 -113
  95. data/lib/sequel/adapters/mysql.rb +42 -61
  96. data/lib/sequel/adapters/mysql2.rb +126 -35
  97. data/lib/sequel/adapters/odbc.rb +21 -28
  98. data/lib/sequel/adapters/odbc/db2.rb +3 -1
  99. data/lib/sequel/adapters/odbc/mssql.rb +11 -15
  100. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  101. data/lib/sequel/adapters/oracle.rb +62 -68
  102. data/lib/sequel/adapters/postgres.rb +257 -311
  103. data/lib/sequel/adapters/postgresql.rb +3 -1
  104. data/lib/sequel/adapters/shared/access.rb +75 -79
  105. data/lib/sequel/adapters/shared/db2.rb +96 -74
  106. data/lib/sequel/adapters/shared/mssql.rb +258 -213
  107. data/lib/sequel/adapters/shared/mysql.rb +284 -216
  108. data/lib/sequel/adapters/shared/oracle.rb +175 -60
  109. data/lib/sequel/adapters/shared/postgres.rb +829 -383
  110. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
  111. data/lib/sequel/adapters/shared/sqlite.rb +382 -159
  112. data/lib/sequel/adapters/sqlanywhere.rb +53 -38
  113. data/lib/sequel/adapters/sqlite.rb +111 -105
  114. data/lib/sequel/adapters/tinytds.rb +38 -46
  115. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
  116. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
  117. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  118. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  119. data/lib/sequel/adapters/utils/replace.rb +3 -4
  120. data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
  121. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  122. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  123. data/lib/sequel/ast_transformer.rb +13 -89
  124. data/lib/sequel/connection_pool.rb +54 -26
  125. data/lib/sequel/connection_pool/sharded_single.rb +19 -12
  126. data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
  127. data/lib/sequel/connection_pool/single.rb +21 -12
  128. data/lib/sequel/connection_pool/threaded.rb +137 -119
  129. data/lib/sequel/core.rb +352 -320
  130. data/lib/sequel/database.rb +19 -2
  131. data/lib/sequel/database/connecting.rb +70 -55
  132. data/lib/sequel/database/dataset.rb +15 -5
  133. data/lib/sequel/database/dataset_defaults.rb +20 -102
  134. data/lib/sequel/database/features.rb +20 -4
  135. data/lib/sequel/database/logging.rb +25 -7
  136. data/lib/sequel/database/misc.rb +132 -118
  137. data/lib/sequel/database/query.rb +51 -28
  138. data/lib/sequel/database/schema_generator.rb +188 -75
  139. data/lib/sequel/database/schema_methods.rb +161 -92
  140. data/lib/sequel/database/transactions.rb +260 -58
  141. data/lib/sequel/dataset.rb +28 -12
  142. data/lib/sequel/dataset/actions.rb +354 -170
  143. data/lib/sequel/dataset/dataset_module.rb +46 -0
  144. data/lib/sequel/dataset/features.rb +81 -34
  145. data/lib/sequel/dataset/graph.rb +82 -58
  146. data/lib/sequel/dataset/misc.rb +139 -47
  147. data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
  148. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  149. data/lib/sequel/dataset/query.rb +428 -214
  150. data/lib/sequel/dataset/sql.rb +446 -339
  151. data/lib/sequel/deprecated.rb +14 -2
  152. data/lib/sequel/exceptions.rb +48 -16
  153. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  154. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  155. data/lib/sequel/extensions/_pretty_table.rb +10 -9
  156. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  157. data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
  158. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  159. data/lib/sequel/extensions/blank.rb +2 -0
  160. data/lib/sequel/extensions/caller_logging.rb +79 -0
  161. data/lib/sequel/extensions/columns_introspection.rb +9 -4
  162. data/lib/sequel/extensions/connection_expiration.rb +99 -0
  163. data/lib/sequel/extensions/connection_validator.rb +26 -13
  164. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  165. data/lib/sequel/extensions/constraint_validations.rb +93 -38
  166. data/lib/sequel/extensions/core_extensions.rb +45 -53
  167. data/lib/sequel/extensions/core_refinements.rb +44 -46
  168. data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
  169. data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
  170. data/lib/sequel/extensions/date_arithmetic.rb +42 -16
  171. data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
  172. data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
  173. data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
  174. data/lib/sequel/extensions/error_sql.rb +7 -3
  175. data/lib/sequel/extensions/escaped_like.rb +100 -0
  176. data/lib/sequel/extensions/eval_inspect.rb +14 -15
  177. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  178. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  179. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  180. data/lib/sequel/extensions/from_block.rb +2 -31
  181. data/lib/sequel/extensions/graph_each.rb +19 -6
  182. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  183. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  184. data/lib/sequel/extensions/index_caching.rb +109 -0
  185. data/lib/sequel/extensions/inflector.rb +8 -4
  186. data/lib/sequel/extensions/integer64.rb +32 -0
  187. data/lib/sequel/extensions/looser_typecasting.rb +19 -9
  188. data/lib/sequel/extensions/migration.rb +132 -80
  189. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
  190. data/lib/sequel/extensions/named_timezones.rb +88 -23
  191. data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
  192. data/lib/sequel/extensions/null_dataset.rb +12 -8
  193. data/lib/sequel/extensions/pagination.rb +35 -28
  194. data/lib/sequel/extensions/pg_array.rb +227 -316
  195. data/lib/sequel/extensions/pg_array_ops.rb +19 -7
  196. data/lib/sequel/extensions/pg_enum.rb +69 -24
  197. data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
  198. data/lib/sequel/extensions/pg_hstore.rb +50 -59
  199. data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
  200. data/lib/sequel/extensions/pg_inet.rb +34 -15
  201. data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
  202. data/lib/sequel/extensions/pg_interval.rb +26 -26
  203. data/lib/sequel/extensions/pg_json.rb +422 -141
  204. data/lib/sequel/extensions/pg_json_ops.rb +248 -9
  205. data/lib/sequel/extensions/pg_loose_count.rb +5 -1
  206. data/lib/sequel/extensions/pg_range.rb +162 -146
  207. data/lib/sequel/extensions/pg_range_ops.rb +10 -5
  208. data/lib/sequel/extensions/pg_row.rb +53 -87
  209. data/lib/sequel/extensions/pg_row_ops.rb +36 -13
  210. data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
  211. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  212. data/lib/sequel/extensions/pretty_table.rb +4 -0
  213. data/lib/sequel/extensions/query.rb +12 -7
  214. data/lib/sequel/extensions/round_timestamps.rb +6 -9
  215. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  216. data/lib/sequel/extensions/s.rb +59 -0
  217. data/lib/sequel/extensions/schema_caching.rb +14 -1
  218. data/lib/sequel/extensions/schema_dumper.rb +83 -55
  219. data/lib/sequel/extensions/select_remove.rb +8 -4
  220. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  221. data/lib/sequel/extensions/server_block.rb +50 -17
  222. data/lib/sequel/extensions/server_logging.rb +61 -0
  223. data/lib/sequel/extensions/split_array_nil.rb +8 -4
  224. data/lib/sequel/extensions/sql_comments.rb +96 -0
  225. data/lib/sequel/extensions/sql_expr.rb +4 -1
  226. data/lib/sequel/extensions/string_agg.rb +181 -0
  227. data/lib/sequel/extensions/string_date_time.rb +2 -0
  228. data/lib/sequel/extensions/symbol_aref.rb +53 -0
  229. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  230. data/lib/sequel/extensions/symbol_as.rb +23 -0
  231. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  232. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  233. data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
  234. data/lib/sequel/extensions/to_dot.rb +15 -5
  235. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  236. data/lib/sequel/model.rb +36 -126
  237. data/lib/sequel/model/associations.rb +850 -257
  238. data/lib/sequel/model/base.rb +652 -764
  239. data/lib/sequel/model/dataset_module.rb +13 -10
  240. data/lib/sequel/model/default_inflections.rb +3 -1
  241. data/lib/sequel/model/errors.rb +3 -3
  242. data/lib/sequel/model/exceptions.rb +12 -12
  243. data/lib/sequel/model/inflections.rb +8 -19
  244. data/lib/sequel/model/plugins.rb +111 -0
  245. data/lib/sequel/plugins/accessed_columns.rb +2 -0
  246. data/lib/sequel/plugins/active_model.rb +32 -7
  247. data/lib/sequel/plugins/after_initialize.rb +3 -1
  248. data/lib/sequel/plugins/association_dependencies.rb +27 -18
  249. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  250. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  251. data/lib/sequel/plugins/association_pks.rb +181 -83
  252. data/lib/sequel/plugins/association_proxies.rb +33 -9
  253. data/lib/sequel/plugins/auto_validations.rb +58 -23
  254. data/lib/sequel/plugins/before_after_save.rb +8 -0
  255. data/lib/sequel/plugins/blacklist_security.rb +23 -12
  256. data/lib/sequel/plugins/boolean_readers.rb +9 -6
  257. data/lib/sequel/plugins/boolean_subsets.rb +64 -0
  258. data/lib/sequel/plugins/caching.rb +27 -16
  259. data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
  260. data/lib/sequel/plugins/column_conflicts.rb +18 -3
  261. data/lib/sequel/plugins/column_select.rb +9 -5
  262. data/lib/sequel/plugins/columns_updated.rb +42 -0
  263. data/lib/sequel/plugins/composition.rb +36 -24
  264. data/lib/sequel/plugins/constraint_validations.rb +37 -16
  265. data/lib/sequel/plugins/csv_serializer.rb +58 -35
  266. data/lib/sequel/plugins/dataset_associations.rb +60 -18
  267. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  268. data/lib/sequel/plugins/defaults_setter.rb +74 -13
  269. data/lib/sequel/plugins/delay_add_association.rb +4 -1
  270. data/lib/sequel/plugins/dirty.rb +65 -24
  271. data/lib/sequel/plugins/eager_each.rb +27 -3
  272. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  273. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  274. data/lib/sequel/plugins/error_splitter.rb +19 -12
  275. data/lib/sequel/plugins/finder.rb +246 -0
  276. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  277. data/lib/sequel/plugins/force_encoding.rb +9 -12
  278. data/lib/sequel/plugins/hook_class_methods.rb +39 -54
  279. data/lib/sequel/plugins/input_transformer.rb +20 -10
  280. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  281. data/lib/sequel/plugins/insert_returning_select.rb +4 -2
  282. data/lib/sequel/plugins/instance_filters.rb +12 -8
  283. data/lib/sequel/plugins/instance_hooks.rb +36 -17
  284. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  285. data/lib/sequel/plugins/inverted_subsets.rb +24 -13
  286. data/lib/sequel/plugins/json_serializer.rb +123 -47
  287. data/lib/sequel/plugins/lazy_attributes.rb +20 -14
  288. data/lib/sequel/plugins/list.rb +40 -26
  289. data/lib/sequel/plugins/many_through_many.rb +28 -12
  290. data/lib/sequel/plugins/modification_detection.rb +17 -5
  291. data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
  292. data/lib/sequel/plugins/nested_attributes.rb +55 -28
  293. data/lib/sequel/plugins/optimistic_locking.rb +5 -3
  294. data/lib/sequel/plugins/pg_array_associations.rb +52 -18
  295. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
  296. data/lib/sequel/plugins/pg_row.rb +7 -51
  297. data/lib/sequel/plugins/prepared_statements.rb +53 -72
  298. data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
  299. data/lib/sequel/plugins/rcte_tree.rb +43 -63
  300. data/lib/sequel/plugins/serialization.rb +37 -44
  301. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
  302. data/lib/sequel/plugins/sharding.rb +17 -10
  303. data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
  304. data/lib/sequel/plugins/singular_table_names.rb +2 -0
  305. data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
  306. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  307. data/lib/sequel/plugins/split_values.rb +13 -6
  308. data/lib/sequel/plugins/static_cache.rb +79 -53
  309. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  310. data/lib/sequel/plugins/string_stripper.rb +5 -3
  311. data/lib/sequel/plugins/subclasses.rb +20 -2
  312. data/lib/sequel/plugins/subset_conditions.rb +48 -0
  313. data/lib/sequel/plugins/table_select.rb +4 -2
  314. data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
  315. data/lib/sequel/plugins/throw_failures.rb +110 -0
  316. data/lib/sequel/plugins/timestamps.rb +22 -8
  317. data/lib/sequel/plugins/touch.rb +21 -8
  318. data/lib/sequel/plugins/tree.rb +57 -30
  319. data/lib/sequel/plugins/typecast_on_load.rb +14 -4
  320. data/lib/sequel/plugins/unlimited_update.rb +3 -7
  321. data/lib/sequel/plugins/update_or_create.rb +6 -4
  322. data/lib/sequel/plugins/update_primary_key.rb +3 -1
  323. data/lib/sequel/plugins/update_refresh.rb +28 -15
  324. data/lib/sequel/plugins/uuid.rb +70 -0
  325. data/lib/sequel/plugins/validate_associated.rb +20 -0
  326. data/lib/sequel/plugins/validation_class_methods.rb +40 -19
  327. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  328. data/lib/sequel/plugins/validation_helpers.rb +49 -31
  329. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  330. data/lib/sequel/plugins/xml_serializer.rb +31 -30
  331. data/lib/sequel/sql.rb +479 -329
  332. data/lib/sequel/timezones.rb +62 -32
  333. data/lib/sequel/version.rb +10 -3
  334. metadata +177 -477
  335. data/Rakefile +0 -165
  336. data/doc/active_record.rdoc +0 -912
  337. data/doc/release_notes/1.0.txt +0 -38
  338. data/doc/release_notes/1.1.txt +0 -143
  339. data/doc/release_notes/1.3.txt +0 -101
  340. data/doc/release_notes/1.4.0.txt +0 -53
  341. data/doc/release_notes/1.5.0.txt +0 -155
  342. data/doc/release_notes/2.0.0.txt +0 -298
  343. data/doc/release_notes/2.1.0.txt +0 -271
  344. data/doc/release_notes/2.10.0.txt +0 -328
  345. data/doc/release_notes/2.11.0.txt +0 -215
  346. data/doc/release_notes/2.12.0.txt +0 -534
  347. data/doc/release_notes/2.2.0.txt +0 -253
  348. data/doc/release_notes/2.3.0.txt +0 -88
  349. data/doc/release_notes/2.4.0.txt +0 -106
  350. data/doc/release_notes/2.5.0.txt +0 -137
  351. data/doc/release_notes/2.6.0.txt +0 -157
  352. data/doc/release_notes/2.7.0.txt +0 -166
  353. data/doc/release_notes/2.8.0.txt +0 -171
  354. data/doc/release_notes/2.9.0.txt +0 -97
  355. data/doc/release_notes/3.0.0.txt +0 -221
  356. data/doc/release_notes/3.1.0.txt +0 -406
  357. data/doc/release_notes/3.10.0.txt +0 -286
  358. data/doc/release_notes/3.11.0.txt +0 -254
  359. data/doc/release_notes/3.12.0.txt +0 -304
  360. data/doc/release_notes/3.13.0.txt +0 -210
  361. data/doc/release_notes/3.14.0.txt +0 -118
  362. data/doc/release_notes/3.15.0.txt +0 -78
  363. data/doc/release_notes/3.16.0.txt +0 -45
  364. data/doc/release_notes/3.17.0.txt +0 -58
  365. data/doc/release_notes/3.18.0.txt +0 -120
  366. data/doc/release_notes/3.19.0.txt +0 -67
  367. data/doc/release_notes/3.2.0.txt +0 -268
  368. data/doc/release_notes/3.20.0.txt +0 -41
  369. data/doc/release_notes/3.21.0.txt +0 -87
  370. data/doc/release_notes/3.22.0.txt +0 -39
  371. data/doc/release_notes/3.23.0.txt +0 -172
  372. data/doc/release_notes/3.24.0.txt +0 -420
  373. data/doc/release_notes/3.25.0.txt +0 -88
  374. data/doc/release_notes/3.26.0.txt +0 -88
  375. data/doc/release_notes/3.27.0.txt +0 -82
  376. data/doc/release_notes/3.28.0.txt +0 -304
  377. data/doc/release_notes/3.29.0.txt +0 -459
  378. data/doc/release_notes/3.3.0.txt +0 -192
  379. data/doc/release_notes/3.30.0.txt +0 -135
  380. data/doc/release_notes/3.31.0.txt +0 -146
  381. data/doc/release_notes/3.32.0.txt +0 -202
  382. data/doc/release_notes/3.33.0.txt +0 -157
  383. data/doc/release_notes/3.34.0.txt +0 -671
  384. data/doc/release_notes/3.35.0.txt +0 -144
  385. data/doc/release_notes/3.36.0.txt +0 -245
  386. data/doc/release_notes/3.37.0.txt +0 -338
  387. data/doc/release_notes/3.38.0.txt +0 -234
  388. data/doc/release_notes/3.39.0.txt +0 -237
  389. data/doc/release_notes/3.4.0.txt +0 -325
  390. data/doc/release_notes/3.40.0.txt +0 -73
  391. data/doc/release_notes/3.41.0.txt +0 -155
  392. data/doc/release_notes/3.42.0.txt +0 -74
  393. data/doc/release_notes/3.43.0.txt +0 -105
  394. data/doc/release_notes/3.44.0.txt +0 -152
  395. data/doc/release_notes/3.45.0.txt +0 -179
  396. data/doc/release_notes/3.46.0.txt +0 -122
  397. data/doc/release_notes/3.47.0.txt +0 -270
  398. data/doc/release_notes/3.48.0.txt +0 -477
  399. data/doc/release_notes/3.5.0.txt +0 -510
  400. data/doc/release_notes/3.6.0.txt +0 -366
  401. data/doc/release_notes/3.7.0.txt +0 -179
  402. data/doc/release_notes/3.8.0.txt +0 -151
  403. data/doc/release_notes/3.9.0.txt +0 -233
  404. data/doc/release_notes/4.0.0.txt +0 -262
  405. data/doc/release_notes/4.1.0.txt +0 -85
  406. data/doc/release_notes/4.10.0.txt +0 -226
  407. data/doc/release_notes/4.11.0.txt +0 -147
  408. data/doc/release_notes/4.12.0.txt +0 -105
  409. data/doc/release_notes/4.13.0.txt +0 -169
  410. data/doc/release_notes/4.14.0.txt +0 -68
  411. data/doc/release_notes/4.15.0.txt +0 -56
  412. data/doc/release_notes/4.16.0.txt +0 -36
  413. data/doc/release_notes/4.17.0.txt +0 -38
  414. data/doc/release_notes/4.18.0.txt +0 -36
  415. data/doc/release_notes/4.19.0.txt +0 -45
  416. data/doc/release_notes/4.2.0.txt +0 -129
  417. data/doc/release_notes/4.20.0.txt +0 -79
  418. data/doc/release_notes/4.21.0.txt +0 -94
  419. data/doc/release_notes/4.22.0.txt +0 -72
  420. data/doc/release_notes/4.23.0.txt +0 -65
  421. data/doc/release_notes/4.24.0.txt +0 -99
  422. data/doc/release_notes/4.25.0.txt +0 -181
  423. data/doc/release_notes/4.26.0.txt +0 -44
  424. data/doc/release_notes/4.3.0.txt +0 -40
  425. data/doc/release_notes/4.4.0.txt +0 -92
  426. data/doc/release_notes/4.5.0.txt +0 -34
  427. data/doc/release_notes/4.6.0.txt +0 -30
  428. data/doc/release_notes/4.7.0.txt +0 -103
  429. data/doc/release_notes/4.8.0.txt +0 -175
  430. data/doc/release_notes/4.9.0.txt +0 -190
  431. data/lib/sequel/adapters/cubrid.rb +0 -142
  432. data/lib/sequel/adapters/do.rb +0 -156
  433. data/lib/sequel/adapters/do/mysql.rb +0 -64
  434. data/lib/sequel/adapters/do/postgres.rb +0 -42
  435. data/lib/sequel/adapters/do/sqlite3.rb +0 -40
  436. data/lib/sequel/adapters/jdbc/as400.rb +0 -82
  437. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
  438. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
  439. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
  440. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
  441. data/lib/sequel/adapters/odbc/progress.rb +0 -8
  442. data/lib/sequel/adapters/shared/cubrid.rb +0 -243
  443. data/lib/sequel/adapters/shared/firebird.rb +0 -245
  444. data/lib/sequel/adapters/shared/informix.rb +0 -52
  445. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
  446. data/lib/sequel/adapters/shared/progress.rb +0 -38
  447. data/lib/sequel/adapters/swift.rb +0 -158
  448. data/lib/sequel/adapters/swift/mysql.rb +0 -47
  449. data/lib/sequel/adapters/swift/postgres.rb +0 -45
  450. data/lib/sequel/adapters/swift/sqlite.rb +0 -47
  451. data/lib/sequel/adapters/utils/pg_types.rb +0 -68
  452. data/lib/sequel/dataset/mutation.rb +0 -109
  453. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
  454. data/lib/sequel/extensions/filter_having.rb +0 -59
  455. data/lib/sequel/extensions/hash_aliases.rb +0 -45
  456. data/lib/sequel/extensions/meta_def.rb +0 -31
  457. data/lib/sequel/extensions/query_literals.rb +0 -80
  458. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
  459. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
  460. data/lib/sequel/extensions/set_overrides.rb +0 -72
  461. data/lib/sequel/no_core_ext.rb +0 -1
  462. data/lib/sequel/plugins/association_autoreloading.rb +0 -7
  463. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
  464. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
  465. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
  466. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
  467. data/lib/sequel/plugins/schema.rb +0 -80
  468. data/lib/sequel/plugins/scissors.rb +0 -33
  469. data/spec/adapters/db2_spec.rb +0 -160
  470. data/spec/adapters/firebird_spec.rb +0 -411
  471. data/spec/adapters/informix_spec.rb +0 -100
  472. data/spec/adapters/mssql_spec.rb +0 -706
  473. data/spec/adapters/mysql_spec.rb +0 -1287
  474. data/spec/adapters/oracle_spec.rb +0 -313
  475. data/spec/adapters/postgres_spec.rb +0 -3725
  476. data/spec/adapters/spec_helper.rb +0 -43
  477. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  478. data/spec/adapters/sqlite_spec.rb +0 -653
  479. data/spec/bin_spec.rb +0 -254
  480. data/spec/core/connection_pool_spec.rb +0 -1016
  481. data/spec/core/database_spec.rb +0 -2531
  482. data/spec/core/dataset_spec.rb +0 -5098
  483. data/spec/core/deprecated_spec.rb +0 -70
  484. data/spec/core/expression_filters_spec.rb +0 -1243
  485. data/spec/core/mock_adapter_spec.rb +0 -462
  486. data/spec/core/object_graph_spec.rb +0 -303
  487. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  488. data/spec/core/schema_generator_spec.rb +0 -179
  489. data/spec/core/schema_spec.rb +0 -1659
  490. data/spec/core/spec_helper.rb +0 -34
  491. data/spec/core/version_spec.rb +0 -7
  492. data/spec/core_extensions_spec.rb +0 -699
  493. data/spec/extensions/accessed_columns_spec.rb +0 -51
  494. data/spec/extensions/active_model_spec.rb +0 -123
  495. data/spec/extensions/after_initialize_spec.rb +0 -24
  496. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  497. data/spec/extensions/association_dependencies_spec.rb +0 -117
  498. data/spec/extensions/association_pks_spec.rb +0 -365
  499. data/spec/extensions/association_proxies_spec.rb +0 -86
  500. data/spec/extensions/auto_validations_spec.rb +0 -192
  501. data/spec/extensions/blacklist_security_spec.rb +0 -88
  502. data/spec/extensions/blank_spec.rb +0 -69
  503. data/spec/extensions/boolean_readers_spec.rb +0 -93
  504. data/spec/extensions/caching_spec.rb +0 -270
  505. data/spec/extensions/class_table_inheritance_spec.rb +0 -420
  506. data/spec/extensions/column_conflicts_spec.rb +0 -60
  507. data/spec/extensions/column_select_spec.rb +0 -108
  508. data/spec/extensions/columns_introspection_spec.rb +0 -91
  509. data/spec/extensions/composition_spec.rb +0 -242
  510. data/spec/extensions/connection_validator_spec.rb +0 -120
  511. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
  512. data/spec/extensions/constraint_validations_spec.rb +0 -325
  513. data/spec/extensions/core_refinements_spec.rb +0 -519
  514. data/spec/extensions/csv_serializer_spec.rb +0 -173
  515. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  516. data/spec/extensions/dataset_associations_spec.rb +0 -311
  517. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  518. data/spec/extensions/date_arithmetic_spec.rb +0 -150
  519. data/spec/extensions/defaults_setter_spec.rb +0 -101
  520. data/spec/extensions/delay_add_association_spec.rb +0 -52
  521. data/spec/extensions/dirty_spec.rb +0 -180
  522. data/spec/extensions/eager_each_spec.rb +0 -42
  523. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  524. data/spec/extensions/error_splitter_spec.rb +0 -18
  525. data/spec/extensions/error_sql_spec.rb +0 -20
  526. data/spec/extensions/eval_inspect_spec.rb +0 -73
  527. data/spec/extensions/filter_having_spec.rb +0 -40
  528. data/spec/extensions/force_encoding_spec.rb +0 -114
  529. data/spec/extensions/from_block_spec.rb +0 -21
  530. data/spec/extensions/graph_each_spec.rb +0 -109
  531. data/spec/extensions/hash_aliases_spec.rb +0 -24
  532. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  533. data/spec/extensions/inflector_spec.rb +0 -183
  534. data/spec/extensions/input_transformer_spec.rb +0 -54
  535. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  536. data/spec/extensions/instance_filters_spec.rb +0 -79
  537. data/spec/extensions/instance_hooks_spec.rb +0 -276
  538. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  539. data/spec/extensions/json_serializer_spec.rb +0 -291
  540. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  541. data/spec/extensions/list_spec.rb +0 -267
  542. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  543. data/spec/extensions/many_through_many_spec.rb +0 -2172
  544. data/spec/extensions/meta_def_spec.rb +0 -21
  545. data/spec/extensions/migration_spec.rb +0 -712
  546. data/spec/extensions/modification_detection_spec.rb +0 -80
  547. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  548. data/spec/extensions/named_timezones_spec.rb +0 -108
  549. data/spec/extensions/nested_attributes_spec.rb +0 -697
  550. data/spec/extensions/null_dataset_spec.rb +0 -85
  551. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  552. data/spec/extensions/pagination_spec.rb +0 -118
  553. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  554. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  555. data/spec/extensions/pg_array_spec.rb +0 -395
  556. data/spec/extensions/pg_enum_spec.rb +0 -92
  557. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  558. data/spec/extensions/pg_hstore_spec.rb +0 -206
  559. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  560. data/spec/extensions/pg_inet_spec.rb +0 -52
  561. data/spec/extensions/pg_interval_spec.rb +0 -76
  562. data/spec/extensions/pg_json_ops_spec.rb +0 -229
  563. data/spec/extensions/pg_json_spec.rb +0 -218
  564. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  565. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  566. data/spec/extensions/pg_range_spec.rb +0 -404
  567. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  568. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  569. data/spec/extensions/pg_row_spec.rb +0 -360
  570. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  571. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  572. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  573. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  574. data/spec/extensions/prepared_statements_spec.rb +0 -103
  575. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  576. data/spec/extensions/pretty_table_spec.rb +0 -92
  577. data/spec/extensions/query_literals_spec.rb +0 -183
  578. data/spec/extensions/query_spec.rb +0 -102
  579. data/spec/extensions/rcte_tree_spec.rb +0 -392
  580. data/spec/extensions/round_timestamps_spec.rb +0 -43
  581. data/spec/extensions/schema_caching_spec.rb +0 -41
  582. data/spec/extensions/schema_dumper_spec.rb +0 -789
  583. data/spec/extensions/schema_spec.rb +0 -117
  584. data/spec/extensions/scissors_spec.rb +0 -26
  585. data/spec/extensions/select_remove_spec.rb +0 -38
  586. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  587. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  588. data/spec/extensions/serialization_spec.rb +0 -362
  589. data/spec/extensions/server_block_spec.rb +0 -90
  590. data/spec/extensions/set_overrides_spec.rb +0 -61
  591. data/spec/extensions/sharding_spec.rb +0 -198
  592. data/spec/extensions/shared_caching_spec.rb +0 -175
  593. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  594. data/spec/extensions/singular_table_names_spec.rb +0 -22
  595. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  596. data/spec/extensions/spec_helper.rb +0 -71
  597. data/spec/extensions/split_array_nil_spec.rb +0 -24
  598. data/spec/extensions/split_values_spec.rb +0 -22
  599. data/spec/extensions/sql_expr_spec.rb +0 -60
  600. data/spec/extensions/static_cache_spec.rb +0 -361
  601. data/spec/extensions/string_date_time_spec.rb +0 -95
  602. data/spec/extensions/string_stripper_spec.rb +0 -68
  603. data/spec/extensions/subclasses_spec.rb +0 -66
  604. data/spec/extensions/table_select_spec.rb +0 -71
  605. data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
  606. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  607. data/spec/extensions/timestamps_spec.rb +0 -175
  608. data/spec/extensions/to_dot_spec.rb +0 -154
  609. data/spec/extensions/touch_spec.rb +0 -203
  610. data/spec/extensions/tree_spec.rb +0 -274
  611. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  612. data/spec/extensions/unlimited_update_spec.rb +0 -20
  613. data/spec/extensions/update_or_create_spec.rb +0 -87
  614. data/spec/extensions/update_primary_key_spec.rb +0 -100
  615. data/spec/extensions/update_refresh_spec.rb +0 -53
  616. data/spec/extensions/validate_associated_spec.rb +0 -52
  617. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  618. data/spec/extensions/validation_helpers_spec.rb +0 -541
  619. data/spec/extensions/xml_serializer_spec.rb +0 -207
  620. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  621. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  622. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  623. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  624. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  625. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  626. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  627. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  628. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  629. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  630. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  631. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  632. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  633. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  634. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  635. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  636. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  637. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  638. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  639. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  640. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  641. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  642. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  643. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  644. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  645. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  646. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  647. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  648. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  649. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  650. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  651. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  652. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  653. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  654. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  655. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  656. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  657. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  658. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  659. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  660. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  661. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  662. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  663. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  664. data/spec/guards_helper.rb +0 -55
  665. data/spec/integration/associations_test.rb +0 -2454
  666. data/spec/integration/database_test.rb +0 -113
  667. data/spec/integration/dataset_test.rb +0 -1808
  668. data/spec/integration/eager_loader_test.rb +0 -687
  669. data/spec/integration/migrator_test.rb +0 -240
  670. data/spec/integration/model_test.rb +0 -226
  671. data/spec/integration/plugin_test.rb +0 -2240
  672. data/spec/integration/prepared_statement_test.rb +0 -467
  673. data/spec/integration/schema_test.rb +0 -817
  674. data/spec/integration/spec_helper.rb +0 -48
  675. data/spec/integration/timezone_test.rb +0 -86
  676. data/spec/integration/transaction_test.rb +0 -374
  677. data/spec/integration/type_test.rb +0 -133
  678. data/spec/model/association_reflection_spec.rb +0 -525
  679. data/spec/model/associations_spec.rb +0 -4426
  680. data/spec/model/base_spec.rb +0 -759
  681. data/spec/model/class_dataset_methods_spec.rb +0 -146
  682. data/spec/model/dataset_methods_spec.rb +0 -149
  683. data/spec/model/eager_loading_spec.rb +0 -2137
  684. data/spec/model/hooks_spec.rb +0 -604
  685. data/spec/model/inflector_spec.rb +0 -26
  686. data/spec/model/model_spec.rb +0 -982
  687. data/spec/model/plugins_spec.rb +0 -299
  688. data/spec/model/record_spec.rb +0 -2147
  689. data/spec/model/spec_helper.rb +0 -46
  690. data/spec/model/validations_spec.rb +0 -193
  691. data/spec/sequel_coverage.rb +0 -15
  692. data/spec/spec_config.rb +0 -10
data/bin/sequel CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen-string-literal: true
2
3
 
3
- require 'rubygems'
4
4
  require 'optparse'
5
5
 
6
6
  code = nil
7
7
  copy_databases = nil
8
8
  dump_migration = nil
9
9
  dump_schema = nil
10
+ dump_indexes = nil
10
11
  env = nil
11
12
  migrate_dir = nil
12
13
  migrate_ver = nil
@@ -83,7 +84,7 @@ options = OptionParser.new do |opts|
83
84
  end
84
85
 
85
86
  opts.on("-M", "--migrate-version VER", "migrate the database to version given") do |v|
86
- migrate_ver = Integer(v)
87
+ migrate_ver = Integer(v, 10)
87
88
  end
88
89
 
89
90
  opts.on("-N", "--no-test-connection", "do not test the connection") do
@@ -106,6 +107,11 @@ options = OptionParser.new do |opts|
106
107
  opts.on_tail("-v", "--version", "Show version") do
107
108
  show_version = true
108
109
  end
110
+
111
+ opts.on("-X", "--dump-indexes filename", "dump the index cache for all tables to the file") do |v|
112
+ dump_indexes = v
113
+ exclusive_options << :X
114
+ end
109
115
  end
110
116
  opts = options
111
117
  opts.parse!
@@ -116,26 +122,27 @@ error_proc = lambda do |msg|
116
122
  $stderr.puts(msg)
117
123
  exit 1
118
124
  end
125
+ extra_proc = lambda do
126
+ $stderr.puts("Warning: last #{ARGV.length} arguments ignored") unless ARGV.empty?
127
+ end
119
128
 
120
129
  error_proc["Error: Must specify -m if using -M"] if migrate_ver && !migrate_dir
121
130
  error_proc["Error: Cannot specify #{exclusive_options.map{|v| "-#{v}"}.join(' and ')} together"] if exclusive_options.length > 1
122
131
 
123
132
  connect_proc = lambda do |database|
124
- db = if database.nil? || database.empty?
125
- Sequel.connect('mock:///')
133
+ db_opts = {:test=>test, :loggers=>loggers}
134
+ if database.nil? || database.empty?
135
+ Sequel.connect('mock:///', db_opts)
126
136
  elsif File.exist?(database)
127
137
  require 'yaml'
128
138
  env ||= "development"
129
139
  db_config = YAML.load_file(database)
130
140
  db_config = db_config[env] || db_config[env.to_sym] || db_config
131
141
  db_config.keys.each{|k| db_config[k.to_sym] = db_config.delete(k)}
132
- Sequel.connect(db_config)
142
+ Sequel.connect(db_config, db_opts)
133
143
  else
134
- Sequel.connect(database)
144
+ Sequel.connect(database, db_opts)
135
145
  end
136
- db.loggers = loggers
137
- db.test_connection if test
138
- db
139
146
  end
140
147
 
141
148
  begin
@@ -151,32 +158,47 @@ begin
151
158
  DB = connect_proc[db]
152
159
  load_dirs.each{|d| d.is_a?(Array) ? require(d.first) : Dir["#{d}/**/*.rb"].each{|f| load(f)}}
153
160
  if migrate_dir
161
+ extra_proc.call
154
162
  Sequel.extension :migration, :core_extensions
155
163
  Sequel::Migrator.apply(DB, migrate_dir, migrate_ver)
156
164
  exit
157
165
  end
158
166
  if dump_migration
167
+ extra_proc.call
159
168
  DB.extension :schema_dumper
160
169
  puts DB.dump_schema_migration(:same_db=>dump_migration==:same_db)
161
170
  exit
162
171
  end
163
172
  if dump_schema
173
+ extra_proc.call
164
174
  DB.extension :schema_caching
165
175
  DB.tables.each{|t| DB.schema(Sequel::SQL::Identifier.new(t))}
166
176
  DB.dump_schema_cache(dump_schema)
167
177
  exit
168
178
  end
179
+ if dump_indexes
180
+ extra_proc.call
181
+ DB.extension :index_caching
182
+ DB.tables.each{|t| DB.indexes(Sequel::SQL::Identifier.new(t))}
183
+ DB.dump_index_cache(dump_indexes)
184
+ exit
185
+ end
169
186
  if copy_databases
170
187
  Sequel.extension :migration
171
188
  DB.extension :schema_dumper
172
189
 
173
190
  db2 = ARGV.shift
174
191
  error_proc["Error: Must specify database connection string or path to yaml file as second argument for database you want to copy to"] if db2.nil? || db2.empty?
192
+ extra_proc.call
175
193
  start_time = Time.now
176
194
  TO_DB = connect_proc[db2]
177
195
  same_db = DB.database_type==TO_DB.database_type
178
196
  index_opts = {:same_db=>same_db}
179
197
  index_opts[:index_names] = :namespace if !DB.global_index_namespace? && TO_DB.global_index_namespace?
198
+ if DB.database_type == :sqlite && !same_db
199
+ # SQLite integer types allows 64-bit integers
200
+ TO_DB.extension :integer64
201
+ end
180
202
 
181
203
  puts "Databases connections successful"
182
204
  schema_migration = eval(DB.dump_schema_migration(:indexes=>false, :same_db=>same_db))
@@ -225,6 +247,7 @@ begin
225
247
  exit
226
248
  end
227
249
  if code
250
+ extra_proc.call
228
251
  eval(code)
229
252
  exit
230
253
  end
@@ -1,26 +1,149 @@
1
1
  = Advanced Associations
2
2
 
3
- Sequel::Model has the most powerful and flexible associations of any ruby ORM.
3
+ Sequel::Model's association support is powerful and flexible, but it can be difficult for
4
+ new users to understand what the support enables. This guide shows off some of the more
5
+ advanced Sequel::Model association features.
4
6
 
5
- == Background: Sequel::Model association options
7
+ You should probably review the {Model Associations Basics and Options guide}[rdoc-ref:doc/association_basics.rdoc]
8
+ before reviewing this guide.
9
+
10
+ == Sequel::Model Eager Loading
11
+
12
+ Sequel::Model offers two different ways to perform eager loading, +eager+ and
13
+ +eager_graph+. +eager+ uses an SQL query per association, +eager_graph+ uses a single
14
+ SQL query containing JOINs.
15
+
16
+ Assuming the following associations:
17
+
18
+ Artist.one_to_many :albums
19
+ Album.one_to_many :tracks
20
+ Tracks.many_to_one :lyric
21
+
22
+ Let's say you wanted to load all artists and eagerly load the related albums, tracks, and lyrics.
23
+
24
+ Artist.eager(albums: {tracks: :lyric})
25
+ # 4 Queries:
26
+ # SELECT * FROM artists;
27
+ # SELECT * FROM albums WHERE (artist_id IN (...));
28
+ # SELECT * FROM tracks WHERE (album_id IN (...));
29
+ # SELECT * FROM lyrics WHERE (id IN (...));
30
+
31
+ Artist.eager_graph(albums: {tracks: :lyric})
32
+ # 1 Query:
33
+ # SELECT artists.id, artists.name, ...
34
+ # albums.id AS albums_id, albums.name AS albums_name, ...
35
+ # tracks.id AS tracks_id, tracks.name AS tracks_name, ...
36
+ # lyric.id AS lyric_id, ...
37
+ # FROM artists
38
+ # LEFT OUTER JOIN albums ON (albums.artist_id = artists.id)
39
+ # LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)
40
+ # LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id);
41
+
42
+ In general, the recommendation is to use +eager+ unless you have a reason to use +eager_graph+.
43
+ +eager_graph+ is needed when you want to reference columns in an associated table. For example,
44
+ if you want to order the loading of returned artists based on the names of the albums, you cannot
45
+ do:
46
+
47
+ Artist.eager(albums: {tracks: :lyric}).order{albums[:name]}
48
+
49
+ because the initial query Sequel will use would be:
50
+
51
+ # SELECT * FROM artists ORDER BY albums.name;
52
+
53
+ and +albums+ is not a valid qualifier in such a query. In this situation, you must use +eager_graph+:
54
+
55
+ Artist.eager_graph(albums: {tracks: :lyric}).order{albums[:name]}
56
+
57
+ Whether +eager+ or +eager_graph+ performs better is association and database dependent. If
58
+ you are concerned about performance, you should try benchmarking both cases with appropriate
59
+ data to see which performs better.
60
+
61
+ === Mixing eager and eager_graph
62
+
63
+ Sequel offers the ability to mix +eager+ and +eager_graph+ when loading results. This can
64
+ be done at the main level by calling both +eager+ and +eager_graph+ on the same dataset:
65
+
66
+ Album.eager(:artist).eager_graph(:tracks)
67
+ # 2 Queries:
68
+ # SELECT albums.id, albums.name, ...
69
+ # artist.id AS artist_id, artist.name AS artist_name, ...
70
+ # FROM albums
71
+ # LEFT OUTER JOIN artists AS artist ON (artist.id = albums.artist_id);
72
+ # SELECT * FROM artists WHERE (id IN (...));
73
+
74
+ You can also use +eager+ to load initial associations, and +eager_graph+ to load
75
+ remaining associations, by using +eager_graph+ in an eager load callback:
76
+
77
+ Artist.eager(albums: {tracks: proc{|ds| ds.eager_graph(:lyric)}})
78
+ # 3 Queries:
79
+ # SELECT * FROM artists;
80
+ # SELECT * FROM albums WHERE (artist_id IN (...));
81
+ # SELECT tracks.id, tracks.name, ...
82
+ # lyric.id AS lyric_id, ...
83
+ # FROM tracks
84
+ # LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id)
85
+ # WHERE (tracks.album_id IN (...));
86
+
87
+ Using the +eager_graph_eager+ plugin, you can use +eager_graph+ to load the
88
+ initial associations, and +eager+ to load the remaining associations. When
89
+ you call +eager_graph_eager+, you must specify the dependency chain at
90
+ which to start the eager loading via +eager+:
91
+
92
+ Artist.plugin :eager_graph_eager
93
+ Artist.eager_graph(albums: :tracks).eager_graph_eager([:albums, :tracks], :lyric)
94
+ # 2 Queries:
95
+ # SELECT artists.id, artists.name, ...
96
+ # albums.id AS albums_id, albums.name AS albums_name, ...
97
+ # tracks.id AS tracks_id, tracks.name AS tracks_name, ...
98
+ # FROM artists
99
+ # LEFT OUTER JOIN albums ON (albums.artist_id = artists.id)
100
+ # LEFT OUTER JOIN tracks ON (tracks.album_id= albums.id);
101
+ # SELECT * FROM lyrics WHERE (id IN (...));
102
+
103
+ These two approaches can also be nested, with +eager+ -> +eager_graph+ -> +eager+:
104
+
105
+ Album.plugin :eager_graph_eager
106
+ Artist.eager(albums: proc{|ds| ds.eager_graph(:tracks).eager_graph_eager([:tracks], :lyric)})
107
+ # 3 Queries:
108
+ # SELECT * FROM artists;
109
+ # SELECT albums.id, albums.name, ...
110
+ # tracks.id AS tracks_id, tracks.name AS tracks_name, ...
111
+ # FROM albums
112
+ # LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)
113
+ # WHERE (albums.artist_id IN (...));
114
+ # SELECT * FROM lyrics WHERE (id IN (...));
115
+
116
+ Or with 2 separate +eager_graph+ queries:
117
+
118
+ Artist.eager_graph(:albums).eager_graph_eager([:albums], :tracks=>proc{|ds| ds.eager_graph(:lyric)})
119
+ # 2 Queries:
120
+ # SELECT artists.id, artists.name, ...
121
+ # albums.id AS albums_id, albums.name AS albums_name, ...
122
+ # FROM artists
123
+ # LEFT OUTER JOIN albums ON (albums.artist_id = artists.id);
124
+ # SELECT tracks.id, tracks.name, ...
125
+ # lyric.id AS lyric_id, ...
126
+ # FROM tracks
127
+ # LEFT OUTER JOIN lyrics AS lyric ON (lyric.id = tracks.lyric_id)
128
+ # WHERE (tracks.album_id IN (...));
129
+
130
+ == Sequel::Model Association Loading Options
6
131
 
7
132
  There are a bunch of advanced association options that are available to
8
- handle more complex cases. First we'll go over some of
9
- the simpler ones:
133
+ handle more complex cases. First we'll go over some of the simpler ones:
10
134
 
11
135
  All associations take a block that can be used to further filter/modify the
12
- default dataset. There's also an :eager_block option if you want to use
13
- a different block when eager loading via <tt>Dataset#eager</tt>. Association blocks are
14
- useful for things like:
136
+ default dataset:
15
137
 
16
- Artist.one_to_many :gold_albums, :class=>:Album do |ds|
138
+ Artist.one_to_many :gold_albums, class: :Album do |ds|
17
139
  ds.where{copies_sold > 500000}
18
140
  end
19
141
 
20
- There are a whole bunch of options for changing how the association is eagerly
21
- loaded via <tt>Dataset#eager_graph</tt>: <tt>:graph_block</tt>, <tt>:graph_conditions</tt>,
22
- <tt>:graph_only_conditions</tt>, <tt>:graph_join_type</tt> (and <tt>:graph_join_table_*</tt> ones for
23
- JOINing to the join table in a many_to_many association).
142
+ There's also an :eager_block option if you want to use a different block when
143
+ eager loading via <tt>Dataset#eager</tt>.
144
+
145
+ There are many options for changing how the association is eagerly
146
+ loaded via <tt>Dataset#eager_graph</tt>:
24
147
 
25
148
  :graph_join_type :: The type of join to do (<tt>:inner</tt>, <tt>:left</tt>, <tt>:right</tt>)
26
149
  :graph_conditions :: Additional conditions to put on join (needs to be a
@@ -42,28 +165,23 @@ These can be used like this:
42
165
 
43
166
  # Makes Artist.eager_graph(:required_albums).all not return artists that
44
167
  # don't have any albums
45
- Artist.one_to_many :required_albums, :class=>:Album, :graph_join_type=>:inner
168
+ Artist.one_to_many :required_albums, class: :Album, graph_join_type: :inner
46
169
 
47
170
  # Makes sure all returned albums have the active flag set
48
- Artist.one_to_many :active_albums, :class=>:Album, \
49
- :graph_conditions=>{:active=>true}
171
+ Artist.one_to_many :active_albums, class: :Album, graph_conditions: {active: true}
50
172
 
51
173
  # Only returns albums that have sold more than 500,000 copies
52
- Artist.one_to_many :gold_albums, :class=>:Album, \
53
- :graph_block=>proc{|j,lj,js| Sequel.qualify(j, :copies_sold) > 500000}
174
+ Artist.one_to_many :gold_albums, class: :Album,
175
+ graph_block: proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
54
176
 
55
177
  # Handles the case where the tables are associated by a case insensitive name string
56
- Artist.one_to_many :albums, :key=>:artist_name, \
57
- :graph_only_conditions=>nil, \
58
- :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel.qualify(j, :artist_name))=>Sequel.function(:lower, Sequel.qualify(lj, :name))}}
178
+ Artist.one_to_many :albums, key: :artist_name,
179
+ graph_only_conditions: nil,
180
+ graph_block: proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>Sequel.function(:lower, Sequel[lj][:name])}}
59
181
 
60
182
  # Handles the case where both key columns have the name artist_name, and you want to use
61
183
  # a JOIN USING
62
- Artist.one_to_many :albums, :key=>:artist_name, :graph_only_conditions=>[:artist_name]
63
-
64
- Remember, using +eager_graph+ is generally only necessary when you need to
65
- filter/order based on columns in an associated table, it is recommended to
66
- use +eager+ for eager loading if possible.
184
+ Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: [:artist_name]
67
185
 
68
186
  One advantage of using +eager_graph+ is that you can easily filter/order
69
187
  on columns in an associated table on a per-query basis, using regular
@@ -73,14 +191,16 @@ ordered by the albums name, you can do:
73
191
 
74
192
  albums = Artist.
75
193
  eager_graph(:albums).
76
- where(Sequel.like(:albums__name, 'A%')).
77
- order(:albums__name).
194
+ where{Sequel.like(albums[:name], 'A%')}.
195
+ order{albums[:name]}.
78
196
  all
79
197
 
80
198
  For lazy loading (e.g. Model[1].association), the <tt>:dataset</tt> option can be used
81
199
  to specify an arbitrary dataset (one that uses different keys, multiple keys,
82
200
  joins to other tables, etc.).
83
201
 
202
+ == Custom Eager Loaders
203
+
84
204
  For eager loading via +eager+, the <tt>:eager_loader</tt> option can be used to specify
85
205
  how to eagerly load a complex association. This is an extremely powerful
86
206
  option. Though it can often be verbose (compared to other things in Sequel),
@@ -211,7 +331,7 @@ and the tracks eager loader looks like:
211
331
  Album.one_to_many :tracks, :eager_loader=>(proc do |eo_opts|
212
332
  eo_opts[:rows].each{|album| album.associations[:tracks] = []}
213
333
  id_map = eo_opts[:id_map]
214
- Track.where(:id=>id_map.keys).all do |tracks|
334
+ Track.where(:album_id=>id_map.keys).all do |track|
215
335
  if albums = id_map[track.album_id]
216
336
  albums.each do |album|
217
337
  album.associations[:tracks] << track
@@ -244,7 +364,7 @@ loading.
244
364
 
245
365
  Sequel supports specifying limits and/or offsets for associations:
246
366
 
247
- Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10
367
+ Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10
248
368
 
249
369
  For retrieving the associated objects for a single object, this just uses
250
370
  a LIMIT:
@@ -260,7 +380,7 @@ approach. Sequel has 4 separate strategies for dealing with such cases.
260
380
  The default strategy used on all databases is a UNION-based approach, which
261
381
  will submit multiple subqueries in a UNION query:
262
382
 
263
- Artist.where(:id=>[1,2]).eager(:first_10_albums).all
383
+ Artist.where(id: [1,2]).eager(:first_10_albums).all
264
384
  # SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 1) LIMIT 10) UNION ALL
265
385
  # SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 2) LIMIT 10)
266
386
 
@@ -272,9 +392,9 @@ index, you'll want to manually specify the :eager_limit_strategy option as shown
272
392
  On PostgreSQL, for *_one associations that don't use an offset, you can
273
393
  choose to use a the distinct on strategy:
274
394
 
275
- Artist.one_to_one :first_album, :class=>:Album, :order=>:release_date,
276
- :eager_limit_strategy=>:distinct_on
277
- Artist.where(:id=>[1,2]).eager(:first_album).all
395
+ Artist.one_to_one :first_album, class: :Album, order: :release_date,
396
+ eager_limit_strategy: :distinct_on
397
+ Artist.where(id: [1,2]).eager(:first_album).all
278
398
  # SELECT DISTINCT ON (albums.artist_id) *
279
399
  # FROM albums
280
400
  # WHERE (albums.artist_id IN (1, 2))
@@ -283,13 +403,13 @@ choose to use a the distinct on strategy:
283
403
  Otherwise, if the database supports window functions, you can choose to use
284
404
  the window function strategy:
285
405
 
286
- Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10,
287
- :eager_limit_strategy=>:window_function
406
+ Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10,
407
+ eager_limit_strategy: :window_function
288
408
  Artist.where(:id=>[1,2]).eager(:first_10_albums).all
289
409
  # SELECT * FROM (
290
- # SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY release_date) AS x_sequel_row_number_x
291
- # FROM tracks
292
- # WHERE (tracks.album_id IN (1, 2))
410
+ # SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
411
+ # FROM albums
412
+ # WHERE (albums.artist_id IN (1, 2))
293
413
  # ) AS t1
294
414
  # WHERE (x_sequel_row_number_x <= 10)
295
415
 
@@ -297,6 +417,29 @@ Alternatively, you can use the :ruby strategy, which will fall back to
297
417
  retrieving all records, and then will slice the resulting array to get
298
418
  the first 10 after retrieval.
299
419
 
420
+ === Dynamic Eager Loading Limits
421
+
422
+ If you need to eager load variable numbers of records (with limits that aren't
423
+ known at the time of the association definition), Sequel supports an
424
+ :eager_limit dataset option that can be defined in an eager loading callback:
425
+
426
+ Artist.one_to_many :albums
427
+ Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3)}).all
428
+ # SELECT * FROM (
429
+ # SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
430
+ # FROM albums
431
+ # WHERE (albums.artist_id IN (1, 2))
432
+ # ) AS t1
433
+ # WHERE (x_sequel_row_number_x <= 3)
434
+
435
+ You can also customize the :eager_limit_strategy on a case-by-case basis by passing in that option in the same way:
436
+
437
+ Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3, eager_limit_strategy: :ruby)}).all
438
+ # SELECT * FROM albums WHERE (albums.artist_id IN (1, 2)) ORDER BY release_date
439
+
440
+ The :eager_limit and :eager_limit_strategy options currently only work when
441
+ eager loading via #eager, not with #eager_graph.
442
+
300
443
  === Eager Loading via eager_graph_with_options
301
444
 
302
445
  When eager loading an association via eager_graph (which uses JOINs), the
@@ -310,7 +453,7 @@ eager_graph_with_options method with the :limit_strategy option.
310
453
  The :distinct_on strategy uses DISTINCT ON in a subquery and JOINs that
311
454
  subquery:
312
455
 
313
- Artist.eager_graph_with_options(:first_album, :limit_strategy=>true).all
456
+ Artist.eager_graph_with_options(:first_album, limit_strategy: :distinct_on).all
314
457
  # SELECT artists.id, artists.name, first_album.id AS first_album_id,
315
458
  # first_album.name AS first_album_name, first_album.artist_id,
316
459
  # first_album.release_date
@@ -324,7 +467,7 @@ subquery:
324
467
  The :window_function approach JOINs to a nested subquery using a window
325
468
  function:
326
469
 
327
- Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
470
+ Artist.eager_graph_with_options(:first_10_albums, limit_strategy: :window_function).all
328
471
  # SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
329
472
  # first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
330
473
  # first_10_albums.release_date
@@ -340,7 +483,7 @@ function:
340
483
  The :correlated_subquery approach JOINs to a nested subquery using a correlated
341
484
  subquery:
342
485
 
343
- Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
486
+ Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>:correlated_subquery).all
344
487
  # SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
345
488
  # first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
346
489
  # first_10_albums.release_date
@@ -357,8 +500,6 @@ subquery:
357
500
  # )
358
501
  # ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
359
502
 
360
- (SELECT * FROM tracks WHERE (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)))
361
-
362
503
  The reason that Sequel does not automatically use the :distinct_on, :window function
363
504
  or :correlated_subquery strategy for eager_graph is that it can perform much worse than the
364
505
  default of just doing the array slicing in ruby. If you are only using eager_graph to
@@ -380,7 +521,7 @@ strategy based on the database you are using, and you can override it using the
380
521
 
381
522
  The :distinct_on strategy:
382
523
 
383
- Artist.where(:first_album=>Album[1]).all
524
+ Artist.where(first_album: Album[1]).all
384
525
  # SELECT *
385
526
  # FROM artists
386
527
  # WHERE (artists.id IN (
@@ -394,7 +535,7 @@ The :distinct_on strategy:
394
535
 
395
536
  The :window_function strategy:
396
537
 
397
- Artist.where(:first_10_albums=>Album[1]).all
538
+ Artist.where(first_10_albums: Album[1]).all
398
539
  # SELECT *
399
540
  # FROM artists
400
541
  # WHERE (artists.id IN (
@@ -410,7 +551,7 @@ The :window_function strategy:
410
551
 
411
552
  The :correlated_subquery strategy:
412
553
 
413
- Artist.where(:first_10_albums=>Album[1]).all
554
+ Artist.where(first_10_albums: Album[1]).all
414
555
  # SELECT *
415
556
  # FROM artists
416
557
  # WHERE (artists.id IN (
@@ -424,11 +565,11 @@ The :correlated_subquery strategy:
424
565
  # LIMIT 1
425
566
  # )) AND (albums.id = 1))))
426
567
 
427
- Note that filtering by limited associations does not work on MySQL, as does not support
568
+ Note that filtering by limited associations does not work on MySQL, as MySQL does not support
428
569
  any of the strategies. It's also not supported when using composite keys on databases
429
570
  that don't support window functions and don't support multiple columns in IN.
430
571
 
431
- == Additional Association Types
572
+ === Additional Association Types
432
573
 
433
574
  While the above examples for limited associations showed one_to_many and one_to_one associations,
434
575
  it's just because those are the simplest examples. Sequel supports all of the same features for
@@ -436,29 +577,7 @@ many_to_many and one_through_one associations that are enabled by default, as we
436
577
  many_through_many and one_through_many associations that are added by the many_through_many
437
578
  plugin.
438
579
 
439
- == ActiveRecord associations
440
-
441
- Sequel supports all of associations that ActiveRecord supports, though some
442
- require different approaches or custom <tt>:eager_loader</tt> options.
443
-
444
- === Association callbacks
445
-
446
- Sequel supports the same callbacks that ActiveRecord does for +one_to_many+ and
447
- +many_to_many+ associations: <tt>:before_add</tt>, <tt>:before_remove</tt>, <tt>:after_add</tt>, and
448
- <tt>:after_remove</tt>. For +many_to_one+ associations and +one_to_one+ associations, Sequel
449
- supports the <tt>:before_set</tt> and <tt>:after_set</tt> callbacks. On all associations,
450
- Sequel supports <tt>:after_load</tt>, which is called after the association has been
451
- loaded.
452
-
453
- Each of these options can be a symbol specifying an instance method
454
- that takes one argument (the associated object), or a proc that takes
455
- two arguments (the current object and the associated object), or an
456
- array of symbols and procs. For <tt>:after_load</tt> with a *_to_many association,
457
- the associated object argument is an array of associated objects.
458
-
459
- If any of the before callbacks return +false+, the adding/removing
460
- does not happen and it either raises a <tt>Sequel::HookFailed</tt> (the default), or
461
- returns false (if +raise_on_save_failure+ is false).
580
+ == More advanced association examples
462
581
 
463
582
  === Association extensions
464
583
 
@@ -481,36 +600,21 @@ the model object that created the association dataset via the dataset's
481
600
  end
482
601
  end
483
602
  class Author < Sequel::Model
484
- one_to_many :authorships, :extend=>FindOrCreate
485
- end
486
- Author.first.authorships_dataset.find_or_create(:name=>'Blah', :number=>10)
487
-
488
- === <tt>has_many :through</tt> associations
489
-
490
- +many_to_many+ handles the usual case of a <tt>has_many :through</tt> with a +belongs_to+ in
491
- the associated model. It doesn't break on the case where the join table is a
492
- model table, unlike ActiveRecord's +has_and_belongs_to_many+.
493
-
494
- ActiveRecord:
495
-
496
- class Author < ActiveRecord::Base
497
- has_many :authorships
498
- has_many :books, :through => :authorships
603
+ one_to_many :authorships, extend: FindOrCreate
499
604
  end
605
+ Author.first.authorships_dataset.find_or_create(name: 'Blah', number: 10)
500
606
 
501
- class Authorship < ActiveRecord::Base
502
- belongs_to :author
503
- belongs_to :book
504
- end
607
+ === many_to_many associations through model tables
505
608
 
506
- @author = Author.find :first
507
- @author.books
508
-
509
- Sequel::Model:
609
+ The many_to_many association can be used even when the join table is a table used for a
610
+ model. The only requirement is the join table has foreign keys to both the current
611
+ model and the associated model. Anytime there is a one_to_many association from model A to
612
+ model B, and model B has a many_to_one association to model C, you can use a many_to_many
613
+ association from model A to model C.
510
614
 
511
615
  class Author < Sequel::Model
512
616
  one_to_many :authorships
513
- many_to_many :books, :join_table=>:authorships
617
+ many_to_many :books, join_table: :authorships
514
618
  end
515
619
 
516
620
  class Authorship < Sequel::Model
@@ -521,33 +625,17 @@ Sequel::Model:
521
625
  @author = Author.first
522
626
  @author.books
523
627
 
524
- If you use an association other than +belongs_to+ in the associated model, such as a +has_many+,
525
- you still use a +many_to_many+ association, but you need to use some options:
628
+ === many_to_many for three-level associations
526
629
 
527
- ActiveRecord:
528
-
529
- class Firm < ActiveRecord::Base
530
- has_many :clients
531
- has_many :invoices, :through => :clients
532
- end
533
-
534
- class Client < ActiveRecord::Base
535
- belongs_to :firm
536
- has_many :invoices
537
- end
538
-
539
- class Invoice < ActiveRecord::Base
540
- belongs_to :client
541
- has_one :firm, :through => :client
542
- end
543
-
544
- Firm.find(:first).invoices
545
-
546
- Sequel::Model:
630
+ You can even use a many_to_many association between model A and model C if model A has a
631
+ one_to_many association to model B, and model B has a one_to_many association to model C.
632
+ You just need to use the appropriate :right_key and :right_primary_key options. And in
633
+ the reverse direction from model C to model A, you can use a one_through_one association
634
+ using the :left_key and :left_primary_key options.
547
635
 
548
636
  class Firm < Sequel::Model
549
637
  one_to_many :clients
550
- many_to_many :invoices, :join_table=>:clients, :right_key=>:id, :right_primary_key=>:client_id
638
+ many_to_many :invoices, join_table: :clients, right_key: :id, right_primary_key: :client_id
551
639
  end
552
640
 
553
641
  class Client < Sequel::Model
@@ -557,12 +645,13 @@ Sequel::Model:
557
645
 
558
646
  class Invoice < Sequel::Model
559
647
  many_to_one :client
560
- one_through_one :firm, :join_table=>:clients, :left_key=>:id, :left_primary_key=>:client_id, :right_key=>:firm_id
648
+ one_through_one :firm, join_table: :clients, left_key: :id, left_primary_key: :client_id
561
649
  end
562
650
 
563
651
  Firm.first.invoices
652
+ Invoice.first.firm
564
653
 
565
- To handle cases where there are multiple join tables, use the many_through_many
654
+ To handle cases where there are multiple join tables, you can use the many_through_many
566
655
  plugin that ships with Sequel.
567
656
 
568
657
  === Polymorphic Associations
@@ -579,38 +668,19 @@ you are stuck with an existing design that uses them.
579
668
  If you must use them, look for the sequel_polymorphic external plugin, as it makes using
580
669
  polymorphic associations in Sequel about as easy as it is in ActiveRecord. However,
581
670
  here's how they can be done using Sequel's custom associations (the sequel_polymorphic
582
- plugin is just a generic version of this code):
583
-
584
- ActiveRecord:
585
-
586
- class Asset < ActiveRecord::Base
587
- belongs_to :attachable, :polymorphic => true
588
- end
589
-
590
- class Post < ActiveRecord::Base
591
- has_many :assets, :as => :attachable
592
- end
593
-
594
- class Note < ActiveRecord::Base
595
- has_many :assets, :as => :attachable
596
- end
597
-
598
- @asset.attachable = @post
599
- @asset.attachable = @note
600
-
601
- Sequel::Model:
671
+ external plugin is just a generic version of this code):
602
672
 
603
673
  class Asset < Sequel::Model
604
- many_to_one :attachable, :reciprocal=>:assets,
605
- :setter=>(proc do |attachable|
674
+ many_to_one :attachable, reciprocal: :assets,
675
+ setter: (lambda do |attachable|
606
676
  self[:attachable_id] = (attachable.pk if attachable)
607
677
  self[:attachable_type] = (attachable.class.name if attachable)
608
678
  end),
609
- :dataset=>(proc do
679
+ dataset: (proc do
610
680
  klass = attachable_type.constantize
611
681
  klass.where(klass.primary_key=>attachable_id)
612
682
  end),
613
- :eager_loader=>(proc do |eo|
683
+ eager_loader: (lambda do |eo|
614
684
  id_map = {}
615
685
  eo[:rows].each do |asset|
616
686
  asset.associations[:attachable] = nil
@@ -628,24 +698,22 @@ Sequel::Model:
628
698
  end
629
699
 
630
700
  class Post < Sequel::Model
631
- one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Post'},
632
- :adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Post')},
633
- :remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
634
- :clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
701
+ one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Post'},
702
+ adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Post')},
703
+ remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
704
+ clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
635
705
  end
636
706
 
637
707
  class Note < Sequel::Model
638
- one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Note'},
639
- :adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Note')},
640
- :remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
641
- :clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
708
+ one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Note'},
709
+ adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Note')},
710
+ remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
711
+ clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
642
712
  end
643
713
 
644
714
  @asset.attachable = @post
645
715
  @asset.attachable = @note
646
716
 
647
- == Other advanced associations
648
-
649
717
  === Joining on multiple keys
650
718
 
651
719
  Let's say you have two tables that are associated with each other with multiple
@@ -657,36 +725,36 @@ associations:
657
725
  # associated favorite track
658
726
 
659
727
  class Track < Sequel::Model
660
- many_to_one :favorite_track, :key=>[:disc_number, :number, :album_id], :primary_key=>[:disc_number, :number, :album_id]
728
+ many_to_one :favorite_track, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
661
729
  end
662
730
  class FavoriteTrack < Sequel::Model
663
- one_to_one :tracks, :key=>[:disc_number, :number, :album_id], :primary_key=>[:disc_number, :number, :album_id]
731
+ one_to_one :tracks, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
664
732
  end
665
733
 
666
- === Tree - All Ancestors and Descendents
734
+ === Tree - All Ancestors and Descendants
667
735
 
668
736
  Let's say you want to store a tree relationship in your database, it's pretty
669
737
  simple:
670
738
 
671
739
  class Node < Sequel::Model
672
- many_to_one :parent, :class=>self
673
- one_to_many :children, :key=>:parent_id, :class=>self
740
+ many_to_one :parent, class: self
741
+ one_to_many :children, key: :parent_id, class: self
674
742
  end
675
743
 
676
744
  You can easily get a node's parent with node.parent, and a node's children with
677
745
  node.children. You can even eager load the relationship up to a certain depth:
678
746
 
679
747
  # Eager load three generations of generations of children for a given node
680
- Node.filter(:id=>1).eager(:children=>{:children=>:children}).all.first
748
+ Node.where(id: 1).eager(children: {children: :children}).all.first
681
749
  # Load parents and grandparents for a group of nodes
682
- Node.filter{id < 10}.eager(:parent=>:parent).all
750
+ Node.where{id < 10}.eager(parent: :parent).all
683
751
 
684
- What if you want to get all ancestors up to the root node, or all descendents,
752
+ What if you want to get all ancestors up to the root node, or all descendants,
685
753
  without knowing the depth of the tree?
686
754
 
687
755
  class Node < Sequel::Model
688
- many_to_one :ancestors, :class=>self,
689
- :eager_loader=>(proc do |eo|
756
+ many_to_one :ancestors, class: self,
757
+ eager_loader: (lambda do |eo|
690
758
  # Handle cases where the root node has the same parent_id as primary_key
691
759
  # and also when it is NULL
692
760
  non_root_nodes = eo[:rows].reject do |n|
@@ -702,15 +770,15 @@ without knowing the depth of the tree?
702
770
  id_map = {}
703
771
  # Create an map of parent_ids to nodes that have that parent id
704
772
  non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
705
- # Doesn't cause an infinte loop, because when only the root node
773
+ # Doesn't cause an infinite loop, because when only the root node
706
774
  # is left, this is not called.
707
- Node.where(Node.primary_key=>id_map.keys).eager(:ancestors).all do |node|
775
+ Node.where(id: id_map.keys).eager(:ancestors).all do |node|
708
776
  # Populate the parent association for each node
709
777
  id_map[node.pk].each{|n| n.associations[:parent] = node}
710
778
  end
711
779
  end
712
780
  end)
713
- many_to_one :descendants, :eager_loader=>(proc do |eo|
781
+ many_to_one :descendants, eager_loader: (lambda do |eo|
714
782
  id_map = {}
715
783
  eo[:rows].each do |n|
716
784
  # Initialize an empty array of child associations for each parent node
@@ -722,7 +790,7 @@ without knowing the depth of the tree?
722
790
  # if no records are returned. Exclude id = parent_id to avoid infinite loop
723
791
  # if the root note is one of the returned records and it has parent_id = id
724
792
  # instead of parent_id = NULL.
725
- Node.where(:parent_id=>id_map.keys).exclude(:id=>:parent_id).eager(:descendants).all do |node|
793
+ Node.where(parent_id: id_map.keys).exclude(id: :parent_id).eager(:descendants).all do |node|
726
794
  # Get the parent from the identity map
727
795
  parent = id_map[node.parent_id]
728
796
  # Set the child's parent association to the parent
@@ -733,11 +801,7 @@ without knowing the depth of the tree?
733
801
  end)
734
802
  end
735
803
 
736
- Note that unlike ActiveRecord, Sequel supports common table expressions, which allows you to use recursive queries.
737
- The results are not the same as in the above case, as all descendents are stored in a single association,
738
- but all descendants can be both lazy loaded or eager loaded in a single query (assuming your database
739
- supports recursive common table expressions). Sequel ships with an +rcte_tree+ plugin that makes
740
- this easy:
804
+ Note that Sequel ships with an rcte_tree plugin that does all of the above and more:
741
805
 
742
806
  class Node < Sequel::Model
743
807
  plugin :rcte_tree
@@ -757,21 +821,21 @@ What you want to do is get all songs for a given artist, ordered by the song's
757
821
  name, with no duplicates?
758
822
 
759
823
  class Artist < Sequel::Model
760
- one_to_many :songs, :order=>:songs__name, \
761
- :dataset=>proc{Song.select_all(:songs).join(Lyric, :id=>:lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])}, \
762
- :eager_loader=>(proc do |eo|
824
+ one_to_many :songs, order: Sequel[:songs][:name],
825
+ dataset: proc{Song.select_all(:songs).join(:lyrics, id: :lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])},
826
+ eager_loader: (lambda do |eo|
763
827
  h = eo[:id_map]
764
828
  ids = h.keys
765
829
  eo[:rows].each{|r| r.associations[:songs] = []}
766
830
  Song.select_all(:songs).
767
- select_append(:lyrics__composer_id, :lyrics__arranger_id, :lyrics__vocalist_id, :lyrics__lyricist_id).
768
- join(Lyric, :id=>:lyric_id){Sequel.or(:composer_id=>ids, :arranger_id=>ids, :vocalist_id=>ids, :lyricist_id=>ids)}.
769
- order(:songs__name).all do |song|
770
- [:composer_id, :arranger_id, :vocalist_id, :lyricist_id].each do |x|
771
- recs = h[song.values.delete(x)]
772
- recs.each{|r| r.associations[:songs] << song} if recs
831
+ select_append{[lyrics[:composer_id], lyrics[:arranger_id], lyrics[:vocalist_id], lyrics[:lyricist_id]]}.
832
+ join(:lyrics, id: :lyric_id){Sequel.or(composer_id: ids, arranger_id: ids, vocalist_id: ids, lyricist_id: ids)}.
833
+ order{songs[:name]}.all do |song|
834
+ [:composer_id, :arranger_id, :vocalist_id, :lyricist_id].each do |x|
835
+ recs = h[song.values.delete(x)]
836
+ recs.each{|r| r.associations[:songs] << song} if recs
837
+ end
773
838
  end
774
- end
775
839
  eo[:rows].each{|r| r.associations[:songs].uniq!}
776
840
  end)
777
841
  end
@@ -788,11 +852,11 @@ associated tickets.
788
852
 
789
853
  class Project < Sequel::Model
790
854
  one_to_many :tickets
791
- many_to_one :ticket_hours, :read_only=>true, :key=>:id,
792
- :dataset=>proc{Ticket.where(:project_id=>id).select{sum(hours).as(hours)}},
793
- :eager_loader=>(proc do |eo|
855
+ many_to_one :ticket_hours, read_only: true, key: :id,
856
+ dataset: proc{Ticket.where(:project_id=>id).select{sum(hours).as(hours)}},
857
+ eager_loader: (lambda do |eo|
794
858
  eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
795
- Ticket.where(:project_id=>eo[:id_map].keys).
859
+ Ticket.where(project_id: eo[:id_map].keys).
796
860
  select_group(:project_id).
797
861
  select_append{sum(hours).as(hours)}.
798
862
  all do |t|
@@ -815,4 +879,4 @@ associated tickets.
815
879
  end
816
880
 
817
881
  Note that it is often better to use a sum cache instead of this approach. You can implement
818
- a sum cache using +after_create+ and +after_delete+ hooks, or preferrably using a database trigger.
882
+ a sum cache using +after_create+, +after_update+, and +after_delete+ hooks, or preferably using a database trigger.