activerecord 7.0.8.6 → 7.2.2.1

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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +631 -1939
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +29 -29
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +16 -13
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +35 -12
  10. data/lib/active_record/associations/association_scope.rb +16 -9
  11. data/lib/active_record/associations/belongs_to_association.rb +23 -8
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  13. data/lib/active_record/associations/builder/association.rb +3 -3
  14. data/lib/active_record/associations/builder/belongs_to.rb +22 -8
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  16. data/lib/active_record/associations/builder/has_many.rb +3 -4
  17. data/lib/active_record/associations/builder/has_one.rb +3 -4
  18. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  19. data/lib/active_record/associations/collection_association.rb +26 -14
  20. data/lib/active_record/associations/collection_proxy.rb +29 -11
  21. data/lib/active_record/associations/errors.rb +265 -0
  22. data/lib/active_record/associations/foreign_association.rb +10 -3
  23. data/lib/active_record/associations/has_many_association.rb +21 -14
  24. data/lib/active_record/associations/has_many_through_association.rb +17 -7
  25. data/lib/active_record/associations/has_one_association.rb +10 -3
  26. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  27. data/lib/active_record/associations/join_dependency.rb +10 -10
  28. data/lib/active_record/associations/nested_error.rb +47 -0
  29. data/lib/active_record/associations/preloader/association.rb +33 -8
  30. data/lib/active_record/associations/preloader/branch.rb +7 -1
  31. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  32. data/lib/active_record/associations/preloader.rb +13 -10
  33. data/lib/active_record/associations/singular_association.rb +7 -1
  34. data/lib/active_record/associations/through_association.rb +22 -11
  35. data/lib/active_record/associations.rb +354 -485
  36. data/lib/active_record/attribute_assignment.rb +0 -4
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  38. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  39. data/lib/active_record/attribute_methods/dirty.rb +53 -35
  40. data/lib/active_record/attribute_methods/primary_key.rb +45 -25
  41. data/lib/active_record/attribute_methods/query.rb +28 -16
  42. data/lib/active_record/attribute_methods/read.rb +8 -7
  43. data/lib/active_record/attribute_methods/serialization.rb +131 -32
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
  45. data/lib/active_record/attribute_methods/write.rb +6 -6
  46. data/lib/active_record/attribute_methods.rb +148 -33
  47. data/lib/active_record/attributes.rb +64 -50
  48. data/lib/active_record/autosave_association.rb +69 -37
  49. data/lib/active_record/base.rb +9 -5
  50. data/lib/active_record/callbacks.rb +11 -25
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -42
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +323 -88
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +217 -63
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
  69. data/lib/active_record/connection_adapters/column.rb +9 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
  77. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
  79. data/lib/active_record/connection_adapters/pool_config.rb +20 -10
  80. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  87. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  89. data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
  90. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
  91. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  92. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
  93. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  94. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
  96. data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
  97. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  101. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
  102. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  103. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
  104. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
  105. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  106. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  107. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  108. data/lib/active_record/connection_adapters.rb +124 -1
  109. data/lib/active_record/connection_handling.rb +96 -104
  110. data/lib/active_record/core.rb +251 -176
  111. data/lib/active_record/counter_cache.rb +68 -34
  112. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
  113. data/lib/active_record/database_configurations/database_config.rb +26 -5
  114. data/lib/active_record/database_configurations/hash_config.rb +52 -34
  115. data/lib/active_record/database_configurations/url_config.rb +37 -12
  116. data/lib/active_record/database_configurations.rb +87 -34
  117. data/lib/active_record/delegated_type.rb +39 -10
  118. data/lib/active_record/deprecator.rb +7 -0
  119. data/lib/active_record/destroy_association_async_job.rb +3 -1
  120. data/lib/active_record/dynamic_matchers.rb +2 -2
  121. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  122. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  123. data/lib/active_record/encryption/config.rb +25 -1
  124. data/lib/active_record/encryption/configurable.rb +12 -19
  125. data/lib/active_record/encryption/context.rb +10 -3
  126. data/lib/active_record/encryption/contexts.rb +5 -1
  127. data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
  128. data/lib/active_record/encryption/encryptable_record.rb +45 -21
  129. data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
  130. data/lib/active_record/encryption/encryptor.rb +18 -3
  131. data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
  132. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  133. data/lib/active_record/encryption/key_generator.rb +12 -1
  134. data/lib/active_record/encryption/key_provider.rb +1 -1
  135. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  136. data/lib/active_record/encryption/message_serializer.rb +6 -0
  137. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  138. data/lib/active_record/encryption/properties.rb +3 -3
  139. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  140. data/lib/active_record/encryption/scheme.rb +22 -21
  141. data/lib/active_record/encryption.rb +3 -0
  142. data/lib/active_record/enum.rb +129 -28
  143. data/lib/active_record/errors.rb +151 -31
  144. data/lib/active_record/explain.rb +21 -12
  145. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  146. data/lib/active_record/fixture_set/render_context.rb +2 -0
  147. data/lib/active_record/fixture_set/table_row.rb +29 -8
  148. data/lib/active_record/fixtures.rb +167 -97
  149. data/lib/active_record/future_result.rb +47 -8
  150. data/lib/active_record/gem_version.rb +4 -4
  151. data/lib/active_record/inheritance.rb +34 -18
  152. data/lib/active_record/insert_all.rb +72 -22
  153. data/lib/active_record/integration.rb +11 -8
  154. data/lib/active_record/internal_metadata.rb +124 -20
  155. data/lib/active_record/locking/optimistic.rb +8 -7
  156. data/lib/active_record/locking/pessimistic.rb +5 -2
  157. data/lib/active_record/log_subscriber.rb +18 -22
  158. data/lib/active_record/marshalling.rb +59 -0
  159. data/lib/active_record/message_pack.rb +124 -0
  160. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  161. data/lib/active_record/middleware/database_selector.rb +6 -8
  162. data/lib/active_record/middleware/shard_selector.rb +3 -1
  163. data/lib/active_record/migration/command_recorder.rb +106 -8
  164. data/lib/active_record/migration/compatibility.rb +147 -5
  165. data/lib/active_record/migration/default_strategy.rb +22 -0
  166. data/lib/active_record/migration/execution_strategy.rb +19 -0
  167. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  168. data/lib/active_record/migration.rb +234 -117
  169. data/lib/active_record/model_schema.rb +90 -102
  170. data/lib/active_record/nested_attributes.rb +48 -11
  171. data/lib/active_record/normalization.rb +163 -0
  172. data/lib/active_record/persistence.rb +168 -339
  173. data/lib/active_record/promise.rb +84 -0
  174. data/lib/active_record/query_cache.rb +18 -25
  175. data/lib/active_record/query_logs.rb +92 -52
  176. data/lib/active_record/query_logs_formatter.rb +41 -0
  177. data/lib/active_record/querying.rb +33 -8
  178. data/lib/active_record/railtie.rb +129 -85
  179. data/lib/active_record/railties/controller_runtime.rb +22 -7
  180. data/lib/active_record/railties/databases.rake +145 -154
  181. data/lib/active_record/railties/job_runtime.rb +23 -0
  182. data/lib/active_record/readonly_attributes.rb +32 -5
  183. data/lib/active_record/reflection.rb +267 -69
  184. data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
  185. data/lib/active_record/relation/batches.rb +198 -63
  186. data/lib/active_record/relation/calculations.rb +250 -93
  187. data/lib/active_record/relation/delegation.rb +30 -19
  188. data/lib/active_record/relation/finder_methods.rb +93 -18
  189. data/lib/active_record/relation/merger.rb +6 -6
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -3
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  193. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  194. data/lib/active_record/relation/predicate_builder.rb +28 -16
  195. data/lib/active_record/relation/query_attribute.rb +2 -1
  196. data/lib/active_record/relation/query_methods.rb +576 -107
  197. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  198. data/lib/active_record/relation/spawn_methods.rb +5 -4
  199. data/lib/active_record/relation/where_clause.rb +7 -19
  200. data/lib/active_record/relation.rb +580 -90
  201. data/lib/active_record/result.rb +49 -48
  202. data/lib/active_record/runtime_registry.rb +63 -1
  203. data/lib/active_record/sanitization.rb +70 -25
  204. data/lib/active_record/schema.rb +8 -7
  205. data/lib/active_record/schema_dumper.rb +63 -14
  206. data/lib/active_record/schema_migration.rb +75 -24
  207. data/lib/active_record/scoping/default.rb +15 -5
  208. data/lib/active_record/scoping/named.rb +3 -2
  209. data/lib/active_record/scoping.rb +2 -1
  210. data/lib/active_record/secure_password.rb +60 -0
  211. data/lib/active_record/secure_token.rb +21 -3
  212. data/lib/active_record/signed_id.rb +27 -6
  213. data/lib/active_record/statement_cache.rb +7 -7
  214. data/lib/active_record/store.rb +8 -8
  215. data/lib/active_record/suppressor.rb +3 -1
  216. data/lib/active_record/table_metadata.rb +1 -1
  217. data/lib/active_record/tasks/database_tasks.rb +190 -118
  218. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  219. data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
  220. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  221. data/lib/active_record/test_fixtures.rb +170 -155
  222. data/lib/active_record/testing/query_assertions.rb +121 -0
  223. data/lib/active_record/timestamp.rb +31 -17
  224. data/lib/active_record/token_for.rb +123 -0
  225. data/lib/active_record/touch_later.rb +12 -7
  226. data/lib/active_record/transaction.rb +132 -0
  227. data/lib/active_record/transactions.rb +106 -24
  228. data/lib/active_record/translation.rb +0 -2
  229. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  230. data/lib/active_record/type/internal/timezone.rb +7 -2
  231. data/lib/active_record/type/serialized.rb +1 -3
  232. data/lib/active_record/type/time.rb +4 -0
  233. data/lib/active_record/type_caster/connection.rb +4 -4
  234. data/lib/active_record/validations/absence.rb +1 -1
  235. data/lib/active_record/validations/associated.rb +9 -3
  236. data/lib/active_record/validations/numericality.rb +5 -4
  237. data/lib/active_record/validations/presence.rb +5 -28
  238. data/lib/active_record/validations/uniqueness.rb +61 -11
  239. data/lib/active_record/validations.rb +12 -5
  240. data/lib/active_record/version.rb +1 -1
  241. data/lib/active_record.rb +247 -33
  242. data/lib/arel/alias_predication.rb +1 -1
  243. data/lib/arel/collectors/bind.rb +2 -0
  244. data/lib/arel/collectors/composite.rb +7 -0
  245. data/lib/arel/collectors/sql_string.rb +1 -1
  246. data/lib/arel/collectors/substitute_binds.rb +1 -1
  247. data/lib/arel/errors.rb +10 -0
  248. data/lib/arel/factory_methods.rb +4 -0
  249. data/lib/arel/nodes/binary.rb +6 -7
  250. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  251. data/lib/arel/nodes/cte.rb +36 -0
  252. data/lib/arel/nodes/fragments.rb +35 -0
  253. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  254. data/lib/arel/nodes/leading_join.rb +8 -0
  255. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  256. data/lib/arel/nodes/node.rb +115 -5
  257. data/lib/arel/nodes/sql_literal.rb +13 -0
  258. data/lib/arel/nodes/table_alias.rb +4 -0
  259. data/lib/arel/nodes.rb +6 -2
  260. data/lib/arel/predications.rb +3 -1
  261. data/lib/arel/select_manager.rb +1 -1
  262. data/lib/arel/table.rb +9 -5
  263. data/lib/arel/tree_manager.rb +8 -3
  264. data/lib/arel/update_manager.rb +2 -1
  265. data/lib/arel/visitors/dot.rb +1 -0
  266. data/lib/arel/visitors/mysql.rb +17 -5
  267. data/lib/arel/visitors/postgresql.rb +1 -12
  268. data/lib/arel/visitors/sqlite.rb +25 -0
  269. data/lib/arel/visitors/to_sql.rb +112 -34
  270. data/lib/arel/visitors/visitor.rb +2 -2
  271. data/lib/arel.rb +21 -3
  272. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  273. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  274. data/lib/rails/generators/active_record/migration.rb +3 -1
  275. data/lib/rails/generators/active_record/model/USAGE +113 -0
  276. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  277. metadata +56 -14
  278. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  279. data/lib/active_record/null_relation.rb +0 -63
