sequel 4.49.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (484) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +130 -0
  3. data/README.rdoc +195 -136
  4. data/Rakefile +26 -42
  5. data/bin/sequel +6 -9
  6. data/doc/advanced_associations.rdoc +91 -168
  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/release_notes/5.1.0.txt +31 -0
  29. data/doc/release_notes/5.2.0.txt +33 -0
  30. data/doc/release_notes/5.3.0.txt +121 -0
  31. data/doc/schema_modification.rdoc +78 -64
  32. data/doc/security.rdoc +97 -88
  33. data/doc/sharding.rdoc +43 -30
  34. data/doc/sql.rdoc +53 -65
  35. data/doc/testing.rdoc +4 -5
  36. data/doc/thread_safety.rdoc +2 -4
  37. data/doc/transactions.rdoc +18 -17
  38. data/doc/validations.rdoc +48 -45
  39. data/doc/virtual_rows.rdoc +87 -115
  40. data/lib/sequel/adapters/ado/access.rb +7 -13
  41. data/lib/sequel/adapters/ado/mssql.rb +2 -9
  42. data/lib/sequel/adapters/ado.rb +9 -25
  43. data/lib/sequel/adapters/amalgalite.rb +3 -18
  44. data/lib/sequel/adapters/ibmdb.rb +9 -45
  45. data/lib/sequel/adapters/jdbc/db2.rb +8 -37
  46. data/lib/sequel/adapters/jdbc/derby.rb +4 -50
  47. data/lib/sequel/adapters/jdbc/h2.rb +6 -26
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -27
  49. data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
  50. data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
  51. data/lib/sequel/adapters/jdbc/mysql.rb +11 -15
  52. data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
  53. data/lib/sequel/adapters/jdbc/postgresql.rb +23 -33
  54. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
  55. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
  56. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
  57. data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
  58. data/lib/sequel/adapters/jdbc.rb +18 -74
  59. data/lib/sequel/adapters/mock.rb +4 -30
  60. data/lib/sequel/adapters/mysql.rb +7 -44
  61. data/lib/sequel/adapters/mysql2.rb +5 -23
  62. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  63. data/lib/sequel/adapters/odbc/mssql.rb +4 -12
  64. data/lib/sequel/adapters/odbc/oracle.rb +1 -1
  65. data/lib/sequel/adapters/odbc.rb +0 -19
  66. data/lib/sequel/adapters/oracle.rb +8 -13
  67. data/lib/sequel/adapters/postgres.rb +28 -150
  68. data/lib/sequel/adapters/postgresql.rb +1 -1
  69. data/lib/sequel/adapters/shared/access.rb +11 -51
  70. data/lib/sequel/adapters/shared/db2.rb +3 -61
  71. data/lib/sequel/adapters/shared/mssql.rb +21 -157
  72. data/lib/sequel/adapters/shared/mysql.rb +61 -227
  73. data/lib/sequel/adapters/shared/oracle.rb +13 -41
  74. data/lib/sequel/adapters/shared/postgres.rb +58 -264
  75. data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
  76. data/lib/sequel/adapters/shared/sqlite.rb +22 -101
  77. data/lib/sequel/adapters/sqlanywhere.rb +4 -23
  78. data/lib/sequel/adapters/sqlite.rb +2 -19
  79. data/lib/sequel/adapters/tinytds.rb +5 -15
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  81. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -4
  82. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
  83. data/lib/sequel/adapters/utils/replace.rb +0 -5
  84. data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
  85. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
  86. data/lib/sequel/ast_transformer.rb +3 -94
  87. data/lib/sequel/connection_pool/sharded_single.rb +1 -4
  88. data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
  89. data/lib/sequel/connection_pool/single.rb +0 -2
  90. data/lib/sequel/connection_pool/threaded.rb +94 -110
  91. data/lib/sequel/connection_pool.rb +38 -28
  92. data/lib/sequel/core.rb +42 -101
  93. data/lib/sequel/database/connecting.rb +23 -60
  94. data/lib/sequel/database/dataset.rb +6 -9
  95. data/lib/sequel/database/dataset_defaults.rb +4 -48
  96. data/lib/sequel/database/features.rb +5 -4
  97. data/lib/sequel/database/logging.rb +2 -9
  98. data/lib/sequel/database/misc.rb +36 -55
  99. data/lib/sequel/database/query.rb +8 -13
  100. data/lib/sequel/database/schema_generator.rb +93 -64
  101. data/lib/sequel/database/schema_methods.rb +61 -79
  102. data/lib/sequel/database/transactions.rb +4 -24
  103. data/lib/sequel/database.rb +12 -2
  104. data/lib/sequel/dataset/actions.rb +57 -107
  105. data/lib/sequel/dataset/dataset_module.rb +4 -16
  106. data/lib/sequel/dataset/features.rb +35 -30
  107. data/lib/sequel/dataset/graph.rb +40 -49
  108. data/lib/sequel/dataset/misc.rb +12 -37
  109. data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
  110. data/lib/sequel/dataset/prepared_statements.rb +23 -51
  111. data/lib/sequel/dataset/query.rb +91 -161
  112. data/lib/sequel/dataset/sql.rb +33 -225
  113. data/lib/sequel/dataset.rb +18 -10
  114. data/lib/sequel/deprecated.rb +18 -27
  115. data/lib/sequel/exceptions.rb +1 -17
  116. data/lib/sequel/extensions/_model_pg_row.rb +0 -7
  117. data/lib/sequel/extensions/_pretty_table.rb +1 -3
  118. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  119. data/lib/sequel/extensions/connection_expiration.rb +1 -1
  120. data/lib/sequel/extensions/connection_validator.rb +1 -1
  121. data/lib/sequel/extensions/constraint_validations.rb +11 -11
  122. data/lib/sequel/extensions/core_extensions.rb +39 -49
  123. data/lib/sequel/extensions/core_refinements.rb +39 -45
  124. data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
  125. data/lib/sequel/extensions/date_arithmetic.rb +7 -7
  126. data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
  127. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  128. data/lib/sequel/extensions/eval_inspect.rb +4 -11
  129. data/lib/sequel/extensions/freeze_datasets.rb +1 -69
  130. data/lib/sequel/extensions/from_block.rb +1 -35
  131. data/lib/sequel/extensions/graph_each.rb +2 -2
  132. data/lib/sequel/extensions/identifier_mangling.rb +9 -19
  133. data/lib/sequel/extensions/implicit_subquery.rb +2 -2
  134. data/lib/sequel/extensions/inflector.rb +4 -4
  135. data/lib/sequel/extensions/migration.rb +27 -43
  136. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
  137. data/lib/sequel/extensions/null_dataset.rb +2 -8
  138. data/lib/sequel/extensions/pagination.rb +1 -17
  139. data/lib/sequel/extensions/pg_array.rb +20 -189
  140. data/lib/sequel/extensions/pg_extended_date_support.rb +230 -0
  141. data/lib/sequel/extensions/pg_hstore.rb +11 -50
  142. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  143. data/lib/sequel/extensions/pg_inet.rb +3 -16
  144. data/lib/sequel/extensions/pg_interval.rb +1 -20
  145. data/lib/sequel/extensions/pg_json.rb +7 -27
  146. data/lib/sequel/extensions/pg_loose_count.rb +1 -1
  147. data/lib/sequel/extensions/pg_range.rb +6 -121
  148. data/lib/sequel/extensions/pg_range_ops.rb +1 -3
  149. data/lib/sequel/extensions/pg_row.rb +5 -77
  150. data/lib/sequel/extensions/pg_row_ops.rb +2 -13
  151. data/lib/sequel/extensions/query.rb +3 -4
  152. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  153. data/lib/sequel/extensions/schema_dumper.rb +13 -13
  154. data/lib/sequel/extensions/select_remove.rb +3 -3
  155. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  156. data/lib/sequel/extensions/sql_comments.rb +2 -2
  157. data/lib/sequel/extensions/string_agg.rb +11 -8
  158. data/lib/sequel/extensions/symbol_aref.rb +6 -20
  159. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  160. data/lib/sequel/model/associations.rb +129 -131
  161. data/lib/sequel/model/base.rb +133 -731
  162. data/lib/sequel/model/default_inflections.rb +1 -1
  163. data/lib/sequel/model/errors.rb +0 -3
  164. data/lib/sequel/model/exceptions.rb +2 -6
  165. data/lib/sequel/model/inflections.rb +1 -26
  166. data/lib/sequel/model/plugins.rb +1 -0
  167. data/lib/sequel/model.rb +27 -62
  168. data/lib/sequel/plugins/active_model.rb +2 -5
  169. data/lib/sequel/plugins/association_dependencies.rb +15 -15
  170. data/lib/sequel/plugins/association_pks.rb +14 -28
  171. data/lib/sequel/plugins/association_proxies.rb +6 -7
  172. data/lib/sequel/plugins/auto_validations.rb +4 -4
  173. data/lib/sequel/plugins/before_after_save.rb +0 -43
  174. data/lib/sequel/plugins/blacklist_security.rb +9 -8
  175. data/lib/sequel/plugins/boolean_readers.rb +3 -3
  176. data/lib/sequel/plugins/boolean_subsets.rb +2 -2
  177. data/lib/sequel/plugins/caching.rb +5 -5
  178. data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
  179. data/lib/sequel/plugins/column_conflicts.rb +2 -2
  180. data/lib/sequel/plugins/column_select.rb +2 -2
  181. data/lib/sequel/plugins/composition.rb +15 -24
  182. data/lib/sequel/plugins/constraint_validations.rb +4 -3
  183. data/lib/sequel/plugins/csv_serializer.rb +13 -20
  184. data/lib/sequel/plugins/dataset_associations.rb +2 -2
  185. data/lib/sequel/plugins/def_dataset_method.rb +5 -5
  186. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  187. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  188. data/lib/sequel/plugins/finder.rb +16 -10
  189. data/lib/sequel/plugins/force_encoding.rb +1 -7
  190. data/lib/sequel/plugins/hook_class_methods.rb +4 -106
  191. data/lib/sequel/plugins/input_transformer.rb +10 -11
  192. data/lib/sequel/plugins/insert_returning_select.rb +1 -9
  193. data/lib/sequel/plugins/instance_filters.rb +5 -5
  194. data/lib/sequel/plugins/instance_hooks.rb +7 -52
  195. data/lib/sequel/plugins/inverted_subsets.rb +3 -1
  196. data/lib/sequel/plugins/json_serializer.rb +19 -19
  197. data/lib/sequel/plugins/lazy_attributes.rb +1 -10
  198. data/lib/sequel/plugins/list.rb +6 -6
  199. data/lib/sequel/plugins/many_through_many.rb +11 -8
  200. data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
  201. data/lib/sequel/plugins/nested_attributes.rb +18 -31
  202. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  203. data/lib/sequel/plugins/pg_array_associations.rb +8 -2
  204. data/lib/sequel/plugins/pg_row.rb +2 -11
  205. data/lib/sequel/plugins/prepared_statements.rb +13 -66
  206. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  207. data/lib/sequel/plugins/rcte_tree.rb +7 -7
  208. data/lib/sequel/plugins/serialization.rb +15 -33
  209. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  210. data/lib/sequel/plugins/sharding.rb +2 -8
  211. data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
  212. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  213. data/lib/sequel/plugins/static_cache.rb +8 -9
  214. data/lib/sequel/plugins/string_stripper.rb +3 -3
  215. data/lib/sequel/plugins/subclasses.rb +1 -1
  216. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  217. data/lib/sequel/plugins/table_select.rb +2 -2
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  219. data/lib/sequel/plugins/timestamps.rb +6 -7
  220. data/lib/sequel/plugins/touch.rb +4 -8
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +2 -2
  223. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  224. data/lib/sequel/plugins/update_or_create.rb +3 -3
  225. data/lib/sequel/plugins/update_refresh.rb +3 -3
  226. data/lib/sequel/plugins/uuid.rb +7 -11
  227. data/lib/sequel/plugins/validation_class_methods.rb +10 -9
  228. data/lib/sequel/plugins/validation_contexts.rb +4 -4
  229. data/lib/sequel/plugins/validation_helpers.rb +26 -25
  230. data/lib/sequel/plugins/whitelist_security.rb +13 -9
  231. data/lib/sequel/plugins/xml_serializer.rb +24 -25
  232. data/lib/sequel/sql.rb +145 -276
  233. data/lib/sequel/timezones.rb +8 -23
  234. data/lib/sequel/version.rb +2 -2
  235. data/lib/sequel.rb +1 -1
  236. data/spec/adapter_spec.rb +1 -1
  237. data/spec/adapters/db2_spec.rb +2 -103
  238. data/spec/adapters/mssql_spec.rb +89 -68
  239. data/spec/adapters/mysql_spec.rb +111 -478
  240. data/spec/adapters/oracle_spec.rb +1 -9
  241. data/spec/adapters/postgres_spec.rb +459 -664
  242. data/spec/adapters/spec_helper.rb +12 -31
  243. data/spec/adapters/sqlanywhere_spec.rb +2 -77
  244. data/spec/adapters/sqlite_spec.rb +8 -146
  245. data/spec/bin_spec.rb +11 -16
  246. data/spec/core/connection_pool_spec.rb +173 -74
  247. data/spec/core/database_spec.rb +96 -244
  248. data/spec/core/dataset_spec.rb +99 -414
  249. data/spec/core/deprecated_spec.rb +3 -3
  250. data/spec/core/expression_filters_spec.rb +37 -144
  251. data/spec/core/mock_adapter_spec.rb +241 -4
  252. data/spec/core/object_graph_spec.rb +11 -60
  253. data/spec/core/placeholder_literalizer_spec.rb +1 -14
  254. data/spec/core/schema_generator_spec.rb +51 -40
  255. data/spec/core/schema_spec.rb +88 -77
  256. data/spec/core/spec_helper.rb +6 -24
  257. data/spec/core/version_spec.rb +1 -1
  258. data/spec/core_extensions_spec.rb +7 -83
  259. data/spec/core_model_spec.rb +2 -2
  260. data/spec/deprecation_helper.rb +2 -14
  261. data/spec/extensions/accessed_columns_spec.rb +1 -1
  262. data/spec/extensions/active_model_spec.rb +3 -3
  263. data/spec/extensions/after_initialize_spec.rb +1 -1
  264. data/spec/extensions/arbitrary_servers_spec.rb +2 -2
  265. data/spec/extensions/association_dependencies_spec.rb +1 -1
  266. data/spec/extensions/association_pks_spec.rb +30 -92
  267. data/spec/extensions/association_proxies_spec.rb +1 -1
  268. data/spec/extensions/auto_literal_strings_spec.rb +1 -12
  269. data/spec/extensions/auto_validations_spec.rb +1 -1
  270. data/spec/extensions/blacklist_security_spec.rb +1 -1
  271. data/spec/extensions/blank_spec.rb +1 -1
  272. data/spec/extensions/boolean_readers_spec.rb +1 -1
  273. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  274. data/spec/extensions/caching_spec.rb +1 -1
  275. data/spec/extensions/class_table_inheritance_spec.rb +53 -1118
  276. data/spec/extensions/column_conflicts_spec.rb +1 -1
  277. data/spec/extensions/column_select_spec.rb +4 -4
  278. data/spec/extensions/columns_introspection_spec.rb +1 -1
  279. data/spec/extensions/columns_updated_spec.rb +1 -1
  280. data/spec/extensions/composition_spec.rb +8 -30
  281. data/spec/extensions/connection_expiration_spec.rb +3 -3
  282. data/spec/extensions/connection_validator_spec.rb +3 -3
  283. data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
  284. data/spec/extensions/constraint_validations_spec.rb +1 -1
  285. data/spec/extensions/core_refinements_spec.rb +1 -3
  286. data/spec/extensions/csv_serializer_spec.rb +4 -9
  287. data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
  288. data/spec/extensions/dataset_associations_spec.rb +2 -1
  289. data/spec/extensions/dataset_source_alias_spec.rb +1 -1
  290. data/spec/extensions/date_arithmetic_spec.rb +3 -3
  291. data/spec/extensions/def_dataset_method_spec.rb +1 -1
  292. data/spec/extensions/defaults_setter_spec.rb +2 -2
  293. data/spec/extensions/delay_add_association_spec.rb +8 -9
  294. data/spec/extensions/dirty_spec.rb +1 -1
  295. data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
  296. data/spec/extensions/eager_each_spec.rb +2 -2
  297. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  298. data/spec/extensions/error_splitter_spec.rb +1 -1
  299. data/spec/extensions/error_sql_spec.rb +1 -1
  300. data/spec/extensions/eval_inspect_spec.rb +1 -1
  301. data/spec/extensions/finder_spec.rb +1 -1
  302. data/spec/extensions/force_encoding_spec.rb +2 -5
  303. data/spec/extensions/freeze_datasets_spec.rb +1 -1
  304. data/spec/extensions/graph_each_spec.rb +5 -5
  305. data/spec/extensions/hook_class_methods_spec.rb +1 -194
  306. data/spec/extensions/identifier_mangling_spec.rb +17 -170
  307. data/spec/extensions/implicit_subquery_spec.rb +1 -5
  308. data/spec/extensions/inflector_spec.rb +1 -1
  309. data/spec/extensions/input_transformer_spec.rb +7 -2
  310. data/spec/extensions/insert_returning_select_spec.rb +1 -1
  311. data/spec/extensions/instance_filters_spec.rb +1 -1
  312. data/spec/extensions/instance_hooks_spec.rb +1 -95
  313. data/spec/extensions/inverted_subsets_spec.rb +1 -1
  314. data/spec/extensions/json_serializer_spec.rb +1 -1
  315. data/spec/extensions/lazy_attributes_spec.rb +1 -7
  316. data/spec/extensions/list_spec.rb +5 -6
  317. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  318. data/spec/extensions/many_through_many_spec.rb +25 -33
  319. data/spec/extensions/migration_spec.rb +12 -2
  320. data/spec/extensions/modification_detection_spec.rb +1 -1
  321. data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
  322. data/spec/extensions/named_timezones_spec.rb +3 -3
  323. data/spec/extensions/nested_attributes_spec.rb +1 -29
  324. data/spec/extensions/null_dataset_spec.rb +1 -11
  325. data/spec/extensions/optimistic_locking_spec.rb +2 -2
  326. data/spec/extensions/pagination_spec.rb +1 -1
  327. data/spec/extensions/pg_array_associations_spec.rb +22 -26
  328. data/spec/extensions/pg_array_ops_spec.rb +1 -1
  329. data/spec/extensions/pg_array_spec.rb +3 -48
  330. data/spec/extensions/pg_enum_spec.rb +1 -1
  331. data/spec/extensions/pg_extended_date_support_spec.rb +122 -0
  332. data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
  333. data/spec/extensions/pg_hstore_spec.rb +22 -31
  334. data/spec/extensions/pg_inet_ops_spec.rb +1 -1
  335. data/spec/extensions/pg_inet_spec.rb +1 -14
  336. data/spec/extensions/pg_interval_spec.rb +3 -13
  337. data/spec/extensions/pg_json_ops_spec.rb +1 -1
  338. data/spec/extensions/pg_json_spec.rb +1 -13
  339. data/spec/extensions/pg_loose_count_spec.rb +1 -1
  340. data/spec/extensions/pg_range_ops_spec.rb +1 -1
  341. data/spec/extensions/pg_range_spec.rb +3 -88
  342. data/spec/extensions/pg_row_ops_spec.rb +1 -1
  343. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  344. data/spec/extensions/pg_row_spec.rb +1 -44
  345. data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
  346. data/spec/extensions/prepared_statements_safe_spec.rb +7 -7
  347. data/spec/extensions/prepared_statements_spec.rb +13 -48
  348. data/spec/extensions/pretty_table_spec.rb +40 -9
  349. data/spec/extensions/query_spec.rb +1 -12
  350. data/spec/extensions/rcte_tree_spec.rb +23 -34
  351. data/spec/extensions/round_timestamps_spec.rb +1 -5
  352. data/spec/extensions/s_spec.rb +1 -1
  353. data/spec/extensions/schema_caching_spec.rb +1 -1
  354. data/spec/extensions/schema_dumper_spec.rb +43 -32
  355. data/spec/extensions/select_remove_spec.rb +1 -1
  356. data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
  357. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  358. data/spec/extensions/serialization_spec.rb +5 -17
  359. data/spec/extensions/server_block_spec.rb +1 -1
  360. data/spec/extensions/server_logging_spec.rb +2 -2
  361. data/spec/extensions/sharding_spec.rb +1 -1
  362. data/spec/extensions/shared_caching_spec.rb +1 -28
  363. data/spec/extensions/single_table_inheritance_spec.rb +2 -5
  364. data/spec/extensions/singular_table_names_spec.rb +1 -1
  365. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  366. data/spec/extensions/spec_helper.rb +5 -27
  367. data/spec/extensions/split_array_nil_spec.rb +1 -1
  368. data/spec/extensions/split_values_spec.rb +1 -1
  369. data/spec/extensions/sql_comments_spec.rb +1 -1
  370. data/spec/extensions/sql_expr_spec.rb +1 -1
  371. data/spec/extensions/static_cache_spec.rb +1 -1
  372. data/spec/extensions/string_agg_spec.rb +2 -2
  373. data/spec/extensions/string_date_time_spec.rb +1 -1
  374. data/spec/extensions/string_stripper_spec.rb +1 -1
  375. data/spec/extensions/subclasses_spec.rb +1 -1
  376. data/spec/extensions/subset_conditions_spec.rb +1 -1
  377. data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
  378. data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
  379. data/spec/extensions/synchronize_sql_spec.rb +124 -0
  380. data/spec/extensions/table_select_spec.rb +4 -4
  381. data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
  382. data/spec/extensions/thread_local_timezones_spec.rb +1 -1
  383. data/spec/extensions/timestamps_spec.rb +5 -7
  384. data/spec/extensions/to_dot_spec.rb +1 -1
  385. data/spec/extensions/touch_spec.rb +1 -1
  386. data/spec/extensions/tree_spec.rb +1 -1
  387. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  388. data/spec/extensions/unlimited_update_spec.rb +1 -1
  389. data/spec/extensions/update_or_create_spec.rb +12 -16
  390. data/spec/extensions/update_primary_key_spec.rb +4 -3
  391. data/spec/extensions/update_refresh_spec.rb +1 -1
  392. data/spec/extensions/uuid_spec.rb +10 -13
  393. data/spec/extensions/validate_associated_spec.rb +1 -1
  394. data/spec/extensions/validation_class_methods_spec.rb +3 -3
  395. data/spec/extensions/validation_contexts_spec.rb +1 -1
  396. data/spec/extensions/validation_helpers_spec.rb +10 -44
  397. data/spec/extensions/whitelist_security_spec.rb +5 -5
  398. data/spec/extensions/xml_serializer_spec.rb +8 -13
  399. data/spec/guards_helper.rb +2 -1
  400. data/spec/integration/associations_test.rb +1 -23
  401. data/spec/integration/database_test.rb +7 -7
  402. data/spec/integration/dataset_test.rb +12 -47
  403. data/spec/integration/eager_loader_test.rb +1 -1
  404. data/spec/integration/migrator_test.rb +1 -1
  405. data/spec/integration/model_test.rb +4 -82
  406. data/spec/integration/plugin_test.rb +7 -23
  407. data/spec/integration/prepared_statement_test.rb +8 -88
  408. data/spec/integration/schema_test.rb +10 -10
  409. data/spec/integration/spec_helper.rb +17 -21
  410. data/spec/integration/timezone_test.rb +5 -5
  411. data/spec/integration/transaction_test.rb +3 -55
  412. data/spec/integration/type_test.rb +9 -9
  413. data/spec/model/association_reflection_spec.rb +24 -9
  414. data/spec/model/associations_spec.rb +124 -303
  415. data/spec/model/base_spec.rb +43 -137
  416. data/spec/model/class_dataset_methods_spec.rb +2 -20
  417. data/spec/model/dataset_methods_spec.rb +1 -20
  418. data/spec/model/eager_loading_spec.rb +48 -17
  419. data/spec/model/hooks_spec.rb +5 -300
  420. data/spec/model/inflector_spec.rb +1 -1
  421. data/spec/model/model_spec.rb +29 -339
  422. data/spec/model/plugins_spec.rb +2 -16
  423. data/spec/model/record_spec.rb +33 -129
  424. data/spec/model/spec_helper.rb +5 -15
  425. data/spec/model/validations_spec.rb +1 -1
  426. data/spec/sequel_warning.rb +1 -12
  427. metadata +19 -65
  428. data/doc/active_record.rdoc +0 -927
  429. data/lib/sequel/adapters/cubrid.rb +0 -160
  430. data/lib/sequel/adapters/do/mysql.rb +0 -69
  431. data/lib/sequel/adapters/do/postgres.rb +0 -46
  432. data/lib/sequel/adapters/do/sqlite3.rb +0 -41
  433. data/lib/sequel/adapters/do.rb +0 -166
  434. data/lib/sequel/adapters/jdbc/as400.rb +0 -92
  435. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
  436. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
  437. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
  438. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
  439. data/lib/sequel/adapters/odbc/progress.rb +0 -12
  440. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  441. data/lib/sequel/adapters/shared/firebird.rb +0 -261
  442. data/lib/sequel/adapters/shared/informix.rb +0 -63
  443. data/lib/sequel/adapters/shared/progress.rb +0 -40
  444. data/lib/sequel/adapters/swift/mysql.rb +0 -50
  445. data/lib/sequel/adapters/swift/postgres.rb +0 -49
  446. data/lib/sequel/adapters/swift/sqlite.rb +0 -48
  447. data/lib/sequel/adapters/swift.rb +0 -169
  448. data/lib/sequel/adapters/utils/pg_types.rb +0 -4
  449. data/lib/sequel/dataset/mutation.rb +0 -98
  450. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
  451. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
  452. data/lib/sequel/extensions/filter_having.rb +0 -65
  453. data/lib/sequel/extensions/hash_aliases.rb +0 -51
  454. data/lib/sequel/extensions/meta_def.rb +0 -37
  455. data/lib/sequel/extensions/query_literals.rb +0 -86
  456. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
  457. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
  458. data/lib/sequel/extensions/set_overrides.rb +0 -82
  459. data/lib/sequel/no_core_ext.rb +0 -4
  460. data/lib/sequel/plugins/association_autoreloading.rb +0 -11
  461. data/lib/sequel/plugins/identifier_columns.rb +0 -49
  462. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
  463. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
  464. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
  465. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
  466. data/lib/sequel/plugins/schema.rb +0 -84
  467. data/lib/sequel/plugins/scissors.rb +0 -37
  468. data/spec/core/dataset_mutation_spec.rb +0 -253
  469. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
  470. data/spec/extensions/before_after_save_spec.rb +0 -40
  471. data/spec/extensions/filter_having_spec.rb +0 -42
  472. data/spec/extensions/from_block_spec.rb +0 -21
  473. data/spec/extensions/hash_aliases_spec.rb +0 -26
  474. data/spec/extensions/identifier_columns_spec.rb +0 -19
  475. data/spec/extensions/meta_def_spec.rb +0 -35
  476. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
  477. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
  478. data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
  479. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
  480. data/spec/extensions/query_literals_spec.rb +0 -185
  481. data/spec/extensions/schema_spec.rb +0 -123
  482. data/spec/extensions/scissors_spec.rb +0 -27
  483. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
  484. data/spec/extensions/set_overrides_spec.rb +0 -75
