sequel 4.49.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (477) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -0
  3. data/README.rdoc +195 -136
  4. data/Rakefile +26 -42
  5. data/bin/sequel +3 -5
  6. data/doc/advanced_associations.rdoc +86 -163
  7. data/doc/association_basics.rdoc +197 -274
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +66 -43
  10. data/doc/code_order.rdoc +1 -8
  11. data/doc/core_extensions.rdoc +81 -56
  12. data/doc/dataset_basics.rdoc +8 -17
  13. data/doc/dataset_filtering.rdoc +81 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/mass_assignment.rdoc +73 -30
  16. data/doc/migration.rdoc +19 -36
  17. data/doc/model_dataset_method_design.rdoc +14 -17
  18. data/doc/model_hooks.rdoc +15 -25
  19. data/doc/model_plugins.rdoc +10 -10
  20. data/doc/mssql_stored_procedures.rdoc +3 -3
  21. data/doc/object_model.rdoc +52 -70
  22. data/doc/opening_databases.rdoc +39 -32
  23. data/doc/postgresql.rdoc +48 -38
  24. data/doc/prepared_statements.rdoc +27 -22
  25. data/doc/querying.rdoc +173 -150
  26. data/doc/reflection.rdoc +5 -6
  27. data/doc/release_notes/5.0.0.txt +159 -0
  28. data/doc/schema_modification.rdoc +63 -60
  29. data/doc/security.rdoc +97 -88
  30. data/doc/sharding.rdoc +43 -30
  31. data/doc/sql.rdoc +53 -65
  32. data/doc/testing.rdoc +3 -5
  33. data/doc/thread_safety.rdoc +2 -4
  34. data/doc/transactions.rdoc +18 -17
  35. data/doc/validations.rdoc +48 -45
  36. data/doc/virtual_rows.rdoc +87 -115
  37. data/lib/sequel.rb +1 -1
  38. data/lib/sequel/adapters/ado.rb +9 -25
  39. data/lib/sequel/adapters/ado/access.rb +7 -13
  40. data/lib/sequel/adapters/ado/mssql.rb +2 -9
  41. data/lib/sequel/adapters/amalgalite.rb +3 -18
  42. data/lib/sequel/adapters/ibmdb.rb +9 -45
  43. data/lib/sequel/adapters/jdbc.rb +13 -73
  44. data/lib/sequel/adapters/jdbc/db2.rb +8 -37
  45. data/lib/sequel/adapters/jdbc/derby.rb +4 -50
  46. data/lib/sequel/adapters/jdbc/h2.rb +4 -25
  47. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -26
  48. data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
  49. data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
  50. data/lib/sequel/adapters/jdbc/mysql.rb +1 -15
  51. data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
  52. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -31
  53. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
  54. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
  55. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
  56. data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
  57. data/lib/sequel/adapters/mock.rb +4 -30
  58. data/lib/sequel/adapters/mysql.rb +7 -44
  59. data/lib/sequel/adapters/mysql2.rb +5 -23
  60. data/lib/sequel/adapters/odbc.rb +0 -19
  61. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  62. data/lib/sequel/adapters/odbc/mssql.rb +4 -12
  63. data/lib/sequel/adapters/odbc/oracle.rb +1 -1
  64. data/lib/sequel/adapters/oracle.rb +7 -13
  65. data/lib/sequel/adapters/postgres.rb +13 -57
  66. data/lib/sequel/adapters/postgresql.rb +1 -1
  67. data/lib/sequel/adapters/shared/access.rb +11 -51
  68. data/lib/sequel/adapters/shared/db2.rb +3 -61
  69. data/lib/sequel/adapters/shared/mssql.rb +21 -157
  70. data/lib/sequel/adapters/shared/mysql.rb +23 -224
  71. data/lib/sequel/adapters/shared/oracle.rb +13 -41
  72. data/lib/sequel/adapters/shared/postgres.rb +44 -259
  73. data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
  74. data/lib/sequel/adapters/shared/sqlite.rb +12 -101
  75. data/lib/sequel/adapters/sqlanywhere.rb +4 -23
  76. data/lib/sequel/adapters/sqlite.rb +2 -19
  77. data/lib/sequel/adapters/tinytds.rb +5 -15
  78. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  79. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -4
  80. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
  81. data/lib/sequel/adapters/utils/replace.rb +0 -5
  82. data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
  83. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
  84. data/lib/sequel/ast_transformer.rb +3 -94
  85. data/lib/sequel/connection_pool.rb +26 -28
  86. data/lib/sequel/connection_pool/sharded_single.rb +1 -4
  87. data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
  88. data/lib/sequel/connection_pool/single.rb +0 -2
  89. data/lib/sequel/connection_pool/threaded.rb +94 -110
  90. data/lib/sequel/core.rb +42 -101
  91. data/lib/sequel/database.rb +12 -2
  92. data/lib/sequel/database/connecting.rb +23 -60
  93. data/lib/sequel/database/dataset.rb +6 -9
  94. data/lib/sequel/database/dataset_defaults.rb +4 -48
  95. data/lib/sequel/database/features.rb +5 -4
  96. data/lib/sequel/database/logging.rb +2 -9
  97. data/lib/sequel/database/misc.rb +23 -55
  98. data/lib/sequel/database/query.rb +8 -13
  99. data/lib/sequel/database/schema_generator.rb +89 -64
  100. data/lib/sequel/database/schema_methods.rb +61 -79
  101. data/lib/sequel/database/transactions.rb +4 -24
  102. data/lib/sequel/dataset.rb +18 -10
  103. data/lib/sequel/dataset/actions.rb +53 -107
  104. data/lib/sequel/dataset/dataset_module.rb +3 -15
  105. data/lib/sequel/dataset/features.rb +30 -30
  106. data/lib/sequel/dataset/graph.rb +40 -49
  107. data/lib/sequel/dataset/misc.rb +12 -37
  108. data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
  109. data/lib/sequel/dataset/prepared_statements.rb +23 -51
  110. data/lib/sequel/dataset/query.rb +71 -155
  111. data/lib/sequel/dataset/sql.rb +30 -225
  112. data/lib/sequel/deprecated.rb +18 -27
  113. data/lib/sequel/exceptions.rb +1 -17
  114. data/lib/sequel/extensions/_model_pg_row.rb +0 -7
  115. data/lib/sequel/extensions/_pretty_table.rb +1 -3
  116. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  117. data/lib/sequel/extensions/connection_expiration.rb +1 -1
  118. data/lib/sequel/extensions/connection_validator.rb +1 -1
  119. data/lib/sequel/extensions/constraint_validations.rb +11 -11
  120. data/lib/sequel/extensions/core_extensions.rb +39 -49
  121. data/lib/sequel/extensions/core_refinements.rb +39 -45
  122. data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
  123. data/lib/sequel/extensions/date_arithmetic.rb +7 -7
  124. data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
  125. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  126. data/lib/sequel/extensions/eval_inspect.rb +4 -11
  127. data/lib/sequel/extensions/freeze_datasets.rb +1 -69
  128. data/lib/sequel/extensions/from_block.rb +1 -35
  129. data/lib/sequel/extensions/graph_each.rb +2 -2
  130. data/lib/sequel/extensions/identifier_mangling.rb +9 -19
  131. data/lib/sequel/extensions/implicit_subquery.rb +2 -2
  132. data/lib/sequel/extensions/inflector.rb +4 -4
  133. data/lib/sequel/extensions/migration.rb +23 -40
  134. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
  135. data/lib/sequel/extensions/null_dataset.rb +2 -8
  136. data/lib/sequel/extensions/pagination.rb +1 -17
  137. data/lib/sequel/extensions/pg_array.rb +20 -189
  138. data/lib/sequel/extensions/pg_hstore.rb +11 -50
  139. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  140. data/lib/sequel/extensions/pg_inet.rb +2 -15
  141. data/lib/sequel/extensions/pg_interval.rb +1 -20
  142. data/lib/sequel/extensions/pg_json.rb +7 -27
  143. data/lib/sequel/extensions/pg_loose_count.rb +1 -1
  144. data/lib/sequel/extensions/pg_range.rb +6 -121
  145. data/lib/sequel/extensions/pg_range_ops.rb +1 -3
  146. data/lib/sequel/extensions/pg_row.rb +5 -77
  147. data/lib/sequel/extensions/pg_row_ops.rb +2 -13
  148. data/lib/sequel/extensions/query.rb +3 -4
  149. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  150. data/lib/sequel/extensions/schema_dumper.rb +13 -13
  151. data/lib/sequel/extensions/select_remove.rb +3 -3
  152. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  153. data/lib/sequel/extensions/sql_comments.rb +2 -2
  154. data/lib/sequel/extensions/string_agg.rb +11 -8
  155. data/lib/sequel/extensions/symbol_aref.rb +6 -20
  156. data/lib/sequel/model.rb +27 -62
  157. data/lib/sequel/model/associations.rb +128 -131
  158. data/lib/sequel/model/base.rb +171 -711
  159. data/lib/sequel/model/default_inflections.rb +1 -1
  160. data/lib/sequel/model/errors.rb +0 -3
  161. data/lib/sequel/model/exceptions.rb +2 -6
  162. data/lib/sequel/model/inflections.rb +1 -26
  163. data/lib/sequel/model/plugins.rb +1 -0
  164. data/lib/sequel/plugins/active_model.rb +2 -5
  165. data/lib/sequel/plugins/association_dependencies.rb +15 -15
  166. data/lib/sequel/plugins/association_pks.rb +14 -28
  167. data/lib/sequel/plugins/association_proxies.rb +6 -7
  168. data/lib/sequel/plugins/auto_validations.rb +4 -4
  169. data/lib/sequel/plugins/before_after_save.rb +0 -43
  170. data/lib/sequel/plugins/blacklist_security.rb +9 -8
  171. data/lib/sequel/plugins/boolean_readers.rb +3 -3
  172. data/lib/sequel/plugins/boolean_subsets.rb +2 -2
  173. data/lib/sequel/plugins/caching.rb +5 -5
  174. data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
  175. data/lib/sequel/plugins/column_conflicts.rb +2 -2
  176. data/lib/sequel/plugins/column_select.rb +2 -2
  177. data/lib/sequel/plugins/composition.rb +15 -24
  178. data/lib/sequel/plugins/constraint_validations.rb +4 -3
  179. data/lib/sequel/plugins/csv_serializer.rb +13 -20
  180. data/lib/sequel/plugins/dataset_associations.rb +2 -2
  181. data/lib/sequel/plugins/def_dataset_method.rb +5 -5
  182. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  183. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  184. data/lib/sequel/plugins/finder.rb +16 -10
  185. data/lib/sequel/plugins/force_encoding.rb +1 -7
  186. data/lib/sequel/plugins/hook_class_methods.rb +4 -106
  187. data/lib/sequel/plugins/input_transformer.rb +10 -11
  188. data/lib/sequel/plugins/insert_returning_select.rb +1 -9
  189. data/lib/sequel/plugins/instance_filters.rb +5 -5
  190. data/lib/sequel/plugins/instance_hooks.rb +7 -52
  191. data/lib/sequel/plugins/inverted_subsets.rb +3 -1
  192. data/lib/sequel/plugins/json_serializer.rb +19 -19
  193. data/lib/sequel/plugins/lazy_attributes.rb +1 -10
  194. data/lib/sequel/plugins/list.rb +6 -6
  195. data/lib/sequel/plugins/many_through_many.rb +11 -8
  196. data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
  197. data/lib/sequel/plugins/nested_attributes.rb +18 -31
  198. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  199. data/lib/sequel/plugins/pg_array_associations.rb +8 -2
  200. data/lib/sequel/plugins/pg_row.rb +2 -11
  201. data/lib/sequel/plugins/prepared_statements.rb +13 -66
  202. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  203. data/lib/sequel/plugins/rcte_tree.rb +7 -7
  204. data/lib/sequel/plugins/serialization.rb +15 -33
  205. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  206. data/lib/sequel/plugins/sharding.rb +2 -8
  207. data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
  208. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  209. data/lib/sequel/plugins/static_cache.rb +8 -9
  210. data/lib/sequel/plugins/string_stripper.rb +3 -3
  211. data/lib/sequel/plugins/subclasses.rb +1 -1
  212. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  213. data/lib/sequel/plugins/table_select.rb +2 -2
  214. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  215. data/lib/sequel/plugins/timestamps.rb +6 -7
  216. data/lib/sequel/plugins/touch.rb +4 -8
  217. data/lib/sequel/plugins/tree.rb +3 -3
  218. data/lib/sequel/plugins/typecast_on_load.rb +2 -2
  219. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  220. data/lib/sequel/plugins/update_or_create.rb +3 -3
  221. data/lib/sequel/plugins/update_refresh.rb +3 -3
  222. data/lib/sequel/plugins/uuid.rb +7 -11
  223. data/lib/sequel/plugins/validation_class_methods.rb +10 -9
  224. data/lib/sequel/plugins/validation_contexts.rb +4 -4
  225. data/lib/sequel/plugins/validation_helpers.rb +26 -25
  226. data/lib/sequel/plugins/whitelist_security.rb +13 -9
  227. data/lib/sequel/plugins/xml_serializer.rb +24 -25
  228. data/lib/sequel/sql.rb +145 -276
  229. data/lib/sequel/timezones.rb +8 -22
  230. data/lib/sequel/version.rb +2 -2
  231. data/spec/adapter_spec.rb +1 -1
  232. data/spec/adapters/db2_spec.rb +2 -103
  233. data/spec/adapters/mssql_spec.rb +89 -68
  234. data/spec/adapters/mysql_spec.rb +101 -480
  235. data/spec/adapters/oracle_spec.rb +1 -9
  236. data/spec/adapters/postgres_spec.rb +312 -565
  237. data/spec/adapters/spec_helper.rb +12 -31
  238. data/spec/adapters/sqlanywhere_spec.rb +2 -77
  239. data/spec/adapters/sqlite_spec.rb +8 -146
  240. data/spec/bin_spec.rb +11 -16
  241. data/spec/core/connection_pool_spec.rb +173 -74
  242. data/spec/core/database_spec.rb +64 -244
  243. data/spec/core/dataset_spec.rb +81 -415
  244. data/spec/core/deprecated_spec.rb +3 -3
  245. data/spec/core/expression_filters_spec.rb +37 -144
  246. data/spec/core/mock_adapter_spec.rb +176 -4
  247. data/spec/core/object_graph_spec.rb +11 -60
  248. data/spec/core/placeholder_literalizer_spec.rb +1 -14
  249. data/spec/core/schema_generator_spec.rb +51 -40
  250. data/spec/core/schema_spec.rb +74 -77
  251. data/spec/core/spec_helper.rb +6 -24
  252. data/spec/core/version_spec.rb +1 -1
  253. data/spec/core_extensions_spec.rb +7 -83
  254. data/spec/core_model_spec.rb +2 -2
  255. data/spec/deprecation_helper.rb +2 -14
  256. data/spec/extensions/accessed_columns_spec.rb +1 -1
  257. data/spec/extensions/active_model_spec.rb +3 -3
  258. data/spec/extensions/after_initialize_spec.rb +1 -1
  259. data/spec/extensions/arbitrary_servers_spec.rb +2 -2
  260. data/spec/extensions/association_dependencies_spec.rb +1 -1
  261. data/spec/extensions/association_pks_spec.rb +4 -59
  262. data/spec/extensions/association_proxies_spec.rb +1 -1
  263. data/spec/extensions/auto_literal_strings_spec.rb +1 -12
  264. data/spec/extensions/auto_validations_spec.rb +1 -1
  265. data/spec/extensions/blacklist_security_spec.rb +1 -1
  266. data/spec/extensions/blank_spec.rb +1 -1
  267. data/spec/extensions/boolean_readers_spec.rb +1 -1
  268. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  269. data/spec/extensions/caching_spec.rb +1 -1
  270. data/spec/extensions/class_table_inheritance_spec.rb +35 -1086
  271. data/spec/extensions/column_conflicts_spec.rb +1 -1
  272. data/spec/extensions/column_select_spec.rb +4 -4
  273. data/spec/extensions/columns_introspection_spec.rb +1 -1
  274. data/spec/extensions/columns_updated_spec.rb +1 -1
  275. data/spec/extensions/composition_spec.rb +1 -7
  276. data/spec/extensions/connection_expiration_spec.rb +3 -3
  277. data/spec/extensions/connection_validator_spec.rb +3 -3
  278. data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
  279. data/spec/extensions/constraint_validations_spec.rb +1 -1
  280. data/spec/extensions/core_refinements_spec.rb +1 -3
  281. data/spec/extensions/csv_serializer_spec.rb +4 -9
  282. data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
  283. data/spec/extensions/dataset_associations_spec.rb +2 -1
  284. data/spec/extensions/dataset_source_alias_spec.rb +1 -1
  285. data/spec/extensions/date_arithmetic_spec.rb +3 -3
  286. data/spec/extensions/def_dataset_method_spec.rb +1 -1
  287. data/spec/extensions/defaults_setter_spec.rb +2 -2
  288. data/spec/extensions/delay_add_association_spec.rb +8 -9
  289. data/spec/extensions/dirty_spec.rb +1 -1
  290. data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
  291. data/spec/extensions/eager_each_spec.rb +2 -2
  292. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  293. data/spec/extensions/error_splitter_spec.rb +1 -1
  294. data/spec/extensions/error_sql_spec.rb +1 -1
  295. data/spec/extensions/eval_inspect_spec.rb +1 -1
  296. data/spec/extensions/finder_spec.rb +1 -1
  297. data/spec/extensions/force_encoding_spec.rb +2 -5
  298. data/spec/extensions/freeze_datasets_spec.rb +1 -1
  299. data/spec/extensions/graph_each_spec.rb +5 -5
  300. data/spec/extensions/hook_class_methods_spec.rb +1 -194
  301. data/spec/extensions/identifier_mangling_spec.rb +17 -170
  302. data/spec/extensions/implicit_subquery_spec.rb +1 -5
  303. data/spec/extensions/inflector_spec.rb +1 -1
  304. data/spec/extensions/input_transformer_spec.rb +7 -2
  305. data/spec/extensions/insert_returning_select_spec.rb +1 -1
  306. data/spec/extensions/instance_filters_spec.rb +1 -1
  307. data/spec/extensions/instance_hooks_spec.rb +1 -95
  308. data/spec/extensions/inverted_subsets_spec.rb +1 -1
  309. data/spec/extensions/json_serializer_spec.rb +1 -1
  310. data/spec/extensions/lazy_attributes_spec.rb +1 -7
  311. data/spec/extensions/list_spec.rb +1 -1
  312. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  313. data/spec/extensions/many_through_many_spec.rb +1 -1
  314. data/spec/extensions/migration_spec.rb +2 -2
  315. data/spec/extensions/modification_detection_spec.rb +1 -1
  316. data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
  317. data/spec/extensions/named_timezones_spec.rb +3 -3
  318. data/spec/extensions/nested_attributes_spec.rb +1 -29
  319. data/spec/extensions/null_dataset_spec.rb +1 -11
  320. data/spec/extensions/optimistic_locking_spec.rb +1 -1
  321. data/spec/extensions/pagination_spec.rb +1 -1
  322. data/spec/extensions/pg_array_associations_spec.rb +4 -1
  323. data/spec/extensions/pg_array_ops_spec.rb +1 -1
  324. data/spec/extensions/pg_array_spec.rb +3 -48
  325. data/spec/extensions/pg_enum_spec.rb +1 -1
  326. data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
  327. data/spec/extensions/pg_hstore_spec.rb +23 -32
  328. data/spec/extensions/pg_inet_ops_spec.rb +1 -1
  329. data/spec/extensions/pg_inet_spec.rb +1 -14
  330. data/spec/extensions/pg_interval_spec.rb +3 -13
  331. data/spec/extensions/pg_json_ops_spec.rb +1 -1
  332. data/spec/extensions/pg_json_spec.rb +1 -13
  333. data/spec/extensions/pg_loose_count_spec.rb +1 -1
  334. data/spec/extensions/pg_range_ops_spec.rb +1 -1
  335. data/spec/extensions/pg_range_spec.rb +3 -88
  336. data/spec/extensions/pg_row_ops_spec.rb +1 -1
  337. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  338. data/spec/extensions/pg_row_spec.rb +1 -44
  339. data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
  340. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  341. data/spec/extensions/prepared_statements_spec.rb +13 -48
  342. data/spec/extensions/pretty_table_spec.rb +1 -1
  343. data/spec/extensions/query_spec.rb +1 -12
  344. data/spec/extensions/rcte_tree_spec.rb +1 -1
  345. data/spec/extensions/round_timestamps_spec.rb +1 -5
  346. data/spec/extensions/s_spec.rb +1 -1
  347. data/spec/extensions/schema_caching_spec.rb +1 -1
  348. data/spec/extensions/schema_dumper_spec.rb +1 -1
  349. data/spec/extensions/select_remove_spec.rb +1 -1
  350. data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
  351. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  352. data/spec/extensions/serialization_spec.rb +2 -14
  353. data/spec/extensions/server_block_spec.rb +1 -1
  354. data/spec/extensions/server_logging_spec.rb +2 -2
  355. data/spec/extensions/sharding_spec.rb +1 -1
  356. data/spec/extensions/shared_caching_spec.rb +1 -28
  357. data/spec/extensions/single_table_inheritance_spec.rb +2 -5
  358. data/spec/extensions/singular_table_names_spec.rb +1 -1
  359. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  360. data/spec/extensions/spec_helper.rb +5 -27
  361. data/spec/extensions/split_array_nil_spec.rb +1 -1
  362. data/spec/extensions/split_values_spec.rb +1 -1
  363. data/spec/extensions/sql_comments_spec.rb +1 -1
  364. data/spec/extensions/sql_expr_spec.rb +1 -1
  365. data/spec/extensions/static_cache_spec.rb +1 -1
  366. data/spec/extensions/string_agg_spec.rb +2 -2
  367. data/spec/extensions/string_date_time_spec.rb +1 -1
  368. data/spec/extensions/string_stripper_spec.rb +1 -1
  369. data/spec/extensions/subclasses_spec.rb +1 -1
  370. data/spec/extensions/subset_conditions_spec.rb +1 -1
  371. data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
  372. data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
  373. data/spec/extensions/table_select_spec.rb +4 -4
  374. data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
  375. data/spec/extensions/thread_local_timezones_spec.rb +1 -1
  376. data/spec/extensions/timestamps_spec.rb +3 -3
  377. data/spec/extensions/to_dot_spec.rb +1 -1
  378. data/spec/extensions/touch_spec.rb +1 -1
  379. data/spec/extensions/tree_spec.rb +1 -1
  380. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  381. data/spec/extensions/unlimited_update_spec.rb +1 -1
  382. data/spec/extensions/update_or_create_spec.rb +1 -1
  383. data/spec/extensions/update_primary_key_spec.rb +4 -3
  384. data/spec/extensions/update_refresh_spec.rb +1 -1
  385. data/spec/extensions/uuid_spec.rb +10 -12
  386. data/spec/extensions/validate_associated_spec.rb +1 -1
  387. data/spec/extensions/validation_class_methods_spec.rb +3 -3
  388. data/spec/extensions/validation_contexts_spec.rb +1 -1
  389. data/spec/extensions/validation_helpers_spec.rb +10 -44
  390. data/spec/extensions/whitelist_security_spec.rb +5 -5
  391. data/spec/extensions/xml_serializer_spec.rb +3 -3
  392. data/spec/guards_helper.rb +2 -1
  393. data/spec/integration/associations_test.rb +1 -23
  394. data/spec/integration/database_test.rb +7 -7
  395. data/spec/integration/dataset_test.rb +5 -47
  396. data/spec/integration/eager_loader_test.rb +1 -1
  397. data/spec/integration/migrator_test.rb +1 -1
  398. data/spec/integration/model_test.rb +4 -82
  399. data/spec/integration/plugin_test.rb +6 -22
  400. data/spec/integration/prepared_statement_test.rb +8 -88
  401. data/spec/integration/schema_test.rb +6 -6
  402. data/spec/integration/spec_helper.rb +13 -21
  403. data/spec/integration/timezone_test.rb +5 -5
  404. data/spec/integration/transaction_test.rb +3 -55
  405. data/spec/integration/type_test.rb +9 -9
  406. data/spec/model/association_reflection_spec.rb +24 -9
  407. data/spec/model/associations_spec.rb +124 -303
  408. data/spec/model/base_spec.rb +18 -137
  409. data/spec/model/class_dataset_methods_spec.rb +2 -20
  410. data/spec/model/dataset_methods_spec.rb +1 -20
  411. data/spec/model/eager_loading_spec.rb +17 -11
  412. data/spec/model/hooks_spec.rb +5 -300
  413. data/spec/model/inflector_spec.rb +1 -1
  414. data/spec/model/model_spec.rb +15 -320
  415. data/spec/model/plugins_spec.rb +2 -16
  416. data/spec/model/record_spec.rb +29 -121
  417. data/spec/model/spec_helper.rb +5 -15
  418. data/spec/model/validations_spec.rb +1 -1
  419. data/spec/sequel_warning.rb +1 -12
  420. metadata +8 -64
  421. data/doc/active_record.rdoc +0 -927
  422. data/lib/sequel/adapters/cubrid.rb +0 -160
  423. data/lib/sequel/adapters/do.rb +0 -166
  424. data/lib/sequel/adapters/do/mysql.rb +0 -69
  425. data/lib/sequel/adapters/do/postgres.rb +0 -46
  426. data/lib/sequel/adapters/do/sqlite3.rb +0 -41
  427. data/lib/sequel/adapters/jdbc/as400.rb +0 -92
  428. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
  429. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
  430. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
  431. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
  432. data/lib/sequel/adapters/odbc/progress.rb +0 -12
  433. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  434. data/lib/sequel/adapters/shared/firebird.rb +0 -261
  435. data/lib/sequel/adapters/shared/informix.rb +0 -63
  436. data/lib/sequel/adapters/shared/progress.rb +0 -40
  437. data/lib/sequel/adapters/swift.rb +0 -169
  438. data/lib/sequel/adapters/swift/mysql.rb +0 -50
  439. data/lib/sequel/adapters/swift/postgres.rb +0 -49
  440. data/lib/sequel/adapters/swift/sqlite.rb +0 -48
  441. data/lib/sequel/adapters/utils/pg_types.rb +0 -4
  442. data/lib/sequel/dataset/mutation.rb +0 -98
  443. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
  444. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
  445. data/lib/sequel/extensions/filter_having.rb +0 -65
  446. data/lib/sequel/extensions/hash_aliases.rb +0 -51
  447. data/lib/sequel/extensions/meta_def.rb +0 -37
  448. data/lib/sequel/extensions/query_literals.rb +0 -86
  449. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
  450. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
  451. data/lib/sequel/extensions/set_overrides.rb +0 -82
  452. data/lib/sequel/no_core_ext.rb +0 -4
  453. data/lib/sequel/plugins/association_autoreloading.rb +0 -11
  454. data/lib/sequel/plugins/identifier_columns.rb +0 -49
  455. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
  456. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
  457. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
  458. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
  459. data/lib/sequel/plugins/schema.rb +0 -84
  460. data/lib/sequel/plugins/scissors.rb +0 -37
  461. data/spec/core/dataset_mutation_spec.rb +0 -253
  462. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
  463. data/spec/extensions/before_after_save_spec.rb +0 -40
  464. data/spec/extensions/filter_having_spec.rb +0 -42
  465. data/spec/extensions/from_block_spec.rb +0 -21
  466. data/spec/extensions/hash_aliases_spec.rb +0 -26
  467. data/spec/extensions/identifier_columns_spec.rb +0 -19
  468. data/spec/extensions/meta_def_spec.rb +0 -35
  469. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
  470. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
  471. data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
  472. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
  473. data/spec/extensions/query_literals_spec.rb +0 -185
  474. data/spec/extensions/schema_spec.rb +0 -123
  475. data/spec/extensions/scissors_spec.rb +0 -27
  476. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
  477. data/spec/extensions/set_overrides_spec.rb +0 -75
