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
@@ -2,16 +2,7 @@
2
2
 
3
3
  == Introduction
4
4
 
5
- Datasets are the primary way Sequel uses to access the database. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as objects is what gives Sequel most of its power. However, if you haven't been exposed to the dataset concept before, it can be a little disorienting. This document aims to give a basic introduction to datasets and how to use them.
6
-
7
- == What a Dataset Represents
8
-
9
- A Dataset can be thought of representing one of two concepts:
10
-
11
- * An SQL query
12
- * An abstract set of rows and some related behavior
13
-
14
- The first concept is more easily understood, so you should probably start with that assumption.
5
+ Datasets are the primary way Sequel uses to access the database. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as datasets is what gives Sequel most of its power. This document aims to give a basic introduction to datasets and how to use them.
15
6
 
16
7
  == Basics
17
8
 
@@ -22,9 +13,9 @@ The most basic dataset is the simple selection of all columns in a table:
22
13
 
23
14
  Here, DB represents your Sequel::Database object, and ds is your dataset, with the SQL query it represents below it.
24
15
 
25
- One of the core dataset ideas that should be understood is that datasets use a functional style of modification, in which methods called on the dataset return modified copies of the dataset, they don't modify the dataset themselves:
16
+ One of the core dataset ideas that should be understood is that datasets are frozen and use a functional style of modification, in which methods called on the dataset return modified copies of the dataset, they don't modify the dataset themselves:
26
17
 
27
- ds2 = ds.where(:id=>1)
18
+ ds2 = ds.where(id: 1)
28
19
  ds2
29
20
  # SELECT * FROM posts WHERE id = 1
30
21
  ds
@@ -35,7 +26,7 @@ Note how ds itself is not modified. This is because ds.where returns a modified
35
26
  # Thread safe:
36
27
  100.times do |i|
37
28
  Thread.new do
38
- ds.where(:id=>i).first
29
+ ds.where(id: i).first
39
30
  end
40
31
  end
41
32
 
@@ -48,7 +39,7 @@ Thread safety you don't really need to worry about, but chainability is core to
48
39
  Another important thing to realize is that dataset methods that return modified datasets do not execute the dataset's code on the database. Only dataset methods that return or yield results will execute the code on the database:
49
40
 
50
41
  # No SQL queries sent:
51
- ds3 = ds.select(:id, :name).order(:name).filter{id < 100}
42
+ ds3 = ds.select(:id, :name).order(:name).where{id < 100}
52
43
 
53
44
  # Until you call a method that returns results
54
45
  results = ds3.all
@@ -56,12 +47,12 @@ Another important thing to realize is that dataset methods that return modified
56
47
  One important consequence of this API style is that if you use a method chain that includes both methods that return modified copies and a method that executes the SQL, the method that executes the SQL should generally be the last method in the chain:
57
48
 
58
49
  # Good
59
- ds.select(:id, :name).order(:name).filter{id < 100}.all
50
+ ds.select(:id, :name).order(:name).where{id < 100}.all
60
51
 
61
52
  # Bad
62
- ds.all.select(:id, :name).order(:name).filter{id < 100}
53
+ ds.all.select(:id, :name).order(:name).where{id < 100}
63
54
 
64
- This is because all will return an array of hashes, and select, order, and filter are dataset methods, not array methods.
55
+ This is because all will return an array of hashes, and +select+, +order+, and +where+ are dataset methods, not array methods.
65
56
 
66
57
  == Methods
67
58
 
@@ -77,7 +68,7 @@ Most dataset methods fall into this category, which can be further broken down b
77
68
  SELECT:: select, select_all, select_append, select_group, select_more
78
69
  FROM:: from, from_self
79
70
  JOIN:: join, left_join, right_join, full_join, natural_join, natural_left_join, natural_right_join, natural_full_join, cross_join, inner_join, left_outer_join, right_outer_join, full_outer_join, join_table
80
- WHERE:: where, filter, exclude, exclude_where, and, or, grep, invert, unfiltered
71
+ WHERE:: where, filter, exclude, or, grep, invert, unfiltered
81
72
  GROUP:: group, group_by, group_and_count, group_append, select_group, ungrouped
82
73
  HAVING:: having, exclude_having, invert, unfiltered
