activerecord 6.1.7 → 7.2.2

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 (333) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +616 -1290
  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 +19 -8
  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 +30 -27
  30. data/lib/active_record/associations/join_dependency.rb +28 -20
  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 +429 -522
  40. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  41. data/lib/active_record/attribute_assignment.rb +1 -5
  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 +15 -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 +57 -54
  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 +19 -35
  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 +325 -604
  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 +230 -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 +378 -143
  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 +348 -165
  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 +403 -77
  108. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  109. data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
  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 +310 -253
  125. data/lib/active_record/counter_cache.rb +68 -34
  126. data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
  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 +58 -0
  165. data/lib/active_record/enum.rb +170 -62
  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 +59 -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 +145 -158
  199. data/lib/active_record/nested_attributes.rb +61 -23
  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 +18 -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 +229 -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 +332 -103
  214. data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
  215. data/lib/active_record/relation/batches.rb +200 -65
  216. data/lib/active_record/relation/calculations.rb +301 -112
  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 +870 -163
  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 +6 -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 +288 -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 +65 -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/sqlite.rb +25 -0
  317. data/lib/arel/visitors/to_sql.rb +170 -36
  318. data/lib/arel/visitors/visitor.rb +2 -2
  319. data/lib/arel.rb +23 -4
  320. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  321. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  322. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  323. data/lib/rails/generators/active_record/migration.rb +3 -1
  324. data/lib/rails/generators/active_record/model/USAGE +113 -0
  325. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  326. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  327. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  328. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  329. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  330. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  331. metadata +103 -17
  332. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  333. 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,55 @@ 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
+ dump_db_configs = []
179
+
180
+ each_current_configuration(env) do |db_config|
181
+ with_temporary_pool(db_config) do
182
+ begin
183
+ database_initialized = migration_connection_pool.schema_migration.table_exists?
184
+ rescue ActiveRecord::NoDatabaseError
185
+ create(db_config)
186
+ retry
187
+ end
188
+
189
+ unless database_initialized
190
+ if File.exist?(schema_dump_path(db_config))
191
+ load_schema(db_config, ActiveRecord.schema_format, nil)
192
+ end
193
+
194
+ seed = true
195
+ end
196
+ end
197
+ end
198
+
199
+ each_current_environment(env) do |environment|
200
+ db_configs_with_versions(environment).sort.each do |version, db_configs|
201
+ dump_db_configs |= db_configs
202
+
203
+ db_configs.each do |db_config|
204
+ with_temporary_pool(db_config) do
205
+ migrate(version)
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ # Dump schema for databases that were migrated.
212
+ if ActiveRecord.dump_schema_after_migration
213
+ dump_db_configs.each do |db_config|
214
+ with_temporary_pool(db_config) do
215
+ dump_schema(db_config)
216
+ end
217
+ end
218
+ end
219
+
220
+ load_seed if seed
195
221
  end
196
222
 
197
223
  def drop(configuration, *arguments)
@@ -215,51 +241,73 @@ module ActiveRecord
215
241
  end
216
242
 
217
243
  def truncate_tables(db_config)
218
- ActiveRecord::Base.establish_connection(db_config)
219
-
220
- connection = ActiveRecord::Base.connection
221
- connection.truncate_tables(*connection.tables)
244
+ with_temporary_connection(db_config) do |conn|
245
+ conn.truncate_tables(*conn.tables)
246
+ end
222
247
  end
223
248
  private :truncate_tables
224
249
 
225
250
  def truncate_all(environment = env)
226
- ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
251
+ configs_for(env_name: environment).each do |db_config|
227
252
  truncate_tables(db_config)
228
253
  end
229
254
  end
230
255
 
231
- def migrate
232
- check_target_version
233
-
256
+ def migrate(version = nil)
234
257
  scope = ENV["SCOPE"]
235
258
  verbose_was, Migration.verbose = Migration.verbose, verbose?
236
259
 
237
- Base.connection.migration_context.migrate(target_version) do |migration|
238
- scope.blank? || scope == migration.scope
260
+ check_target_version
261
+
262
+ migration_connection_pool.migration_context.migrate(target_version) do |migration|
263
+ if version.blank?
264
+ scope.blank? || scope == migration.scope
265
+ else
266
+ migration.version == version
267
+ end
268
+ end.tap do |migrations_ran|
269
+ Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
239
270
  end
240
271
 
241
- ActiveRecord::Base.clear_cache!
272
+ migration_connection_pool.schema_cache.clear!
242
273
  ensure
243
274
  Migration.verbose = verbose_was
244
275
  end
245
276
 