@@ -7,6 +7,7 @@ require "active_support/core_ext/array/access"
7
7
  require "active_support/core_ext/enumerable"
8
8
  require "active_support/core_ext/module/attribute_accessors"
9
9
  require "active_support/actionable_error"
10
+ require "active_record/migration/pending_migration_connection"
10
11
 
11
12
  module ActiveRecord
12
13
  class MigrationError < ActiveRecordError # :nodoc:
@@ -20,7 +21,7 @@ module ActiveRecord
20
21
  # For example the following migration is not reversible.
21
22
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
22
23
  #
23
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.0]
24
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
24
25
  # def change
25
26
  # create_table :distributors do |t|
26
27
  # t.string :zipcode
@@ -38,7 +39,7 @@ module ActiveRecord
38
39
  #
39
40
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
40
41
  #
41
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
42
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
42
43
  # def up
43
44
  # create_table :distributors do |t|
44
45
  # t.string :zipcode
@@ -63,7 +64,7 @@ module ActiveRecord
63
64
  #
64
65
  # 2. Use the #reversible method in <tt>#change</tt> method:
65
66
  #
66
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
67
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
67
68
  # def change
68
69
  # create_table :distributors do |t|
69
70
  # t.string :zipcode
@@ -130,6 +131,22 @@ module ActiveRecord
130
131
  end
