activerecord 6.1.7 → 7.2.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 (332) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +520 -1385
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +31 -31
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +17 -14
  7. data/lib/active_record/association_relation.rb +2 -12
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +60 -21
  10. data/lib/active_record/associations/association_scope.rb +17 -12
  11. data/lib/active_record/associations/belongs_to_association.rb +37 -11
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
  13. data/lib/active_record/associations/builder/association.rb +11 -5
  14. data/lib/active_record/associations/builder/belongs_to.rb +41 -14
  15. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +4 -4
  19. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  20. data/lib/active_record/associations/collection_association.rb +46 -36
  21. data/lib/active_record/associations/collection_proxy.rb +44 -16
  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 +10 -3
  25. data/lib/active_record/associations/has_many_association.rb +29 -19
  26. data/lib/active_record/associations/has_many_through_association.rb +12 -7
  27. data/lib/active_record/associations/has_one_association.rb +20 -10
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  30. data/lib/active_record/associations/join_dependency.rb +23 -15
  31. data/lib/active_record/associations/nested_error.rb +47 -0
  32. data/lib/active_record/associations/preloader/association.rb +212 -53
  33. data/lib/active_record/associations/preloader/batch.rb +48 -0
  34. data/lib/active_record/associations/preloader/branch.rb +153 -0
  35. data/lib/active_record/associations/preloader/through_association.rb +50 -16
  36. data/lib/active_record/associations/preloader.rb +50 -121
  37. data/lib/active_record/associations/singular_association.rb +15 -3
  38. data/lib/active_record/associations/through_association.rb +25 -14
  39. data/lib/active_record/associations.rb +404 -509
  40. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  41. data/lib/active_record/attribute_assignment.rb +2 -14
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  43. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  44. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  45. data/lib/active_record/attribute_methods/primary_key.rb +47 -27
  46. data/lib/active_record/attribute_methods/query.rb +31 -19
  47. data/lib/active_record/attribute_methods/read.rb +14 -11
  48. data/lib/active_record/attribute_methods/serialization.rb +174 -37
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -9
  50. data/lib/active_record/attribute_methods/write.rb +12 -15
  51. data/lib/active_record/attribute_methods.rb +164 -52
  52. data/lib/active_record/attributes.rb +51 -49
  53. data/lib/active_record/autosave_association.rb +74 -57
  54. data/lib/active_record/base.rb +27 -5
  55. data/lib/active_record/callbacks.rb +18 -34
  56. data/lib/active_record/coders/column_serializer.rb +61 -0
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +70 -46
  59. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +327 -612
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -64
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +377 -142
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +345 -166
  75. data/lib/active_record/connection_adapters/column.rb +13 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
  78. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
  79. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  81. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  82. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  83. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
  85. data/lib/active_record/connection_adapters/pool_config.rb +26 -16
  86. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  87. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  88. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
  89. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  94. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  100. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
  103. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  104. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  105. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
  106. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  107. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +401 -77
  108. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  109. data/lib/active_record/connection_adapters/postgresql_adapter.rb +518 -251
  110. data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
  111. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  112. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
  113. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
  114. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
  119. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  120. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  121. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  122. data/lib/active_record/connection_adapters.rb +130 -6
  123. data/lib/active_record/connection_handling.rb +132 -146
  124. data/lib/active_record/core.rb +276 -251
  125. data/lib/active_record/counter_cache.rb +68 -34
  126. data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -3
  127. data/lib/active_record/database_configurations/database_config.rb +34 -10
  128. data/lib/active_record/database_configurations/hash_config.rb +107 -31
  129. data/lib/active_record/database_configurations/url_config.rb +38 -13
  130. data/lib/active_record/database_configurations.rb +96 -60
  131. data/lib/active_record/delegated_type.rb +90 -20
  132. data/lib/active_record/deprecator.rb +7 -0
  133. data/lib/active_record/destroy_association_async_job.rb +4 -2
  134. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  135. data/lib/active_record/dynamic_matchers.rb +3 -3
  136. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +68 -0
  140. data/lib/active_record/encryption/configurable.rb +60 -0
  141. data/lib/active_record/encryption/context.rb +42 -0
  142. data/lib/active_record/encryption/contexts.rb +76 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +170 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +53 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  159. data/lib/active_record/encryption/message_serializer.rb +96 -0
  160. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  161. data/lib/active_record/encryption/properties.rb +76 -0
  162. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  163. data/lib/active_record/encryption/scheme.rb +100 -0
  164. data/lib/active_record/encryption.rb +56 -0
  165. data/lib/active_record/enum.rb +163 -63
  166. data/lib/active_record/errors.rb +210 -27
  167. data/lib/active_record/explain.rb +21 -12
  168. data/lib/active_record/explain_registry.rb +11 -6
  169. data/lib/active_record/explain_subscriber.rb +1 -1
  170. data/lib/active_record/fixture_set/file.rb +15 -1
  171. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  172. data/lib/active_record/fixture_set/render_context.rb +2 -0
  173. data/lib/active_record/fixture_set/table_row.rb +70 -14
  174. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  175. data/lib/active_record/fixtures.rb +179 -112
  176. data/lib/active_record/future_result.rb +178 -0
  177. data/lib/active_record/gem_version.rb +4 -4
  178. data/lib/active_record/inheritance.rb +85 -31
  179. data/lib/active_record/insert_all.rb +148 -32
  180. data/lib/active_record/integration.rb +14 -10
  181. data/lib/active_record/internal_metadata.rb +123 -23
  182. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  183. data/lib/active_record/locking/optimistic.rb +43 -27
  184. data/lib/active_record/locking/pessimistic.rb +15 -6
  185. data/lib/active_record/log_subscriber.rb +41 -29
  186. data/lib/active_record/marshalling.rb +56 -0
  187. data/lib/active_record/message_pack.rb +124 -0
  188. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  189. data/lib/active_record/middleware/database_selector.rb +23 -13
  190. data/lib/active_record/middleware/shard_selector.rb +62 -0
  191. data/lib/active_record/migration/command_recorder.rb +113 -16
  192. data/lib/active_record/migration/compatibility.rb +235 -46
  193. data/lib/active_record/migration/default_strategy.rb +22 -0
  194. data/lib/active_record/migration/execution_strategy.rb +19 -0
  195. data/lib/active_record/migration/join_table.rb +1 -1
  196. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  197. data/lib/active_record/migration.rb +374 -177
  198. data/lib/active_record/model_schema.rb +143 -159
  199. data/lib/active_record/nested_attributes.rb +48 -21
  200. data/lib/active_record/no_touching.rb +3 -3
  201. data/lib/active_record/normalization.rb +163 -0
  202. data/lib/active_record/persistence.rb +282 -283
  203. data/lib/active_record/promise.rb +84 -0
  204. data/lib/active_record/query_cache.rb +19 -25
  205. data/lib/active_record/query_logs.rb +189 -0
  206. data/lib/active_record/query_logs_formatter.rb +41 -0
  207. data/lib/active_record/querying.rb +44 -9
  208. data/lib/active_record/railtie.rb +234 -71
  209. data/lib/active_record/railties/controller_runtime.rb +25 -11
  210. data/lib/active_record/railties/databases.rake +189 -256
  211. data/lib/active_record/railties/job_runtime.rb +23 -0
  212. data/lib/active_record/readonly_attributes.rb +41 -3
  213. data/lib/active_record/reflection.rb +325 -103
  214. data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
  215. data/lib/active_record/relation/batches.rb +198 -63
  216. data/lib/active_record/relation/calculations.rb +300 -111
  217. data/lib/active_record/relation/delegation.rb +33 -22
  218. data/lib/active_record/relation/finder_methods.rb +123 -52
  219. data/lib/active_record/relation/merger.rb +26 -19
  220. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  221. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  222. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  223. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  224. data/lib/active_record/relation/predicate_builder.rb +29 -22
  225. data/lib/active_record/relation/query_attribute.rb +30 -12
  226. data/lib/active_record/relation/query_methods.rb +842 -150
  227. data/lib/active_record/relation/record_fetch_warning.rb +10 -9
  228. data/lib/active_record/relation/spawn_methods.rb +7 -6
  229. data/lib/active_record/relation/where_clause.rb +15 -36
  230. data/lib/active_record/relation.rb +736 -145
  231. data/lib/active_record/result.rb +67 -54
  232. data/lib/active_record/runtime_registry.rb +71 -13
  233. data/lib/active_record/sanitization.rb +84 -34
  234. data/lib/active_record/schema.rb +39 -23
  235. data/lib/active_record/schema_dumper.rb +90 -31
  236. data/lib/active_record/schema_migration.rb +74 -23
  237. data/lib/active_record/scoping/default.rb +72 -15
  238. data/lib/active_record/scoping/named.rb +5 -13
  239. data/lib/active_record/scoping.rb +65 -34
  240. data/lib/active_record/secure_password.rb +60 -0
  241. data/lib/active_record/secure_token.rb +21 -3
  242. data/lib/active_record/serialization.rb +6 -1
  243. data/lib/active_record/signed_id.rb +30 -9
  244. data/lib/active_record/statement_cache.rb +7 -7
  245. data/lib/active_record/store.rb +10 -10
  246. data/lib/active_record/suppressor.rb +13 -15
  247. data/lib/active_record/table_metadata.rb +7 -3
  248. data/lib/active_record/tasks/database_tasks.rb +277 -149
  249. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  250. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  251. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  252. data/lib/active_record/test_databases.rb +1 -1
  253. data/lib/active_record/test_fixtures.rb +173 -155
  254. data/lib/active_record/testing/query_assertions.rb +121 -0
  255. data/lib/active_record/timestamp.rb +32 -19
  256. data/lib/active_record/token_for.rb +123 -0
  257. data/lib/active_record/touch_later.rb +12 -7
  258. data/lib/active_record/transaction.rb +132 -0
  259. data/lib/active_record/transactions.rb +118 -41
  260. data/lib/active_record/translation.rb +3 -5
  261. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  262. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  263. data/lib/active_record/type/internal/timezone.rb +7 -2
  264. data/lib/active_record/type/serialized.rb +9 -7
  265. data/lib/active_record/type/time.rb +4 -0
  266. data/lib/active_record/type/type_map.rb +17 -20
  267. data/lib/active_record/type.rb +1 -2
  268. data/lib/active_record/type_caster/connection.rb +4 -4
  269. data/lib/active_record/validations/absence.rb +1 -1
  270. data/lib/active_record/validations/associated.rb +13 -7
  271. data/lib/active_record/validations/numericality.rb +5 -4
  272. data/lib/active_record/validations/presence.rb +5 -28
  273. data/lib/active_record/validations/uniqueness.rb +64 -15
  274. data/lib/active_record/validations.rb +12 -5
  275. data/lib/active_record/version.rb +1 -1
  276. data/lib/active_record.rb +444 -32
  277. data/lib/arel/alias_predication.rb +1 -1
  278. data/lib/arel/attributes/attribute.rb +0 -8
  279. data/lib/arel/collectors/bind.rb +2 -0
  280. data/lib/arel/collectors/composite.rb +7 -0
  281. data/lib/arel/collectors/sql_string.rb +1 -1
  282. data/lib/arel/collectors/substitute_binds.rb +1 -1
  283. data/lib/arel/crud.rb +28 -22
  284. data/lib/arel/delete_manager.rb +18 -4
  285. data/lib/arel/errors.rb +10 -0
  286. data/lib/arel/factory_methods.rb +4 -0
  287. data/lib/arel/filter_predications.rb +9 -0
  288. data/lib/arel/insert_manager.rb +2 -3
  289. data/lib/arel/nodes/binary.rb +6 -7
  290. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  291. data/lib/arel/nodes/casted.rb +1 -1
  292. data/lib/arel/nodes/cte.rb +36 -0
  293. data/lib/arel/nodes/delete_statement.rb +12 -13
  294. data/lib/arel/nodes/filter.rb +10 -0
  295. data/lib/arel/nodes/fragments.rb +35 -0
  296. data/lib/arel/nodes/function.rb +1 -0
  297. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  298. data/lib/arel/nodes/insert_statement.rb +2 -2
  299. data/lib/arel/nodes/leading_join.rb +8 -0
  300. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  301. data/lib/arel/nodes/node.rb +115 -5
  302. data/lib/arel/nodes/select_core.rb +2 -2
  303. data/lib/arel/nodes/select_statement.rb +2 -2
  304. data/lib/arel/nodes/sql_literal.rb +13 -0
  305. data/lib/arel/nodes/table_alias.rb +4 -0
  306. data/lib/arel/nodes/update_statement.rb +8 -3
  307. data/lib/arel/nodes.rb +7 -2
  308. data/lib/arel/predications.rb +14 -4
  309. data/lib/arel/select_manager.rb +11 -5
  310. data/lib/arel/table.rb +9 -6
  311. data/lib/arel/tree_manager.rb +8 -15
  312. data/lib/arel/update_manager.rb +20 -5
  313. data/lib/arel/visitors/dot.rb +81 -90
  314. data/lib/arel/visitors/mysql.rb +23 -5
  315. data/lib/arel/visitors/postgresql.rb +1 -22
  316. data/lib/arel/visitors/to_sql.rb +170 -36
  317. data/lib/arel/visitors/visitor.rb +2 -2
  318. data/lib/arel.rb +23 -4
  319. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  320. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  321. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  322. data/lib/rails/generators/active_record/migration.rb +3 -1
  323. data/lib/rails/generators/active_record/model/USAGE +113 -0
  324. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  325. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  326. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  327. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  328. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  329. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  330. metadata +100 -14
  331. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  332. data/lib/active_record/null_relation.rb +0 -67