83
74
  ORDER:: order, order_by, order_append, order_prepend, order_more, reverse, reverse_order, unordered
@@ -85,16 +76,16 @@ LIMIT/OFFSET:: limit, offset, unlimited
85
76
  compounds:: union, intersect, except
86
77
  locking:: for_update, lock_style
87
78
  common table expressions:: with, with_recursive
88
- other:: clone, distinct, naked, qualify, server, with_sql
79
+ other:: distinct, naked, qualify, server, with_sql
89
80
 
90
81
  === Methods that execute code on the database
91
82
 
92
83
  Most other dataset methods commonly used will execute the dataset's SQL on the database:
93
84
 
94
- SELECT (All Records):: all, each, map, to_hash, to_hash_groups, select_map, select_order_map, select_hash, select_hash_groups
85
+ SELECT (All Records):: all, each, map, as_hash, to_hash_groups, select_map, select_order_map, select_hash, select_hash_groups
95
86
  SELECT (First Record):: first, last, [], single_record
96
87
  SELECT (Single Value):: get, single_value
97
- SELECT (Aggregates):: count, avg, max, min, sum, range, interval
88
+ SELECT (Aggregates):: count, avg, max, min, sum
98
89
  INSERT:: insert, <<, import, multi_insert
99
90
  UPDATE:: update
100
91
  DELETE:: delete
@@ -1,203 +1,216 @@
1
1
  = Dataset Filtering
2
2
 
3
- Sequel is very flexibile when it comes to filtering records. You can specify your conditions as a custom string, as a string with parameters, as a hash of values to compare against, or as ruby code that Sequel translates into SQL expressions.
4
-
5
- == Filtering using a custom filter string
6
-
7
- If you wish to write your SQL by hand, you can just supply it to the dataset's #where method:
8
-
9
- items.where('x < 10').sql
10
- #=> "SELECT * FROM items WHERE x < 10"
11
-
12
- In order to prevent SQL injection, you can replace literal values with question marks and supply the values as additional arguments:
13
-
14
- items.where('category = ?', 'ruby').sql
15
- #=> "SELECT * FROM items WHERE category = 'ruby'"
16
-
17
- You can also use placeholders with :placeholder and a hash of placeholder values:
18
-
19
- items.where('category = :category', :category=>'ruby').sql
20
- #=> "SELECT * FROM items WHERE category = 'ruby'"
21
-
22
- === Specifying SQL functions
23
-
24
- Sequel also allows you to specify functions by using the Sequel.function method:
25
-
26
- items.literal(Sequel.function(:avg, :price)) #=> "avg(price)"
27
-
28
- If you are specifying a filter/selection/order, you can use a virtual row block:
29
-
30
- items.select{avg(price)}
31
-
32
- You can also use the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc] and the +sql_function+ method:
33
-
34
- :avg.sql_function(:price)
3
+ Sequel is very flexible when it comes to filtering records. You can specify your conditions as a hash of values to compare against, or as ruby code that Sequel translates into SQL expressions, or as an SQL code fragment (with optional parameters), .
35
4
 
36
5
  == Filtering using a hash
37
6
 
38
7
  If you just need to compare records against values, you can supply a hash:
39
8
 
40
- items.where(:category => 'ruby').sql
41
- #=> "SELECT * FROM items WHERE (category = 'ruby')"
9
+ items.where(category: 'ruby').sql
10
+ # "SELECT * FROM items WHERE (category = 'ruby')"
42
11
 
43
12
  Sequel can check for null values:
44
13
 
45
- items.where(:category => nil).sql
46
- #=> "SELECT * FROM items WHERE (category IS NULL)"
14
+ items.where(category: nil).sql
15
+ # "SELECT * FROM items WHERE (category IS NULL)"
47
16
 
48
17
  Or compare two columns:
49
18
 
50
- items.where(:x => :some_table__y).sql
51
- #=> "SELECT * FROM items WHERE (x = some_table.y)"
19
+ items.where{{x: some_table[:y]}}.sql
20
+ # "SELECT * FROM items WHERE (x = some_table.y)"
52
21
 
53
22
  And also compare against multiple values:
54
23
 