131
132
  end
132
133
 
134
+ class InvalidMigrationTimestampError < MigrationError # :nodoc:
135
+ def initialize(version = nil, name = nil)
136
+ if version && name
137
+ super(<<~MSG)
138
+ Invalid timestamp #{version} for migration file: #{name}.
139
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
140
+ MSG
141
+ else
142
+ super(<<~MSG)
143
+ Invalid timestamp for migration.
144
+ Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
145
+ MSG
146
+ end
147
+ end
148
+ end
149
+
133
150
  class PendingMigrationError < MigrationError # :nodoc:
134
151
  include ActiveSupport::ActionableError
135
152
 
@@ -137,32 +154,37 @@ module ActiveRecord
137
154
  ActiveRecord::Tasks::DatabaseTasks.migrate
138
155
 
139
156
  if ActiveRecord.dump_schema_after_migration
140
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(
141
- ActiveRecord::Base.connection_db_config
142
- )
157
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
158
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
143
159
  end
144
160
  end
145
161
 
146
- def initialize(message = nil)
147
- super(message || detailed_migration_message)
162
+ def initialize(message = nil, pending_migrations: nil)
163
+ if pending_migrations.nil?
164
+ pending_migrations = connection_pool.migration_context.open.pending_migrations
165
+ end
166
+
167
+ super(message || detailed_migration_message(pending_migrations))
148
168
  end
149
169
 
150
170
  private
151
- def detailed_migration_message
171
+ def detailed_migration_message(pending_migrations)
152
172
  message = "Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate"
153
- message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env)
173
+ message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
154
174
  message += "\n\n"
155
175
 
156
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157
-
158
176
  message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159
177
 
160
178
  pending_migrations.each do |pending_migration|
161
- message += "#{pending_migration.basename}\n"
179
+ message += "#{pending_migration.filename}\n"
162
180
  end
163
181
 
164
182
  message
165
183
  end
184
+
185
+ def connection_pool
186
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
187
+ end
166
188
  end
167
189
 
168
190
  class ConcurrentMigrationError < MigrationError # :nodoc:
@@ -228,7 +250,7 @@ module ActiveRecord
228
250
  #
229
251
  # Example of a simple migration:
230
252
  #
231
- # class AddSsl < ActiveRecord::Migration[7.0]
253
+ # class AddSsl < ActiveRecord::Migration[7.2]
232
254
  # def up