@@ -6,14 +6,16 @@ module ActiveRecord
6
6
  module Tasks # :nodoc:
7
7
  class DatabaseNotSupported < StandardError; end # :nodoc:
8
8
 
9
+ # = Active Record \DatabaseTasks
10
+ #
9
11
  # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
10
12
  # logic behind common tasks used to manage database and migrations.
11
13
  #
12
- # The tasks defined here are used with Rails commands provided by Active Record.
14
+ # The tasks defined here are used with \Rails commands provided by Active Record.
13
15
  #
14
16
  # In order to use DatabaseTasks, a few config values need to be set. All the needed
15
- # config values are set by Rails already, so it's necessary to do it only if you
16
- # want to change the defaults or when you want to use Active Record outside of Rails
17
+ # config values are set by \Rails already, so it's necessary to do it only if you
18
+ # want to change the defaults or when you want to use Active Record outside of \Rails
17
19
  # (in such case after configuring the database tasks, you can also use the rake tasks
18
20
  # defined in Active Record).
19
21
  #
@@ -27,7 +29,7 @@ module ActiveRecord
27
29
  # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
28
30
  # * +root+: a path to the root of the application.
29
31
  #
30
- # Example usage of DatabaseTasks outside Rails could look as such:
32
+ # Example usage of DatabaseTasks outside \Rails could look as such:
31
33
  #