55
- items.where(:category => ['ruby', 'perl']).sql
56
- #=> "SELECT * FROM items WHERE (category IN ('ruby', 'perl'))"
24
+ items.where(category: ['ruby', 'perl']).sql
25
+ # "SELECT * FROM items WHERE (category IN ('ruby', 'perl'))"
57
26
 
58
27
  Ranges (both inclusive and exclusive) can also be used:
59
28
 
60
- items.where(:price => 100..200).sql
61
- #=> "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
29
+ items.where(price: 100..200).sql
30
+ # "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
62
31
 
63
- items.where(:price => 100...200).sql
64
- #=> "SELECT * FROM items WHERE (price >= 100 AND price < 200)"
32
+ items.where(price: 100...200).sql
33
+ # "SELECT * FROM items WHERE (price >= 100 AND price < 200)"
65
34
 
66
35
  == Filtering using an array
67
36
 
68
37
  If you need to select multiple items from a dataset, you can supply an array:
69
38
 
70
- item_array = [1, 38, 47, 99]
71
- items.where(:id => item_array).sql
72
- #=> "SELECT * FROM items WHERE (id IN (1, 38, 47, 99))"
39
+ items.where(id: [1, 38, 47, 99]).sql
40
+ # "SELECT * FROM items WHERE (id IN (1, 38, 47, 99))"
73
41
 
74
42
  == Filtering using expressions
75
43
 
76
- You can pass a block to where, which is evaluated in a special context:
44
+ You can pass a block to where (referred to as a virtual row block), which is evaluated in a special context:
77
45
 
78
46
  items.where{price * 2 < 50}.sql
79
- #=> "SELECT * FROM items WHERE ((price * 2) < 50)
47
+ # "SELECT * FROM items WHERE ((price * 2) < 50)
80
48
 
81
49
  This works for the standard inequality and arithmetic operators:
82
50
 
83
51
  items.where{price + 100 < 200}.sql
84
- #=> "SELECT * FROM items WHERE ((price + 100) < 200)
52
+ # "SELECT * FROM items WHERE ((price + 100) < 200)
85
53
 
86
54
  items.where{price - 100 > 200}.sql
87
- #=> "SELECT * FROM items WHERE ((price - 100) > 200)
55
+ # "SELECT * FROM items WHERE ((price - 100) > 200)
88
56
 
89
57
  items.where{price * 100 <= 200}.sql
90
- #=> "SELECT * FROM items WHERE ((price * 100) <= 200)
58
+ # "SELECT * FROM items WHERE ((price * 100) <= 200)
91
59
 
92
60
  items.where{price / 100 >= 200}.sql
93
- #=> "SELECT * FROM items WHERE ((price / 100) >= 200)
61
+ # "SELECT * FROM items WHERE ((price / 100) >= 200)
62
+
63
+ items.where{price ** 2 >= 200}.sql
64
+ # "SELECT * FROM items WHERE (power(price, 2) >= 200)
94
65
 
95
66
  You use the overloaded bitwise and (&) and or (|) operators to combine expressions:
96
67
 
97
68
  items.where{(price + 100 < 200) & (price * 100 <= 200)}.sql
98
- #=> "SELECT * FROM items WHERE (((price + 100) < 200) AND ((price * 100) <= 200))
69
+ # "SELECT * FROM items WHERE (((price + 100) < 200) AND ((price * 100) <= 200))
99
70
 
100
71
  items.where{(price - 100 > 200) | (price / 100 >= 200)}.sql
101
- #=> "SELECT * FROM items WHERE (((price - 100) > 200) OR ((price / 100) >= 200))
72
+ # "SELECT * FROM items WHERE (((price - 100) > 200) OR ((price / 100) >= 200))
102
73
 
103
74
  To filter by equality, you use the standard hash, which can be combined with other expressions using Sequel.& and Sequel.|:
104
75
 
105
- items.where{Sequel.&({:category => 'ruby'}, (price + 100 < 200))}.sql
106
- #=> "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
76
+ items.where{Sequel.&({category: 'ruby'}, (price + 100 < 200))}.sql
77
+ # "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
107
78
 
108
79
  You can also use the =~ operator:
109
80
 
110
81
  items.where{(category =~ 'ruby') & (price + 100 < 200)}.sql
111
- #=> "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
82
+ # "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
112
83
 
113
84
  This works with other hash values, such as arrays and ranges:
114
85
 
115
- items.where{Sequel.|({:category => ['ruby', 'other']}, (price - 100 > 200))}.sql
116
- #=> "SELECT * FROM items WHERE ((category IN ('ruby', 'other')) OR ((price - 100) <= 200))"
86
+ items.where{Sequel.|({category: ['ruby', 'other']}, (price - 100 > 200))}.sql
87
+ # "SELECT * FROM items WHERE ((category IN ('ruby', 'other')) OR ((price - 100) > 200))"
117
88
 
118
89
  items.where{(price =~ (100..200)) & :active}.sql
119
- #=> "SELECT * FROM items WHERE ((price >= 100 AND price <= 200) AND active)"
90
+ # "SELECT * FROM items WHERE ((price >= 100 AND price <= 200) AND active)"
91
+
92
+ == Filtering using a custom filter string
93
+
94
+ If you wish to include an SQL fragment as part of a filter, you need to wrap it with +Sequel.lit+ to mark that it is literal SQL code, and pass it to the #where method:
95
+
96
+ items.where(Sequel.lit('x < 10')).sql
97
+ # "SELECT * FROM items WHERE x < 10"
98
+
99
+ In order to prevent SQL injection, you can replace literal values with question marks and supply the values as additional arguments to +Sequel.lit+:
100
+
101
+ items.where(Sequel.lit('category = ?', 'ruby')).sql
102
+ # "SELECT * FROM items WHERE category = 'ruby'"
103
+
104
+ You can also use placeholders with :placeholder and a hash of placeholder values:
105
+
106
+ items.where(Sequel.lit('category = :category', category: "ruby")).sql
107
+ # "SELECT * FROM items WHERE category = 'ruby'"
108
+
109
+ In order to combine AND and OR together, you have a few options:
110
+
111
+ items.where(category: nil).or(category: "ruby")
112
+ # SELECT * FROM items WHERE (category IS NULL) OR (category = 'ruby')
113
+
114
+ This won't work if you add other conditions:
115
+
116
+ items.where(name: "Programming in Ruby").where(category: nil).or(category: 'ruby')
117
+ # SELECT * FROM items WHERE ((name = 'Programming in Ruby') AND (category IS NULL)) OR (category = 'ruby')
118
+
119
+ The OR applies globally and not locally. To fix this, use & and |:
120
+
121
+ items.where(Sequel[name: "Programming in Ruby"] & (Sequel[category: nil] | Sequel[category: "ruby"]))
122
+ # SELECT * FROM items WHERE ((name = 'Programming in Ruby') AND ((category IS NULL) OR (category = 'ruby')))
123
+
124
+ === Specifying SQL functions
125
+
126
+ Sequel also allows you to specify functions by using the Sequel.function method:
127
+
128
+ items.literal(Sequel.function(:avg, :price)) # "avg(price)"
129
+
130
+ If you are specifying a filter/selection/order, you can use a virtual row block:
131
+
132
+ items.select{avg(price)}
120
133
 
121
134
  === Negating conditions
122
135
 
123
136
  You can use the exclude method to exclude whole conditions:
124
137
 
125
- items.exclude(:category => 'ruby').sql
126
- #=> "SELECT * FROM items WHERE (category != 'ruby')"
138
+ items.exclude(category: 'ruby').sql
139
+ # "SELECT * FROM items WHERE (category != 'ruby')"
127
140
 
128
141
  items.exclude(:active).sql
129
- #=> "SELECT * FROM items WHERE NOT active"
142
+ # "SELECT * FROM items WHERE NOT active"
130
143
 
131
144
  items.exclude{price / 100 >= 200}.sql
132
- #=> "SELECT * FROM items WHERE ((price / 100) < 200)
145
+ # "SELECT * FROM items WHERE ((price / 100) < 200)
133
146
 
134
147
  To exclude only parts of conditions, you can use when in combination with Sequel.~ or the ~ method on Sequel expressions:
135
148
 
136
- items.where{Sequel.&(Sequel.~(:category => 'ruby'), (price + 100 < 200))}.sql
137
- #=> "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
149
+ items.where{Sequel.&(Sequel.~(category: 'ruby'), (price + 100 < 200))}.sql
150
+ # "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
138
151
 
