activerecord 6.0.0 → 7.2.3

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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -5,6 +5,11 @@ module ActiveRecord
5
5
  module CounterCache
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ included do
9
+ class_attribute :_counter_cache_columns, instance_accessor: false, default: []
10
+ class_attribute :counter_cached_association_names, instance_writer: false, default: []
11
+ end
12
+
8
13
  module ClassMethods
9
14
  # Resets one or more counter caches to their correct value using an SQL
10
15
  # count query. This is useful when adding new counter caches, or if the
@@ -23,12 +28,13 @@ module ActiveRecord
23
28
  # # For the Post with id #1, reset the comments_count
24
29
  # Post.reset_counters(1, :comments)
25
30
  #
26
- # # Like above, but also touch the +updated_at+ and/or +updated_on+
31
+ # # Like above, but also touch the updated_at and/or updated_on
27
32
  # # attributes.
28
33
  # Post.reset_counters(1, :comments, touch: true)
29
34
  def reset_counters(id, *counters, touch: nil)
30
35
  object = find(id)
31
36
 
37
+ updates = {}
32
38
  counters.each do |counter_association|
33
39
  has_many_association = _reflect_on_association(counter_association)
34
40
  unless has_many_association
@@ -47,16 +53,21 @@ module ActiveRecord
47
53
  reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
48
54
  counter_name = reflection.counter_cache_column
49
55
 
50
- updates = { counter_name => object.send(counter_association).count(:all) }
51
-
52
- if touch
53
- names = touch if touch != true
54
- updates.merge!(touch_attributes_with_time(*names))
55
- end
56
+ count_was = object.send(counter_name)
57
+ count = object.send(counter_association).count(:all)
58
+ updates[counter_name] = count if count != count_was
59
+ end
56
60
 
57
- unscoped.where(primary_key => object.id).update_all(updates)
61
+ if touch
62
+ names = touch if touch != true
63
+ names = Array.wrap(names)
64
+ options = names.extract_options!
65
+ touch_updates = touch_attributes_with_time(*names, **options)
66
+ updates.merge!(touch_updates)
58
67
  end
59
68
 
69
+ unscoped.where(primary_key => [object.id]).update_all(updates) if updates.any?
70
+
60
71
  true
61
72
  end
62
73
 
@@ -77,31 +88,32 @@ module ActiveRecord
77
88
  #
78
89
  # ==== Examples
79
90
  #
80
- # # For the Post with id of 5, decrement the comment_count by 1, and
81
- # # increment the action_count by 1
82
- # Post.update_counters 5, comment_count: -1, action_count: 1
91
+ # # For the Post with id of 5, decrement the comments_count by 1, and
92
+ # # increment the actions_count by 1
93
+ # Post.update_counters 5, comments_count: -1, actions_count: 1
83
94
  # # Executes the following SQL:
84
95
  # # UPDATE posts
85
- # # SET comment_count = COALESCE(comment_count, 0) - 1,
86
- # # action_count = COALESCE(action_count, 0) + 1
96
+ # # SET comments_count = COALESCE(comments_count, 0) - 1,
97
+ # # actions_count = COALESCE(actions_count, 0) + 1
87
98
  # # WHERE id = 5
88
99
  #
89
- # # For the Posts with id of 10 and 15, increment the comment_count by 1
90
- # Post.update_counters [10, 15], comment_count: 1
100
+ # # For the Posts with id of 10 and 15, increment the comments_count by 1
101
+ # Post.update_counters [10, 15], comments_count: 1
91
102
  # # Executes the following SQL:
92
103
  # # UPDATE posts
93
- # # SET comment_count = COALESCE(comment_count, 0) + 1
104
+ # # SET comments_count = COALESCE(comments_count, 0) + 1
94
105
  # # WHERE id IN (10, 15)
95
106
  #
96
- # # For the Posts with id of 10 and 15, increment the comment_count by 1
107
+ # # For the Posts with id of 10 and 15, increment the comments_count by 1
97
108
  # # and update the updated_at value for each counter.
98
- # Post.update_counters [10, 15], comment_count: 1, touch: true
109
+ # Post.update_counters [10, 15], comments_count: 1, touch: true
99
110
  # # Executes the following SQL:
100
111
  # # UPDATE posts
101
- # # SET comment_count = COALESCE(comment_count, 0) + 1,
112
+ # # SET comments_count = COALESCE(comments_count, 0) + 1,
102
113
  # # `updated_at` = '2016-10-13T09:59:23-05:00'