32
34
  # include ActiveRecord::Tasks
33
35
  # DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
@@ -39,35 +41,33 @@ module ActiveRecord
39
41
  ##
40
42
  # :singleton-method:
41
43
  # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
44
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
45
+ # Example:
46
+ # ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
47
+ # mysql2: ['--no-defaults', '--skip-add-drop-table'],
48
+ # postgres: '--no-tablespaces'
49
+ # }
42
50
  mattr_accessor :structure_dump_flags, instance_accessor: false
43
51
 
44
52
  ##
45
53
  # :singleton-method:
46
54
  # Extra flags passed to database CLI tool when calling db:schema:load
55
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
47
56
  mattr_accessor :structure_load_flags, instance_accessor: false
48
57
 
49
58
  extend self
50
59
 
51
- attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
52
- deprecate :current_config=
60
+ attr_writer :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
53
61
  attr_accessor :database_configuration
54
62
 
55
63
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
56
64
 
57
- def check_protected_environments!
58
- unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
59
- current = ActiveRecord::Base.connection.migration_context.current_environment
60
- stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
61
-
62
- if ActiveRecord::Base.connection.migration_context.protected_environment?
63
- raise ActiveRecord::ProtectedEnvironmentError.new(stored)
64
- end
65
+ def check_protected_environments!(environment = env)
66
+ return if ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
65
67
 