233
255
  # add_column :accounts, :ssl_enabled, :boolean, default: true
234
256
  # end
@@ -248,7 +270,7 @@ module ActiveRecord
248
270
  #
249
271
  # Example of a more complex migration that also needs to initialize data:
250
272
  #
251
- # class AddSystemSettings < ActiveRecord::Migration[7.0]
273
+ # class AddSystemSettings < ActiveRecord::Migration[7.2]
252
274
  # def up
253
275
  # create_table :system_settings do |t|
254
276
  # t.string :name
@@ -356,15 +378,16 @@ module ActiveRecord
356
378
  # == Irreversible transformations
357
379
  #
358
380
  # Some transformations are destructive in a manner that cannot be reversed.
359
- # Migrations of that kind should raise an <tt>ActiveRecord::IrreversibleMigration</tt>
381
+ # Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
360
382
  # exception in their +down+ method.
361
383
  #
362
- # == Running migrations from within Rails
384
+ # == Running migrations from within \Rails
363
385
  #
364
- # The Rails package has several tools to help create and apply migrations.
386
+ # The \Rails package has several tools to help create and apply migrations.
365
387
  #
366
388
  # To generate a new migration, you can use
367
- # bin/rails generate migration MyNewMigration
389
+ #
390
+ # $ bin/rails generate migration MyNewMigration
368
391
  #
369
392
  # where MyNewMigration is the name of your migration. The generator will
370
393
  # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
@@ -373,10 +396,10 @@ module ActiveRecord
373
396
  #
374
397
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
375
398
  #
376
- # bin/rails generate migration add_fieldname_to_tablename fieldname:string
399
+ # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
400
  #
378
401
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
379
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
402
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
380
403
  # def change
381
404
  # add_column :tablenames, :fieldname, :string
382
405
  # end
@@ -395,14 +418,14 @@ module ActiveRecord
395
418
  # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
396
419
  # the latest two migrations.
397
420
  #
398
- # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
421
+ # If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
399
422
  # that step will fail and you'll have some manual work to do.
400
423
  #
401
424
  # == More examples
402
425
  #
403
426
  # Not all migrations change the schema. Some just fix the data:
404
427
  #
405
- # class RemoveEmptyTags < ActiveRecord::Migration[7.0]
428
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.2]
406
429
  # def up
407
430
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
408
431
  # end
@@ -415,7 +438,7 @@ module ActiveRecord
415
438
  #
416
439
  # Others remove columns when they migrate up instead of down:
417
440
  #
418
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
441
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
419
442
  # def up
420
443
  # remove_column :items, :incomplete_items_count
421
444
  # remove_column :items, :completed_items_count
@@ -429,7 +452,7 @@ module ActiveRecord
429
452
  #
430
453
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
431
454
  #
432
- # class MakeJoinUnique < ActiveRecord::Migration[7.0]
455
+ # class MakeJoinUnique < ActiveRecord::Migration[7.2]
433
456
  # def up
434
457
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
435
458
  # end
@@ -446,7 +469,7 @@ module ActiveRecord
446
469
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
447
470
  # latest column data from after the new column was added. Example:
448
471
  #
449
- # class AddPeopleSalary < ActiveRecord::Migration[7.0]
472
+ # class AddPeopleSalary < ActiveRecord::Migration[7.2]
450
473
  # def up
451
474
  # add_column :people, :salary, :integer
452
475
  # Person.reset_column_information
@@ -462,7 +485,7 @@ module ActiveRecord
462
485
  # them to the console as they happen, along with benchmarks describing how
463
486
  # long each step took.
464
487
  #
465
- # You can quiet them down by setting ActiveRecord::Migration.verbose = false.
488
+ # You can quiet them down by setting <tt>ActiveRecord::Migration.verbose = false</tt>.
466
489
  #
467
490
  # You can also insert your own messages and benchmarks by using the +say_with_time+
468
491
  # method:
@@ -482,11 +505,15 @@ module ActiveRecord
482
505
  #
483
506
  # == Timestamped Migrations
484
507
  #
485
- # By default, Rails generates migrations that look like:
508
+ # By default, \Rails generates migrations that look like:
486
509
  #
487
510
  # 20080717013526_your_migration_name.rb
488
511
  #
489
- # The prefix is a generation timestamp (in UTC).
512
+ # The prefix is a generation timestamp (in UTC). Timestamps should not be
513
+ # modified manually. To validate that migration timestamps adhere to the
514
+ # format Active Record expects, you can use the following configuration option:
515
+ #
516
+ # config.active_record.validate_migration_timestamps = true
490
517
  #
491
518
  # If you'd prefer to use numeric prefixes, you can turn timestamped migrations
492
519
  # off by setting:
@@ -504,7 +531,7 @@ module ActiveRecord
504
531
  # To define a reversible migration, define the +change+ method in your
505
532
  # migration like this:
506
533
  #
507
- # class TenderloveMigration < ActiveRecord::Migration[7.0]
534
+ # class TenderloveMigration < ActiveRecord::Migration[7.2]
508
535
  # def change
509
536
  # create_table(:horses) do |t|
510
537
  # t.column :content, :text
@@ -521,11 +548,11 @@ module ActiveRecord
521
548
  # as before.
522
549
  #
523
550
  # If a command cannot be reversed, an
