sequel 3.21.0 → 3.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,17 +1,20 @@
1
1
  module Sequel
2
2
  class Dataset
3
3
  # ---------------------
4
- # :section: Methods that describe what the dataset supports
4
+ # :section: 4 - Methods that describe what the dataset supports
5
5
  # These methods all return booleans, with most describing whether or not the
6
6
  # dataset supports a feature.
7
7
  # ---------------------
8
8
 
9
- # Method used to check if WITH is supported
10
- WITH_SUPPORTED=:select_with_sql
11
-
12
9
  # Whether this dataset quotes identifiers.
13
10
  def quote_identifiers?
14
- @quote_identifiers
11
+ if defined?(@quote_identifiers)
12
+ @quote_identifiers
13
+ elsif db.respond_to?(:quote_identifiers?)
14
+ @quote_identifiers = db.quote_identifiers?
15
+ else
16
+ @quote_identifiers = false
17
+ end
15
18
  end
16
19
 
17
20
  # Whether this dataset will provide accurate number of rows matched for
@@ -21,22 +24,59 @@ module Sequel
21
24
  true
22
25
  end
23
26
 
27
+ # Whether you must use a column alias list for recursive CTEs (false by
28
+ # default).
29
+ def recursive_cte_requires_column_aliases?
30
+ false
31
+ end
32
+
24
33
  # Whether the dataset requires SQL standard datetimes (false by default,
25
34
  # as most allow strings with ISO 8601 format).
26
35
  def requires_sql_standard_datetimes?
27
36
  false
28
37
  end
29
38
 
39
+ # Whether type specifiers are required for prepared statement/bound
40
+ # variable argument placeholders (i.e. :bv__integer)
41
+ def requires_placeholder_type_specifiers?
42
+ false
43
+ end
44
+
30
45
  # Whether the dataset supports common table expressions (the WITH clause).
31
- def supports_cte?
32
- select_clause_methods.include?(WITH_SUPPORTED)
46
+ # If given, +type+ can be :select, :insert, :update, or :delete, in which case it
47
+ # determines whether WITH is supported for the respective statement type.
48
+ def supports_cte?(type=:select)
49
+ send(:"#{type}_clause_methods").include?(:"#{type}_with_sql")
33
50
  end
34
51
 
35
- # Whether the dataset supports the DISTINCT ON clause, false by default.
52
+ # Whether the dataset supports common table expressions (the WITH clause)
53
+ # in subqueries. If false, applies the WITH clause to the main query, which can cause issues
54
+ # if multiple WITH clauses use the same name.
55
+ def supports_cte_in_subqueries?
56
+ false
57
+ end
58
+
59
+ # Whether the dataset supports or can emulate the DISTINCT ON clause, false by default.
36
60
  def supports_distinct_on?
37
61
  false
38
62
  end
39
63
 
64
+ # Whether the dataset supports CUBE with GROUP BY.
65
+ def supports_group_cube?
66
+ false
67
+ end
68
+
69
+ # Whether the dataset supports ROLLUP with GROUP BY.
70
+ def supports_group_rollup?
71
+ false
72
+ end
73
+
74
+ # Whether this dataset supports the +insert_select+ method for returning all columns values
75
+ # directly from an insert query.
76
+ def supports_insert_select?
77
+ supports_returning?(:insert)
78
+ end
79
+
40
80
  # Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
41
81
  def supports_intersect_except?
42
82
  true
@@ -67,7 +107,29 @@ module Sequel
67
107
  def supports_multiple_column_in?
68
108
  true
69
109
  end
110
+
111
+ # Whether the dataset supports or can fully emulate the DISTINCT ON clause,
112
+ # including respecting the ORDER BY clause, false by default
113
+ def supports_ordered_distinct_on?
114
+ supports_distinct_on?
115
+ end
70
116
 
117
+ # Whether the dataset supports pattern matching by regular expressions.
118
+ def supports_regexp?
119
+ false
120
+ end
121
+
122
+ # Whether the RETURNING clause is supported for the given type of query.
123
+ # +type+ can be :insert, :update, or :delete.
124
+ def supports_returning?(type)
125
+ send(:"#{type}_clause_methods").include?(:"#{type}_returning_sql")
126
+ end
127
+
128
+ # Whether the database supports SELECT *, column FROM table
129
+ def supports_select_all_and_column?
130
+ true
131
+ end
132
+
71
133
  # Whether the dataset supports timezones in literal timestamps