139
152
  items.where{~(category =~ 'ruby') & (price + 100 < 200)}.sql
140
- #=> "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
153
+ # "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
141
154
 
142
- On Ruby 1.9+, you can also use the !~ method:
155
+ You can also use the !~ method:
143
156
 
144
157
  items.where{(category !~ 'ruby') & (price + 100 < 200)}.sql
145
- #=> "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
158
+ # "SELECT * FROM items WHERE ((category != 'ruby') AND ((price + 100) < 200))"
146
159
 
147
160
  === Comparing against column references
148
161
 
149
162
  You can also compare against other columns:
150
163
 
151
164
  items.where{credit > debit}.sql
152
- #=> "SELECT * FROM items WHERE (credit > debit)
165
+ # "SELECT * FROM items WHERE (credit > debit)
153
166
 
154
167
  Or against SQL functions:
155
168
 
156
169
  items.where{price - 100 < max(price)}.sql
157
- #=> "SELECT * FROM items WHERE ((price - 100) < max(price))"
170
+ # "SELECT * FROM items WHERE ((price - 100) < max(price))"
158
171
 
159
172
  == String search functions
160
173
 
161
174
  You can search SQL strings in a case sensitive manner using the Sequel.like method:
162
175
 
163
176
  items.where(Sequel.like(:name, 'Acme%')).sql
164
- #=> "SELECT * FROM items WHERE (name LIKE 'Acme%' ESCAPE '\')"
177
+ # "SELECT * FROM items WHERE (name LIKE 'Acme%' ESCAPE '\')"
165
178
 
166
179
  You can search SQL strings in a case insensitive manner using the Sequel.ilike method:
167
180
 
168
181
  items.where(Sequel.ilike(:name, 'Acme%')).sql
169
- #=> "SELECT * FROM items WHERE (name ILIKE 'Acme%' ESCAPE '\')"
182
+ # "SELECT * FROM items WHERE (name ILIKE 'Acme%' ESCAPE '\')"
170
183
 
171
- You can specify a Regexp as a like argument, but this will probably only work
184
+ You can specify a Regexp as a hash value (or like argument), but this will probably only work
172
185
  on PostgreSQL and MySQL:
173
186
 
174
- items.where(Sequel.like(:name, /Acme.*/)).sql
175
- #=> "SELECT * FROM items WHERE (name ~ 'Acme.*')"
187
+ items.where(name: /Acme.*/).sql
188
+ # "SELECT * FROM items WHERE (name ~ 'Acme.*')"
176
189
 
177
190
  Like can also take more than one argument:
178
191
 
179
192
  items.where(Sequel.like(:name, 'Acme%', /Beta.*/)).sql
180
- #=> "SELECT * FROM items WHERE ((name LIKE 'Acme%' ESCAPE '\') OR (name ~ 'Beta.*'))"
193
+ # "SELECT * FROM items WHERE ((name LIKE 'Acme%' ESCAPE '\') OR (name ~ 'Beta.*'))"
181
194
 
182
195
  == String concatenation
183
196
 
184
197
  You can concatenate SQL strings using Sequel.join:
185
198
 
186
199
  items.where(Sequel.join([:name, :comment]).like('Jo%nice%')).sql
187
- #=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Jo%nice%' ESCAPE '\')"
200
+ # "SELECT * FROM items WHERE ((name || comment) LIKE 'Jo%nice%' ESCAPE '\')"
188
201
 
189
202
  Sequel.join also takes a join argument:
190
203
 
191
- items.filter(Sequel.join([:name, :comment], ':').like('John:%nice%')).sql
192
- #=> "SELECT * FROM items WHERE ((name || ':' || comment) LIKE 'John:%nice%' ESCAPE '\')"
204
+ items.where(Sequel.join([:name, :comment], ':').like('John:%nice%')).sql
205
+ # "SELECT * FROM items WHERE ((name || ':' || comment) LIKE 'John:%nice%' ESCAPE '\')"
193
206
 
194
207
  == Filtering using sub-queries
195
208
 
196
- One of the best features of Sequel is the ability to use datasets as sub-queries. Sub-queries can be very useful for filtering records, and many times provide a simpler alternative to table joins. Sub-queries can be used in all forms of filters:
209
+ Datasets can be used as subqueries. Subqueries can be very useful for filtering records, and many times provide a simpler alternative to table joins. Subqueries can be used in all forms of filters:
197
210
 