66
- if stored && stored != current
67
- raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
68
- end
68
+ configs_for(env_name: environment).each do |db_config|
69
+ check_current_protected_environment!(db_config)
69
70
  end
70
- rescue ActiveRecord::NoDatabaseError
71
71
  end
72
72
 
73
73
  def register_task(pattern, task)
@@ -76,6 +76,7 @@ module ActiveRecord
76
76
  end
77
77
 
78
78
  register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
79
+ register_task(/trilogy/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
79
80
  register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
80
81
  register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
81
82
 
@@ -103,11 +104,6 @@ module ActiveRecord
103
104
  @env ||= Rails.env
104
105
  end
105
106
 
106
- def spec
107
- @spec ||= "primary"
108
- end
109
- deprecate spec: "please use name instead"
110
-
111
107
  def name
112
108
  @name ||= "primary"
113
109
  end
@@ -116,18 +112,6 @@ module ActiveRecord
116
112
  @seed_loader ||= Rails.application
117
113
  end
118
114
 
119
- def current_config(options = {})
120
- if options.has_key?(:config)
121
- @current_config = options[:config]
122
- else
123
- env_name = options[:env] || env
124
- name = options[:spec] || "primary"
125
-
126
- @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
127
- end
128
- end
129
- deprecate :current_config
130
-
131
115
  def create(configuration, *arguments)
132
116
  db_config = resolve_configuration(configuration)
133
117
  database_adapter_for(db_config, *arguments).create
@@ -141,28 +125,20 @@ module ActiveRecord
141
125
  end
142
126
 
143
127
  def create_all
144
- old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
128
+ db_config = migration_connection.pool.db_config
129
+
145
130
  each_local_configuration { |db_config| create(db_config) }
146
- if old_pool
147
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
148
- end
131
+
132
+ migration_class.establish_connection(db_config)
149
133
  end
150
134
 
151
- def setup_initial_database_yaml
135
+ def setup_initial_database_yaml # :nodoc:
152
136
  return {} unless defined?(Rails)
153
137
 
154
- begin
155
- Rails.application.config.load_database_yaml
156
- rescue
157
- unless ActiveRecord::Base.suppress_multiple_database_warning
158
- $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
159
- end
160
-
161
- {}
162
- end
138
+ Rails.application.config.load_database_yaml
163
139
  end
164
140
 
165
- def for_each(databases)
141
+ def for_each(databases) # :nodoc:
166
142
  return {} unless defined?(Rails)
167
143
 
168
144
  database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
@@ -171,12 +147,14 @@ module ActiveRecord
171
147
  return if database_configs.count == 1
172
148
 
173
149
  database_configs.each do |db_config|
150
+ next unless db_config.database_tasks?
151
+
174
152
  yield db_config.name
175
153
  end
176
154
  end
177
155
 
178
- def raise_for_multi_db(environment = env, command:)
179
- db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment)
156
+ def raise_for_multi_db(environment = env, command:) # :nodoc:
157
+ db_configs = configs_for(env_name: environment)
180
158
 