72
134
  def supports_timestamp_timezones?
73
135
  false
@@ -82,5 +144,36 @@ module Sequel
82
144
  def supports_window_functions?
83
145
  false
84
146
  end
147
+
148
+ # Whether the dataset supports WHERE TRUE (or WHERE 1 for databases that
149
+ # that use 1 for true).
150
+ def supports_where_true?
151
+ true
152
+ end
153
+
154
+ private
155
+
156
+ # Whether insert(nil) or insert({}) must be emulated by
157
+ # using at least one value, false by default.
158
+ def insert_supports_empty_values?
159
+ true
160
+ end
161
+
162
+ # Whether using an offset returns an extra row number column that should be
163
+ # eliminated, false by default.
164
+ def offset_returns_row_number_column?
165
+ false
166
+ end
167
+
168
+ # Whether the RETURNING clause is used for the given dataset.
169
+ # +type+ can be :insert, :update, or :delete.
170
+ def uses_returning?(type)
171
+ opts[:returning] && !@opts[:sql] && supports_returning?(type)
172
+ end
173
+
174
+ # Whether the dataset uses WITH ROLLUP/CUBE instead of ROLLUP()/CUBE().
175
+ def uses_with_rollup?
176
+ false
177
+ end
85
178
  end
86
179
  end
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Dataset
3
3
  # ---------------------
4
- # :section: Methods related to dataset graphing
4
+ # :section: 5 - Methods related to dataset graphing
5
5
  # Dataset graphing changes the dataset to yield hashes where keys are table
6
6
  # name symbols and values are hashes representing the columns related to
7
7
  # that table. All of these methods return modified copies of the receiver.
@@ -63,6 +63,7 @@ module Sequel
63
63
  # determines the alias to use.
64
64
  # :implicit_qualifier :: The qualifier of implicit conditions, see #join_table.
65
65
  # :join_type :: The type of join to use (passed to +join_table+). Defaults to :left_outer.
66
+ # :qualify:: The type of qualification to do, see #join_table.
66
67
  # :select :: An array of columns to select. When not used, selects
67
68
  # all columns in the given dataset. When set to false, selects no
68
69
  # columns and is like simply joining the tables, though graph keeps
@@ -72,9 +73,8 @@ module Sequel
72
73
  # alias the table. You will get an error if the the alias (or table) name is
73
74
  # used more than once.
74
75
  def graph(dataset, join_conditions = nil, options = {}, &block)
75
- # Allow the use of a model, dataset, or symbol as the first argument
76
+ # Allow the use of a dataset or symbol as the first argument
76
77
  # Find the table name/dataset based on the argument
77
- dataset = dataset.dataset if dataset.respond_to?(:dataset)
78
78
  table_alias = options[:table_alias]
79
79
  case dataset
80
80
  when Symbol
@@ -90,7 +90,7 @@ module Sequel
90
90
  table_alias ||= dataset_alias((@opts[:num_dataset_sources] || 0)+1)
91
91
  end
92
92
  else
93
- raise Error, "The dataset argument should be a symbol, dataset, or model"
93
+ raise Error, "The dataset argument should be a symbol or dataset"
94
94
  end
95
95
 
96
96
  # Raise Sequel::Error with explanation that the table alias has been used
@@ -106,7 +106,7 @@ module Sequel
106
106
  ds = (!@opts[:graph] && (@opts[:from].length > 1 || @opts[:join])) ? from_self(:alias=>options[:from_self_alias] || first_source) : self
107
107
 
108
108
  # Join the table early in order to avoid cloning the dataset twice
109
- ds = ds.join_table(options[:join_type] || :left_outer, table, join_conditions, :table_alias=>table_alias, :implicit_qualifier=>options[:implicit_qualifier], &block)
109
+ ds = ds.join_table(options[:join_type] || :left_outer, table, join_conditions, :table_alias=>table_alias, :implicit_qualifier=>options[:implicit_qualifier], :qualify=>options[:qualify], &block)
110
110
  opts = ds.opts
111
111
 
112
112
  # Whether to include the table in the result set