277
+ def db_configs_with_versions(environment = env) # :nodoc:
278
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
279
+
280
+ with_temporary_pool_for_each(env: environment) do |pool|
281
+ db_config = pool.db_config
282
+ versions_to_run = pool.migration_context.pending_migration_versions
283
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
284
+
285
+ versions_to_run.each do |version|
286
+ next if target_version && target_version != version
287
+ db_configs_with_versions[version] << db_config
288
+ end
289
+ end
290
+
291
+ db_configs_with_versions
292
+ end
293
+
246
294
  def migrate_status
247
- unless ActiveRecord::Base.connection.schema_migration.table_exists?
295
+ unless migration_connection_pool.schema_migration.table_exists?
248
296
  Kernel.abort "Schema migrations table does not exist yet."
249
297
  end
250
298
 
251
299
  # output
252
- puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
300
+ puts "\ndatabase: #{migration_connection_pool.db_config.database}\n\n"
253
301
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
254
302
  puts "-" * 50
255
- ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
303
+ migration_connection_pool.migration_context.migrations_status.each do |status, version, name|
256
304
  puts "#{status.center(8)} #{version.ljust(14)} #{name}"
257
305
  end
258
306
  puts
259
307
  end
260
308
 
261
309
  def check_target_version
262
- if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
310
+ if target_version && !Migration.valid_version_format?(ENV["VERSION"])
263
311
  raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
264
312
  end
265
313
  end
@@ -269,7 +317,7 @@ module ActiveRecord
269
317
  end
270
318
 
271
319
  def charset_current(env_name = env, db_name = name)
272
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
320
+ db_config = configs_for(env_name: env_name, name: db_name)
273
321
  charset(db_config)
274
322
  end
275
323
 
@@ -279,7 +327,7 @@ module ActiveRecord
279
327
  end
280
328
 
281
329
  def collation_current(env_name = env, db_name = name)
282
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
330
+ db_config = configs_for(env_name: env_name, name: db_name)
283
331
  collation(db_config)
284
332
  end
285
333
 
@@ -299,27 +347,30 @@ module ActiveRecord
299
347
 
300
348
  def purge_current(environment = env)
301
349
  each_current_configuration(environment) { |db_config| purge(db_config) }
302
- ActiveRecord::Base.establish_connection(environment.to_sym)
350
+
351
+ migration_class.establish_connection(environment.to_sym)
303
352
  end
304
353
 
305
354
  def structure_dump(configuration, *arguments)
306
355
  db_config = resolve_configuration(configuration)
307
356
  filename = arguments.delete_at(0)
308
- database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
357
+ flags = structure_dump_flags_for(db_config.adapter)
358
+ database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
309
359
  end
310
360
 
311
361
  def structure_load(configuration, *arguments)
312
362
  db_config = resolve_configuration(configuration)
313
363
  filename = arguments.delete_at(0)
314
- database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
364
+ flags = structure_load_flags_for(db_config.adapter)
365
+ database_adapter_for(db_config, *arguments).structure_load(filename, flags)
315
366
  end
316
367
 
317
- def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
- file ||= dump_filename(db_config.name, format)
368
+ def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
369
+ file ||= schema_dump_path(db_config, format)
370
+ return unless file
319
371
 
320
372
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
321
373
  check_schema_file(file)
322
- ActiveRecord::Base.establish_connection(db_config)
323
374
 
324
375
  case format
325
376
  when :ruby
@@ -329,112 +380,111 @@ module ActiveRecord
329
380
  else
330
381
  raise ArgumentError, "unknown format #{format.inspect}"
331
382
  end
332
- ActiveRecord::InternalMetadata.create_table
333
- ActiveRecord::InternalMetadata[:environment] = db_config.env_name
334
- ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
383
+
384
+ migration_connection_pool.internal_metadata.create_table_and_set_flags(db_config.env_name, schema_sha1(file))
335
385
  ensure
336
386
  Migration.verbose = verbose_was
337
387
  end
338
388
 
339
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
389
+ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
340
390
  db_config = resolve_configuration(configuration)
341
391
 
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)
392
+ file ||= schema_dump_path(db_config)
349
393
 
350
- return true unless File.exist?(file)
394
+ return true unless file && File.exist?(file)
351
395
 
352
- ActiveRecord::Base.establish_connection(db_config)
396
+ with_temporary_pool(db_config) do |pool|
397
+ internal_metadata = pool.internal_metadata
398
+ return false unless internal_metadata.enabled?
399
+ return false unless internal_metadata.table_exists?
353
400
 
354
- return false unless ActiveRecord::InternalMetadata.enabled?
355
- return false unless ActiveRecord::InternalMetadata.table_exists?
356
-
357
- ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
401
+ internal_metadata[:schema_sha1] == schema_sha1(file)
402
+ end
358
403
  end