181
159
  if db_configs.count > 1
182
160
  dbs_list = []
@@ -191,7 +169,44 @@ module ActiveRecord
191
169
 
192
170
  def create_current(environment = env, name = nil)
193
171
  each_current_configuration(environment, name) { |db_config| create(db_config) }
194
- ActiveRecord::Base.establish_connection(environment.to_sym)
172
+
173
+ migration_class.establish_connection(environment.to_sym)
174
+ end
175
+
176
+ def prepare_all
177
+ seed = false
178
+
179
+ each_current_configuration(env) do |db_config|
180
+ with_temporary_pool(db_config) do
181
+ begin
182
+ database_initialized = migration_connection_pool.schema_migration.table_exists?
183
+ rescue ActiveRecord::NoDatabaseError
184
+ create(db_config)
185
+ retry
186
+ end
187
+
188
+ unless database_initialized
189
+ if File.exist?(schema_dump_path(db_config))
190
+ load_schema(db_config, ActiveRecord.schema_format, nil)
191
+ end
192
+
193
+ seed = true
194
+ end
195
+ end
196
+ end
197
+
198
+ each_current_environment(env) do |environment|
199
+ db_configs_with_versions(environment).sort.each do |version, db_configs|
200
+ db_configs.each do |db_config|
201
+ with_temporary_pool(db_config) do
202
+ migrate(version)
203
+ dump_schema(db_config) if ActiveRecord.dump_schema_after_migration
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ load_seed if seed
195
210
  end
196
211
 
197
212
  def drop(configuration, *arguments)
@@ -215,51 +230,73 @@ module ActiveRecord
215
230
  end
216
231
 
217
232
  def truncate_tables(db_config)
218
- ActiveRecord::Base.establish_connection(db_config)
219
-
220
- connection = ActiveRecord::Base.connection
221
- connection.truncate_tables(*connection.tables)
233
+ with_temporary_connection(db_config) do |conn|
234
+ conn.truncate_tables(*conn.tables)
235
+ end
222
236
  end
223
237
  private :truncate_tables
224
238
 
225
239
  def truncate_all(environment = env)
226
- ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
240
+ configs_for(env_name: environment).each do |db_config|
227
241
  truncate_tables(db_config)
228
242
  end
229
243
  end
230
244
 
231
- def migrate
232
- check_target_version
233
-
245
+ def migrate(version = nil)
234
246
  scope = ENV["SCOPE"]
235
247
  verbose_was, Migration.verbose = Migration.verbose, verbose?
236
248
 
237
- Base.connection.migration_context.migrate(target_version) do |migration|
238
- scope.blank? || scope == migration.scope
249
+ check_target_version
250
+
251
+ migration_connection_pool.migration_context.migrate(target_version) do |migration|
252
+ if version.blank?
253
+ scope.blank? || scope == migration.scope
254
+ else
255
+ migration.version == version
256
+ end
257
+ end.tap do |migrations_ran|
258
+ Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
239
259
  end
240
260
 
241
- ActiveRecord::Base.clear_cache!
261
+ migration_connection_pool.schema_cache.clear!
242
262
  ensure
243
263
  Migration.verbose = verbose_was
244
264
  end
245
265
 
266
+ def db_configs_with_versions(environment = env) # :nodoc:
267
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
268
+
269
+ with_temporary_pool_for_each(env: environment) do |pool|
270
+ db_config = pool.db_config
271
+ versions_to_run = pool.migration_context.pending_migration_versions
272
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
273
+
274
+ versions_to_run.each do |version|
275
+ next if target_version && target_version != version
276
+ db_configs_with_versions[version] << db_config
277
+ end
278
+ end
279
+
280
+ db_configs_with_versions
281
+ end
282
+
246
283
  def migrate_status
247
- unless ActiveRecord::Base.connection.schema_migration.table_exists?
284
+ unless migration_connection_pool.schema_migration.table_exists?
248
285
  Kernel.abort "Schema migrations table does not exist yet."
249
286
  end
250
287
 