198
211
  refs = consumer_refs.where(:logged_in).select(:consumer_id)
199
- consumers.where(:id => refs).sql
200
- #=> "SELECT * FROM consumers WHERE (id IN (SELECT consumer_id FROM consumer_refs WHERE logged_in))"
212
+ consumers.where(id: refs).sql
213
+ # "SELECT * FROM consumers WHERE (id IN (SELECT consumer_id FROM consumer_refs WHERE logged_in))"
201
214
 
202
215
  Note that if you are checking for the inclusion of a single column in a subselect, the subselect should only select a single column.
203
216
 
@@ -205,5 +218,5 @@ Note that if you are checking for the inclusion of a single column in a subselec
205
218
 
206
219
  By default, if you chain calls to +where+, the conditions get ANDed together. If you want to use an OR for a condition, you can use the +or+ method:
207
220
 
208
- items.where(:name=>'Food').or(:vendor=>1).sql
209
- #=> "SELECT * FROM items WHERE ((name = 'Food') OR (vendor = 1))"
221
+ items.where(name: 'Food').or(vendor: 1).sql
222
+ # "SELECT * FROM items WHERE ((name = 'Food') OR (vendor = 1))"
@@ -10,7 +10,7 @@ Global extensions are loaded via <tt>Sequel.extension</tt>:
10
10
 
11
11
  Sequel.extension :named_timezones
12
12
 
13
- What this does is require the relevent extension from <tt>sequel/extensions/named_timezones</tt> somewhere in the ruby path. Actually, that is all that does. Global extensions are just a simpler, consistent way to require code that modifies Sequel.
13
+ All this does is require the relevent extension from <tt>sequel/extensions/named_timezones</tt> somewhere in the ruby path. Global extensions are just a simpler, consistent way to require code that modifies Sequel.
14
14
 
15
15
  == Database Extensions
16
16
 
@@ -28,18 +28,11 @@ All future <tt>Sequel::Database</tt> instances created afterward will then autom
28
28
 
29
29
  == Dataset Extensions
30
30
 
31
- Dataset extensions should add or modify the behavior of a single <tt>Sequel::Dataset</tt> instance. They are loaded via <tt>Sequel::Dataset#extension</tt> or <tt>Sequel::Dataset#extension!</tt>. <tt>Sequel::Dataset#extension</tt> returns a modifies copy of the dataset that includes the extension (similar to how most dataset query methods work):
31
+ Dataset extensions should add or modify the behavior of a single <tt>Sequel::Dataset</tt> instance. They are loaded via <tt>Sequel::Dataset#extension</tt>. <tt>Sequel::Dataset#extension</tt> returns a modifies copy of the dataset that includes the extension (similar to how most dataset query methods work):
32
32
 
33
33
  ds = DB[:a].extension(:columns_introspection)
34
34
 
35
- <tt>Sequel::Dataset#extension!</tt> modifies a dataset to include the extension (similar to how dataset mutation methods work):
36
-
37
- ds = DB[:a]
38
- ds.extension!(:columns_introspection)
39
-
40
- It is recommended you only use <tt>Sequel::Dataset#extension!</tt> if you have good reasons to.
41
-
42
- The first thing loading a Dataset extension does is load the relevent extension globally. Similar to Database extensions, loading a Dataset extension globally should not affect state other than maybe adding a module. After loading the extension globally, it modifies the related <tt>Sequel::Dataset</tt> instance to modify its behavior.
35
+ The first thing loading a Dataset extension does is load the relevent extension globally. Similar to Database extensions, loading a Dataset extension globally should not affect state other than maybe adding a module. After loading the extension globally, it returned a modified copy of the <tt>Sequel::Dataset</tt> with the extension loaded into it.
43
36
 
44
37
  If you want to load an extension into all future datasets for a given <tt>Sequel::Database</tt> instance, you can also load it as a Database extension:
45
38
 
@@ -1,33 +1,42 @@
1
1
  = Sequel::Model Mass Assignment
2
2
 