524
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
551
+ # ActiveRecord::IrreversibleMigration exception will be raised when
525
552
  # the migration is moving down.
526
553
  #
527
554
  # For a list of commands that are reversible, please see
528
- # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
555
+ # +ActiveRecord::Migration::CommandRecorder+.
529
556
  #
530
557
  # == Transactional Migrations
531
558
  #
@@ -534,7 +561,7 @@ module ActiveRecord
534
561
  # can't execute inside a transaction though, and for these situations
535
562
  # you can turn the automatic transactions off.
536
563
  #
537
- # class ChangeEnum < ActiveRecord::Migration[7.0]
564
+ # class ChangeEnum < ActiveRecord::Migration[7.2]
538
565
  # disable_ddl_transaction!
539
566
  #
540
567
  # def up
@@ -548,6 +575,8 @@ module ActiveRecord
548
575
  autoload :CommandRecorder, "active_record/migration/command_recorder"
549
576
  autoload :Compatibility, "active_record/migration/compatibility"
550
577
  autoload :JoinTable, "active_record/migration/join_table"
578
+ autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
579
+ autoload :DefaultStrategy, "active_record/migration/default_strategy"
551
580
 
552
581
  # This must be defined before the inherited hook, below
553
582
  class Current < Migration # :nodoc:
@@ -610,6 +639,13 @@ module ActiveRecord
610
639
 
611
640
  MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
612
641
 
642
+ def self.valid_version_format?(version_string) # :nodoc:
643
+ [
644
+ MigrationFilenameRegexp,
645
+ /\A\d(_?\d)*\z/ # integer with optional underscores
646
+ ].any? { |pattern| pattern.match?(version_string) }
647
+ end
648
+
613
649
  # This class is used to verify that all migrations have been run before
614
650
  # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
615
651
  class CheckPending
@@ -624,7 +660,7 @@ module ActiveRecord
624
660
  @mutex.synchronize do
625
661
  @watcher ||= build_watcher do
626
662
  @needs_check = true
627
- ActiveRecord::Migration.check_pending!(connection)
663
+ ActiveRecord::Migration.check_pending_migrations
628
664
  @needs_check = false
629
665
  end
630
666
 
@@ -640,12 +676,14 @@ module ActiveRecord
640
676
 
641
677
  private
642
678
  def build_watcher(&block)
643
- paths = Array(connection.migration_context.migrations_paths)
679
+ current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
680
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
681
+ paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
644
682
  @file_watcher.new([], paths.index_with(["rb"]), &block)
645
683
  end
646
684
 
647
685
  def connection
648
- ActiveRecord::Base.connection
686
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
649
687
  end
650
688
  end
651
689
 
@@ -657,32 +695,36 @@ module ActiveRecord
657
695
  delegate || superclass.nearest_delegate
658
696
  end
659
697
 
660
- # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
661
- def check_pending!(connection = Base.connection)
662
- raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
663
- end
698
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending
699
+ # for all database configurations in an environment.
700
+ def check_all_pending!
701
+ pending_migrations = []
664
702
 
665
- def load_schema_if_pending!
666
- current_db_config = Base.connection_db_config
667
- all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
703
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: env) do |pool|
704
+ if pending = pool.migration_context.open.pending_migrations
705
+ pending_migrations << pending
706
+ end
707
+ end
708
+
709
+ migrations = pending_migrations.flatten
668
710
 
669
- needs_update = !all_configs.all? do |db_config|
670
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
711
+ if migrations.any?
712
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
671
713
  end
714
+ end
672
715
 
673
- if needs_update
716
+ def load_schema_if_pending!
717
+ if any_schema_needs_update?
674
718
  # Roundtrip to Rake to allow plugins to hook into database initialization.
675
719
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
720
+
676
721
  FileUtils.cd(root) do
677
- Base.clear_all_connections!
722
+ Base.connection_handler.clear_all_connections!(:all)
678
723
  system("bin/rails db:test:prepare")
679
724
  end
680
725
  end
681
726
 
682
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
683
- Base.establish_connection(current_db_config)
684
-
685
- check_pending!
727
+ check_pending_migrations
686
728
  end
687
729
 
688
730
  def maintain_test_schema! # :nodoc:
@@ -691,10 +733,9 @@ module ActiveRecord
691
733
  end
692
734
  end
693
735
 
694
- def method_missing(name, *args, &block) # :nodoc:
695
- nearest_delegate.send(name, *args, &block)
736
+ def method_missing(name, ...) # :nodoc:
737
+ nearest_delegate.send(name, ...)
696
738
  end
697
- ruby2_keywords(:method_missing)
698
739
 
699
740
  def migrate(direction)
700
741
  new.migrate direction
@@ -707,12 +748,55 @@ module ActiveRecord
707
748
  def disable_ddl_transaction!
708
749
  @disable_ddl_transaction = true
709
750
  end
751
+
752
+ def check_pending_migrations # :nodoc:
753
+ migrations = pending_migrations
754
+
755
+ if migrations.any?
756
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
757
+ end
758
+ end
759
+
760
+ private
761
+ def any_schema_needs_update?
762
+ !db_configs_in_current_env.all? do |db_config|
763
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
764
+ end
765
+ end
766
+
767
+ def db_configs_in_current_env
768
+ ActiveRecord::Base.configurations.configs_for(env_name: env)
769
+ end
770
+
771
+ def pending_migrations
772
+ pending_migrations = []
773
+
774
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
775
+ ActiveRecord::PendingMigrationConnection.with_temporary_pool(db_config) do |pool|
776
+ if pending = pool.migration_context.open.pending_migrations
777
+ pending_migrations << pending
778
+ end
779
+ end
780
+ end
781
+
782
+ pending_migrations.flatten
783
+ end
784
+
785
+ def env
786
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
787
+ end
710
788
  end
