activerecord 7.0.10 → 7.1.0.beta1
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1348 -1672
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -17
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +16 -11
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +12 -9
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +313 -217
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +48 -38
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +65 -49
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -122
- data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -115
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +352 -55
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +72 -95
- data/lib/active_record/core.rb +131 -142
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +11 -6
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +52 -12
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +89 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +119 -83
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +58 -11
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +100 -4
- data/lib/active_record/migration/compatibility.rb +131 -5
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +215 -112
- data/lib/active_record/model_schema.rb +50 -32
- data/lib/active_record/nested_attributes.rb +31 -6
- data/lib/active_record/normalization.rb +158 -0
- data/lib/active_record/persistence.rb +183 -33
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +108 -46
- data/lib/active_record/railties/controller_runtime.rb +10 -5
- data/lib/active_record/railties/databases.rake +139 -145
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +169 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +152 -63
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +85 -15
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +351 -62
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +75 -34
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +41 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +27 -15
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +52 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
|
20
20
|
# For example the following migration is not reversible.
|
|
21
21
|
# Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
|
|
22
22
|
#
|
|
23
|
-
# class IrreversibleMigrationExample < ActiveRecord::Migration[7.
|
|
23
|
+
# class IrreversibleMigrationExample < ActiveRecord::Migration[7.1]
|
|
24
24
|
# def change
|
|
25
25
|
# create_table :distributors do |t|
|
|
26
26
|
# t.string :zipcode
|
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
|
38
38
|
#
|
|
39
39
|
# 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
|
|
40
40
|
#
|
|
41
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[7.
|
|
41
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
|
|
42
42
|
# def up
|
|
43
43
|
# create_table :distributors do |t|
|
|
44
44
|
# t.string :zipcode
|
|
@@ -63,7 +63,7 @@ module ActiveRecord
|
|
|
63
63
|
#
|
|
64
64
|
# 2. Use the #reversible method in <tt>#change</tt> method:
|
|
65
65
|
#
|
|
66
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[7.
|
|
66
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
|
|
67
67
|
# def change
|
|
68
68
|
# create_table :distributors do |t|
|
|
69
69
|
# t.string :zipcode
|
|
@@ -137,32 +137,38 @@ module ActiveRecord
|
|
|
137
137
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
|
138
138
|
|
|
139
139
|
if ActiveRecord.dump_schema_after_migration
|
|
140
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
|
141
|
-
|
|
142
|
-
)
|
|
140
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
141
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
|
|
143
142
|
end
|
|
144
143
|
end
|
|
145
144
|
|
|
146
|
-
def initialize(message = nil)
|
|
147
|
-
|
|
145
|
+
def initialize(message = nil, pending_migrations: nil)
|
|
146
|
+
if pending_migrations.nil?
|
|
147
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
148
|
+
pending_migrations = connection.migration_context.open.pending_migrations
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
super(message || detailed_migration_message(pending_migrations))
|
|
148
152
|
end
|
|
149
153
|
|
|
150
154
|
private
|
|
151
|
-
def detailed_migration_message
|
|
155
|
+
def detailed_migration_message(pending_migrations)
|
|
152
156
|
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)
|
|
157
|
+
message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
|
|
154
158
|
message += "\n\n"
|
|
155
159
|
|
|
156
|
-
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
|
|
157
|
-
|
|
158
160
|
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
|
|
159
161
|
|
|
160
162
|
pending_migrations.each do |pending_migration|
|
|
161
|
-
message += "#{pending_migration.
|
|
163
|
+
message += "#{pending_migration.filename}\n"
|
|
162
164
|
end
|
|
163
165
|
|
|
164
166
|
message
|
|
165
167
|
end
|
|
168
|
+
|
|
169
|
+
def connection
|
|
170
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
171
|
+
end
|
|
166
172
|
end
|
|
167
173
|
|
|
168
174
|
class ConcurrentMigrationError < MigrationError # :nodoc:
|
|
@@ -228,7 +234,7 @@ module ActiveRecord
|
|
|
228
234
|
#
|
|
229
235
|
# Example of a simple migration:
|
|
230
236
|
#
|
|
231
|
-
# class AddSsl < ActiveRecord::Migration[7.
|
|
237
|
+
# class AddSsl < ActiveRecord::Migration[7.1]
|
|
232
238
|
# def up
|
|
233
239
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
|
234
240
|
# end
|
|
@@ -248,7 +254,7 @@ module ActiveRecord
|
|
|
248
254
|
#
|
|
249
255
|
# Example of a more complex migration that also needs to initialize data:
|
|
250
256
|
#
|
|
251
|
-
# class AddSystemSettings < ActiveRecord::Migration[7.
|
|
257
|
+
# class AddSystemSettings < ActiveRecord::Migration[7.1]
|
|
252
258
|
# def up
|
|
253
259
|
# create_table :system_settings do |t|
|
|
254
260
|
# t.string :name
|
|
@@ -356,16 +362,15 @@ module ActiveRecord
|
|
|
356
362
|
# == Irreversible transformations
|
|
357
363
|
#
|
|
358
364
|
# Some transformations are destructive in a manner that cannot be reversed.
|
|
359
|
-
# Migrations of that kind should raise an
|
|
365
|
+
# Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
|
|
360
366
|
# exception in their +down+ method.
|
|
361
367
|
#
|
|
362
|
-
# == Running migrations from within Rails
|
|
368
|
+
# == Running migrations from within \Rails
|
|
363
369
|
#
|
|
364
|
-
# The Rails package has several tools to help create and apply migrations.
|
|
370
|
+
# The \Rails package has several tools to help create and apply migrations.
|
|
365
371
|
#
|
|
366
372
|
# To generate a new migration, you can use
|
|
367
|
-
#
|
|
368
|
-
# $ bin/rails generate migration MyNewMigration
|
|
373
|
+
# bin/rails generate migration MyNewMigration
|
|
369
374
|
#
|
|
370
375
|
# where MyNewMigration is the name of your migration. The generator will
|
|
371
376
|
# create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
|
|
@@ -374,10 +379,10 @@ module ActiveRecord
|
|
|
374
379
|
#
|
|
375
380
|
# There is a special syntactic shortcut to generate migrations that add fields to a table.
|
|
376
381
|
#
|
|
377
|
-
#
|
|
382
|
+
# bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
|
378
383
|
#
|
|
379
384
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
|
380
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[7.
|
|
385
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
|
|
381
386
|
# def change
|
|
382
387
|
# add_column :tablenames, :fieldname, :string
|
|
383
388
|
# end
|
|
@@ -396,14 +401,14 @@ module ActiveRecord
|
|
|
396
401
|
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
|
397
402
|
# the latest two migrations.
|
|
398
403
|
#
|
|
399
|
-
# If any of the migrations throw an
|
|
404
|
+
# If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
|
|
400
405
|
# that step will fail and you'll have some manual work to do.
|
|
401
406
|
#
|
|
402
407
|
# == More examples
|
|
403
408
|
#
|
|
404
409
|
# Not all migrations change the schema. Some just fix the data:
|
|
405
410
|
#
|
|
406
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[7.
|
|
411
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[7.1]
|
|
407
412
|
# def up
|
|
408
413
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
|
409
414
|
# end
|
|
@@ -416,7 +421,7 @@ module ActiveRecord
|
|
|
416
421
|
#
|
|
417
422
|
# Others remove columns when they migrate up instead of down:
|
|
418
423
|
#
|
|
419
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.
|
|
424
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
|
|
420
425
|
# def up
|
|
421
426
|
# remove_column :items, :incomplete_items_count
|
|
422
427
|
# remove_column :items, :completed_items_count
|
|
@@ -430,7 +435,7 @@ module ActiveRecord
|
|
|
430
435
|
#
|
|
431
436
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
|
432
437
|
#
|
|
433
|
-
# class MakeJoinUnique < ActiveRecord::Migration[7.
|
|
438
|
+
# class MakeJoinUnique < ActiveRecord::Migration[7.1]
|
|
434
439
|
# def up
|
|
435
440
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
|
436
441
|
# end
|
|
@@ -447,7 +452,7 @@ module ActiveRecord
|
|
|
447
452
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
|
448
453
|
# latest column data from after the new column was added. Example:
|
|
449
454
|
#
|
|
450
|
-
# class AddPeopleSalary < ActiveRecord::Migration[7.
|
|
455
|
+
# class AddPeopleSalary < ActiveRecord::Migration[7.1]
|
|
451
456
|
# def up
|
|
452
457
|
# add_column :people, :salary, :integer
|
|
453
458
|
# Person.reset_column_information
|
|
@@ -483,7 +488,7 @@ module ActiveRecord
|
|
|
483
488
|
#
|
|
484
489
|
# == Timestamped Migrations
|
|
485
490
|
#
|
|
486
|
-
# By default, Rails generates migrations that look like:
|
|
491
|
+
# By default, \Rails generates migrations that look like:
|
|
487
492
|
#
|
|
488
493
|
# 20080717013526_your_migration_name.rb
|
|
489
494
|
#
|
|
@@ -505,7 +510,7 @@ module ActiveRecord
|
|
|
505
510
|
# To define a reversible migration, define the +change+ method in your
|
|
506
511
|
# migration like this:
|
|
507
512
|
#
|
|
508
|
-
# class TenderloveMigration < ActiveRecord::Migration[7.
|
|
513
|
+
# class TenderloveMigration < ActiveRecord::Migration[7.1]
|
|
509
514
|
# def change
|
|
510
515
|
# create_table(:horses) do |t|
|
|
511
516
|
# t.column :content, :text
|
|
@@ -522,11 +527,11 @@ module ActiveRecord
|
|
|
522
527
|
# as before.
|
|
523
528
|
#
|
|
524
529
|
# If a command cannot be reversed, an
|
|
525
|
-
#
|
|
530
|
+
# ActiveRecord::IrreversibleMigration exception will be raised when
|
|
526
531
|
# the migration is moving down.
|
|
527
532
|
#
|
|
528
533
|
# For a list of commands that are reversible, please see
|
|
529
|
-
#
|
|
534
|
+
# +ActiveRecord::Migration::CommandRecorder+.
|
|
530
535
|
#
|
|
531
536
|
# == Transactional Migrations
|
|
532
537
|
#
|
|
@@ -535,7 +540,7 @@ module ActiveRecord
|
|
|
535
540
|
# can't execute inside a transaction though, and for these situations
|
|
536
541
|
# you can turn the automatic transactions off.
|
|
537
542
|
#
|
|
538
|
-
# class ChangeEnum < ActiveRecord::Migration[7.
|
|
543
|
+
# class ChangeEnum < ActiveRecord::Migration[7.1]
|
|
539
544
|
# disable_ddl_transaction!
|
|
540
545
|
#
|
|
541
546
|
# def up
|
|
@@ -549,6 +554,8 @@ module ActiveRecord
|
|
|
549
554
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
|
550
555
|
autoload :Compatibility, "active_record/migration/compatibility"
|
|
551
556
|
autoload :JoinTable, "active_record/migration/join_table"
|
|
557
|
+
autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
|
|
558
|
+
autoload :DefaultStrategy, "active_record/migration/default_strategy"
|
|
552
559
|
|
|
553
560
|
# This must be defined before the inherited hook, below
|
|
554
561
|
class Current < Migration # :nodoc:
|
|
@@ -611,6 +618,13 @@ module ActiveRecord
|
|
|
611
618
|
|
|
612
619
|
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
|
|
613
620
|
|
|
621
|
+
def self.valid_version_format?(version_string) # :nodoc:
|
|
622
|
+
[
|
|
623
|
+
MigrationFilenameRegexp,
|
|
624
|
+
/\A\d(_?\d)*\z/ # integer with optional underscores
|
|
625
|
+
].any? { |pattern| pattern.match?(version_string) }
|
|
626
|
+
end
|
|
627
|
+
|
|
614
628
|
# This class is used to verify that all migrations have been run before
|
|
615
629
|
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
|
616
630
|
class CheckPending
|
|
@@ -625,7 +639,7 @@ module ActiveRecord
|
|
|
625
639
|
@mutex.synchronize do
|
|
626
640
|
@watcher ||= build_watcher do
|
|
627
641
|
@needs_check = true
|
|
628
|
-
ActiveRecord::Migration.
|
|
642
|
+
ActiveRecord::Migration.check_pending_migrations
|
|
629
643
|
@needs_check = false
|
|
630
644
|
end
|
|
631
645
|
|
|
@@ -641,12 +655,14 @@ module ActiveRecord
|
|
|
641
655
|
|
|
642
656
|
private
|
|
643
657
|
def build_watcher(&block)
|
|
644
|
-
|
|
658
|
+
current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
|
659
|
+
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
|
|
660
|
+
paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
|
|
645
661
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
|
646
662
|
end
|
|
647
663
|
|
|
648
664
|
def connection
|
|
649
|
-
ActiveRecord::
|
|
665
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
650
666
|
end
|
|
651
667
|
end
|
|
652
668
|
|
|
@@ -658,32 +674,53 @@ module ActiveRecord
|
|
|
658
674
|
delegate || superclass.nearest_delegate
|
|
659
675
|
end
|
|
660
676
|
|
|
661
|
-
# Raises
|
|
662
|
-
|
|
663
|
-
|
|
677
|
+
# Raises ActiveRecord::PendingMigrationError error if any migrations are pending.
|
|
678
|
+
#
|
|
679
|
+
# This is deprecated in favor of +check_all_pending!+
|
|
680
|
+
def check_pending!(connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection)
|
|
681
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
|
682
|
+
The `check_pending!` method is deprecated in favor of `check_all_pending!`. The
|
|
683
|
+
new implementation will loop through all available database configurations and find
|
|
684
|
+
pending migrations. The prior implementation did not permit this.
|
|
685
|
+
MSG
|
|
686
|
+
|
|
687
|
+
pending_migrations = connection.migration_context.open.pending_migrations
|
|
688
|
+
|
|
689
|
+
if pending_migrations.any?
|
|
690
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
|
|
691
|
+
end
|
|
664
692
|
end
|
|
665
693
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
694
|
+
# Raises ActiveRecord::PendingMigrationError error if any migrations are pending
|
|
695
|
+
# for all database configurations in an environment.
|
|
696
|
+
def check_all_pending!
|
|
697
|
+
pending_migrations = []
|
|
698
|
+
|
|
699
|
+
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
|
|
700
|
+
if pending = connection.migration_context.open.pending_migrations
|
|
701
|
+
pending_migrations << pending
|
|
702
|
+
end
|
|
703
|
+
end
|
|
669
704
|
|
|
670
|
-
|
|
671
|
-
|
|
705
|
+
migrations = pending_migrations.flatten
|
|
706
|
+
|
|
707
|
+
if migrations.any?
|
|
708
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
|
672
709
|
end
|
|
710
|
+
end
|
|
673
711
|
|
|
674
|
-
|
|
712
|
+
def load_schema_if_pending!
|
|
713
|
+
if any_schema_needs_update?
|
|
675
714
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
|
676
715
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
|
716
|
+
|
|
677
717
|
FileUtils.cd(root) do
|
|
678
|
-
Base.clear_all_connections!
|
|
718
|
+
Base.connection_handler.clear_all_connections!(:all)
|
|
679
719
|
system("bin/rails db:test:prepare")
|
|
680
720
|
end
|
|
681
721
|
end
|
|
682
722
|
|
|
683
|
-
|
|
684
|
-
Base.establish_connection(current_db_config)
|
|
685
|
-
|
|
686
|
-
check_pending!
|
|
723
|
+
check_pending_migrations
|
|
687
724
|
end
|
|
688
725
|
|
|
689
726
|
def maintain_test_schema! # :nodoc:
|
|
@@ -708,6 +745,41 @@ module ActiveRecord
|
|
|
708
745
|
def disable_ddl_transaction!
|
|
709
746
|
@disable_ddl_transaction = true
|
|
710
747
|
end
|
|
748
|
+
|
|
749
|
+
def check_pending_migrations # :nodoc:
|
|
750
|
+
migrations = pending_migrations
|
|
751
|
+
|
|
752
|
+
if migrations.any?
|
|
753
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
|
754
|
+
end
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
private
|
|
758
|
+
def any_schema_needs_update?
|
|
759
|
+
!db_configs_in_current_env.all? do |db_config|
|
|
760
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
|
|
761
|
+
end
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def db_configs_in_current_env
|
|
765
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env)
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
def pending_migrations
|
|
769
|
+
pending_migrations = []
|
|
770
|
+
|
|
771
|
+
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
|
|
772
|
+
if pending = connection.migration_context.open.pending_migrations
|
|
773
|
+
pending_migrations << pending
|
|
774
|
+
end
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
pending_migrations.flatten
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
def env
|
|
781
|
+
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
|
782
|
+
end
|
|
711
783
|
end
|
|
712
784
|
|
|
713
785
|
def disable_ddl_transaction # :nodoc:
|
|
@@ -723,6 +795,10 @@ module ActiveRecord
|
|
|
723
795
|
@connection = nil
|
|
724
796
|
end
|
|
725
797
|
|
|
798
|
+
def execution_strategy
|
|
799
|
+
@execution_strategy ||= ActiveRecord.migration_strategy.new(self)
|
|
800
|
+
end
|
|
801
|
+
|
|
726
802
|
self.verbose = true
|
|
727
803
|
# instantiate the delegate object after initialize is defined
|
|
728
804
|
self.delegate = new
|
|
@@ -734,7 +810,7 @@ module ActiveRecord
|
|
|
734
810
|
# and create the table 'apples' on the way up, and the reverse
|
|
735
811
|
# on the way down.
|
|
736
812
|
#
|
|
737
|
-
# class FixTLMigration < ActiveRecord::Migration[7.
|
|
813
|
+
# class FixTLMigration < ActiveRecord::Migration[7.1]
|
|
738
814
|
# def change
|
|
739
815
|
# revert do
|
|
740
816
|
# create_table(:horses) do |t|
|
|
@@ -753,7 +829,7 @@ module ActiveRecord
|
|
|
753
829
|
#
|
|
754
830
|
# require_relative "20121212123456_tenderlove_migration"
|
|
755
831
|
#
|
|
756
|
-
# class FixupTLMigration < ActiveRecord::Migration[7.
|
|
832
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.1]
|
|
757
833
|
# def change
|
|
758
834
|
# revert TenderloveMigration
|
|
759
835
|
#
|
|
@@ -804,7 +880,7 @@ module ActiveRecord
|
|
|
804
880
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
|
805
881
|
# even when migrating down:
|
|
806
882
|
#
|
|
807
|
-
# class SplitNameMigration < ActiveRecord::Migration[7.
|
|
883
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.1]
|
|
808
884
|
# def change
|
|
809
885
|
# add_column :users, :first_name, :string
|
|
810
886
|
# add_column :users, :last_name, :string
|
|
@@ -832,7 +908,7 @@ module ActiveRecord
|
|
|
832
908
|
# In the following example, the new column +published+ will be given
|
|
833
909
|
# the value +true+ for all existing records.
|
|
834
910
|
#
|
|
835
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[7.
|
|
911
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.1]
|
|
836
912
|
# def change
|
|
837
913
|
# add_column :posts, :published, :boolean, default: false
|
|
838
914
|
# up_only do
|
|
@@ -885,7 +961,7 @@ module ActiveRecord
|
|
|
885
961
|
end
|
|
886
962
|
|
|
887
963
|
time = nil
|
|
888
|
-
ActiveRecord::
|
|
964
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
|
889
965
|
time = Benchmark.measure do
|
|
890
966
|
exec_migration(conn, direction)
|
|
891
967
|
end
|
|
@@ -910,6 +986,7 @@ module ActiveRecord
|
|
|
910
986
|
end
|
|
911
987
|
ensure
|
|
912
988
|
@connection = nil
|
|
989
|
+
@execution_strategy = nil
|
|
913
990
|
end
|
|
914
991
|
|
|
915
992
|
def write(text = "")
|
|
@@ -948,7 +1025,7 @@ module ActiveRecord
|
|
|
948
1025
|
end
|
|
949
1026
|
|
|
950
1027
|
def connection
|
|
951
|
-
@connection || ActiveRecord::
|
|
1028
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
952
1029
|
end
|
|
953
1030
|
|
|
954
1031
|
def method_missing(method, *arguments, &block)
|
|
@@ -962,22 +1039,23 @@ module ActiveRecord
|
|
|
962
1039
|
end
|
|
963
1040
|
end
|
|
964
1041
|
end
|
|
965
|
-
return super unless
|
|
966
|
-
|
|
1042
|
+
return super unless execution_strategy.respond_to?(method)
|
|
1043
|
+
execution_strategy.send(method, *arguments, &block)
|
|
967
1044
|
end
|
|
968
1045
|
end
|
|
969
1046
|
ruby2_keywords(:method_missing)
|
|
970
1047
|
|
|
971
1048
|
def copy(destination, sources, options = {})
|
|
972
1049
|
copied = []
|
|
973
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
|
974
1050
|
|
|
975
1051
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
|
1052
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
|
1053
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
|
976
1054
|
|
|
977
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
|
1055
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
|
978
1056
|
last = destination_migrations.last
|
|
979
1057
|
sources.each do |scope, path|
|
|
980
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
|
1058
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
|
981
1059
|
|
|
982
1060
|
source_migrations.each do |migration|
|
|
983
1061
|
source = File.binread(migration.filename)
|
|
@@ -1038,7 +1116,7 @@ module ActiveRecord
|
|
|
1038
1116
|
if ActiveRecord.timestamped_migrations
|
|
1039
1117
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
|
1040
1118
|
else
|
|
1041
|
-
|
|
1119
|
+
"%.3d" % number.to_i
|
|
1042
1120
|
end
|
|
1043
1121
|
end
|
|
1044
1122
|
|
|
@@ -1108,19 +1186,44 @@ module ActiveRecord
|
|
|
1108
1186
|
end
|
|
1109
1187
|
end
|
|
1110
1188
|
|
|
1189
|
+
# = \Migration \Context
|
|
1190
|
+
#
|
|
1111
1191
|
# MigrationContext sets the context in which a migration is run.
|
|
1112
1192
|
#
|
|
1113
1193
|
# A migration context requires the path to the migrations is set
|
|
1114
1194
|
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
|
1115
|
-
# class can be provided.
|
|
1116
|
-
#
|
|
1117
|
-
#
|
|
1195
|
+
# class can be provided. Multiple database applications will instantiate
|
|
1196
|
+
# a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
|
|
1197
|
+
# handle this for you.
|
|
1118
1198
|
class MigrationContext
|
|
1119
|
-
attr_reader :migrations_paths, :schema_migration
|
|
1199
|
+
attr_reader :migrations_paths, :schema_migration, :internal_metadata
|
|
1200
|
+
|
|
1201
|
+
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
|
|
1202
|
+
if schema_migration == SchemaMigration
|
|
1203
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
|
1204
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
|
1205
|
+
to use the default connection, remove this argument. If you want to use a
|
|
1206
|
+
specific connection, instantiate MigrationContext with the connection's schema
|
|
1207
|
+
migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
|
|
1208
|
+
MSG
|
|
1209
|
+
|
|
1210
|
+
schema_migration = nil
|
|
1211
|
+
end
|
|
1212
|
+
|
|
1213
|
+
if internal_metadata == InternalMetadata
|
|
1214
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
|
1215
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
|
1216
|
+
to use the default connection, remove this argument. If you want to use a
|
|
1217
|
+
specific connection, instantiate MigrationContext with the connection's internal
|
|
1218
|
+
metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
|
|
1219
|
+
MSG
|
|
1220
|
+
|
|
1221
|
+
internal_metadata = nil
|
|
1222
|
+
end
|
|
1120
1223
|
|
|
1121
|
-
def initialize(migrations_paths, schema_migration = SchemaMigration)
|
|
1122
1224
|
@migrations_paths = migrations_paths
|
|
1123
|
-
@schema_migration = schema_migration
|
|
1225
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection)
|
|
1226
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection)
|
|
1124
1227
|
end
|
|
1125
1228
|
|
|
1126
1229
|
# Runs the migrations in the +migrations_path+.
|
|
@@ -1164,7 +1267,7 @@ module ActiveRecord
|
|
|
1164
1267
|
migrations
|
|
1165
1268
|
end
|
|
1166
1269
|
|
|
1167
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
|
1270
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
1168
1271
|
end
|
|
1169
1272
|
|
|
1170
1273
|
def down(target_version = nil, &block) # :nodoc:
|
|
@@ -1174,20 +1277,20 @@ module ActiveRecord
|
|
|
1174
1277
|
migrations
|
|
1175
1278
|
end
|
|
1176
1279
|
|
|
1177
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
|
1280
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
1178
1281
|
end
|
|
1179
1282
|
|
|
1180
1283
|
def run(direction, target_version) # :nodoc:
|
|
1181
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
|
1284
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
|
1182
1285
|
end
|
|
1183
1286
|
|
|
1184
1287
|
def open # :nodoc:
|
|
1185
|
-
Migrator.new(:up, migrations, schema_migration)
|
|
1288
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
|
1186
1289
|
end
|
|
1187
1290
|
|
|
1188
1291
|
def get_all_versions # :nodoc:
|
|
1189
1292
|
if schema_migration.table_exists?
|
|
1190
|
-
schema_migration.
|
|
1293
|
+
schema_migration.integer_versions
|
|
1191
1294
|
else
|
|
1192
1295
|
[]
|
|
1193
1296
|
end
|
|
@@ -1246,16 +1349,20 @@ module ActiveRecord
|
|
|
1246
1349
|
end
|
|
1247
1350
|
|
|
1248
1351
|
def last_stored_environment # :nodoc:
|
|
1249
|
-
return nil unless
|
|
1352
|
+
return nil unless connection.internal_metadata.enabled?
|
|
1250
1353
|
return nil if current_version == 0
|
|
1251
|
-
raise NoEnvironmentInSchemaError unless
|
|
1354
|
+
raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
|
|
1252
1355
|
|
|
1253
|
-
environment =
|
|
1356
|
+
environment = connection.internal_metadata[:environment]
|
|
1254
1357
|
raise NoEnvironmentInSchemaError unless environment
|
|
1255
1358
|
environment
|
|
1256
1359
|
end
|
|
1257
1360
|
|
|
1258
1361
|
private
|
|
1362
|
+
def connection
|
|
1363
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
1364
|
+
end
|
|
1365
|
+
|
|
1259
1366
|
def migration_files
|
|
1260
1367
|
paths = Array(migrations_paths)
|
|
1261
1368
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
|
@@ -1266,7 +1373,7 @@ module ActiveRecord
|
|
|
1266
1373
|
end
|
|
1267
1374
|
|
|
1268
1375
|
def move(direction, steps)
|
|
1269
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
|
1376
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
|
1270
1377
|
|
|
1271
1378
|
if current_version != 0 && !migrator.current_migration
|
|
1272
1379
|
raise UnknownMigrationVersionError.new(current_version)
|
|
@@ -1291,23 +1398,28 @@ module ActiveRecord
|
|
|
1291
1398
|
|
|
1292
1399
|
# For cases where a table doesn't exist like loading from schema cache
|
|
1293
1400
|
def current_version
|
|
1294
|
-
|
|
1401
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
1402
|
+
schema_migration = SchemaMigration.new(connection)
|
|
1403
|
+
internal_metadata = InternalMetadata.new(connection)
|
|
1404
|
+
|
|
1405
|
+
MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
|
|
1295
1406
|
end
|
|
1296
1407
|
end
|
|
1297
1408
|
|
|
1298
1409
|
self.migrations_paths = ["db/migrate"]
|
|
1299
1410
|
|
|
1300
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
|
1411
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
|
1301
1412
|
@direction = direction
|
|
1302
1413
|
@target_version = target_version
|
|
1303
1414
|
@migrated_versions = nil
|
|
1304
1415
|
@migrations = migrations
|
|
1305
1416
|
@schema_migration = schema_migration
|
|
1417
|
+
@internal_metadata = internal_metadata
|
|
1306
1418
|
|
|
1307
1419
|
validate(@migrations)
|
|
1308
1420
|
|
|
1309
1421
|
@schema_migration.create_table
|
|
1310
|
-
|
|
1422
|
+
@internal_metadata.create_table
|
|
1311
1423
|
end
|
|
1312
1424
|
|
|
1313
1425
|
def current_version
|
|
@@ -1360,18 +1472,21 @@ module ActiveRecord
|
|
|
1360
1472
|
end
|
|
1361
1473
|
|
|
1362
1474
|
def load_migrated
|
|
1363
|
-
@migrated_versions = Set.new(@schema_migration.
|
|
1475
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
|
1364
1476
|
end
|
|
1365
1477
|
|
|
1366
1478
|
private
|
|
1479
|
+
def connection
|
|
1480
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
1481
|
+
end
|
|
1482
|
+
|
|
1367
1483
|
# Used for running a specific migration.
|
|
1368
1484
|
def run_without_lock
|
|
1369
1485
|
migration = migrations.detect { |m| m.version == @target_version }
|
|
1370
1486
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
|
1371
|
-
result = execute_migration_in_transaction(migration)
|
|
1372
1487
|
|
|
1373
1488
|
record_environment
|
|
1374
|
-
|
|
1489
|
+
execute_migration_in_transaction(migration)
|
|
1375
1490
|
end
|
|
1376
1491
|
|
|
1377
1492
|
# Used for running multiple migrations up to or down to a certain value.
|
|
@@ -1380,15 +1495,15 @@ module ActiveRecord
|
|
|
1380
1495
|
raise UnknownMigrationVersionError.new(@target_version)
|
|
1381
1496
|
end
|
|
1382
1497
|
|
|
1383
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
|
1384
1498
|
record_environment
|
|
1385
|
-
|
|
1499
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
|
1386
1500
|
end
|
|
1387
1501
|
|
|
1388
1502
|
# Stores the current environment in the database.
|
|
1389
1503
|
def record_environment
|
|
1390
1504
|
return if down?
|
|
1391
|
-
|
|
1505
|
+
|
|
1506
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
|
1392
1507
|
end
|
|
1393
1508
|
|
|
1394
1509
|
def ran?(migration)
|
|
@@ -1440,10 +1555,10 @@ module ActiveRecord
|
|
|
1440
1555
|
def record_version_state_after_migrating(version)
|
|
1441
1556
|
if down?
|
|
1442
1557
|
migrated.delete(version)
|
|
1443
|
-
@schema_migration.
|
|
1558
|
+
@schema_migration.delete_version(version.to_s)
|
|
1444
1559
|
else
|
|
1445
1560
|
migrated << version
|
|
1446
|
-
@schema_migration.
|
|
1561
|
+
@schema_migration.create_version(version.to_s)
|
|
1447
1562
|
end
|
|
1448
1563
|
end
|
|
1449
1564
|
|
|
@@ -1458,50 +1573,38 @@ module ActiveRecord
|
|
|
1458
1573
|
# Wrap the migration in a transaction only if supported by the adapter.
|
|
1459
1574
|
def ddl_transaction(migration, &block)
|
|
1460
1575
|
if use_transaction?(migration)
|
|
1461
|
-
|
|
1576
|
+
connection.transaction(&block)
|
|
1462
1577
|
else
|
|
1463
1578
|
yield
|
|
1464
1579
|
end
|
|
1465
1580
|
end
|
|
1466
1581
|
|
|
1467
1582
|
def use_transaction?(migration)
|
|
1468
|
-
!migration.disable_ddl_transaction &&
|
|
1583
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
|
1469
1584
|
end
|
|
1470
1585
|
|
|
1471
1586
|
def use_advisory_lock?
|
|
1472
|
-
|
|
1587
|
+
connection.advisory_locks_enabled?
|
|
1473
1588
|
end
|
|
1474
1589
|
|
|
1475
1590
|
def with_advisory_lock
|
|
1476
1591
|
lock_id = generate_migrator_advisory_lock_id
|
|
1477
1592
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
yield
|
|
1483
|
-
ensure
|
|
1484
|
-
if got_lock && !connection.release_advisory_lock(lock_id)
|
|
1485
|
-
raise ConcurrentMigrationError.new(
|
|
1486
|
-
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
|
1487
|
-
)
|
|
1488
|
-
end
|
|
1489
|
-
end
|
|
1490
|
-
end
|
|
1491
|
-
|
|
1492
|
-
def with_advisory_lock_connection(&block)
|
|
1493
|
-
pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
|
1494
|
-
ActiveRecord::Base.connection_db_config
|
|
1495
|
-
)
|
|
1496
|
-
|
|
1497
|
-
pool.with_connection(&block)
|
|
1593
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
|
1594
|
+
raise ConcurrentMigrationError unless got_lock
|
|
1595
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
|
1596
|
+
yield
|
|
1498
1597
|
ensure
|
|
1499
|
-
|
|
1598
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
|
1599
|
+
raise ConcurrentMigrationError.new(
|
|
1600
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
|
1601
|
+
)
|
|
1602
|
+
end
|
|
1500
1603
|
end
|
|
1501
1604
|
|
|
1502
1605
|
MIGRATOR_SALT = 2053462845
|
|
1503
1606
|
def generate_migrator_advisory_lock_id
|
|
1504
|
-
db_name_hash = Zlib.crc32(
|
|
1607
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
|
1505
1608
|
MIGRATOR_SALT * db_name_hash
|
|
1506
1609
|
end
|
|
1507
1610
|
end
|