103
114
  # # WHERE id IN (10, 15)
104
115
  def update_counters(id, counters)
116
+ id = [id] if composite_primary_key? && id.is_a?(Array) && !id[0].is_a?(Array)
105
117
  unscoped.where!(primary_key => id).update_counters(counters)
106
118
  end
107
119
 
@@ -116,6 +128,7 @@ module ActiveRecord
116
128
  #
117
129
  # * +counter_name+ - The name of the field that should be incremented.
118
130
  # * +id+ - The id of the object that should be incremented or an array of ids.
131
+ # * <tt>:by</tt> - The amount by which to increment the value. Defaults to +1+.
119
132
  # * <tt>:touch</tt> - Touch timestamp columns when updating.
120
133
  # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
121
134
  # touch that column or an array of symbols to touch just those ones.
@@ -126,10 +139,14 @@ module ActiveRecord
126
139
  # DiscussionBoard.increment_counter(:posts_count, 5)
127
140
  #
128
141
  # # Increment the posts_count column for the record with an id of 5
142
+ # # by a specific amount.
143
+ # DiscussionBoard.increment_counter(:posts_count, 5, by: 3)
144
+ #
145
+ # # Increment the posts_count column for the record with an id of 5
129
146
  # # and update the updated_at value.
130
147
  # DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
131
- def increment_counter(counter_name, id, touch: nil)
132
- update_counters(id, counter_name => 1, touch: touch)
148
+ def increment_counter(counter_name, id, by: 1, touch: nil)
149
+ update_counters(id, counter_name => by, touch: touch)
133
150
  end
134
151
 
135
152
  # Decrement a numeric field by one, via a direct SQL update.
@@ -141,6 +158,7 @@ module ActiveRecord
141
158
  #
142
159
  # * +counter_name+ - The name of the field that should be decremented.
143
160
  # * +id+ - The id of the object that should be decremented or an array of ids.
161
+ # * <tt>:by</tt> - The amount by which to decrement the value. Defaults to +1+.
144
162
  # * <tt>:touch</tt> - Touch timestamp columns when updating.
145
163
  # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
146
164
  # touch that column or an array of symbols to touch just those ones.
@@ -151,10 +169,30 @@ module ActiveRecord
151
169
  # DiscussionBoard.decrement_counter(:posts_count, 5)
152
170
  #
153
171
  # # Decrement the posts_count column for the record with an id of 5
172
+ # by a specific amount.
173
+ # DiscussionBoard.decrement_counter(:posts_count, 5, by: 3)
174
+ #
175
+ # # Decrement the posts_count column for the record with an id of 5
154
176
  # # and update the updated_at value.
155
177
  # DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
156
- def decrement_counter(counter_name, id, touch: nil)
157
- update_counters(id, counter_name => -1, touch: touch)
178
+ def decrement_counter(counter_name, id, by: 1, touch: nil)
179
+ update_counters(id, counter_name => -by, touch: touch)
180
+ end
181
+
182
+ def counter_cache_column?(name) # :nodoc:
183
+ _counter_cache_columns.include?(name)
184
+ end
185
+
186
+ def load_schema! # :nodoc:
187
+ super
188
+
189
+ association_names = _reflections.filter_map do |name, reflection|
190
+ next unless reflection.belongs_to? && reflection.counter_cache_column
191
+
192
+ name.to_sym
193
+ end
194
+
195
+ self.counter_cached_association_names |= association_names
158
196
  end
159
197
  end
160
198
 
@@ -162,8 +200,8 @@ module ActiveRecord
162
200
  def _create_record(attribute_names = self.attribute_names)
163
201
  id = super
164
202
 
165
- each_counter_cached_associations do |association|
166
- association.increment_counters
203
+ counter_cached_association_names.each do |association_name|
204
+ association(association_name).increment_counters
167
205
  end
168
206
 
169
207
  id
@@ -173,9 +211,10 @@ module ActiveRecord
173
211
  affected_rows = super
174
212
 
175
213
  if affected_rows > 0
176
- each_counter_cached_associations do |association|
177
- foreign_key = association.reflection.foreign_key.to_sym
178
- unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
214
+ counter_cached_association_names.each do |association_name|
215
+ association = association(association_name)
216
+
217
+ unless destroyed_by_association && _foreign_keys_equal?(destroyed_by_association.foreign_key, association.reflection.foreign_key)
179
218
  association.decrement_counters
180
219
  end
181
220
  end
@@ -184,10 +223,8 @@ module ActiveRecord
184
223
  affected_rows
185
224
  end