711
789
 
712
790
  def disable_ddl_transaction # :nodoc:
713
791
  self.class.disable_ddl_transaction
714
792
  end
715
793
 
794
+ ##
795
+ # :singleton-method: verbose
796
+ #
797
+ # Specifies if migrations will write the actions they are taking to the console as they
798
+ # happen, along with benchmarks describing how long each step took. Defaults to
799
+ # true.
716
800
  cattr_accessor :verbose
717
801
  attr_accessor :name, :version
718
802
 
@@ -720,6 +804,11 @@ module ActiveRecord
720
804
  @name = name
721
805
  @version = version
722
806
  @connection = nil
807
+ @pool = nil
808
+ end
809
+
810
+ def execution_strategy
811
+ @execution_strategy ||= ActiveRecord.migration_strategy.new(self)
723
812
  end
724
813
 
725
814
  self.verbose = true
@@ -733,7 +822,7 @@ module ActiveRecord
733
822
  # and create the table 'apples' on the way up, and the reverse
734
823
  # on the way down.
735
824
  #
736
- # class FixTLMigration < ActiveRecord::Migration[7.0]
825
+ # class FixTLMigration < ActiveRecord::Migration[7.2]
737
826
  # def change
738
827
  # revert do
739
828
  # create_table(:horses) do |t|
@@ -752,7 +841,7 @@ module ActiveRecord
752
841
  #
753
842
  # require_relative "20121212123456_tenderlove_migration"
754
843
  #
755
- # class FixupTLMigration < ActiveRecord::Migration[7.0]
844
+ # class FixupTLMigration < ActiveRecord::Migration[7.2]
756
845
  # def change
757
846
  # revert TenderloveMigration
758
847
  #
@@ -803,7 +892,7 @@ module ActiveRecord
803
892
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
804
893
  # even when migrating down:
805
894
  #
806
- # class SplitNameMigration < ActiveRecord::Migration[7.0]
895
+ # class SplitNameMigration < ActiveRecord::Migration[7.2]
807
896
  # def change
808
897
  # add_column :users, :first_name, :string
809
898
  # add_column :users, :last_name, :string
@@ -831,7 +920,7 @@ module ActiveRecord
831
920
  # In the following example, the new column +published+ will be given
832
921
  # the value +true+ for all existing records.
833
922
  #
834
- # class AddPublishedToPosts < ActiveRecord::Migration[7.0]
923
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.2]
835
924
  # def change
836
925
  # add_column :posts, :published, :boolean, default: false
837
926
  # up_only do
@@ -884,7 +973,7 @@ module ActiveRecord
884
973
  end
885
974
 
886
975
  time = nil
887
- ActiveRecord::Base.connection_pool.with_connection do |conn|
976
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
888
977
  time = Benchmark.measure do
889
978
  exec_migration(conn, direction)
890
979
  end
@@ -909,6 +998,7 @@ module ActiveRecord
909
998
  end
910
999
  ensure
911
1000
  @connection = nil
1001
+ @execution_strategy = nil
912
1002
  end
913
1003
 
914
1004
  def write(text = "")
@@ -947,7 +1037,11 @@ module ActiveRecord
947
1037
  end
948
1038
 
949
1039
  def connection
950
- @connection || ActiveRecord::Base.connection
1040
+ @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
1041
+ end
1042
+
1043
+ def connection_pool
1044
+ @pool || ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
951
1045
  end
952
1046
 
953
1047
  def method_missing(method, *arguments, &block)
@@ -961,22 +1055,23 @@ module ActiveRecord
961
1055
  end
962
1056
  end
963
1057
  end
964
- return super unless connection.respond_to?(method)
965
- connection.send(method, *arguments, &block)
1058
+ return super unless execution_strategy.respond_to?(method)
1059
+ execution_strategy.send(method, *arguments, &block)
966
1060
  end
967
1061
  end
968
1062
  ruby2_keywords(:method_missing)
969
1063
 
970
1064
  def copy(destination, sources, options = {})
971
1065
  copied = []
972
- schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
973
1066
 
974
1067
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
1068
+ schema_migration = SchemaMigration::NullSchemaMigration.new
1069
+ internal_metadata = InternalMetadata::NullInternalMetadata.new
975
1070
 
976
- destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
1071
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
977
1072
  last = destination_migrations.last
978
1073
  sources.each do |scope, path|
979
- source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
1074
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
980
1075
 
981
1076
  source_migrations.each do |migration|
982
1077
  source = File.binread(migration.filename)
@@ -1037,7 +1132,7 @@ module ActiveRecord
1037
1132
  if ActiveRecord.timestamped_migrations