@@ -115,7 +115,11 @@ module Sequel
115
115
  add_columns = !ds.opts.include?(:graph_aliases)
116
116
 
117
117
  # Setup the initial graph data structure if it doesn't exist
118
- unless graph = opts[:graph]
118
+ if graph = opts[:graph]
119
+ opts[:graph] = graph = graph.dup
120
+ select = opts[:select].dup
121
+ [:column_aliases, :table_aliases, :column_alias_num].each{|k| graph[k] = graph[k].dup}
122
+ else
119
123
  master = alias_symbol(ds.first_source_alias)
120
124
  raise_alias_error.call if master == table_alias
121
125
  # Master hash storing all .graph related information
@@ -130,10 +134,33 @@ module Sequel
130
134
  # aliased, but are not included if set_graph_aliases
131
135
  # has been used.
132
136
  if add_columns
133
- select = opts[:select] = []
134
- columns.each do |column|
135
- column_aliases[column] = [master, column]
136
- select.push(SQL::QualifiedIdentifier.new(master, column))
137
+ if (select = @opts[:select]) && !select.empty? && !(select.length == 1 && (select.first.is_a?(SQL::ColumnAll)))
138
+ select = select.each do |sel|
139
+ column = case sel
140
+ when Symbol
141
+ _, c, a = split_symbol(sel)
142
+ (a || c).to_sym
143
+ when SQL::Identifier
144
+ sel.value.to_sym
145
+ when SQL::QualifiedIdentifier
146
+ column = sel.column
147
+ column = column.value if column.is_a?(SQL::Identifier)
148
+ column.to_sym
149
+ when SQL::AliasedExpression
150
+ column = sel.aliaz
151
+ column = column.value if column.is_a?(SQL::Identifier)
152
+ column.to_sym
153
+ else
154
+ raise Error, "can't figure out alias to use for graphing for #{sel.inspect}"
155
+ end
156
+ column_aliases[column] = [master, column]
157
+ end
158
+ select = qualified_expression(select, master)
159
+ else
160
+ select = columns.map do |column|
161
+ column_aliases[column] = [master, column]
162
+ SQL::QualifiedIdentifier.new(master, column)
163
+ end
137
164
  end
138
165
  end
139
166
  end
@@ -147,7 +174,6 @@ module Sequel
147
174
 
148
175
  # Add the columns to the selection unless we are ignoring them
149
176
  if add_table && add_columns
150
- select = opts[:select]
151
177
  column_aliases = graph[:column_aliases]
152
178
  ca_num = graph[:column_alias_num]
153
179
  # Which columns to add to the result set
@@ -165,15 +191,16 @@ module Sequel
165
191
  column_alias = :"#{column_alias}_#{column_alias_num}"
166
192
  ca_num[column_alias] += 1
167
193
  end
168
- [column_alias, SQL::QualifiedIdentifier.new(table_alias, column).as(column_alias)]
194
+ [column_alias, SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(table_alias, column), column_alias)]
169
195
  else
170
- [column, SQL::QualifiedIdentifier.new(table_alias, column)]
196
+ ident = SQL::QualifiedIdentifier.new(table_alias, column)
197
+ [column, ident]
171
198
  end
172
199
  column_aliases[col_alias] = [table_alias, column]
173
200
  select.push(identifier)
174
201
  end
175
202
  end
176
- ds
203
+ add_columns ? ds.select(*select) : ds
177
204
  end
178
205
 
179
206
  # This allows you to manually specify the graph aliases to use
@@ -225,7 +252,7 @@ module Sequel
225
252
  column ||= col_alias
226
253
  gas[col_alias] = [table, column]
227
254
  identifier = value || SQL::QualifiedIdentifier.new(table, column)
228
- identifier = SQL::AliasedExpression.new(identifier, col_alias) if value or column != col_alias
255
+ identifier = SQL::AliasedExpression.new(identifier, col_alias) if value || column != col_alias
229
256
  identifier
230
257
  end
231
258
  [identifiers, gas]
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Dataset
3
3
  # ---------------------
4
- # :section: Miscellaneous methods
4
+ # :section: 6 - Miscellaneous methods
5
5
  # These methods don't fit cleanly into another section.
6
6
  # ---------------------
7
7
 