@@ -16,14 +16,11 @@ as it never calls eval on a string that is derived from user input.
16
16
  However, some Sequel methods used for creating methods via metaprogramming
17
17
  could conceivably be abused to do so:
18
18
 
19
- * Sequel::Schema::CreateTableGenerator.add_type_method
20
- * Sequel::Dataset.def_mutation_method
21
19
  * Sequel::Dataset.def_sql_method
22
- * Sequel::Model::Plugins.def_dataset_methods
23
- * Sequel.def_adapter_method (private)
24
- * Sequel::SQL::Expression.to_s_method (private)
25
- * Sequel::Plugins::HookClassMethods::ClassMethods#add_hook_type
20
+ * Sequel::JDBC.load_driver
26
21
  * Sequel::Plugins.def_dataset_methods
22
+ * Sequel::Dataset.prepared_statements_module (private)
23
+ * Sequel::SQL::Expression.to_s_method (private)
27
24
 
28
25
  As long as you don't call those with user input, you should not be
29
26
  vulnerable to code execution.
@@ -48,6 +45,9 @@ There are basically two kinds of possible SQL injections in Sequel:
48
45
  Some Sequel methods are designed to execute raw SQL strings, including:
49
46
 
50
47
  * Sequel::Database#execute
48
+ * Sequel::Database#execute_ddl
49
+ * Sequel::Database#execute_dui
50
+ * Sequel::Database#execute_insert
51
51
  * Sequel::Database#run