186
225
 
187
- def each_counter_cached_associations
188
- _reflections.each do |name, reflection|
189
- yield association(name.to_sym) if reflection.belongs_to? && reflection.counter_cache_column
190
- end
226
+ def _foreign_keys_equal?(fkey1, fkey2)
227
+ fkey1 == fkey2 || Array(fkey1).map(&:to_sym) == Array(fkey2).map(&:to_sym)
191
228
  end
192
229
  end
193
230
  end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+ require "active_support/core_ext/enumerable"
5
+ require "active_support/core_ext/hash/reverse_merge"
6
+
7
+ module ActiveRecord
8
+ class DatabaseConfigurations
9
+ # Expands a connection string into a hash.
10
+ class ConnectionUrlResolver # :nodoc:
11
+ # == Example
12
+ #
13
+ # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
14
+ # ConnectionUrlResolver.new(url).to_hash
15
+ # # => {
16
+ # adapter: "postgresql",
17
+ # host: "localhost",
18
+ # port: 9000,
19
+ # database: "foo_test",
20
+ # username: "foo",
21
+ # password: "bar",
22
+ # pool: "5",
23
+ # timeout: "3000"
24
+ # }
25
+ def initialize(url)
26
+ raise "Database URL cannot be empty" if url.blank?
27
+ @uri = uri_parser.parse(url)
28
+ @adapter = resolved_adapter
29
+
30
+ if @uri.opaque
31
+ @uri.opaque, @query = @uri.opaque.split("?", 2)
32
+ else
33
+ @query = @uri.query
34
+ end
35
+ end
36
+
37
+ # Converts the given URL to a full connection hash.
38
+ def to_hash
39
+ config = raw_config.compact_blank
40
+ config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
41
+ config
42
+ end
43
+
44
+ private
45
+ attr_reader :uri
46
+
47
+ def uri_parser
48
+ @uri_parser ||= URI::RFC2396_Parser.new
49
+ end
50
+
51
+ # Converts the query parameters of the URI into a hash.
52
+ #
53
+ # "localhost?pool=5&reaping_frequency=2"
54
+ # # => { pool: "5", reaping_frequency: "2" }
55
+ #
56
+ # returns empty hash if no query present.
57
+ #
58
+ # "localhost"
59
+ # # => {}
60
+ def query_hash
61
+ Hash[(@query || "").split("&").map { |pair| pair.split("=", 2) }].symbolize_keys
62
+ end
63
+
64
+ def raw_config
65
+ if uri.opaque
66
+ query_hash.merge(
67
+ adapter: @adapter,
68
+ database: uri.opaque
69
+ )
70
+ else
71
+ query_hash.reverse_merge(
72
+ adapter: @adapter,
73
+ username: uri.user,
74
+ password: uri.password,
75
+ port: uri.port,
76
+ database: database_from_path,
77
+ host: uri.hostname
78
+ )
79
+ end
80
+ end
81
+
82
+ def resolved_adapter
83
+ adapter = uri.scheme && @uri.scheme.tr("-", "_")
84
+ if adapter && ActiveRecord.protocol_adapters[adapter]
85
+ adapter = ActiveRecord.protocol_adapters[adapter]
86
+ end
87
+ adapter
88
+ end
89
+
90
+ # Returns name of the database.
91
+ def database_from_path
92
+ if @adapter == "sqlite3"
93
+ # 'sqlite3:/foo' is absolute, because that makes sense. The
94
+ # corresponding relative version, 'sqlite3:foo', is handled
95
+ # elsewhere, as an "opaque".
96
+
97
+ uri.path
98
+ else
99
+ # Only SQLite uses a filename as the "database" name; for
100
+ # anything else, a leading slash would be silly.
101
+
102
+ uri.path.delete_prefix("/")
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -3,35 +3,102 @@
3
3
  module ActiveRecord
4
4
  class DatabaseConfigurations
5
5
  # ActiveRecord::Base.configurations will return either a HashConfig or
6
- # UrlConfig respectively. It will never return a DatabaseConfig object,
6
+ # UrlConfig respectively. It will never return a +DatabaseConfig+ object,
7
7
  # as this is the parent class for the types of database configuration objects.
8
8
  class DatabaseConfig # :nodoc:
9
- attr_reader :env_name, :spec_name
9
+ attr_reader :env_name, :name
10
10
 
11
- def initialize(env_name, spec_name)
11
+ def initialize(env_name, name)
12
12
  @env_name = env_name