3
- Most Model methods that take a hash of attribute keys and values, including <tt>Model.new</tt>, <tt>Model.create</tt>, <tt>Model#set</tt> and <tt>Model#update</tt> are subject to Sequel's mass assignment rules.
4
- When you pass a hash to these methods, each key has an <tt>=</tt> appended to it (the setter method), and if the setter method exists and access to it is not restricted, Sequel will call the setter method with the hash value.
5
- By default, there are two types of setter methods that are restricted.
3
+ Most Model methods that take a hash of attribute keys and values, including <tt>Model.new</tt>,
4
+ <tt>Model.create</tt>, <tt>Model#set</tt> and <tt>Model#update</tt> are subject to Sequel's mass assignment rules.
5
+
6
+ If you have an instance of a plain Sequel::Model class:
7
+
8
+ class Post < Sequel::Model
9
+ end
10
+ post = Post.new
11
+
12
+ and you call a mass assignment method with a hash:
13
+
14
+ post.set(title: 'T', body: 'B')
15
+
16
+ the mass assignment method will go through each key in the hash, append <tt>=</tt> to it to determine the
17
+ setter method, and if the setter method is defined and access to it is not restricted, Sequel will call the
18
+ setter method with the hash value. So if we assume that the posts table has title and body columns, what
19
+ the above mass assignment call actually does is:
20
+
21
+ post.title=('T')
22
+ post.body=('B')
23
+
24
+ By default, there are two types of setter methods that are restricted.
6
25
  The first is methods like <tt>typecast_on_assignment=</tt> and <tt>==</tt>, which don't affect columns.
7
26
  These methods cannot be enabled for mass assignment.
8
27
  The second is primary key setters.
9
- To enable use of primary key setters, you need to call +unrestrict_primary_key+ for that model:
10
-
11
- Post.unrestrict_primary_key
12
28
 
13
- Since mass assignment by default allows modification of all column values except for primary key columns, it can be a security risk in some cases.
14
- Sequel has multiple ways of securing mass assignment.
15
- The first way is using +set_allowed_columns+:
29
+ So if you do:
16
30
 
17
- Post.set_allowed_columns :title, :body, :category
31
+ post = Post.new(id: 1)
18
32
 
19
- This explicitly sets which methods are allowed (<tt>title=</tt>, <tt>body=</tt>, and <tt>category=</tt>), all other methods will not be allowed.
20
- This method is useful in simple applications where the same columns are allowed in all cases, but not appropriate when different columns are allowed in different scenarios (e.g. admin access vs. user access).
21
- To handle cases where different columns are allowed in different cases, you can use +set_only+ or +update_only+:
33
+ Sequel will raise a Sequel::MassAssignmentRestriction exception, since by default setting the primary key is not allowed.
22
34
 
23
- # user case
24
- post.set_only(params[:post], :title, :body)
25
- # admin case
26
- post.set_only(params[:post], :title, :body, :deleted)
35
+ To enable use of primary key setters, you need to call +unrestrict_primary_key+ for that model:
27
36
 
28
- In this case, only the <tt>title=</tt> and <tt>body=</tt> methods will be allowed in the mass assignment in the user case, and only <tt>title=</tt>, <tt>body=</tt>, and <tt>deleted=</tt> will be allowed for mass assignment in the admin case.
37
+ Post.unrestrict_primary_key
29
38
 
30
- By default, if an invalid setter method call is attempted, Sequel raises a <tt>Sequel::Error</tt> exception. You can have Sequel silently ignore invalid calls by doing:
39
+ If you want to change mass assignment so it ignores attempts to access restricted setter methods, you can do:
31
40
 
32
41
  # Global default
33
42
  Sequel::Model.strict_param_setting = false
@@ -36,20 +45,54 @@ By default, if an invalid setter method call is attempted, Sequel raises a <tt>S
36
45
  # Instance level
37
46
  post.strict_param_setting = false
38
47
 