251
288
  # output
252
- puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
289
+ puts "\ndatabase: #{migration_connection_pool.db_config.database}\n\n"
253
290
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
254
291
  puts "-" * 50
255
- ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
292
+ migration_connection_pool.migration_context.migrations_status.each do |status, version, name|
256
293
  puts "#{status.center(8)} #{version.ljust(14)} #{name}"
257
294
  end
258
295
  puts
259
296
  end
260
297
 
261
298
  def check_target_version
262
- if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
299
+ if target_version && !Migration.valid_version_format?(ENV["VERSION"])
263
300
  raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
264
301
  end
265
302
  end
@@ -269,7 +306,7 @@ module ActiveRecord
269
306
  end
270
307
 
271
308
  def charset_current(env_name = env, db_name = name)
272
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
309
+ db_config = configs_for(env_name: env_name, name: db_name)
273
310
  charset(db_config)
274
311
  end
275
312
 
@@ -279,7 +316,7 @@ module ActiveRecord
279
316
  end
280
317
 
281
318
  def collation_current(env_name = env, db_name = name)
282
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
319
+ db_config = configs_for(env_name: env_name, name: db_name)
283
320
  collation(db_config)
284
321
  end
285
322
 
@@ -299,27 +336,30 @@ module ActiveRecord
299
336
 
300
337
  def purge_current(environment = env)
301
338
  each_current_configuration(environment) { |db_config| purge(db_config) }
302
- ActiveRecord::Base.establish_connection(environment.to_sym)
339
+
340
+ migration_class.establish_connection(environment.to_sym)
303
341
  end
304
342
 
305
343
  def structure_dump(configuration, *arguments)
306
344
  db_config = resolve_configuration(configuration)
307
345
  filename = arguments.delete_at(0)
308
- database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
346
+ flags = structure_dump_flags_for(db_config.adapter)
347
+ database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
309
348
  end
310
349
 
311
350
  def structure_load(configuration, *arguments)
312
351
  db_config = resolve_configuration(configuration)
313
352
  filename = arguments.delete_at(0)
314
- database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
353
+ flags = structure_load_flags_for(db_config.adapter)
354
+ database_adapter_for(db_config, *arguments).structure_load(filename, flags)
315
355
  end
316
356
 
317
- def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
- file ||= dump_filename(db_config.name, format)
357
+ def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
358
+ file ||= schema_dump_path(db_config, format)
359
+ return unless file
319
360
 
320
361
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
321
362
  check_schema_file(file)
322
- ActiveRecord::Base.establish_connection(db_config)
323
363
 
324
364
  case format
325
365
  when :ruby
@@ -329,112 +369,111 @@ module ActiveRecord
329
369
  else
330
370
  raise ArgumentError, "unknown format #{format.inspect}"
331
371
  end
332
- ActiveRecord::InternalMetadata.create_table
333
- ActiveRecord::InternalMetadata[:environment] = db_config.env_name
334
- ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
372
+
373
+ migration_connection_pool.internal_metadata.create_table_and_set_flags(db_config.env_name, schema_sha1(file))
335
374
  ensure
336
375
  Migration.verbose = verbose_was
337
376
  end
338
377
 
339
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
378
+ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
340
379
  db_config = resolve_configuration(configuration)
341
380
 
342
- if environment || name
343
- ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 7.0.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
344
- end
345
-
346
- name ||= db_config.name
347
-
348
- file ||= dump_filename(name, format)
381
+ file ||= schema_dump_path(db_config)
349
382
 
350
- return true unless File.exist?(file)
383
+ return true unless file && File.exist?(file)
351
384
 
352
- ActiveRecord::Base.establish_connection(db_config)
385
+ with_temporary_pool(db_config) do |pool|
386
+ internal_metadata = pool.internal_metadata
387
+ return false unless internal_metadata.enabled?
388
+ return false unless internal_metadata.table_exists?
353
389
 
354
- return false unless ActiveRecord::InternalMetadata.enabled?
355
- return false unless ActiveRecord::InternalMetadata.table_exists?
356
-
357
- ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
390
+ internal_metadata[:schema_sha1] == schema_sha1(file)
391
+ end
358
392
  end
359
393
 
360
- def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
- file ||= dump_filename(db_config.name, format)
394
+ def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
395
+ file ||= schema_dump_path(db_config, format)
362
396
 
363
- check_schema_file(file)
364
-
365
- ActiveRecord::Base.establish_connection(db_config)
397
+ check_schema_file(file) if file
366
398
 