@@ -23,21 +23,17 @@ module Sequel
23
23
  # DB[:posts]
24
24
  #
25
25
  # Sequel::Dataset is an abstract class that is not useful by itself. Each
26
- # database adaptor provides a subclass of Sequel::Dataset, and has
26
+ # database adapter provides a subclass of Sequel::Dataset, and has
27
27
  # the Database#dataset method return an instance of that subclass.
28
28
  def initialize(db, opts = nil)
29
29
  @db = db
30
- @quote_identifiers = db.quote_identifiers? if db.respond_to?(:quote_identifiers?)
31
- @identifier_input_method = db.identifier_input_method if db.respond_to?(:identifier_input_method)
32
- @identifier_output_method = db.identifier_output_method if db.respond_to?(:identifier_output_method)
33
30
  @opts = opts || {}
34
- @row_proc = nil
35
31
  end
36
-
32
+
37
33
  # Define a hash value such that datasets with the same DB, opts, and SQL
38
- # will be consider equal.
34
+ # will be considered equal.
39
35
  def ==(o)
40
- o.is_a?(self.class) && db == o.db && opts == o.opts && sql == o.sql
36
+ o.is_a?(self.class) && db == o.db && opts == o.opts && sql == o.sql
41
37
  end
42
38
 
43
39
  # Alias for ==
@@ -45,15 +41,6 @@ module Sequel
45
41
  self == o
46
42
  end
47
43
 
48
- # Return the dataset as an aliased expression with the given alias. You can
49
- # use this as a FROM or JOIN dataset, or as a column if this dataset
50
- # returns a single row and column.
51
- #
52
- # DB.from(DB[:table].as(:b)) # SELECT * FROM (SELECT * FROM table) AS b
53
- def as(aliaz)
54
- ::Sequel::SQL::AliasedExpression.new(self, aliaz)
55
- end
56
-
57
44
  # Yield a dataset for each server in the connection pool that is tied to that server.
58
45
  # Intended for use in sharded environments where all servers need to be modified
59
46
  # with the same data:
@@ -96,10 +83,10 @@ module Sequel
96
83
  # have a table, raises an error. If the table is aliased, returns the original
97
84
  # table, not the alias
98
85
  #
99
- # DB[:table].first_source_alias
86
+ # DB[:table].first_source_table
100
87
  # # => :table
101
88
  #
102
- # DB[:table___t].first_source_alias
89
+ # DB[:table___t].first_source_table
103
90
  # # => :table
104
91
  def first_source_table
105
92
  source = @opts[:from]
@@ -120,16 +107,48 @@ module Sequel
120
107
  # Define a hash value such that datasets with the same DB, opts, and SQL
121
108
  # will have the same hash value
122
109
  def hash
123
- [db, opts.sort_by{|k| k.to_s}, sql].hash
110
+ [db, opts.sort_by{|k, v| k.to_s}, sql].hash
111
+ end
112
+
113
+ # The String instance method to call on identifiers before sending them to
114
+ # the database.
115
+ def identifier_input_method
116
+ if defined?(@identifier_input_method)
117
+ @identifier_input_method
118
+ elsif db.respond_to?(:identifier_input_method)
119
+ @identifier_input_method = db.identifier_input_method
120
+ else
121
+ @identifier_input_method = nil
122
+ end
123
+ end
124
+
125
+ # The String instance method to call on identifiers before sending them to
126
+ # the database.
127
+ def identifier_output_method
128
+ if defined?(@identifier_output_method)
129
+ @identifier_output_method
130
+ elsif db.respond_to?(:identifier_output_method)
131
+ @identifier_output_method = db.identifier_output_method
132
+ else
133
+ @identifier_output_method = nil
134
+ end
124
135
  end
125
136
 
126
137
  # Returns a string representation of the dataset including the class name
127
138
  # and the corresponding SQL select statement.
128
139
  def inspect
129
- "#<#{self.class}: #{sql.inspect}>"
140
+ c = self.class
141
+ c = c.superclass while c.name.nil? || c.name == ''
142
+ "#<#{c.name}: #{sql.inspect}>"
130
143
  end
131
144
 