data/doc/querying.rdoc CHANGED
@@ -4,15 +4,15 @@ This guide is based on http://guides.rubyonrails.org/active_record_querying.html
4
4
 
5
5
  == Purpose of this Guide
6
6
 
7
- Sequel is a simple to use, very flexible, and powerful database library
7
+ Sequel is a flexible and powerful database library
8
8
  that supports a wide variety of different querying methods. This guide
9
- aims to be a gentle introduction to Sequel's querying support.
9
+ aims to be a introduction to Sequel's querying support.
10
10
 
11
- While you can easily use raw SQL with Sequel, a large part of the
11
+ While you can use raw SQL with Sequel, a large part of the
12
12
  advantage you get from using Sequel is Sequel's ability to abstract
13
- SQL from you and give you a much nicer interface. Sequel also ships with
13
+ SQL from you and give you a pure-ruby interface. Sequel also ships with
14
14
  a {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
15
- which better integrates Sequel's DSL into the ruby language.
15
+ which adds methods to core ruby types to work with Sequel.
16
16
 
17
17
  == Retrieving Objects
18
18
 
@@ -39,7 +39,7 @@ by its primary key value:
39
39
 
40
40
  # Find artist with primary key (id) 1
41
41
  artist = Artist[1]
42
- # SELECT * FROM artists WHERE id = 1
42
+ # SELECT * FROM artists WHERE (id = 1)
43
43
  # => #<Artist @values={:name=>"YJM", :id=>1}>
44
44
 
45
45
  If there is no record with the given primary key, nil will be returned. If you want
@@ -58,7 +58,7 @@ If you just want the first record in the dataset,
58
58
 
59
59
  Any options you pass to +first+ will be used as a filter:
60
60
 
61
- artist = Artist.first(:name => 'YJM')
61
+ artist = Artist.first(name: 'YJM')
62
62
  # SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
63
63
  # => #<Artist @values={:name=>"YJM", :id=>1}>
64
64
 
@@ -72,7 +72,7 @@ raise an exception instead, use <tt>first!</tt>.
72
72
  <tt>Sequel::Dataset#[]</tt> is basically an alias for +first+, except it
73
73
  requires an argument:
74
74
 
75
- DB[:artists][:name => 'YJM']
75
+ DB[:artists][{name: 'YJM'}]
76
76
  # SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
77
77
  # => {:name=>"YJM", :id=>1}
78
78
 
@@ -109,6 +109,15 @@ you want:
109
109
  # SELECT name FROM artists LIMIT 1
110
110
  # => "YJM"
111
111
 
112
+ ==== Retrieving a Multiple Column Values
113
+
114
+ If you want the value for multiple columns, you can pass an array to
115
+ <tt>Sequel::Dataset#get</tt>:
116
+
117
+ artist_id, artist_name, = Artist.get([:id, :name])
118
+ # SELECT name FROM artists LIMIT 1
119
+ # => [1, "YJM"]
120
+
112
121
  === Retrieving Multiple Objects
113
122
 
114
123
  ==== As an Array of Hashes or Model Objects
@@ -181,21 +190,21 @@ an array of arrays of values will be returned:
181
190
  ==== As a Hash
182
191
 
183
192
  Sequel makes it easy to take an SQL query and return it as a ruby hash,
184
- using the +to_hash+ method:
193
+ using the +as_hash+ method:
185
194
 
186
- artist_names = Artist.to_hash(:id, :name)
195
+ artist_names = Artist.as_hash(:id, :name)
187
196
  # SELECT * FROM artists
188
197
  # => {1=>"YJM", 2=>"AS"}
189
198
 
190
- As you can see, the +to_hash+ method uses the first symbol as the key
199
+ As you can see, the +as_hash+ method uses the first symbol as the key
191
200
  and the second symbol as the value. So if you swap the two arguments the hash
192
201
  will have its keys and values transposed:
193
202
 
194
- artist_names = Artist.to_hash(:name, :id)
203
+ artist_names = Artist.as_hash(:name, :id)
195
204
  # SELECT * FROM artists
196
205
  # => {"YJM"=>1, "AS"=>2}
197
206
 
198
- Now what if you have multiple values for the same key? By default, +to_hash+
207
+ Now what if you have multiple values for the same key? By default, +as_hash+
199
208
  will just have the last matching value. If you care about all matching values,
200
209
  use +to_hash_groups+, which makes the values of the array an array of matching
201
210
  values, in the order they were received:
@@ -204,10 +213,10 @@ values, in the order they were received:
204
213
  # SELECT * FROM artists
205
214
  # => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
206
215
 
207
- If you only provide one argument to +to_hash+, it uses the entire hash
216
+ If you only provide one argument to +as_hash+, it uses the entire hash
208
217
  or model object as the value:
209
218
 
210
- artist_names = DB[:artists].to_hash(:name)
219
+ artist_names = DB[:artists].as_hash(:name)
211
220
  # SELECT * FROM artists
212
221
  # => {"YJM"=>{:id=>1, :name=>"YJM"}, "AS"=>{:id=>2, :name=>"AS"}}
213
222
 
@@ -217,12 +226,12 @@ and +to_hash_groups+ works similarly:
217
226
  # SELECT * FROM artists
218
227
  # => {"YJM"=>[{:id=>1, :name=>"YJM"}, {:id=>10, :name=>"YJM"}], ...}
219
228
 
220
- Model datasets have a +to_hash+ method that can be called without any
229
+ Model datasets have a +as_hash+ method that can be called without any
221
230
  arguments, in which case it will use the primary key as the key and
222
231
  the model object as the value. This can be used to easily create an
223
232
  identity map:
224
233
 
225
- artist_names = Artist.to_hash
234
+ artist_names = Artist.as_hash
226
235
  # SELECT * FROM artists
227
236
  # => {1=>#<Artist @values={:id=>1, :name=>"YGM"}>,
228
237
  # 2=>#<Artist @values={:id=>2, :name=>"AS"}>}
@@ -230,7 +239,7 @@ identity map:
230
239
  There is no equivalent handling to +to_hash_groups+, since there would
231
240
  only be one matching record, as the primary key must be unique.
232
241
 
233
- Note that +to_hash+ never modifies the columns selected. However, just
242
+ Note that +as_hash+ never modifies the columns selected. However, just
234
243
  like Sequel has a +select_map+ method to modify the columns selected and
235
244
  return an array, Sequel also has a +select_hash+ method to modify the
236
245
  columns selected and return a hash:
@@ -260,8 +269,8 @@ be using:
260
269
  1. Methods that return row(s), discussed above
261
270
  2. Methods that return modified datasets, discussed below
262
271
 
263
- Sequel uses a method chaining, functional style API to
264
- modify datasets. Let's start with a simple example.
272
+ Sequel datasets are frozen and use a method chaining, functional style API
273
+ that returns modified datasets. Let's start with a simple example.
265
274
 
266
275
  This is a basic dataset that includes all records in the
267
276
  table +artists+:
@@ -273,7 +282,7 @@ Let's say we are only interested in the artists whose names
273
282
  start with "A":
274
283
 
275
284
  ds2 = ds1.where(Sequel.like(:name, 'A%'))
276
- # SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
285
+ # SELECT * FROM artists WHERE (name LIKE 'A%' ESCAPE '\')
277
286
 
278
287
  Here we see that +where+ returns a dataset that adds a +WHERE+
279
288
  clause to the query. It's important to note that +where+ does
@@ -282,10 +291,9 @@ not modify the receiver:
282
291
  ds1
283
292
  # SELECT * FROM artists
284
293
  ds2
285
- # SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
294
+ # SELECT * FROM artists WHERE (name LIKE 'A%' ESCAPE '\')
286
295
 
287
- In Sequel, most dataset methods that you will be using will
288
- not modify the dataset itself, so you can freely use the dataset in multiple
296
+ In Sequel, dataset methods do not modify the dataset itself, so you can freely use the dataset in multiple
289
297
  places without worrying that its usage in one place will affect its usage
290
298
  in another place. This is what is meant by a functional style API.
291
299
 
@@ -293,7 +301,7 @@ Let's say we only want to select the id and name columns, and that
293
301
  we want to order by name:
294
302
 
295
303
  ds3 = ds2.order(:name).select(:id, :name)
296
- # SELECT id, name FROM artists WHERE name LIKE 'A%' ESCAPE '\' ORDER BY name
304
+ # SELECT id, name FROM artists WHERE (name LIKE 'A%' ESCAPE '\') ORDER BY name
297
305
 
298
306
  Note how you don't need to assign the returned value of order to a variable,
299
307
  and then call select on that. Because order just returns a dataset, you can
@@ -315,54 +323,57 @@ below.
315
323
  === Hashes
316
324
 
317
325
  The most common format for providing filters is via a hash. In general, Sequel
318
- treats conditions specified with a hash as equality or inclusion. What type
326
+ treats conditions specified with a hash as equality, inclusion, or identity. What type
319
327
  of condition is used depends on the values in the hash.
320
328
 
321
329
  Unless Sequel has special support for the value's class, it uses a simple
322
330
  equality statement:
323
331
 
324
- Artist.where(:id=>1)
325
- # SELECT * FROM artists WHERE id = 1
332
+ Artist.where(id: 1)
333
+ # SELECT * FROM artists WHERE (id = 1)
326
334
 
327
- Artist.where(:name=>'YJM')
328
- # SELECT * FROM artists WHERE name = 'YJM'
335
+ Artist.where(name: 'YJM')
336
+ # SELECT * FROM artists WHERE (name = 'YJM')
329
337
 
330
- For arrays, Sequel uses the IN operator.
338
+ For arrays, Sequel uses the IN operator with a value list:
331
339
 
332
- Artist.where(:id=>[1, 2])
333
- # SELECT * FROM artists WHERE id IN (1, 2)
340
+ Artist.where(id: [1, 2])
341
+ # SELECT * FROM artists WHERE (id IN (1, 2))
334
342
 
335
343
  For datasets, Sequel uses the IN operator with a subselect:
336
344
 
337
- Artist.where(:id=>Album.select(:artist_id))
338
- # SELECT * FROM artists WHERE id IN (
339
- # SELECT artist_id FROM albums)
345
+ Artist.where(id: Album.select(:artist_id))
346
+ # SELECT * FROM artists WHERE (id IN (
347
+ # SELECT artist_id FROM albums))
340
348
 
341
349
  For boolean values such as nil, true, and false, Sequel uses the IS operator:
342
350
 
343
- Artist.where(:id=>nil)
344
- # SELECT * FROM artists WHERE id IS NULL
351
+ Artist.where(id: nil)
352
+ # SELECT * FROM artists WHERE (id IS NULL)
345
353
 
346
354
  For ranges, Sequel uses a pair of inequality statements:
347
355
 
348
- Artist.where(:id=>1..5)
349
- # SELECT * FROM artists WHERE id >= 1 AND id <= 5
356
+ Artist.where(id: 1..5)
357
+ # SELECT * FROM artists WHERE ((id >= 1) AND (id <= 5))
358
+
359
+ Artist.where(id: 1...5)
360
+ # SELECT * FROM artists WHERE ((id >= 1) AND (id < 5))
350
361
 
351
362
  Finally, for regexps, Sequel uses an SQL regular expression. Note that this
352
363
  is probably only supported on PostgreSQL and MySQL.
353
364
 
354
- Artist.where(:name=>/JM$/)
355
- # SELECT * FROM artists WHERE name ~ 'JM$'
365
+ Artist.where(name: /JM$/)
366
+ # SELECT * FROM artists WHERE (name ~ 'JM$')
356
367
 
357
368
  If there are multiple arguments in the hash, the filters are ANDed together:
358
369
 
359
- Artist.where(:id=>1, :name=>/JM$/)
360
- # SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
370
+ Artist.where(id: 1, name: /JM$/)
371
+ # SELECT * FROM artists WHERE ((id = 1) AND (name ~ 'JM$'))
361
372
 
362
373
  This works the same as if you used two separate +where+ calls:
363
374
 
364
- Artist.where(:id=>1).where(:name=>/JM$/)
365
- # SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
375
+ Artist.where(id: 1).where(name: /JM$/)
376
+ # SELECT * FROM artists WHERE ((id = 1) AND (name ~ 'JM$'))
366
377
 
367
378
  === Array of Two Element Arrays
368
379
 
@@ -371,28 +382,28 @@ advantage to using an array of two element arrays is that it allows you to
371
382
  duplicate keys, so you can do:
372
383
 
373
384
  Artist.where([[:name, /JM$/], [:name, /^YJ/]])
374
- # SELECT * FROM artists WHERE name ~ 'JM$' AND name ~ '^YJ'
385
+ # SELECT * FROM artists WHERE ((name ~ 'JM$')) AND ((name ~ '^YJ'))
375
386
 
376
387
  === Virtual Row Blocks
377
388
 
378
389
  If a block is passed to a filter, it is treated as a virtual row block:
379
390
 
380
391
  Artist.where{id > 5}
381
- # SELECT * FROM artists WHERE id > 5
392
+ # SELECT * FROM artists WHERE (id > 5)
382
393
 
383
394
  You can learn more about virtual row blocks in the {"Virtual Rows" guide}[rdoc-ref:doc/virtual_rows.rdoc].
384
395
 
385
396
  You can provide both regular arguments and a block, in which case the results
386
397
  will be ANDed together:
387
398
 
388
- Artist.where(:name=>'A'...'M'){id > 5}
389
- # SELECT * FROM artists WHERE name >= 'A' AND name < 'M' AND id > 5
399
+ Artist.where(name: 'A'...'M'){id > 5}
400
+ # SELECT * FROM artists WHERE ((name >= 'A') AND (name < 'M') AND (id > 5))
390
401
 
391
402
  Using virtual row blocks, what you can do with single entry hash or an array with
392
403
  a single two element array can also be done using the =~ method:
393
404
 
394
405
  Artist.where{id =~ 5}
395
- # SELECT * FROM artists WHERE id = 5
406
+ # SELECT * FROM artists WHERE (id = 5)
396
407
 
397
408
  === Symbols
398
409
 
@@ -420,43 +431,44 @@ method is Sequel.[], which takes any object and wraps it in a SQL::Expression
420
431
  object. In most cases, the SQL::Expression returned supports the & operator for
421
432
  +AND+, the | operator for +OR+, and the ~ operator for inversion:
422
433
 
423
- Artist.where(Sequel.like(:name, 'Y%') & (Sequel[:b=>1] | Sequel.~(:c=>3)))
424
- # SELECT * FROM artists WHERE name LIKE 'Y%' ESCAPE '\' AND (b = 1 OR c != 3)
434
+ Artist.where(Sequel.like(:name, 'Y%') & (Sequel[{b: 1}] | Sequel.~(c: 3)))
435
+ # SELECT * FROM artists WHERE ((name LIKE 'Y%' ESCAPE '\') AND ((b = 1) OR (c != 3)))
425
436
 
426
437
  You can combine these expression operators with the virtual row support:
427
438
 
428
439
  Artist.where{(a > 1) & ~((b(c) < 1) | d)}
429
- # SELECT * FROM artists WHERE a > 1 AND b(c) >= 1 AND NOT d
440
+ # SELECT * FROM artists WHERE ((a > 1) AND (b(c) >= 1) AND NOT d)
430
441
 
431
442
  Note the use of parentheses when using the & and | operators, as they have lower
432
443
  precedence than other operators. The following will not work:
433
444
 
434
445
  Artist.where{a > 1 & ~(b(c) < 1 | d)}
435
- # Raises a TypeError, as it calls Integer#| with a Sequel::SQL::Identifier
446
+ # Raises a TypeError
436
447
 
437
448
  === Strings with Placeholders
438
449
 
439
- Assuming you want to get your hands dirty and write some SQL, Sequel allows you
440
- to use strings using placeholders for the values:
450
+ Assuming you want to get your hands dirty and use SQL fragments in filters, Sequel allows you
451
+ to do so if you explicitly mark the strings as literal strings using +Sequel.lit+. You can
452
+ use placeholders in the string and pass arguments for the placeholders:
441
453
 
442
- Artist.where("name LIKE ?", 'Y%')
443
- # SELECT * FROM artists WHERE name LIKE 'Y%'
454
+ Artist.where(Sequel.lit("name LIKE ?", 'Y%'))
455
+ # SELECT * FROM artists WHERE (name LIKE 'Y%')
444
456
 
445
457
  This is the most common type of placeholder, where each question mark is substituted
446
458
  with the next argument:
447
459
 
448
- Artist.where("name LIKE ? AND id = ?", 'Y%', 5)
449
- # SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
460
+ Artist.where(Sequel.lit("name LIKE ? AND id = ?", 'Y%', 5))
461
+ # SELECT * FROM artists WHERE (name LIKE 'Y%' AND id = 5)
450
462
 
451
463
  You can also use named placeholders with a hash, where the named placeholders use
452
464
  colons before the placeholder names:
453
465
 
454
- Artist.where("name LIKE :name AND id = :id", :name=>'Y%', :id=>5)
455
- # SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
466
+ Artist.where(Sequel.lit("name LIKE :name AND id = :id", name: 'Y%', id: 5))
467
+ # SELECT * FROM artists WHERE (name LIKE 'Y%' AND id = 5)
456
468
 
457
469
  You don't have to provide any placeholders if you don't want to:
458
470
 
459
- Artist.where("id = 2")
471
+ Artist.where(Sequel.lit("id = 2"))
460
472
  # SELECT * FROM artists WHERE id = 2
461
473
 
462
474
  However, if you are using any untrusted input, you should definitely be using placeholders.
@@ -464,9 +476,9 @@ In general, unless you are hardcoding values in the strings, you should use plac
464
476
  You should never pass a string that has been built using interpolation, unless you are
465
477
  sure of what you are doing.
466
478
 
467
- Artist.where("id = #{params[:id]}") # Don't do this!
468
- Artist.where("id = ?", params[:id]) # Do this instead
469
- Artist.where(:id=>params[:id].to_i) # Even better
479
+ Artist.where(Sequel.lit("id = #{params[:id]}")) # Don't do this!
480
+ Artist.where(Sequel.lit("id = ?", params[:id])) # Do this instead
481
+ Artist.where(id: params[:id].to_i) # Even better
470
482
 
471
483
  === Inverting
472
484
 
@@ -474,53 +486,53 @@ You may be wondering how to specify a not equals condition in Sequel, or the NOT
474
486
  operator. Sequel has generic support for inverting conditions, so to write a not
475
487
  equals condition, you write an equals condition, and invert it:
476
488
 
477
- Artist.where(:id=>5).invert
478
- # SELECT * FROM artists WHERE id != 5
489
+ Artist.where(id: 5).invert
490
+ # SELECT * FROM artists WHERE (id != 5)
479
491
 
480
492
  Note that +invert+ inverts the entire filter:
481
493
 
482
- Artist.where(:id=>5).where{name > 'A'}.invert
483
- # SELECT * FROM artists WHERE id != 5 OR name <= 'A'
494
+ Artist.where(id: 5).where{name > 'A'}.invert
495
+ # SELECT * FROM artists WHERE ((id != 5) OR (name <= 'A'))
484
496
 
485
497
  In general, +invert+ is used rarely, since +exclude+ allows you to invert only specific
486
498
  filters:
487
499
 
488
- Artist.exclude(:id=>5)
489
- # SELECT * FROM artists WHERE id != 5
500
+ Artist.exclude(id: 5)
501
+ # SELECT * FROM artists WHERE (id != 5)
490
502
 
491
- Artist.where(:id=>5).exclude{name > 'A'}
492
- # SELECT * FROM artists WHERE id = 5 OR name <= 'A'
503
+ Artist.where(id: 5).exclude{name > 'A'}
504
+ # SELECT * FROM artists WHERE ((id = 5) OR (name <= 'A')
493
505
 
494
506
  So to do a NOT IN with an array:
495
507
 
496
- Artist.exclude(:id=>[1, 2])
497
- # SELECT * FROM artists WHERE id NOT IN (1, 2)
508
+ Artist.exclude(id: [1, 2])
509
+ # SELECT * FROM artists WHERE (id NOT IN (1, 2))
498
510
 
499
511
  Or to use the NOT LIKE operator:
500
512
 
501
513
  Artist.exclude(Sequel.like(:name, '%J%'))
502
- # SELECT * FROM artists WHERE name NOT LIKE '%J%' ESCAPE '\'
514
+ # SELECT * FROM artists WHERE (name NOT LIKE '%J%' ESCAPE '\')
503
515
 
504
516
  You can use Sequel.~ to negate expressions:
505
517
 
506
- Artist.where(Sequel.~(:id=>5))
518
+ Artist.where(Sequel.~(id: 5))
507
519
  # SELECT * FROM artists WHERE id != 5
508
520
 
509
521
  On Sequel expression objects, you can use ~ to negate them:
510
522
 
511
523
  Artist.where(~Sequel.like(:name, '%J%'))
512
- # SELECT * FROM artists WHERE name NOT LIKE '%J%' ESCAPE '\'
524
+ # SELECT * FROM artists WHERE (name NOT LIKE '%J%' ESCAPE '\')
513
525
 
514
- On Ruby 1.9+, you can use !~ on Sequel expressions to create negated expressions:
526
+ You can use !~ on Sequel expressions to create negated expressions:
515
527
 
516
- Artist.where{ id !~ 5}
517
- # SELECT * FROM artists WHERE id != 5
528
+ Artist.where{id !~ 5}
529
+ # SELECT * FROM artists WHERE (id != 5)
518
530
 
519
531
  === Removing
520
532
 
521
533
  To remove all existing filters, use +unfiltered+:
522
534
 
523
- Artist.where(:id=>1).unfiltered
535
+ Artist.where(id: 1).unfiltered
524
536
  # SELECT * FROM artists
525
537
 
526
538
  == Ordering
@@ -555,14 +567,17 @@ If you want to add a column to the beginning of the existing order:
555
567
  === Reversing
556
568
 
557
569
  Just like you can invert an existing filter, you can reverse an existing
558
- order, using +reverse+:
570
+ order, using +reverse+ without an order:
559
571
 
560
572
  Artist.order(:id).reverse
561
573
  # SELECT FROM artists ORDER BY id DESC
562
574
 
563
- As you might expect, +reverse+ is not used all that much. In general,
564
- <tt>Sequel.desc</tt> is used more commonly to specify a descending order
565
- for columns:
575
+ Alternatively, you can provide reverse with the order:
576
+
577
+ Artist.reverse(:id)
578
+ # SELECT FROM artists ORDER BY id DESC
579
+
580
+ To specify a single entry be reversed, <tt>Sequel.desc</tt> can be used:
566
581
 
567
582
  Artist.order(Sequel.desc(:id))
568
583
  # SELECT FROM artists ORDER BY id DESC
@@ -658,7 +673,7 @@ You can also call the +offset+ method separately:
658
673
  Either of these would return the 11th through 15th records in the original
659
674
  dataset.
660
675
 
661
- To remove a limit from a dataset, use +unlimited+:
676
+ To remove a limit and offset from a dataset, use +unlimited+:
662
677
 
663
678
  Artist.limit(5, 10).unlimited
664
679
  # SELECT * FROM artists
@@ -709,50 +724,46 @@ filters the results after the grouping has been applied, instead of
709
724
  before. One possible use is if you only wanted to return artists
710
725
  who had at least 10 albums:
711
726
 
712
- Album.group_and_count(:artist_id).having{count(:*){} >= 10}
727
+ Album.group_and_count(:artist_id).having{count.function.* >= 10}
713
728
  # SELECT artist_id, count(*) AS count FROM albums
714
- # GROUP BY artist_id HAVING count(*) >= 10
729
+ # GROUP BY artist_id HAVING (count(*) >= 10)
715
730
 
716
731
  Both the WHERE clause and the HAVING clause are removed by +unfiltered+:
717
732
 
718
- Album.group_and_count(:artist_id).having{count(:*){} >= 10}.
733
+ Album.group_and_count(:artist_id).having{count.function.* >= 10}.
719
734
  where(:name.like('A%')).unfiltered
720
735
  # SELECT artist_id, count(*) AS count FROM albums GROUP BY artist_id
721
736
 
722
737
  == Joins
723
738
 
724
- Sequel makes it very easy to join a dataset to another table or dataset.
739
+ Sequel has support for many different SQL join types.
725
740
  The underlying method used is +join_table+:
726
741
 
727
- Album.join_table(:inner, :artists, :id=>:artist_id)
742
+ Album.join_table(:inner, :artists, id: :artist_id)
728
743
  # SELECT * FROM albums
729
- # INNER JOIN artists ON artists.id = albums.artist_id
744
+ # INNER JOIN artists ON (artists.id = albums.artist_id)
730
745
 
731
746
  In most cases, you won't call +join_table+ directly, as Sequel provides
732
747
  shortcuts for all common (and most uncommon) join types. For example
733
748
  +join+ does an inner join:
734
749
 
735
- Album.join(:artists, :id=>:artist_id)
750
+ Album.join(:artists, id: :artist_id)
736
751
  # SELECT * FROM albums
737
- # INNER JOIN artists ON artists.id = albums.artist_id
752
+ # INNER JOIN artists ON (artists.id = albums.artist_id))))
738
753
 
739
754
  And +left_join+ does a LEFT JOIN:
740
755
 
741
- Album.left_join(:artists, :id=>:artist_id)
756
+ Album.left_join(:artists, id: :artist_id)
742
757
  # SELECT * FROM albums
743
- # LEFT JOIN artists ON artists.id = albums.artist_id
758
+ # LEFT JOIN artists ON (artists.id = albums.artist_id)
744
759
 
745
760
  === Table/Dataset to Join
746
761
 
747
762
  For all of these specialized join methods, the first argument is
748
763
  generally the name of the table to which you are joining. However, you
749
- can also provide a model class:
750
-
751
- Album.join(Artist, :id=>:artist_id)
752
-
753
- Or a dataset, in which case a subselect is used:
764
+ can also provide a dataset, in which case a subselect is used:
754
765
 
755
- Album.join(Artist.where{name < 'A'}, :id=>:artist_id)
766
+ Album.join(Artist.where{name < 'A'}, id: :artist_id)
756
767
  # SELECT * FROM albums
757
768
  # INNER JOIN (SELECT * FROM artists WHERE (name < 'A')) AS t1
758
769
  # ON (t1.id = albums.artist_id)
@@ -768,80 +779,78 @@ a few minor exceptions.
768
779
  A hash used as the join conditions operates similarly to a filter,
769
780
  except that unqualified symbol keys are automatically qualified
770
781
  with the table from the first argument, and unqualified symbol values
771
- are automatically qualified with the first table or the last table
772
- joined. This implicit qualification is one of the reasons that joins
773
- in Sequel are easy to specify:
782
+ are automatically qualified with the last table joined (or the first
783
+ table in the dataset if there hasn't been a previous join):
774
784
 
775
- Album.join(:artists, :id=>:artist_id)
785
+ Album.join(:artists, id: :artist_id)
776
786
  # SELECT * FROM albums
777
- # INNER JOIN artists ON artists.id = albums.artist_id
787
+ # INNER JOIN artists ON (artists.id = albums.artist_id)
778
788
 
779
- Note how the <tt>:id</tt> symbol is automatically qualified with +artists+,
789
+ Note how the +id+ symbol is automatically qualified with +artists+,
780
790
  while the +artist_id+ symbol is automatically qualified with +albums+.
781
791
 
782
792
  Because Sequel uses the last joined table for implicit qualifications
783
793
  of values, you can do things like:
784
794
 
785
- Album.join(:artists, :id=>:artist_id).
786
- join(:members, :artist_id=>:id)
795
+ Album.join(:artists, id: :artist_id).
796
+ join(:members, artist_id: :id)
787
797
  # SELECT * FROM albums
788
- # INNER JOIN artists ON artists.id = albums.artist_id
789
- # INNER JOIN members ON members.artist_id = artists.id
798
+ # INNER JOIN artists ON (artists.id = albums.artist_id)
799
+ # INNER JOIN members ON (members.artist_id = artists.id)
790
800
 
791
801
  Note that when joining to the +members+ table, +artist_id+ is qualified
792
802
  with +members+ and +id+ is qualified with +artists+.
793
803
 
794
804
  While a good default, implicit qualification is not always correct:
795
805
 
796
- Album.join(:artists, :id=>:artist_id).
797
- join(:tracks, :album_id=>:id)
806
+ Album.join(:artists, id: :artist_id).
807
+ join(:tracks, album_id: :id)
798
808
  # SELECT * FROM albums
799
- # INNER JOIN artists ON artists.id = albums.artist_id
800
- # INNER JOIN tracks ON tracks.album_id = artists.id
809
+ # INNER JOIN artists ON (artists.id = albums.artist_id)
810
+ # INNER JOIN tracks ON (tracks.album_id = artists.id)
801
811
 
802
812
  Note here how +id+ is qualified with +artists+ instead of +albums+. This
803
813
  is wrong as the foreign key <tt>tracks.album_id</tt> refers to <tt>albums.id</tt>, not
804
814
  <tt>artists.id</tt>. To fix this, you need to explicitly qualify when joining:
805
815
 
806
- Album.join(:artists, :id=>:artist_id).
807
- join(:tracks, :album_id=>Sequel[:albums][:id])
816
+ Album.join(:artists, id: :artist_id).
817
+ join(:tracks, album_id: Sequel[:albums][:id])
808
818
  # SELECT * FROM albums
809
- # INNER JOIN artists ON artists.id = albums.artist_id
810
- # INNER JOIN tracks ON tracks.album_id = albums.id
819
+ # INNER JOIN artists ON (artists.id = albums.artist_id)
820
+ # INNER JOIN tracks ON (tracks.album_id = albums.id)
811
821
 
812
822
  Just like in filters, an array of two element arrays is treated the same
813
823
  as a hash, but allows for duplicate keys:
814
824
 
815
825
  Album.join(:artists, [[:id, :artist_id], [:id, 1..5]])
816
826
  # SELECT * FROM albums INNER JOIN artists
817
- # ON artists.id = albums.artist_id
818
- # AND artists.id >= 1 AND artists.id <= 5
827
+ # ON ((artists.id = albums.artist_id)
828
+ # AND (artists.id >= 1) AND (artists.id <= 5))
819
829
 
820
830
  And just like in the hash case, unqualified symbol elements in the
821
831
  array are implicitly qualified.
822
832
 
823
833
  By default, Sequel only qualifies unqualified symbols in the conditions. However,
824
- You can provide an options hash with a <tt>:qualify=>:deep</tt> option to do a deep
834
+ You can provide an options hash with a <tt>qualify: :deep</tt> option to do a deep
825
835
  qualification, which can qualify subexpressions. For example, let's say you are doing
826
836
  a JOIN using case insensitive string comparison:
827
837
 
828
838
  Album.join(:artists, {Sequel.function(:lower, :name) =>
829
839
  Sequel.function(:lower, :artist_name)},
830
- :qualify => :deep)
840
+ qualify: :deep)
831
841
  # SELECT * FROM albums INNER JOIN artists
832
842
  # ON (lower(artists.name) = lower(albums.artist_name))
833
843
 
834
- Note how the arguments to lower were qualified correctly in both cases. Starting in Sequel 4,
835
- the <tt>:qualify=>:deep</tt> option is going to become the default.
844
+ Note how the arguments to lower were qualified correctly in both cases.
836
845
 
837
846
  ==== USING Joins
838
847
 
839
848
  The most common type of join conditions is a JOIN ON, as displayed
840
849
  above. However, the SQL standard allows for join conditions to be
841
- specified with JOIN USING, which Sequel makes easy to use.
850
+ specified with JOIN USING, assuming the column name is the same in
851
+ both tables.
842
852
 
843
- JOIN USING is useful when the columns you are using have the same
844
- names in both tables. For example, if instead of having a primary
853
+ For example, if instead of having a primary
845
854
  column named +id+ in all of your tables, you use +artist_id+ in your
846
855
  +artists+ table and +album_id+ in your +albums+ table, you could do:
847
856
 
@@ -852,7 +861,7 @@ See here how you specify the USING columns as an array of symbols.
852
861
 
853
862
  ==== NATURAL Joins
854
863
 
855
- NATURAL Joins take it one step further than USING joins, by assuming
864
+ NATURAL joins take it one step further than USING joins, by assuming
856
865
  that all columns with the same names in both tables should be
857
866
  used for joining:
858
867
 
@@ -875,12 +884,12 @@ being used. For example, lets say you wanted to join the albums
875
884
  and artists tables, but only want albums where the artist's name
876
885
  comes before the album's name.
877
886
 
878
- Album.join(:artists, :id=>:artist_id) do |j, lj, js|
887
+ Album.join(:artists, id: :artist_id) do |j, lj, js|
879
888
  Sequel[j][:name] < Sequel[lj][:name]
880
889
  end
881
890
  # SELECT * FROM albums INNER JOIN artists
882
- # ON artists.id = albums.artist_id
883
- # AND artists.name < albums.name
891
+ # ON ((artists.id = albums.artist_id)
892
+ # AND (artists.name < albums.name))
884
893
 
885
894
  Because greater than can't be expressed with a hash in Sequel, you
886
895
  need to use a block and qualify the tables manually.
@@ -905,7 +914,7 @@ Using multiple FROM tables and setting conditions in the WHERE clause is
905
914
  an old-school way of joining tables:
906
915
 
907
916
  DB.from(:albums, :artists).where{{artists[:id]=>albums[:artist_id]}}
908
- # SELECT * FROM albums, artists WHERE artists.id = albums.artist_id
917
+ # SELECT * FROM albums, artists WHERE (artists.id = albums.artist_id)
909
918
 
910
919
  === Using the current dataset in a subselect
911
920
 
@@ -916,7 +925,7 @@ Here's an example using +from_self+:
916
925
  # SELECT * FROM (SELECT * FROM albums ORDER BY artist_id LIMIT 100)
917
926
  # AS t1 GROUP BY artist_id
918
927
 
919
- This is slightly different than without +from_self+:
928
+ This is different than without +from_self+:
920
929
 
921
930
  Album.order(:artist_id).limit(100).group(:artist_id)
922
931
  # SELECT * FROM albums GROUP BY artist_id ORDER BY name LIMIT 100
@@ -937,8 +946,8 @@ current transaction commits. You just use the +for_update+ dataset
937
946
  method when returning the rows:
938
947
 
939
948
  DB.transaction do
940
- album = Album.for_update.first(:id=>1)
941
- # SELECT * FROM albums WHERE id = 1 FOR UPDATE
949
+ album = Album.for_update.first(id: 1)
950
+ # SELECT * FROM albums WHERE (id = 1) FOR UPDATE
942
951
  album.num_tracks += 1
943
952
  album.save
944
953
  end
@@ -956,7 +965,7 @@ stateless nature.
956
965
 
957
966
  == Custom SQL
958
967
 
959
- Sequel makes it easy to use custom SQL by providing it to the <tt>Database#[]</tt>
968
+ Sequel makes it easy to use custom SQL for the query by providing it to the <tt>Database#[]</tt>
960
969
  method as a string:
961
970
 
962
971
  DB["SELECT * FROM artists"]
@@ -973,7 +982,7 @@ With either of these methods, you can use placeholders:
973
982
  DB["SELECT * FROM artists WHERE id = ?", 5]
974
983
  # SELECT * FROM artists WHERE id = 5
975
984
 
976
- DB[:albums].with_sql("SELECT * FROM artists WHERE id = :id", :id=>5)
985
+ DB[:albums].with_sql("SELECT * FROM artists WHERE id = :id", id: 5)
977
986
  # SELECT * FROM artists WHERE id = 5
978
987
 
979
988
  Note that if you specify the dataset using custom SQL, you can still call the dataset
@@ -982,6 +991,13 @@ modification methods, but in many cases they will appear to have no affect:
982
991
  DB["SELECT * FROM artists"].select(:name).order(:id)
983
992
  # SELECT * FROM artists
984
993
 
994
+ You can use the implicit_subquery extension to automatically wrap queries that use
995
+ custom SQL in subqueries if a method is called that would modify the SQL:
996
+
997
+ DB.extension :implicit_subquery
998
+ DB["SELECT * FROM artists"].select(:name).order(:id)
999
+ # SELECT name FROM (SELECT * FROM artists) AS t1 ORDER BY id"
1000
+
985
1001
  If you must drop down to using custom SQL, it's recommended that you only do so for
986
1002
  specific parts of a query. For example, if the reason you are using custom SQL is
987
1003
  to use a custom operator in the database in the SELECT clause:
@@ -1003,12 +1019,12 @@ If you just want to know whether the current dataset would return any rows, use
1003
1019
  # SELECT 1 FROM albums LIMIT 1
1004
1020
  # => false
1005
1021
 
1006
- Album.where(:id=>0).empty?
1007
- # SELECT 1 FROM albums WHERE id = 0 LIMIT 1
1022
+ Album.where(id: 0).empty?
1023
+ # SELECT 1 FROM albums WHERE (id = 0) LIMIT 1
1008
1024
  # => true
1009
1025
 
1010
1026
  Album.where(Sequel.like(:name, 'R%')).empty?
1011
- # SELECT 1 FROM albums WHERE name LIKE 'R%' ESCAPE '\' LIMIT 1
1027
+ # SELECT 1 FROM albums WHERE (name LIKE 'R%' ESCAPE '\') LIMIT 1
1012
1028
  # => false
1013
1029
 
1014
1030
  == Aggregate Calculations
@@ -1022,22 +1038,29 @@ for each of these aggregate functions.
1022
1038
  Album.count
1023
1039
  # SELECT count(*) AS count FROM albums LIMIT 1
1024
1040
  # => 2
1025
-
1041
+
1042
+ If you pass an expression to count, it will return the number of records where
1043
+ that expression in not NULL:
1044
+
1045
+ Album.count(:artist_id)
1046
+ # SELECT count(artist_id) AS count FROM albums LIMIT 1
1047
+ # => 1
1048
+
1026
1049
  The other methods take a column argument and call the aggregate function with
1027
1050
  the argument:
1028
1051
 
1029
1052
  Album.sum(:id)
1030
- # SELECT sum(id) FROM albums LIMIT 1
1053
+ # SELECT sum(id) AS sum FROM albums LIMIT 1
1031
1054
  # => 3
1032
1055
 
1033
1056
  Album.avg(:id)
1034
- # SELECT avg(id) FROM albums LIMIT 1
1057
+ # SELECT avg(id) AS avg FROM albums LIMIT 1
1035
1058
  # => 1.5
1036
1059
 
1037
1060
  Album.min(:id)
1038
- # SELECT min(id) FROM albums LIMIT 1
1061
+ # SELECT min(id) AS min FROM albums LIMIT 1
1039
1062
  # => 1
1040
1063
 
1041
1064
  Album.max(:id)
1042
- # SELECT max(id) FROM albums LIMIT 1
1065
+ # SELECT max(id) AS max FROM albums LIMIT 1
1043
1066
  # => 2