367
- if schema_up_to_date?(db_config, format, file)
368
- truncate_tables(db_config)
369
- else
370
- purge(db_config)
399
+ with_temporary_pool(db_config, clobber: true) do
400
+ if schema_up_to_date?(db_config, format, file)
401
+ truncate_tables(db_config) unless ENV["SKIP_TEST_DATABASE_TRUNCATE"]
402
+ else
403
+ purge(db_config)
404
+ load_schema(db_config, format, file)
405
+ end
406
+ rescue ActiveRecord::NoDatabaseError
407
+ create(db_config)
371
408
  load_schema(db_config, format, file)
372
409
  end
373
- rescue ActiveRecord::NoDatabaseError
374
- create(db_config)
375
- load_schema(db_config, format, file)
376
410
  end
377
411
 
378
- def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
412
+ def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
413
+ return unless db_config.schema_dump
414
+
379
415
  require "active_record/schema_dumper"
380
- filename = dump_filename(db_config.name, format)
381
- connection = ActiveRecord::Base.connection
416
+ filename = schema_dump_path(db_config, format)
417
+ return unless filename
382
418
 
383
419
  FileUtils.mkdir_p(db_dir)
384
420
  case format
385
421
  when :ruby
386
422
  File.open(filename, "w:utf-8") do |file|
387
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
423
+ ActiveRecord::SchemaDumper.dump(migration_connection_pool, file)
388
424
  end
389
425
  when :sql
390
426
  structure_dump(db_config, filename)
391
- if connection.schema_migration.table_exists?
427
+ if migration_connection_pool.schema_migration.table_exists?
392
428
  File.open(filename, "a") do |f|
393
- f.puts connection.dump_schema_information
429
+ f.puts migration_connection.dump_schema_information
394
430
  f.print "\n"
395
431
  end
396
432
  end
397
433
  end
398
434
  end
399
435
 
400
- def schema_file(format = ActiveRecord::Base.schema_format)
401
- File.join(db_dir, schema_file_type(format))
402
- end
436
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
437
+ return ENV["SCHEMA"] if ENV["SCHEMA"]
403
438
 
404
- def schema_file_type(format = ActiveRecord::Base.schema_format)
405
- case format
406
- when :ruby
407
- "schema.rb"
408
- when :sql
409
- "structure.sql"
410
- end
411
- end
439
+ filename = db_config.schema_dump(format)
440
+ return unless filename
412
441
 
413
- def dump_filename(db_config_name, format = ActiveRecord::Base.schema_format)
414
- filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
415
- schema_file_type(format)
442
+ if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
443
+ filename
416
444
  else
417
- "#{db_config_name}_#{schema_file_type(format)}"
445
+ File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
418
446
  end
419
-
420
- ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
447
  end
422
448
 
423
- def cache_dump_filename(db_config_name, schema_cache_path: nil)
424
- filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
425
- "schema_cache.yml"
449
+ def cache_dump_filename(db_config_or_name, schema_cache_path: nil)
450
+ if db_config_or_name.is_a?(DatabaseConfigurations::DatabaseConfig)
451
+ schema_cache_path ||
452
+ db_config_or_name.schema_cache_path ||
453
+ schema_cache_env ||
454
+ db_config_or_name.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
426
455
  else