52
52
  * Sequel::Database#<<
53
53
  * Sequel::Dataset#fetch_rows
@@ -61,9 +61,12 @@ Some Sequel methods are designed to execute raw SQL strings, including:
61
61
 
62
62
  Here are some examples of use:
63
63
 
64
+ DB.execute 'SQL'
65
+ DB.execute_ddl 'SQL'
66
+ DB.execute_dui 'SQL'
67
+ DB.execute_insert 'SQL'
64
68
  DB.run 'SQL'
65
69
  DB << 'SQL'
66
- DB.execute 'SQL'
67
70
  DB.fetch_rows('SQL'){|row| }
68
71
  DB.dataset.with_sql_all('SQL')
69
72
  DB.dataset.with_sql_delete('SQL')
@@ -102,19 +105,16 @@ With these methods you should use placeholders, in which case Sequel automatical
102
105
 
103
106
  Sequel generally treats ruby strings as SQL strings (escaping them correctly), and
104
107
  not as raw SQL. However, you can convert a ruby string to a literal string, and
105
- Sequel will then treat it as raw SQL. This is typically done through String#lit
106
- if the {core_extensions}[rdoc-ref:doc/core_extensions.rdoc] are in use,
107
- or Sequel.lit[rdoc-ref:Sequel::SQL::Builders#lit] if they are not in use.
108
+ Sequel will then treat it as raw SQL. This is typically done through
109
+ Sequel.lit[rdoc-ref:Sequel::SQL::Builders#lit].
108
110
 
109
- 'a'.lit
110
111
  Sequel.lit('a')
111
112
 
112
- Using String#lit or Sequel.lit[rdoc-ref:Sequel::SQL::Builders#lit] to turn a ruby string into a literal string results
113
+ Using Sequel.lit[rdoc-ref:Sequel::SQL::Builders#lit] to turn a ruby string into a literal string results
113
114
  in SQL injection if the string is derived from user input. With both of these
114
115
  methods, the strings can contain placeholders, which you can use to safely include
115
116
  user input inside a literal string:
116
117
 
117
- 'a = ?'.lit(params[:user_id].to_s)
118
118
  Sequel.lit('a = ?', params[:user_id].to_s)
119
119
 
120
120
  Even though they have similar names, note that Sequel::Database#literal operates very differently from
@@ -132,91 +132,107 @@ a ruby string as raw SQL. For example:
132
132
 
133
133
  ==== SQL Filter Fragments
134
134
 
135
- The most common way to use raw SQL with Sequel is in filters:
135
+ Starting in Sequel 5, Sequel does not automatically convert plain strings to
136
+ literal strings in typical code. Instead, you can use Sequel.lit to
137
+ create literal strings:
136
138
 
137
- DB[:table].where("name > 'M'")
139
+ Sequel.lit("name > 'A'")
138
140
 
139
- If a filter method is passed a string as the first argument, it treats the rest of
140
- the arguments (if any) as placeholders to the string. So you should never do:
141
+ To safely include user input as part of an SQL filter fragment, use Sequel.lit
142
+ with placeholders:
141
143
 
142
- DB[:table].where("name > #{params[:id].to_s}") # SQL Injection!
144
+ DB[:table].where(Sequel.lit("name > ?", params[:id].to_s)) # Safe
143
145
 
144
- Instead, you should use a placeholder:
146
+ Be careful to never call Sequel.lit where the first argument is derived from
147
+ user input.
145
148
 
146
- DB[:table].where("name > ?", params[:id].to_s) # Safe
147
-
148
- Note that for that type of query, Sequel generally encourages the following form:
149
+ There are a few uncommon cases where Sequel will still convert
150
+ plain strings to literal strings.
149
151
 
150
- DB[:table].where{|o| o.name > params[:id].to_s} # Safe
152
+ ==== SQL Fragment passed to Dataset#lock_style and Model#lock!
151
153
 
152
- Sequel's DSL supports a wide variety of SQL concepts, so it's possible to
153
- code most applications without ever using raw SQL.
154
+ The Sequel::Dataset#lock_style and Sequel::Model#lock! methods also treat
155
+ an input string as SQL code. This method should not be called with user input.
154
156
 
155
- A large number of dataset methods ultimately pass down their arguments to a filter
156
- method, even some you may not expect, so you should be careful. At least the
157
- following methods pass their arguments to a filter method:
157
+ DB[:table].lock_style(params[:id]) # SQL injection!
158
+ Album.first.lock!(params[:id]) # SQL injection!
159
+
160
+ ==== SQL Type Names
161
+
162
+ In general, most places where Sequel needs to use an SQL type that should
163
+ be specified by the user, it allows you to use a ruby string, and that
164
+ string is used verbatim as the SQL type. You should not use user input
165
+ for type strings.
166
+
167
+ DB[:table].select(Sequel.cast(:a, params[:id])) # SQL injection!
168
+
169
+ ==== SQL Function Names
170
+
171
+ In most cases, Sequel does not quote SQL function names. You should not use
172
+ user input for function names.
173
+
174
+ DB[:table].select(Sequel.function(params[:id])) # SQL injection!
175
+
176
+ ==== auto_literal_strings extension
177
+
178
+ If the auto_literal_strings extension is used for backwards compatibility,
179
+ then Sequel will treat plain strings as literal strings if they are used
180
+ as the first argument to a filtering method. This can lead to SQL
181
+ injection:
182
+
183
+ DB[:table].where("name > #{params[:id].to_s}")
184
+ # SQL injection when using auto_literal_strings extension
185
+
186
+ If you are using the auto_literal_strings extension, you need to be very careful,
187
+ as the following methods will treat a plain string given as the first arguments
188
+ as a literal strings:
158
189
 
159
190
  * Sequel::Dataset#where
160
191
  * Sequel::Dataset#having
161
192
  * Sequel::Dataset#filter
162
193
  * Sequel::Dataset#exclude
163
- * Sequel::Dataset#exclude_where
164
194
  * Sequel::Dataset#exclude_having
165
- * Sequel::Dataset#and
166
195
  * Sequel::Dataset#or
167
196
  * Sequel::Dataset#first
168
197
  * Sequel::Dataset#last
169
198
  * Sequel::Dataset#[]
170
199
 
171
- The Model.find[rdoc-ref:Sequel::Model::ClassMethods#find] and Model.find_or_create[rdoc-ref:Sequel::Model::ClassMethods#find_or_create]
172
- class methods also call down to the filter methods.
200
+ Even stuff that looks like it may be safe isn't:
173
201
 
174
- The no_auto_string_literals extension can be used to remove the default support
175
- for plain strings as literal strings in filter methods.
202
+ DB[:table].first(params[:num_rows])
203
+ # SQL injection when using auto_literal_strings extension
176
204
 
177
- ==== SQL Fragment passed to Dataset#update
205
+ The Model.find[rdoc-ref:Sequel::Model::ClassMethods#find] and
206
+ Model.find_or_create[rdoc-ref:Sequel::Model::ClassMethods#find_or_create]
207
+ class methods also will treat string arguments as literal strings if the
208
+ auto_literal_strings extension is used:
178
209
 
179
- Similar to the filter methods, Sequel::Dataset#update also treats a
180
- string argument as raw SQL:
210
+ Album.find(params[:id])
211
+ # SQL injection when using auto_literal_strings extension
212
+
213
+ Similar to the filter methods, the auto_literal_strings extension
214
+ also makes Sequel::Dataset#update treats a string argument as raw SQL:
181
215
 
182
216
  DB[:table].update("column = 1")
183
217
 
184
218
  So you should not do:
185
219
 
186
- DB[:table].update("column = #{params[:value].to_s}") # SQL Injection!
220
+ DB[:table].update(params[:changes])
221
+ # SQL injection when using auto_literal_strings extension
187
222
 
188
- Instead, you should do:
223
+ or:
189
224
 
190
- DB[:table].update(:column => params[:value].to_s) # Safe
225
+ DB[:table].update("column = #{params[:value].to_s}")
226
+ # SQL injection when using auto_literal_strings extension
191
227
 
192
- The no_auto_string_literals extension can also be used to remove the default support
193
- for plain strings as literal strings in update methods.
194
-
195
- ==== SQL Fragment passed to Dataset#lock_style and Model#lock!
196
-
197
- The Sequel::Dataset#lock_style and Sequel::Model#lock! methods also treat
198
- an input string as SQL code. This method should not be called with user input.
199
-
200
- ==== SQL Fragment passed to Virtual Row #` method
201
-
202
- Virtual row blocks currently support a #` method for using literal SQL:
203
-
204
- DB[:table].where{a > `some SQL`}
205
-
206
- This method should not be called with user input.
207
-
208
- ==== SQL Type Names
209
-
210
- In general, most places where Sequel needs to use an SQL type that should
211
- be specified by the user, it allows you to use a ruby string, and that
212
- string is used verbatim as the SQL type. You should not use user input
213
- for type strings.
214
-
215
- ==== SQL Function Names
228
+ Instead, you should do:
216
229
 
217
- In most cases, Sequel does not quote SQL function names. You should not use
218
- user input for function names.
230
+ DB[:table].update(:column => params[:value].to_s) # Safe
219
231
 
232
+ Because using the auto_literal_strings extension makes SQL injection
233
+ so much eaiser, it is recommended to not use it, and instead
234
+ use Sequel.lit with placeholders.
235
+
220
236
  === SQL Identifier Injections
221
237
 
222
238
  Usually, Sequel treats ruby symbols as SQL identifiers, and ruby
@@ -236,7 +252,7 @@ the Sequel::Dataset#insert and Sequel::Dataset#update methods:
236
252
  DB[:t].insert('b'=>1) # INSERT INTO "t" ("b") VALUES (1)
237
253
 
238
254
  Note how the identifier is still quoted in these cases. Sequel quotes identifiers by default
239
- on most databases. However, it does not quote identifiers by default on DB2 and Informix.
255
+ on most databases. However, it does not quote identifiers by default on DB2.
240
256
  On those databases using an identifier derived from user input can lead to SQL injection.
241
257
  Similarly, if you turn off identifier quoting manually on other databases, you open yourself
242
258
  up to SQL injection if you use identifiers derived from user input.
@@ -262,6 +278,10 @@ uses symbols as identifiers. However, if you are creating symbols from user inp
262
278
  you at least have a denial of service vulnerability in ruby <2.2, and possibly a
263
279
  more serious vulnerability.
264
280
 
281
+ Note that many Database schema modification methods (e.g. create_table, add_column)
282
+ also allow for SQL identifier injections, and possibly also SQL code injections.
283
+ These methods should never be called with user input.
284
+
265
285
  == Denial of Service
266
286
 
267
287
  Sequel converts some strings to symbols. Because symbols in ruby <2.2 are not
@@ -293,7 +313,7 @@ if you allow the user to control the alias name:
293
313
 
294
314
  DB[:table].select(:column.as(params[:alias]))
295
315
 
296
- Then you have a denial of service vulnerability. In general, such a vulnerability
316
+ Then you can have a denial of service vulnerability. In general, such a vulnerability
297
317
  is unlikely, because you are probably indexing into the returned hash(es) by name,
298
318
  and if an alias was used and you didn't expect it, your application wouldn't work.
299
319
 
@@ -353,28 +373,17 @@ These two methods iterate over the second argument (+:name+ and +:copies_sold+ i
353
373
  this example) instead of iterating over the entries in the first argument
354
374
  (<tt>params[:album]</tt> in this example).
355
375
 
356
- In addition to these two methods, you can also use
357
- Model#set_only[rdoc-ref:Sequel::Model::InstanceMethods#set_only] or
358
- Model#update_only[rdoc-ref:Sequel::Model::InstanceMethods#update_only],
359
- which are similar but iterate over the entries in the first argument, checking
360
- the second argument to see if setting the entries is allowed.
361
-
362
- album.set_only(params[:album], [:name, :copies_sold])
363
- album.update_only(params[:album], [:name, :copies_sold])
364
-
365
- If you expect all entries in the second argument to be present in the first
366
- argument, use +set_fields+ or +update_fields+. If you are not sure if all
367
- arguments in the second argument will be present in the first argument, but
368
- do not want to allow setting any column other than the ones listed in the
369
- second argument, use +set_only+ or +update_only+.
370
-
371
- You can override the columns to allow by default during mass assignment via
372
- the Model.set_allowed_columns[rdoc-ref:Sequel::Model::ClassMethods#set_allowed_columns] class method. This is a good
373
- practice, though being explicit on a per-call basis is still recommended:
376
+ If you want to override the columns that Model#set[rdoc-ref:Sequel::Model::InstanceMethods#set]
377
+ allows by default during mass assignment, you can use the whitelist_security plugin, then call
378
+ the set_allowed_columns class method.
374
379
 
380
+ Album.plugin :whitelist_security
375
381
  Album.set_allowed_columns(:name, :copies_sold)
376
382
  Album.create(params[:album]) # Only name and copies_sold set
377
383
 
384
+ Being explicit on a per-call basis using the set_fields and update_fields methods is recommended
385
+ instead of using the whitelist_security plugin and setting a global whitelist.
386
+
378
387
  For more details on the mass assignment methods, see the {Mass Assignment Guide}[rdoc-ref:doc/mass_assignment.rdoc].
379
388
 
380
389
  == General Parameter Handling
@@ -386,7 +395,7 @@ their type. For example:
386
395
  Album.where(:id=>params[:id])
387
396
 
388
397
  is probably a bad idea. Assuming you are using a web framework, <tt>params[:id]</tt> could
389
- be a string, an array, a hash, or nil.
398
+ be a string, an array, a hash, nil, or potentially something else.
390
399
 
391
400
  Assuming that +id+ is an integer field, you probably want to do:
392
401
 
@@ -400,7 +409,7 @@ a string:
400
409
  If you are trying to use an IN clause with a list of id values based on input provided
401
410
  on a web form:
402
411
 
403
- Album.where(:id=>params[:ids].to_a.map{|i| i.to_i})
412
+ Album.where(:id=>params[:ids].to_a.map(&:to_i))
404
413
 
405
414
  Basically, be as explicit as possible. While there aren't any known security issues
406
415
  in Sequel when you do:
@@ -13,7 +13,7 @@ option. Using the :servers database option makes Sequel use a connection pool
13
13
  class that supports sharding, and the minimum required to enable sharding
14
14
  support is to use the empty hash:
15
15
 
16
- DB=Sequel.connect('postgres://master_server/database', :servers=>{})
16
+ DB=Sequel.connect('postgres://master_server/database', servers: {})
17
17
 
18
18
  In most cases, you are probably not going to want to use an empty hash. Keys in the server hash are
19
19
  not restricted to type, but the general recommendation is to use a symbol
@@ -35,8 +35,8 @@ tables you are accessing, unless you really know what you are doing.
35
35
  To use a single, read-only slave that handles SELECT queries, the following
36
36
  is the simplest configuration:
37
37
 
38
- DB=Sequel.connect('postgres://master_server/database', \
39
- :servers=>{:read_only=>{:host=>'slave_server'}})
38
+ DB=Sequel.connect('postgres://master_server/database',
39
+ servers: {read_only: {host: 'slave_server'}})
40
40
 
41
41
  This will use the slave_server for SELECT queries and master_server for
42
42
  other queries.
@@ -48,8 +48,8 @@ the symbol name defined in the connect options. For example:
48
48
  # Force the SELECT to run on the master
49
49
  DB[:users].server(:default).all
50
50
 
51
- # Force the SELECT to run on the read-only slave
52
- DB[:users].server(:read_only).all
51
+ # Force the DELETE to run on the read-only slave
52
+ DB[:users].server(:read_only).delete
53
53
 
54
54
  === Multiple Read-Only Slaves, Single Master
55
55
 
@@ -59,13 +59,13 @@ slave_server1, slave_server2, and slave_server3.
59
59
  num_read_only = 4
60
60
  read_only_host = rand(num_read_only)
61
61
  read_only_proc = proc do |db|
62
- {:host=>"slave_server#{(read_only_host+=1) % num_read_only}"}
62
+ {host: "slave_server#{(read_only_host+=1) % num_read_only}"}
63
63
  end
64
- DB=Sequel.connect('postgres://master_server/database', \
65
- :servers=>{:read_only=>read_only_proc})
64
+ DB=Sequel.connect('postgres://master_server/database',
65
+ servers: {read_only: read_only_proc})
66
66
 
67
67
  This will use one of the slave servers for SELECT queries and use the
68
- master_server for other queries. It's also possible to pick a random host
68
+ master server for other queries. It's also possible to pick a random host
69
69
  instead of using the round robin approach presented above, but that can result
70
70
  in less optimal resource usage.
71
71
 
@@ -78,15 +78,15 @@ it shows that the master database is named :default. So for 4 masters and
78
78
  num_read_only = 4
79
79
  read_only_host = rand(num_read_only)
80
80
  read_only_proc = proc do |db|
81
- {:host=>"slave_server#{(read_only_host+=1) % num_read_only}"}
81
+ {host: "slave_server#{(read_only_host+=1) % num_read_only}"}
82
82
  end
83
83
  num_default = 4
84
84
  default_host = rand(num_default)
85
85
  default_proc = proc do |db|
86
- {:host=>"master_server#{(default_host+=1) % num_default}"}
86
+ {host: "master_server#{(default_host+=1) % num_default}"}
87
87
  end
88
- DB=Sequel.connect('postgres://master_server/database', \
89
- :servers=>{:default=>default_proc, :read_only=>read_only_proc})
88
+ DB=Sequel.connect('postgres://master_server/database',
89
+ servers: {default: default_proc, read_only: read_only_proc})
90
90
 
91
91
  == Sharding
92
92
 
@@ -100,16 +100,16 @@ of 16 shards). First, you need to configure the database:
100
100
 
101
101
  servers = {}
102
102
  (('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
103
- servers[hex.to_sym] = {:host=>"hash_host_#{hex}"}
103
+ servers[hex.to_sym] = {host: "hash_host_#{hex}"}
104
104
  end
105
- DB=Sequel.connect('postgres://hash_host/hashes', :servers=>servers)
105
+ DB=Sequel.connect('postgres://hash_host/hashes', servers: servers)
106
106
 
107
107
  This configures 17 servers, the 16 shard servers (/hash_host_[0-9a-f]/), and 1
108
108
  default server which will be used if no shard is specified ("hash_host"). If
109
109
  you want the default server to be one of the shard servers (e.g. hash_host_a),
110
110
  it's easiest to do:
111
111
 
112
- DB=Sequel.connect('postgres://hash_host_a/hashes', :servers=>servers)
112
+ DB=Sequel.connect('postgres://hash_host_a/hashes', servers: servers)
113
113
 
114
114
  That will still set up a second pool of connections for the default server,
115
115
  since it considers the default server and shard servers independent. Note that
@@ -120,7 +120,7 @@ schemas, so you should always have a default server that works.
120
120
 
121
121
  To set the shard for a given query, you use the Dataset#server method:
122
122
 
123
- DB[:hashes].server(:a).where(:hash=>/31337/)
123
+ DB[:hashes].server(:a).where(hash: /31337/)
124
124
 
125
125
  That will return all matching rows on the hash_host_a shard that have a hash
126
126
  column that contains 31337.
@@ -133,7 +133,7 @@ the shard to use. This is fairly easy using a Sequel::Model:
133
133
  dataset_module do
134
134
  def plaintext_for_hash(hash)
135
135
  raise(ArgumentError, 'Invalid SHA-1 Hash') unless /\A[0-9a-f]{40}\z/.match(hash)
136
- server(hash[0...1].to_sym).where(:hash=>hash).get(:plaintext)
136
+ server(hash[0...1].to_sym).where(hash: hash).get(:plaintext)
137
137
  end
138
138
  end
139
139
  end
@@ -146,24 +146,24 @@ to assume the :default shard. However, you can specify a
146
146
  different shard using the :servers_hash option when connecting
147
147
  to the database:
148
148
 
149
- DB = Sequel.connect('postgres://...', :servers_hash=>Hash.new(:some_shard))
149
+ DB = Sequel.connect('postgres://...', servers_hash: Hash.new(:some_shard))
150
150
 
151
151
  You can also use this feature to raise an exception if an
152
152
  unconfigured shard is used:
153
153
 
154
- DB = Sequel.connect('postgres://...', :servers_hash=>Hash.new{raise 'foo'})
154
+ DB = Sequel.connect('postgres://...', servers_hash: Hash.new{raise 'foo'})
155
155
 
156
156
  If you specify a :servers_hash option to raise an exception for non configured
157
157
  shards you should also explicitly specify a :read_only entry in your :servers option
158
158
  for the case where a shard is not specified. In most cases it is sufficient
159
159
  to make the :read_only entry the same as the :default shard:
160
160
 
161
- servers = {:read_only => {}}
161
+ servers = {read_only: {}}
162
162
  (('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
163
- servers[hex.to_sym] = {:host=>"hash_host_#{hex}"}
163
+ servers[hex.to_sym] = {host: "hash_host_#{hex}"}
164
164
  end
165
- DB=Sequel.connect('postgres://hash_host/hashes', :servers=>servers,
166
- :servers_hash=>Hash.new{raise Exception.new("Invalid Server")})
165
+ DB=Sequel.connect('postgres://hash_host/hashes', servers: servers,
166
+ servers_hash: Hash.new{raise "Invalid Server"})
167
167
 
168
168
  === Sharding Plugin
169
169
 
@@ -176,7 +176,7 @@ work well with shards. You just need to remember to set to model to use the plu
176
176
  plugin :sharding
177
177
  end
178
178
 
179
- Rainbow.server(:a).first(:id=>1).update(:plaintext=>'VGM')
179
+ Rainbow.server(:a).first(id: 1).update(plaintext: 'VGM')
180
180
 
181
181
  If all of your models are sharded, you can set all models to use the plugin via:
182
182
 
@@ -186,7 +186,7 @@ If all of your models are sharded, you can set all models to use the plugin via:
186
186
 
187
187
  By default, you must specify the server/shard you want to use for every dataset/action,
188
188
  or Sequel will use the default shard. If you have a group of queries that should use the
189
- same shard, it can get a bit redundent to specify the same shard for all of them.
189
+ same shard, it can get a bit redundant to specify the same shard for all of them.
190
190
 
191
191
  The server_block extension adds a Database#with_server method that scopes all database
192
192
  access inside the block to the given shard by default:
@@ -194,7 +194,7 @@ access inside the block to the given shard by default:
194
194
  DB.extension :server_block
195
195
  DB.with_server(:a) do
196
196
  # this SELECT query uses the "a" shard
197
- if r = Rainbow.first(:hash=>/31337/)
197
+ if r = Rainbow.first(hash: /31337/)
198
198
  r.count += 1
199
199
  # this UPDATE query also uses the "a" shard
200
200
  r.save
@@ -209,6 +209,19 @@ you retrieve the models inside the block and save them outside of the block. If
209
209
  need to do that, call the server method explicitly on the dataset used to retrieve the
210
210
  model objects.
211
211
 
212
+ The with_server method also supports a second argument for the default read_only server
213
+ to use, which can be useful if you are mixing sharding and master/slave servers:
214
+
215
+ DB.extension :server_block
216
+ DB.with_server(:a, :a_read_only) do
217
+ # this SELECT query uses the "a_read_only" shard
218
+ if r = Rainbow.first(hash: /31337/)
219
+ r.count += 1
220
+ # this UPDATE query also uses the "a" shard
221
+ r.save
222
+ end
223
+ end
224
+
212
225
  === arbitrary_servers Extension
213
226
 
214
227
  By default, Sequel's sharding support is designed to work with predefined shards. It ships
@@ -220,13 +233,13 @@ The arbitrary_servers extension allows you to pass a server/shard options hash a
220
233
  server to use, and those options will be merged directly into the database's default options:
221
234
 
222
235
  DB.extension :arbitrary_servers
223
- DB[:rainbows].server(:host=>'hash_host_a').all
236
+ DB[:rainbows].server(host: 'hash_host_a').all
224
237
  # or
225
- DB[:rainbows].server(:host=>'hash_host_b', :database=>'backup').all
238
+ DB[:rainbows].server(host: 'hash_host_b', database: 'backup').all
226
239
 
227
240
  arbitrary_servers is designed to work well in conjunction with the server_block extension:
228
241
 
229
- DB.with_server(:host=>'hash_host_b', :database=>'backup') do
242
+ DB.with_server(host: 'hash_host_b', database: 'backup') do
230
243
  DB.synchronize do
231
244
  # All queries here default to the backup database on hash_host_b
232
245
  end