359
404
 
360
- def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
- file ||= dump_filename(db_config.name, format)
405
+ def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
406
+ file ||= schema_dump_path(db_config, format)
362
407
 
363
- check_schema_file(file)
408
+ check_schema_file(file) if file
364
409
 
365
- ActiveRecord::Base.establish_connection(db_config)
366
-
367
- if schema_up_to_date?(db_config, format, file)
368
- truncate_tables(db_config)
369
- else
370
- purge(db_config)
410
+ with_temporary_pool(db_config, clobber: true) do
411
+ if schema_up_to_date?(db_config, format, file)
412
+ truncate_tables(db_config) unless ENV["SKIP_TEST_DATABASE_TRUNCATE"]
413
+ else
414
+ purge(db_config)
415
+ load_schema(db_config, format, file)
416
+ end
417
+ rescue ActiveRecord::NoDatabaseError
418
+ create(db_config)
371
419
  load_schema(db_config, format, file)
372
420
  end
373
- rescue ActiveRecord::NoDatabaseError
374
- create(db_config)
375
- load_schema(db_config, format, file)
376
421
  end
377
422
 
378
- def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
423
+ def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
424
+ return unless db_config.schema_dump
425
+
379
426
  require "active_record/schema_dumper"
380
- filename = dump_filename(db_config.name, format)
381
- connection = ActiveRecord::Base.connection
427
+ filename = schema_dump_path(db_config, format)
428
+ return unless filename
382
429
 
383
430
  FileUtils.mkdir_p(db_dir)
384
431
  case format
385
432
  when :ruby
386
433
  File.open(filename, "w:utf-8") do |file|
387
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
434
+ ActiveRecord::SchemaDumper.dump(migration_connection_pool, file)
388
435
  end
389
436
  when :sql
390
437
  structure_dump(db_config, filename)
391
- if connection.schema_migration.table_exists?
438
+ if migration_connection_pool.schema_migration.table_exists?
392
439
  File.open(filename, "a") do |f|
393
- f.puts connection.dump_schema_information
440
+ f.puts migration_connection.dump_schema_information
394
441
  f.print "\n"
395
442
  end
396
443
  end
397
444
  end
398
445
  end
399
446
 
400
- def schema_file(format = ActiveRecord::Base.schema_format)
401
- File.join(db_dir, schema_file_type(format))
402
- end
447
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
448
+ return ENV["SCHEMA"] if ENV["SCHEMA"]
403
449
 
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
450
+ filename = db_config.schema_dump(format)
451
+ return unless filename
412
452
 
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)
453
+ if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
454
+ filename
416
455
  else
417
- "#{db_config_name}_#{schema_file_type(format)}"
456
+ File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
418
457
  end
419
-
420
- ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
458
  end
422
459
 
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"
460
+ def cache_dump_filename(db_config_or_name, schema_cache_path: nil)
461
+ if db_config_or_name.is_a?(DatabaseConfigurations::DatabaseConfig)
462
+ schema_cache_path ||
463
+ db_config_or_name.schema_cache_path ||
464
+ schema_cache_env ||
465
+ db_config_or_name.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
426
466
  else