1038
1133
  [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
1039
1134
  else
1040
- SchemaMigration.normalize_migration_number(number)
1135
+ "%.3d" % number.to_i
1041
1136
  end
1042
1137
  end
1043
1138
 
@@ -1107,19 +1202,22 @@ module ActiveRecord
1107
1202
  end
1108
1203
  end
1109
1204
 
1205
+ # = \Migration \Context
1206
+ #
1110
1207
  # MigrationContext sets the context in which a migration is run.
1111
1208
  #
1112
1209
  # A migration context requires the path to the migrations is set
1113
1210
  # in the +migrations_paths+ parameter. Optionally a +schema_migration+
1114
- # class can be provided. For most applications, +SchemaMigration+ is
1115
- # sufficient. Multiple database applications need a +SchemaMigration+
1116
- # per primary database.
1211
+ # class can be provided. Multiple database applications will instantiate
1212
+ # a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
1213
+ # handle this for you.
1117
1214
  class MigrationContext
1118
- attr_reader :migrations_paths, :schema_migration
1215
+ attr_reader :migrations_paths, :schema_migration, :internal_metadata
1119
1216
 
1120
- def initialize(migrations_paths, schema_migration = SchemaMigration)
1217
+ def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
1121
1218
  @migrations_paths = migrations_paths
1122
- @schema_migration = schema_migration
1219
+ @schema_migration = schema_migration || SchemaMigration.new(connection_pool)
1220
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection_pool)
1123
1221
  end
1124
1222
 
1125
1223
  # Runs the migrations in the +migrations_path+.
@@ -1163,7 +1261,7 @@ module ActiveRecord
1163
1261
  migrations
1164
1262
  end
1165
1263
 
1166
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1264
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1167
1265
  end
1168
1266
 
1169
1267
  def down(target_version = nil, &block) # :nodoc:
@@ -1173,20 +1271,20 @@ module ActiveRecord
1173
1271
  migrations
1174
1272
  end
1175
1273
 
1176
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1274
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1177
1275
  end
1178
1276
 
1179
1277
  def run(direction, target_version) # :nodoc:
1180
- Migrator.new(direction, migrations, schema_migration, target_version).run
1278
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
1181
1279
  end
1182
1280
 
1183
1281
  def open # :nodoc:
1184
- Migrator.new(:up, migrations, schema_migration)
1282
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
1185
1283
  end
1186
1284
 
1187
1285
  def get_all_versions # :nodoc:
1188
1286
  if schema_migration.table_exists?
1189
- schema_migration.all_versions.map(&:to_i)
1287
+ schema_migration.integer_versions
1190
1288
  else
1191
1289
  []
1192
1290
  end
@@ -1209,6 +1307,9 @@ module ActiveRecord
1209
1307
  migrations = migration_files.map do |file|
1210
1308
  version, name, scope = parse_migration_filename(file)
1211
1309
  raise IllegalMigrationNameError.new(file) unless version
1310
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1311
+ raise InvalidMigrationTimestampError.new(version, name)
1312
+ end
1212
1313
  version = version.to_i
1213
1314
  name = name.camelize
1214
1315
 
@@ -1224,6 +1325,9 @@ module ActiveRecord
1224
1325
  file_list = migration_files.filter_map do |file|
1225
1326
  version, name, scope = parse_migration_filename(file)
1226
1327
  raise IllegalMigrationNameError.new(file) unless version
1328
+ if validate_timestamp? && !valid_migration_timestamp?(version)
1329
+ raise InvalidMigrationTimestampError.new(version, name)
1330
+ end
1227
1331
  version = schema_migration.normalize_migration_number(version)
1228
1332
  status = db_list.delete(version) ? "up" : "down"
1229
1333
  [status, version, (name + scope).humanize]
@@ -1245,16 +1349,25 @@ module ActiveRecord
1245
1349
  end
1246
1350
 
1247
1351
  def last_stored_environment # :nodoc:
1248
- return nil unless ActiveRecord::InternalMetadata.enabled?
1352
+ internal_metadata = connection_pool.internal_metadata
1353
+ return nil unless internal_metadata.enabled?
1249
1354
  return nil if current_version == 0
1250
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1355
+ raise NoEnvironmentInSchemaError unless internal_metadata.table_exists?
1251
1356
 
1252
- environment = ActiveRecord::InternalMetadata[:environment]
1357
+ environment = internal_metadata[:environment]
1253
1358
  raise NoEnvironmentInSchemaError unless environment
1254
1359
  environment
1255
1360
  end
1256
1361
 
1257
1362
  private
1363
+ def connection
1364
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1365
+ end
1366
+
1367
+ def connection_pool
1368
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1369
+ end
1370
+
1258
1371
  def migration_files
1259
1372
  paths = Array(migrations_paths)
1260
1373
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1264,8 +1377,16 @@ module ActiveRecord
1264
1377
  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1265
1378
  end
1266
1379
 