13
- @spec_name = spec_name
13
+ @name = name
14
+ @adapter_class = nil
14
15
  end
15
16
 
16
- def replica?
17
+ def adapter_class
18
+ @adapter_class ||= ActiveRecord::ConnectionAdapters.resolve(adapter)
19
+ end
20
+
21
+ def inspect # :nodoc:
22
+ "#<#{self.class.name} env_name=#{@env_name} name=#{@name} adapter_class=#{adapter_class}>"
23
+ end
24
+
25
+ def new_connection
26
+ adapter_class.new(configuration_hash)
27
+ end
28
+
29
+ def validate!
30
+ adapter_class if adapter
31
+
32
+ true
33
+ end
34
+
35
+ def host
17
36
  raise NotImplementedError
18
37
  end
19
38
 
20
- def migrations_paths
39
+ def database
40
+ raise NotImplementedError
41
+ end
42
+
43
+ def _database=(database)
21
44
  raise NotImplementedError
22
45
  end
23
46
 
24
- def url_config?
25
- false
47
+ def adapter
48
+ raise NotImplementedError
26
49
  end
27
50
 
28
- def to_legacy_hash
29
- { env_name => config }
51
+ def pool
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def min_threads
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def max_threads
60
+ raise NotImplementedError
61
+ end
62
+
63
+ def max_queue
64
+ raise NotImplementedError
65
+ end
66
+
67
+ def query_cache
68
+ raise NotImplementedError
69
+ end
70
+
71
+ def checkout_timeout
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def reaping_frequency
76
+ raise NotImplementedError
77
+ end
78
+
79
+ def idle_timeout
80
+ raise NotImplementedError
81
+ end
82
+
83
+ def replica?
84
+ raise NotImplementedError
85
+ end
86
+
87
+ def migrations_paths
88
+ raise NotImplementedError
30
89
  end
31
90
 
32
91
  def for_current_env?
33
92
  env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
34
93
  end
94
+
95
+ def schema_cache_path
96
+ raise NotImplementedError
97
+ end
98
+
99
+ def use_metadata_table?
100
+ raise NotImplementedError
101
+ end
35
102
  end
36
103
  end
37
104
  end
@@ -1,50 +1,172 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActiveRecord
4
6
  class DatabaseConfigurations
5
- # A HashConfig object is created for each database configuration entry that
6
- # is created from a hash.
7
+ # # Active Record Database Hash Config
8
+ #
9
+ # A `HashConfig` object is created for each database configuration entry that is
10
+ # created from a hash.
7
11
  #
8
12
  # A hash config:
9
13
  #
10
- # { "development" => { "database" => "db_name" } }
14
+ # { "development" => { "database" => "db_name" } }
11
15
  #
12
16
  # Becomes:
13
17
  #
14
- # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
15
- # @env_name="development", @spec_name="primary", @config={"database"=>"db_name"}>
16
- #
17
- # ==== Options
18
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
19
+ # @env_name="development", @name="primary", @config={database: "db_name"}>
18
20
  #
19
- # * <tt>:env_name</tt> - The Rails environment, i.e. "development".
20
- # * <tt>:spec_name</tt> - The specification name. In a standard two-tier
21
- # database configuration this will default to "primary". In a multiple
22
- # database three-tier database configuration this corresponds to the name
23
- # used in the second tier, for example "primary_readonly".
24
- # * <tt>:config</tt> - The config hash. This is the hash that contains the
25
- # database adapter, name, and other important information for database
26
- # connections.
21
+ # See ActiveRecord::DatabaseConfigurations for more info.
27
22
  class HashConfig < DatabaseConfig
28
- attr_reader :config
23
+ attr_reader :configuration_hash
29
24
 
30
- def initialize(env_name, spec_name, config)
31
- super(env_name, spec_name)
32
- @config = config
25
+ # Initialize a new `HashConfig` object
26
+ #
27
+ # #### Parameters
28
+ #
29
+ # * `env_name` - The Rails environment, i.e. "development".
30
+ # * `name` - The db config name. In a standard two-tier database configuration
31
+ # this will default to "primary". In a multiple database three-tier database
32
+ # configuration this corresponds to the name used in the second tier, for
33
+ # example "primary_readonly".
34
+ # * `configuration_hash` - The config hash. This is the hash that contains the
35
+ # database adapter, name, and other important information for database
36
+ # connections.
37
+ #
38
+ def initialize(env_name, name, configuration_hash)
39
+ super(env_name, name)
40
+ @configuration_hash = configuration_hash.symbolize_keys.freeze
33
41
  end