132
- # Splits a possible implicit alias in C, handling both SQL::AliasedExpressions
145
+ # The alias to use for the row_number column, used when emulating OFFSET
146
+ # support and for eager limit strategies
147
+ def row_number_column
148
+ :x_sequel_row_number_x
149
+ end
150
+
151
+ # Splits a possible implicit alias in +c+, handling both SQL::AliasedExpressions
133
152
  # and Symbols. Returns an array of two elements, with the first being the
134
153
  # main expression, and the second being the alias.
135
154
  def split_alias(c)
@@ -139,6 +158,8 @@ module Sequel
139
158
  [c_table ? SQL::QualifiedIdentifier.new(c_table, column.to_sym) : column.to_sym, aliaz]
140
159
  when SQL::AliasedExpression
141
160
  [c.expression, c.aliaz]
161
+ when SQL::JoinClause
162
+ [c.table, c.table_alias]
142
163
  else
143
164
  [c, nil]
144
165
  end
@@ -151,6 +172,10 @@ module Sequel
151
172
  # used, where N is an integer starting at 0 and increasing until an
152
173
  # unused one is found.
153
174
  #
175
+ # You can provide a second addition array argument containing symbols
176
+ # that should not be considered valid table aliases. The current aliases
177
+ # for the FROM and JOIN tables are automatically included in this array.
178
+ #
154
179
  # DB[:table].unused_table_alias(:t)
155
180
  # # => :t
156
181
  #
@@ -159,9 +184,11 @@ module Sequel
159
184
  #
160
185
  # DB[:table, :table_0].unused_table_alias(:table)
161
186
  # # => :table_1
162
- def unused_table_alias(table_alias)
187
+ #
188
+ # DB[:table, :table_0].unused_table_alias(:table, [:table_1, :table_2])
189
+ # # => :table_3
190
+ def unused_table_alias(table_alias, used_aliases = [])
163
191
  table_alias = alias_symbol(table_alias)
164
- used_aliases = []
165
192
  used_aliases += opts[:from].map{|t| alias_symbol(t)} if opts[:from]
166
193
  used_aliases += opts[:join].map{|j| j.table_alias ? alias_alias_symbol(j.table_alias) : alias_symbol(j.table)} if opts[:join]
167
194
  if used_aliases.include?(table_alias)
@@ -1,12 +1,12 @@
1
1
  module Sequel
2
2
  class Dataset
3
3
  # ---------------------
4
- # :section: Mutation methods
4
+ # :section: 7 - Mutation methods
5
5
  # These methods modify the receiving dataset and should be used with care.
6
6
  # ---------------------
7
7
 
8
8
  # All methods that should have a ! method added that modifies the receiver.
9
- MUTATION_METHODS = QUERY_METHODS
9
+ MUTATION_METHODS = QUERY_METHODS - [:paginate, :naked]
10
10
 
11
11
  # Setup mutation (e.g. filter!) methods. These operate the same as the
12
12
  # non-! methods, but replace the options of the current dataset with the
@@ -21,17 +21,16 @@ module Sequel
21
21
  def_mutation_method(*MUTATION_METHODS)
22
22
 
23
23
  # Set the method to call on identifiers going into the database for this dataset
24
- attr_accessor :identifier_input_method
24
+ attr_writer :identifier_input_method
25
25
 
26
26
  # Set the method to call on identifiers coming the database for this dataset
27
- attr_accessor :identifier_output_method
27
+ attr_writer :identifier_output_method
28
28
 
29
29
  # Whether to quote identifiers for this dataset
30
30
  attr_writer :quote_identifiers
31
31
 
32
- # The row_proc for this database, should be a Proc that takes
33
- # a single hash argument and returns the object you want
34
- # each to return.
32
+ # The row_proc for this database, should be any object that responds to +call+ with
33
+ # a single hash argument and returns the object you want #each to return.
35
34
  attr_accessor :row_proc
36
35
 
37
36
  # Add a mutation method to this dataset instance.
@@ -40,6 +39,12 @@ module Sequel
40
39
  instance_eval("def #{meth}!(*args, &block); mutation_method(:#{meth}, *args, &block) end", __FILE__, __LINE__)
41
40
  end
42
41
  end
42
+
43
+ # Remove the row_proc from the current dataset.
44
+ def naked!
45
+ self.row_proc = nil
46
+ self
47
+ end
43
48
 
44
49
  private
45
50