427
- "#{db_config_name}_schema_cache.yml"
428
- end
456
+ ActiveRecord.deprecator.warn(<<~MSG.squish)
457
+ Passing a database name to `cache_dump_filename` is deprecated and will be removed in Rails 8.0. Pass a
458
+ `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object instead.
459
+ MSG
460
+
461
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_or_name)
462
+ "schema_cache.yml"
463
+ else
464
+ "#{db_config_or_name}_schema_cache.yml"
465
+ end
429
466
 
430
- schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
467
+ schema_cache_path || schema_cache_env || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
468
+ end
431
469
  end
432
470
 
433
- def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
471
+ def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
434
472
  each_current_configuration(environment) do |db_config|
435
- load_schema(db_config, format, file)
473
+ with_temporary_connection(db_config) do
474
+ load_schema(db_config, format, file)
475
+ end
436
476
  end
437
- ActiveRecord::Base.establish_connection(environment.to_sym)
438
477
  end
439
478
 
440
479
  def check_schema_file(filename)
@@ -457,17 +496,70 @@ module ActiveRecord
457
496
 
458
497
  # Dumps the schema cache in YAML format for the connection into the file
459
498
  #
460
- # ==== Examples:
461
- # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
462
- def dump_schema_cache(conn, filename)
463
- conn.schema_cache.dump_to(filename)
499
+ # ==== Examples
500
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.lease_connection, "tmp/schema_dump.yaml")
501
+ def dump_schema_cache(conn_or_pool, filename)
502
+ conn_or_pool.schema_cache.dump_to(filename)
464
503
  end
465
504
 
466
505
  def clear_schema_cache(filename)
467
506
  FileUtils.rm_f filename, verbose: false
468
507
  end
469
508
 
509
+ def with_temporary_pool_for_each(env: ActiveRecord::Tasks::DatabaseTasks.env, name: nil, clobber: false, &block) # :nodoc:
510
+ if name
511
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env, name: name)
512
+ with_temporary_pool(db_config, clobber: clobber, &block)
513
+ else
514
+ ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
515
+ with_temporary_pool(db_config, clobber: clobber, &block)
516
+ end
517
+ end
518
+ end
519
+
520
+ def with_temporary_connection(db_config, clobber: false, &block) # :nodoc:
521
+ with_temporary_pool(db_config, clobber: clobber) do |pool|
522
+ pool.with_connection(&block)
523
+ end
524
+ end
525
+
526
+ def migration_class # :nodoc:
527
+ ActiveRecord::Base
528
+ end
529
+
530
+ def migration_connection # :nodoc:
531
+ migration_class.lease_connection
532
+ end
533
+
534
+ def migration_connection_pool # :nodoc:
535
+ migration_class.connection_pool
536
+ end
537
+
470
538
  private
539
+ def schema_cache_env
540
+ if ENV["SCHEMA_CACHE"]
541
+ ActiveRecord.deprecator.warn(<<~MSG.squish)
542
+ Setting `ENV["SCHEMA_CACHE"]` is deprecated and will be removed in Rails 8.0.
543
+ Configure the `:schema_cache_path` in the database configuration instead.
544
+ MSG
545
+
546
+ nil
547
+ end
548
+ end
549
+
550
+ def with_temporary_pool(db_config, clobber: false)
551
+ original_db_config = migration_class.connection_db_config
552
+ pool = migration_class.connection_handler.establish_connection(db_config, clobber: clobber)
553
+
554
+ yield pool
555
+ ensure
556
+ migration_class.connection_handler.establish_connection(original_db_config, clobber: clobber)
557
+ end
558
+
559
+ def configs_for(**options)
560
+ Base.configurations.configs_for(**options)
561
+ end
562
+
471
563
  def resolve_configuration(configuration)
472
564
  Base.configurations.resolve(configuration)
473
565
  end
@@ -488,7 +580,7 @@ module ActiveRecord
488
580
  end
489
581
 
490
582
  def class_for_adapter(adapter)
491
- _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
583
+ _key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
492
584
  unless task
493
585
  raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
494
586
  end
@@ -496,11 +588,8 @@ module ActiveRecord
496
588
  end
497
589
 
498
590
  def each_current_configuration(environment, name = nil)
499
- environments = [environment]
500
- environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
501
-
502
- environments.each do |env|
503
- ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
591
+ each_current_environment(environment) do |env|
592
+ configs_for(env_name: env).each do |db_config|
504
593
  next if name && name != db_config.name
505
594
 
506
595
  yield db_config
@@ -508,8 +597,14 @@ module ActiveRecord
508
597
  end
509
598
  end
510
599
 
600
+ def each_current_environment(environment, &block)
601
+ environments = [environment]
602
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
603
+ environments.each(&block)
604
+ end
605
+
511
606
  def each_local_configuration
512
- ActiveRecord::Base.configurations.configs_for.each do |db_config|
607
+ configs_for.each do |db_config|
513
608
  next unless db_config.database
514
609
 
515
610
  if local_database?(db_config)
@@ -526,7 +621,40 @@ module ActiveRecord
526
621
  end
527
622
 
528
623
  def schema_sha1(file)
529
- Digest::SHA1.hexdigest(File.read(file))
624
+ OpenSSL::Digest::SHA1.hexdigest(File.read(file))
625
+ end
626
+
627
+ def structure_dump_flags_for(adapter)
628
+ if structure_dump_flags.is_a?(Hash)
629
+ structure_dump_flags[adapter.to_sym]
630
+ else
631
+ structure_dump_flags
632
+ end
633
+ end
634
+
635
+ def structure_load_flags_for(adapter)
636
+ if structure_load_flags.is_a?(Hash)
637
+ structure_load_flags[adapter.to_sym]
638
+ else
639
+ structure_load_flags
640
+ end
641
+ end
642
+
643
+ def check_current_protected_environment!(db_config)
644
+ with_temporary_pool(db_config) do |pool|
645
+ migration_context = pool.migration_context
646
+ current = migration_context.current_environment
647
+ stored = migration_context.last_stored_environment
648
+
649
+ if migration_context.protected_environment?
650
+ raise ActiveRecord::ProtectedEnvironmentError.new(stored)
651
+ end
652
+
653
+ if stored && stored != current
654
+ raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
655
+ end
656
+ rescue ActiveRecord::NoDatabaseError
657
+ end
530
658
  end
531
659
  end
532
660
  end