34
42
 
35
43
  # Determines whether a database configuration is for a replica / readonly
36
- # connection. If the +replica+ key is present in the config, +replica?+ will
37
- # return +true+.
44
+ # connection. If the `replica` key is present in the config, `replica?` will
45
+ # return `true`.
38
46
  def replica?
39
- config["replica"]
47
+ configuration_hash[:replica]
40
48
  end
41
49
 
42
- # The migrations paths for a database configuration. If the
43
- # +migrations_paths+ key is present in the config, +migrations_paths+
44
- # will return its value.
50
+ # The migrations paths for a database configuration. If the `migrations_paths`
51
+ # key is present in the config, `migrations_paths` will return its value.
45
52
  def migrations_paths
46
- config["migrations_paths"]
53
+ configuration_hash[:migrations_paths]
54
+ end
55
+
56
+ def host
57
+ configuration_hash[:host]
58
+ end
59
+
60
+ def socket # :nodoc:
61
+ configuration_hash[:socket]
62
+ end
63
+
64
+ def database
65
+ configuration_hash[:database]
66
+ end
67
+
68
+ def _database=(database) # :nodoc:
69
+ @configuration_hash = configuration_hash.merge(database: database).freeze
70
+ end
71
+
72
+ def pool
73
+ (configuration_hash[:pool] || 5).to_i
74
+ end
75
+
76
+ def min_threads
77
+ (configuration_hash[:min_threads] || 0).to_i
78
+ end
79
+
80
+ def max_threads
81
+ (configuration_hash[:max_threads] || pool).to_i
82
+ end
83
+
84
+ def query_cache
85
+ configuration_hash[:query_cache]
86
+ end
87
+
88
+ def max_queue
89
+ max_threads * 4
90
+ end
91
+
92
+ def checkout_timeout
93
+ (configuration_hash[:checkout_timeout] || 5).to_f
94
+ end
95
+
96
+ # `reaping_frequency` is configurable mostly for historical reasons, but it
97
+ # could also be useful if someone wants a very low `idle_timeout`.
98
+ def reaping_frequency
99
+ configuration_hash.fetch(:reaping_frequency, 60)&.to_f
100
+ end
101
+
102
+ def idle_timeout
103
+ timeout = configuration_hash.fetch(:idle_timeout, 300).to_f
104
+ timeout if timeout > 0
105
+ end
106
+
107
+ def adapter
108
+ configuration_hash[:adapter]&.to_s
109
+ end
110
+
111
+ # The path to the schema cache dump file for a database. If omitted, the
112
+ # filename will be read from ENV or a default will be derived.
113
+ def schema_cache_path
114
+ configuration_hash[:schema_cache_path]
115
+ end
116
+
117
+ def default_schema_cache_path(db_dir = "db")
118
+ if primary?
119
+ File.join(db_dir, "schema_cache.yml")
120
+ else
121
+ File.join(db_dir, "#{name}_schema_cache.yml")
122
+ end
47
123
  end
124
+
125
+ def lazy_schema_cache_path
126
+ schema_cache_path || default_schema_cache_path
127
+ end
128
+
129
+ def primary? # :nodoc:
130
+ Base.configurations.primary?(name)
131
+ end
132
+
133
+ # Determines whether to dump the schema/structure files and the filename that
134
+ # should be used.
135
+ #
136
+ # If `configuration_hash[:schema_dump]` is set to `false` or `nil` the schema
137
+ # will not be dumped.
138
+ #
139
+ # If the config option is set that will be used. Otherwise Rails will generate
140
+ # the filename from the database config name.
141
+ def schema_dump(format = ActiveRecord.schema_format)
142
+ if configuration_hash.key?(:schema_dump)
143
+ if config = configuration_hash[:schema_dump]
144
+ config
145
+ end
146
+ elsif primary?
147
+ schema_file_type(format)
148
+ else
149
+ "#{name}_#{schema_file_type(format)}"
150
+ end
151
+ end
152
+
153
+ def database_tasks? # :nodoc:
154
+ !replica? && !!configuration_hash.fetch(:database_tasks, true)
155
+ end
156
+
157
+ def use_metadata_table? # :nodoc:
158
+ configuration_hash.fetch(:use_metadata_table, true)
159
+ end
160
+
161
+ private
162
+ def schema_file_type(format)
163
+ case format
164
+ when :ruby
165
+ "schema.rb"
166
+ when :sql
167
+ "structure.sql"
168
+ end
169
+ end
48
170
  end
49
171
  end
50
172
  end