1380
+ def validate_timestamp?
1381
+ ActiveRecord.timestamped_migrations && ActiveRecord.validate_migration_timestamps
1382
+ end
1383
+
1384
+ def valid_migration_timestamp?(version)
1385
+ version.to_i < (Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S").to_i
1386
+ end
1387
+
1267
1388
  def move(direction, steps)
1268
- migrator = Migrator.new(direction, migrations, schema_migration)
1389
+ migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1269
1390
 
1270
1391
  if current_version != 0 && !migrator.current_migration
1271
1392
  raise UnknownMigrationVersionError.new(current_version)
@@ -1290,23 +1411,28 @@ module ActiveRecord
1290
1411
 
1291
1412
  # For cases where a table doesn't exist like loading from schema cache
1292
1413
  def current_version
1293
- MigrationContext.new(migrations_paths, SchemaMigration).current_version
1414
+ connection_pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
1415
+ schema_migration = SchemaMigration.new(connection_pool)
1416
+ internal_metadata = InternalMetadata.new(connection_pool)
1417
+
1418
+ MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
1294
1419
  end
1295
1420
  end
1296
1421
 
1297
1422
  self.migrations_paths = ["db/migrate"]
1298
1423
 
1299
- def initialize(direction, migrations, schema_migration, target_version = nil)
1424
+ def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
1300
1425
  @direction = direction
1301
1426
  @target_version = target_version
1302
1427
  @migrated_versions = nil
1303
1428
  @migrations = migrations
1304
1429
  @schema_migration = schema_migration
1430
+ @internal_metadata = internal_metadata
1305
1431
 
1306
1432
  validate(@migrations)
1307
1433
 
1308
1434
  @schema_migration.create_table
1309
- ActiveRecord::InternalMetadata.create_table
1435
+ @internal_metadata.create_table
1310
1436
  end
1311
1437
 
1312
1438
  def current_version
@@ -1359,18 +1485,21 @@ module ActiveRecord
1359
1485
  end
1360
1486
 
1361
1487
  def load_migrated
1362
- @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1488
+ @migrated_versions = Set.new(@schema_migration.integer_versions)
1363
1489
  end
1364
1490
 
1365
1491
  private
1492
+ def connection
1493
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1494
+ end
1495
+
1366
1496
  # Used for running a specific migration.
1367
1497
  def run_without_lock
1368
1498
  migration = migrations.detect { |m| m.version == @target_version }
1369
1499
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1370
- result = execute_migration_in_transaction(migration)
1371
1500
 
1372
1501
  record_environment
1373
- result
1502
+ execute_migration_in_transaction(migration)
1374
1503
  end
1375
1504
 
1376
1505
  # Used for running multiple migrations up to or down to a certain value.
@@ -1379,15 +1508,15 @@ module ActiveRecord
1379
1508
  raise UnknownMigrationVersionError.new(@target_version)
1380
1509
  end
1381
1510
 
1382
- result = runnable.each(&method(:execute_migration_in_transaction))
1383
1511
  record_environment
1384
- result
1512
+ runnable.each(&method(:execute_migration_in_transaction))
1385
1513
  end
1386
1514
 
1387
1515
  # Stores the current environment in the database.
1388
1516
  def record_environment
1389
1517
  return if down?
1390
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.pool.db_config.env_name
1518
+
1519
+ @internal_metadata[:environment] = connection.pool.db_config.env_name
1391
1520
  end
1392
1521
 
1393
1522
  def ran?(migration)
@@ -1439,10 +1568,10 @@ module ActiveRecord
1439
1568
  def record_version_state_after_migrating(version)
1440
1569
  if down?
1441
1570
  migrated.delete(version)
1442
- @schema_migration.delete_by(version: version.to_s)
1571
+ @schema_migration.delete_version(version.to_s)
1443
1572
  else
1444
1573
  migrated << version
1445
- @schema_migration.create!(version: version.to_s)
1574
+ @schema_migration.create_version(version.to_s)
1446
1575
  end
1447
1576
  end
1448
1577
 
@@ -1457,50 +1586,38 @@ module ActiveRecord
1457
1586
  # Wrap the migration in a transaction only if supported by the adapter.
1458
1587
  def ddl_transaction(migration, &block)
1459
1588
  if use_transaction?(migration)
1460
- Base.transaction(&block)
1589
+ connection.transaction(&block)
1461
1590
  else
1462
1591
  yield
1463
1592
  end
1464
1593
  end
1465
1594
 
1466
1595
  def use_transaction?(migration)
1467
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1596
+ !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
1468
1597
  end
1469
1598
 
1470
1599
  def use_advisory_lock?
1471
- Base.connection.advisory_locks_enabled?
1600
+ connection.advisory_locks_enabled?
1472
1601
  end
1473
1602
 
1474
1603
  def with_advisory_lock
1475
1604
  lock_id = generate_migrator_advisory_lock_id
1476
1605
 
1477
- with_advisory_lock_connection do |connection|
1478
- got_lock = connection.get_advisory_lock(lock_id)
1479
- raise ConcurrentMigrationError unless got_lock
1480
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1481
- yield
1482
- ensure
1483
- if got_lock && !connection.release_advisory_lock(lock_id)
1484
- raise ConcurrentMigrationError.new(
1485
- ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1486
- )
1487
- end
1488
- end
1489
- end
1490
-
1491
- def with_advisory_lock_connection(&block)
1492
- pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
1493
- ActiveRecord::Base.connection_db_config
1494
- )
1495
-
1496
- pool.with_connection(&block)
1606
+ got_lock = connection.get_advisory_lock(lock_id)
1607
+ raise ConcurrentMigrationError unless got_lock
1608
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1609
+ yield
1497
1610
  ensure
1498
- pool&.disconnect!
1611
+ if got_lock && !connection.release_advisory_lock(lock_id)
1612
+ raise ConcurrentMigrationError.new(
1613
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1614
+ )
1615
+ end
1499
1616
  end
1500
1617
 
1501
1618
  MIGRATOR_SALT = 2053462845
1502
1619
  def generate_migrator_advisory_lock_id
1503
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1620
+ db_name_hash = Zlib.crc32(connection.current_database)
1504
1621
  MIGRATOR_SALT * db_name_hash
1505
1622
  end
1506
1623
  end