427
- "#{db_config_name}_schema_cache.yml"
428
- end
467
+ ActiveRecord.deprecator.warn(<<~MSG.squish)
468
+ Passing a database name to `cache_dump_filename` is deprecated and will be removed in Rails 8.0. Pass a
469
+ `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object instead.
470
+ MSG
471
+
472
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_or_name)
473
+ "schema_cache.yml"
474
+ else
475
+ "#{db_config_or_name}_schema_cache.yml"
476
+ end
429
477
 
430
- schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
478
+ schema_cache_path || schema_cache_env || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
479
+ end
431
480
  end
432
481
 
433
- def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
482
+ def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
434
483
  each_current_configuration(environment) do |db_config|
435
- load_schema(db_config, format, file)
484
+ with_temporary_connection(db_config) do
485
+ load_schema(db_config, format, file)
486
+ end
436
487
  end
437
- ActiveRecord::Base.establish_connection(environment.to_sym)
438
488
  end
439
489
 
440
490
  def check_schema_file(filename)
@@ -457,17 +507,70 @@ module ActiveRecord
457
507
 
458
508
  # Dumps the schema cache in YAML format for the connection into the file
459
509
  #
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)
510
+ # ==== Examples
511
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.lease_connection, "tmp/schema_dump.yaml")
512
+ def dump_schema_cache(conn_or_pool, filename)
513
+ conn_or_pool.schema_cache.dump_to(filename)
464
514
  end
465
515
 
466
516
  def clear_schema_cache(filename)
467
517
  FileUtils.rm_f filename, verbose: false
468
518
  end
469
519
 
520
+ def with_temporary_pool_for_each(env: ActiveRecord::Tasks::DatabaseTasks.env, name: nil, clobber: false, &block) # :nodoc:
521
+ if name
522
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env, name: name)
523
+ with_temporary_pool(db_config, clobber: clobber, &block)
524
+ else
525
+ ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
526
+ with_temporary_pool(db_config, clobber: clobber, &block)
527
+ end
528
+ end
529
+ end
530
+
531
+ def with_temporary_connection(db_config, clobber: false, &block) # :nodoc:
532
+ with_temporary_pool(db_config, clobber: clobber) do |pool|
533
+ pool.with_connection(&block)
534
+ end
535
+ end
536
+
537
+ def migration_class # :nodoc:
538
+ ActiveRecord::Base
539
+ end
540
+
541
+ def migration_connection # :nodoc:
542
+ migration_class.lease_connection
543
+ end
544
+
545
+ def migration_connection_pool # :nodoc:
546
+ migration_class.connection_pool
547
+ end
548
+
470
549
  private
550
+ def schema_cache_env
551
+ if ENV["SCHEMA_CACHE"]
552
+ ActiveRecord.deprecator.warn(<<~MSG.squish)
553
+ Setting `ENV["SCHEMA_CACHE"]` is deprecated and will be removed in Rails 8.0.
554
+ Configure the `:schema_cache_path` in the database configuration instead.
555
+ MSG
556
+
557
+ nil
558
+ end
559
+ end
560
+
561
+ def with_temporary_pool(db_config, clobber: false)
562
+ original_db_config = migration_class.connection_db_config
563
+ pool = migration_class.connection_handler.establish_connection(db_config, clobber: clobber)
564
+
565
+ yield pool
566
+ ensure
567
+ migration_class.connection_handler.establish_connection(original_db_config, clobber: clobber)
568
+ end
569
+
570
+ def configs_for(**options)
571
+ Base.configurations.configs_for(**options)
572
+ end
573
+
471
574
  def resolve_configuration(configuration)
472
575
  Base.configurations.resolve(configuration)
473
576
  end
@@ -488,7 +591,7 @@ module ActiveRecord
488
591
  end
489
592
 
490
593
  def class_for_adapter(adapter)
491
- _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
594
+ _key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
492
595
  unless task
493
596
  raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
494
597
  end
@@ -496,11 +599,8 @@ module ActiveRecord
496
599
  end
497
600
 
498
601
  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|
602
+ each_current_environment(environment) do |env|
603
+ configs_for(env_name: env).each do |db_config|
504
604
  next if name && name != db_config.name
505
605
 
506
606
  yield db_config
@@ -508,8 +608,14 @@ module ActiveRecord
508
608
  end
509
609
  end
510
610
 
611
+ def each_current_environment(environment, &block)
612
+ environments = [environment]
613
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
614
+ environments.each(&block)
615
+ end
616
+
511
617
  def each_local_configuration
512
- ActiveRecord::Base.configurations.configs_for.each do |db_config|
618
+ configs_for.each do |db_config|
513
619
  next unless db_config.database
514
620
 
515
621
  if local_database?(db_config)
@@ -526,7 +632,40 @@ module ActiveRecord
526
632
  end
527
633
 
528
634
  def schema_sha1(file)
529
- Digest::SHA1.hexdigest(File.read(file))
635
+ OpenSSL::Digest::SHA1.hexdigest(File.read(file))
636
+ end
637
+
638
+ def structure_dump_flags_for(adapter)
639
+ if structure_dump_flags.is_a?(Hash)
640
+ structure_dump_flags[adapter.to_sym]
641
+ else
642
+ structure_dump_flags
643
+ end
644
+ end
645
+
646
+ def structure_load_flags_for(adapter)
647
+ if structure_load_flags.is_a?(Hash)
648
+ structure_load_flags[adapter.to_sym]
649
+ else
650
+ structure_load_flags
651
+ end
652
+ end
653
+
654
+ def check_current_protected_environment!(db_config)
655
+ with_temporary_pool(db_config) do |pool|
656
+ migration_context = pool.migration_context
657
+ current = migration_context.current_environment
658
+ stored = migration_context.last_stored_environment
659
+
660
+ if migration_context.protected_environment?
661
+ raise ActiveRecord::ProtectedEnvironmentError.new(stored)
662
+ end
663
+
664
+ if stored && stored != current
665
+ raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
666
+ end
667
+ rescue ActiveRecord::NoDatabaseError
668
+ end
530
669
  end
531
670
  end
532
671
  end