39
- In addition to +set_only+ and +update_only+, Sequel also has +set_fields+ and +update_fields+ methods, and these may be a better mass assignment choice for most users.
40
- These methods take two arguments, the attributes hash as the first argument, and a single array of valid field names as the second argument:
48
+ Since mass assignment by default allows modification of all column values except for primary key columns, it can be a security risk in some cases.
49
+ If you are dealing with untrusted input, you are generally going to want to restrict what should be updated.
50
+
51
+ Sequel has <tt>Model#set_fields</tt> and <tt>Model#update_fields</tt> methods, which are designed to be used with untrused input.
52
+ These methods take two arguments, the untrusted hash as the first argument, and a trusted array of field names as the second argument:
53
+
54
+ post.set_fields({title: 'T', body: 'B'}, [:title, :body])
55
+
56
+ Instead of looking at every key in the untrusted hash, +set_fields+ will iterate over the trusted field names, looking each up in the hash, and
57
+ calling the setter method appropriately with the result. +set_fields+ basically translates the above method call to:
58
+
59
+ post.title=('T')
60
+ post.body=('B')
61
+
62
+ By using this method, you can be sure that the mass assignment method only sets the fields you expect it to set.
63
+
64
+ Note that if one of the fields does not exist in the hash:
65
+
66
+ post.set_fields({title: 'T'}, [:title, :body])
41
67
 
42
- post.set_fields(params[:post], [:title, :body])
68
+ +set_fields+ will set the value to nil (the default hash value) by default, with behavior equivalent to:
43
69
 
44
- +set_fields+ and +update_fields+ differ in implementation from +set_only+ and +update_only+.
45
- With +set_only+ and +update_only+, the hash is iterated over and it checks each method call attempt to see if it is valid.
46
- With +set_fields+ and +update_fields+, the array is iterated over, and it just looks up the value in the hash and calls the appropriate setter method.
70
+ post.title=('T')
71
+ post.body=(nil)
72
+
73
+ You can use the :missing option to +set_fields+ to change the behavior:
74
+
75
+ post.set_fields({title: 'T'}, [:title, :body], missing: :skip)
76
+ # post.title=('T') # only
77
+
78
+ post.set_fields({title: 'T'}, [:title, :body], missing: :raise)
79
+ # raises Sequel::Error
80
+
81
+ If you want to set a model level default for the +set_fields+ options, you can use the +default_set_fields_options+ class accessor:
82
+
83
+ # Global default
84
+ Sequel::Model.default_set_fields_options[:missing] = :skip
85
+ # Class level
86
+ Post.default_set_fields_options[:missing] = :skip
47
87
 
48
- +set_fields+ and +update_fields+ are designed for the case where you are expecting specific fields in the input, and want to ignore the other fields.
49
- They work great for things like HTML forms where the form fields are static.
50
- +set_only+ and +update_only+ are designed for cases where you are not sure what fields are going to be present in the input, but still want to make sure only certain setter methods can be called.
51
- They work great for flexible APIs.
88
+ Here's a table describing Sequel's default mass assignment methods:
52
89
 
53
- +set_fields+ and +update_fields+ take an optional argument hash, and currently handles the :missing option. With <tt>:missing=>:skip</tt>, +set_fields+ and +update_fields+ will just skip missing entries in the hash, allowing them to be used in flexible APIs. With <tt>:missing=>:raise</tt>, +set_fields+ and +update_fields+ will raise an error if one of the entries in the hash is missing, instead of just assigning the value to nil or whatever the hash's default value is. That allows stricter checks, similar to the :strict_param_checking setting for the default mass assignment methods. You can use the <tt>Model.default_set_fields_options=</tt> method to set the default options to use for +set_fields+ and +update_fields+ on a global or per-model basis.
90
+ Model.new(hash) :: Creates a new model instance, then calls Model#set(hash)
91
+ Model.create(hash) :: Calls Model.new(hash).save
92
+ Model#set(hash) :: Calls related setter method (unless access is restricted) for each key in the hash, then returns self
93
+ Model#update(hash) :: Calls set(hash).save_changes
94
+ Model#set_fields(hash, columns, options) :: For each column in columns, looks up related entry in hash, and calls the related setter method
95
+ Model#update_fields(hash, columns, options) :: Calls set_fields(hash, columns, options).save_changes
54
96
 
55
- In all of the mass assignment cases, methods starting with +set+ will set the attributes without saving the object, while methods starting with +update+ will set the attributes and then save the changes to the object.
97
+ For backwards compatibility, Sequel also ships with a whitelist_security and blacklist_security plugins that offer additional mass assignment
98
+ methods, but it is recommended to use +set_fields+ or +update_fields+ for untrusted input, and the other methods for trusted input.