activerecord 5.2.8 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1393 -587
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +10 -9
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +122 -47
- data/lib/active_record/associations/association_scope.rb +24 -24
- data/lib/active_record/associations/belongs_to_association.rb +67 -49
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
- data/lib/active_record/associations/builder/association.rb +52 -23
- data/lib/active_record/associations/builder/belongs_to.rb +44 -61
- data/lib/active_record/associations/builder/collection_association.rb +17 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +10 -3
- data/lib/active_record/associations/builder/has_one.rb +35 -3
- data/lib/active_record/associations/builder/singular_association.rb +5 -3
- data/lib/active_record/associations/collection_association.rb +59 -50
- data/lib/active_record/associations/collection_proxy.rb +32 -23
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +27 -14
- data/lib/active_record/associations/has_many_through_association.rb +26 -19
- data/lib/active_record/associations/has_one_association.rb +52 -37
- data/lib/active_record/associations/has_one_through_association.rb +6 -6
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +97 -62
- data/lib/active_record/associations/preloader/association.rb +220 -60
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +85 -40
- data/lib/active_record/associations/preloader.rb +44 -105
- data/lib/active_record/associations/singular_association.rb +9 -17
- data/lib/active_record/associations/through_association.rb +4 -4
- data/lib/active_record/associations.rb +207 -66
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
- data/lib/active_record/attribute_methods/dirty.rb +141 -47
- data/lib/active_record/attribute_methods/primary_key.rb +22 -27
- data/lib/active_record/attribute_methods/query.rb +6 -10
- data/lib/active_record/attribute_methods/read.rb +15 -55
- data/lib/active_record/attribute_methods/serialization.rb +77 -18
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
- data/lib/active_record/attribute_methods/write.rb +18 -37
- data/lib/active_record/attribute_methods.rb +90 -153
- data/lib/active_record/attributes.rb +38 -12
- data/lib/active_record/autosave_association.rb +50 -50
- data/lib/active_record/base.rb +23 -18
- data/lib/active_record/callbacks.rb +159 -44
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
- data/lib/active_record/connection_adapters/column.rb +33 -11
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
- data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +53 -0
- data/lib/active_record/connection_handling.rb +292 -38
- data/lib/active_record/core.rb +385 -158
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
- data/lib/active_record/database_configurations/database_config.rb +83 -0
- data/lib/active_record/database_configurations/hash_config.rb +154 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +256 -0
- data/lib/active_record/delegated_type.rb +250 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +4 -5
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +130 -51
- data/lib/active_record/errors.rb +129 -23
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +187 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +206 -490
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +104 -37
- data/lib/active_record/insert_all.rb +278 -0
- data/lib/active_record/integration.rb +69 -18
- data/lib/active_record/internal_metadata.rb +24 -9
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +41 -26
- data/lib/active_record/locking/pessimistic.rb +18 -8
- data/lib/active_record/log_subscriber.rb +46 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +82 -0
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +246 -64
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration.rb +266 -187
- data/lib/active_record/model_schema.rb +165 -52
- data/lib/active_record/nested_attributes.rb +17 -19
- data/lib/active_record/no_touching.rb +11 -4
- data/lib/active_record/null_relation.rb +2 -7
- data/lib/active_record/persistence.rb +467 -92
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +51 -24
- data/lib/active_record/railtie.rb +224 -57
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +31 -36
- data/lib/active_record/railties/databases.rake +369 -101
- data/lib/active_record/readonly_attributes.rb +15 -0
- data/lib/active_record/reflection.rb +170 -137
- data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
- data/lib/active_record/relation/batches.rb +46 -37
- data/lib/active_record/relation/calculations.rb +168 -96
- data/lib/active_record/relation/delegation.rb +37 -52
- data/lib/active_record/relation/finder_methods.rb +79 -58
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +50 -51
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -46
- data/lib/active_record/relation/query_attribute.rb +9 -10
- data/lib/active_record/relation/query_methods.rb +685 -208
- data/lib/active_record/relation/record_fetch_warning.rb +9 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -10
- data/lib/active_record/relation/where_clause.rb +108 -64
- data/lib/active_record/relation.rb +515 -151
- data/lib/active_record/result.rb +78 -42
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +29 -44
- data/lib/active_record/schema.rb +37 -31
- data/lib/active_record/schema_dumper.rb +74 -23
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +62 -17
- data/lib/active_record/scoping/named.rb +17 -32
- data/lib/active_record/scoping.rb +70 -41
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +6 -4
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +13 -17
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +352 -94
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +44 -34
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +67 -128
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +34 -19
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +7 -4
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +9 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +2 -3
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +39 -31
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +209 -32
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +71 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +258 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +117 -0
- data/lib/arel/tree_manager.rb +60 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors/dot.rb +298 -0
- data/lib/arel/visitors/mysql.rb +99 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +955 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +55 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +162 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "benchmark"
|
3
4
|
require "set"
|
4
5
|
require "zlib"
|
6
|
+
require "active_support/core_ext/array/access"
|
7
|
+
require "active_support/core_ext/enumerable"
|
5
8
|
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/actionable_error"
|
6
10
|
|
7
11
|
module ActiveRecord
|
8
|
-
class MigrationError < ActiveRecordError
|
12
|
+
class MigrationError < ActiveRecordError # :nodoc:
|
9
13
|
def initialize(message = nil)
|
10
14
|
message = "\n\n#{message}\n\n" if message
|
11
15
|
super
|
@@ -16,13 +20,13 @@ module ActiveRecord
|
|
16
20
|
# For example the following migration is not reversible.
|
17
21
|
# Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
|
18
22
|
#
|
19
|
-
# class IrreversibleMigrationExample < ActiveRecord::Migration[
|
23
|
+
# class IrreversibleMigrationExample < ActiveRecord::Migration[7.0]
|
20
24
|
# def change
|
21
25
|
# create_table :distributors do |t|
|
22
26
|
# t.string :zipcode
|
23
27
|
# end
|
24
28
|
#
|
25
|
-
# execute
|
29
|
+
# execute <<~SQL
|
26
30
|
# ALTER TABLE distributors
|
27
31
|
# ADD CONSTRAINT zipchk
|
28
32
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -34,13 +38,13 @@ module ActiveRecord
|
|
34
38
|
#
|
35
39
|
# 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
|
36
40
|
#
|
37
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
41
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
|
38
42
|
# def up
|
39
43
|
# create_table :distributors do |t|
|
40
44
|
# t.string :zipcode
|
41
45
|
# end
|
42
46
|
#
|
43
|
-
# execute
|
47
|
+
# execute <<~SQL
|
44
48
|
# ALTER TABLE distributors
|
45
49
|
# ADD CONSTRAINT zipchk
|
46
50
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -48,7 +52,7 @@ module ActiveRecord
|
|
48
52
|
# end
|
49
53
|
#
|
50
54
|
# def down
|
51
|
-
# execute
|
55
|
+
# execute <<~SQL
|
52
56
|
# ALTER TABLE distributors
|
53
57
|
# DROP CONSTRAINT zipchk
|
54
58
|
# SQL
|
@@ -59,7 +63,7 @@ module ActiveRecord
|
|
59
63
|
#
|
60
64
|
# 2. Use the #reversible method in <tt>#change</tt> method:
|
61
65
|
#
|
62
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
66
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
|
63
67
|
# def change
|
64
68
|
# create_table :distributors do |t|
|
65
69
|
# t.string :zipcode
|
@@ -67,7 +71,7 @@ module ActiveRecord
|
|
67
71
|
#
|
68
72
|
# reversible do |dir|
|
69
73
|
# dir.up do
|
70
|
-
# execute
|
74
|
+
# execute <<~SQL
|
71
75
|
# ALTER TABLE distributors
|
72
76
|
# ADD CONSTRAINT zipchk
|
73
77
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -75,7 +79,7 @@ module ActiveRecord
|
|
75
79
|
# end
|
76
80
|
#
|
77
81
|
# dir.down do
|
78
|
-
# execute
|
82
|
+
# execute <<~SQL
|
79
83
|
# ALTER TABLE distributors
|
80
84
|
# DROP CONSTRAINT zipchk
|
81
85
|
# SQL
|
@@ -86,7 +90,7 @@ module ActiveRecord
|
|
86
90
|
class IrreversibleMigration < MigrationError
|
87
91
|
end
|
88
92
|
|
89
|
-
class DuplicateMigrationVersionError < MigrationError
|
93
|
+
class DuplicateMigrationVersionError < MigrationError # :nodoc:
|
90
94
|
def initialize(version = nil)
|
91
95
|
if version
|
92
96
|
super("Multiple migrations have the version number #{version}.")
|
@@ -96,7 +100,7 @@ module ActiveRecord
|
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
99
|
-
class DuplicateMigrationNameError < MigrationError
|
103
|
+
class DuplicateMigrationNameError < MigrationError # :nodoc:
|
100
104
|
def initialize(name = nil)
|
101
105
|
if name
|
102
106
|
super("Multiple migrations have the name #{name}.")
|
@@ -106,7 +110,7 @@ module ActiveRecord
|
|
106
110
|
end
|
107
111
|
end
|
108
112
|
|
109
|
-
class UnknownMigrationVersionError < MigrationError
|
113
|
+
class UnknownMigrationVersionError < MigrationError # :nodoc:
|
110
114
|
def initialize(version = nil)
|
111
115
|
if version
|
112
116
|
super("No migration with version number #{version}.")
|
@@ -116,7 +120,7 @@ module ActiveRecord
|
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
119
|
-
class IllegalMigrationNameError < MigrationError
|
123
|
+
class IllegalMigrationNameError < MigrationError # :nodoc:
|
120
124
|
def initialize(name = nil)
|
121
125
|
if name
|
122
126
|
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
|
@@ -126,28 +130,51 @@ module ActiveRecord
|
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
129
|
-
class PendingMigrationError < MigrationError
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
class PendingMigrationError < MigrationError # :nodoc:
|
134
|
+
include ActiveSupport::ActionableError
|
135
|
+
|
136
|
+
action "Run pending migrations" do
|
137
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate
|
138
|
+
|
139
|
+
if ActiveRecord.dump_schema_after_migration
|
140
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(
|
141
|
+
ActiveRecord::Base.connection_db_config
|
142
|
+
)
|
137
143
|
end
|
138
144
|
end
|
145
|
+
|
146
|
+
def initialize(message = nil)
|
147
|
+
super(message || detailed_migration_message)
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
def detailed_migration_message
|
152
|
+
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)
|
154
|
+
message += "\n\n"
|
155
|
+
|
156
|
+
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
|
157
|
+
|
158
|
+
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
|
159
|
+
|
160
|
+
pending_migrations.each do |pending_migration|
|
161
|
+
message += "#{pending_migration.basename}\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
message
|
165
|
+
end
|
139
166
|
end
|
140
167
|
|
141
|
-
class ConcurrentMigrationError < MigrationError
|
142
|
-
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
143
|
-
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
168
|
+
class ConcurrentMigrationError < MigrationError # :nodoc:
|
169
|
+
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
170
|
+
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
144
171
|
|
145
172
|
def initialize(message = DEFAULT_MESSAGE)
|
146
173
|
super
|
147
174
|
end
|
148
175
|
end
|
149
176
|
|
150
|
-
class NoEnvironmentInSchemaError < MigrationError
|
177
|
+
class NoEnvironmentInSchemaError < MigrationError # :nodoc:
|
151
178
|
def initialize
|
152
179
|
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
|
153
180
|
if defined?(Rails.env)
|
@@ -158,9 +185,9 @@ module ActiveRecord
|
|
158
185
|
end
|
159
186
|
end
|
160
187
|
|
161
|
-
class ProtectedEnvironmentError < ActiveRecordError
|
188
|
+
class ProtectedEnvironmentError < ActiveRecordError # :nodoc:
|
162
189
|
def initialize(env = "production")
|
163
|
-
msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
|
190
|
+
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
164
191
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
165
192
|
msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
166
193
|
super(msg)
|
@@ -169,7 +196,7 @@ module ActiveRecord
|
|
169
196
|
|
170
197
|
class EnvironmentMismatchError < ActiveRecordError
|
171
198
|
def initialize(current: nil, stored: nil)
|
172
|
-
msg =
|
199
|
+
msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
|
173
200
|
msg << "You are running in `#{ current }` environment. "
|
174
201
|
msg << "If you are sure you want to continue, first set the environment using:\n\n"
|
175
202
|
msg << " bin/rails db:environment:set"
|
@@ -181,6 +208,14 @@ module ActiveRecord
|
|
181
208
|
end
|
182
209
|
end
|
183
210
|
|
211
|
+
class EnvironmentStorageError < ActiveRecordError # :nodoc:
|
212
|
+
def initialize
|
213
|
+
msg = +"You are attempting to store the environment in a database where metadata is disabled.\n"
|
214
|
+
msg << "Check your database configuration to see if this is intended."
|
215
|
+
super(msg)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
184
219
|
# = Active Record Migrations
|
185
220
|
#
|
186
221
|
# Migrations can manage the evolution of a schema used by several physical
|
@@ -193,7 +228,7 @@ module ActiveRecord
|
|
193
228
|
#
|
194
229
|
# Example of a simple migration:
|
195
230
|
#
|
196
|
-
# class AddSsl < ActiveRecord::Migration[
|
231
|
+
# class AddSsl < ActiveRecord::Migration[7.0]
|
197
232
|
# def up
|
198
233
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
199
234
|
# end
|
@@ -213,7 +248,7 @@ module ActiveRecord
|
|
213
248
|
#
|
214
249
|
# Example of a more complex migration that also needs to initialize data:
|
215
250
|
#
|
216
|
-
# class AddSystemSettings < ActiveRecord::Migration[
|
251
|
+
# class AddSystemSettings < ActiveRecord::Migration[7.0]
|
217
252
|
# def up
|
218
253
|
# create_table :system_settings do |t|
|
219
254
|
# t.string :name
|
@@ -285,7 +320,7 @@ module ActiveRecord
|
|
285
320
|
# +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
|
286
321
|
# as +default_or_changes+ will make this change reversible in the migration.
|
287
322
|
# * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
|
288
|
-
# Sets or removes a
|
323
|
+
# Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
|
289
324
|
# indicates whether the value can be +NULL+. See
|
290
325
|
# ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
|
291
326
|
# details.
|
@@ -307,7 +342,7 @@ module ActiveRecord
|
|
307
342
|
# named +column_name+ from the table called +table_name+.
|
308
343
|
# * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
|
309
344
|
# columns from the table definition.
|
310
|
-
# * <tt>remove_foreign_key(from_table,
|
345
|
+
# * <tt>remove_foreign_key(from_table, to_table = nil, **options)</tt>: Removes the
|
311
346
|
# given foreign key from the table called +table_name+.
|
312
347
|
# * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
|
313
348
|
# specified by +column_names+.
|
@@ -329,7 +364,7 @@ module ActiveRecord
|
|
329
364
|
# The Rails package has several tools to help create and apply migrations.
|
330
365
|
#
|
331
366
|
# To generate a new migration, you can use
|
332
|
-
# rails generate migration MyNewMigration
|
367
|
+
# bin/rails generate migration MyNewMigration
|
333
368
|
#
|
334
369
|
# where MyNewMigration is the name of your migration. The generator will
|
335
370
|
# create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
|
@@ -338,41 +373,36 @@ module ActiveRecord
|
|
338
373
|
#
|
339
374
|
# There is a special syntactic shortcut to generate migrations that add fields to a table.
|
340
375
|
#
|
341
|
-
# rails generate migration add_fieldname_to_tablename fieldname:string
|
376
|
+
# bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
342
377
|
#
|
343
378
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
344
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
379
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
|
345
380
|
# def change
|
346
381
|
# add_column :tablenames, :fieldname, :string
|
347
382
|
# end
|
348
383
|
# end
|
349
384
|
#
|
350
385
|
# To run migrations against the currently configured database, use
|
351
|
-
# <tt>rails db:migrate</tt>. This will update the database by running all of the
|
386
|
+
# <tt>bin/rails db:migrate</tt>. This will update the database by running all of the
|
352
387
|
# pending migrations, creating the <tt>schema_migrations</tt> table
|
353
388
|
# (see "About the schema_migrations table" section below) if missing. It will also
|
354
|
-
# invoke the db:schema:dump
|
389
|
+
# invoke the db:schema:dump command, which will update your db/schema.rb file
|
355
390
|
# to match the structure of your database.
|
356
391
|
#
|
357
392
|
# To roll the database back to a previous migration version, use
|
358
|
-
# <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
393
|
+
# <tt>bin/rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
359
394
|
# you wish to downgrade. Alternatively, you can also use the STEP option if you
|
360
|
-
# wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
|
395
|
+
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
361
396
|
# the latest two migrations.
|
362
397
|
#
|
363
398
|
# If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
|
364
399
|
# that step will fail and you'll have some manual work to do.
|
365
400
|
#
|
366
|
-
# == Database support
|
367
|
-
#
|
368
|
-
# Migrations are currently supported in MySQL, PostgreSQL, SQLite,
|
369
|
-
# SQL Server, and Oracle (all supported databases except DB2).
|
370
|
-
#
|
371
401
|
# == More examples
|
372
402
|
#
|
373
403
|
# Not all migrations change the schema. Some just fix the data:
|
374
404
|
#
|
375
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
405
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[7.0]
|
376
406
|
# def up
|
377
407
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
378
408
|
# end
|
@@ -385,7 +415,7 @@ module ActiveRecord
|
|
385
415
|
#
|
386
416
|
# Others remove columns when they migrate up instead of down:
|
387
417
|
#
|
388
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
418
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
|
389
419
|
# def up
|
390
420
|
# remove_column :items, :incomplete_items_count
|
391
421
|
# remove_column :items, :completed_items_count
|
@@ -399,7 +429,7 @@ module ActiveRecord
|
|
399
429
|
#
|
400
430
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
401
431
|
#
|
402
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
432
|
+
# class MakeJoinUnique < ActiveRecord::Migration[7.0]
|
403
433
|
# def up
|
404
434
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
405
435
|
# end
|
@@ -416,7 +446,7 @@ module ActiveRecord
|
|
416
446
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
417
447
|
# latest column data from after the new column was added. Example:
|
418
448
|
#
|
419
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
449
|
+
# class AddPeopleSalary < ActiveRecord::Migration[7.0]
|
420
450
|
# def up
|
421
451
|
# add_column :people, :salary, :integer
|
422
452
|
# Person.reset_column_information
|
@@ -474,7 +504,7 @@ module ActiveRecord
|
|
474
504
|
# To define a reversible migration, define the +change+ method in your
|
475
505
|
# migration like this:
|
476
506
|
#
|
477
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
507
|
+
# class TenderloveMigration < ActiveRecord::Migration[7.0]
|
478
508
|
# def change
|
479
509
|
# create_table(:horses) do |t|
|
480
510
|
# t.column :content, :text
|
@@ -486,9 +516,9 @@ module ActiveRecord
|
|
486
516
|
# This migration will create the horses table for you on the way up, and
|
487
517
|
# automatically figure out how to drop the table on the way down.
|
488
518
|
#
|
489
|
-
# Some commands
|
490
|
-
#
|
491
|
-
#
|
519
|
+
# Some commands cannot be reversed. If you care to define how to move up
|
520
|
+
# and down in these cases, you should define the +up+ and +down+ methods
|
521
|
+
# as before.
|
492
522
|
#
|
493
523
|
# If a command cannot be reversed, an
|
494
524
|
# <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
|
@@ -504,7 +534,7 @@ module ActiveRecord
|
|
504
534
|
# can't execute inside a transaction though, and for these situations
|
505
535
|
# you can turn the automatic transactions off.
|
506
536
|
#
|
507
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
537
|
+
# class ChangeEnum < ActiveRecord::Migration[7.0]
|
508
538
|
# disable_ddl_transaction!
|
509
539
|
#
|
510
540
|
# def up
|
@@ -517,6 +547,7 @@ module ActiveRecord
|
|
517
547
|
class Migration
|
518
548
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
519
549
|
autoload :Compatibility, "active_record/migration/compatibility"
|
550
|
+
autoload :JoinTable, "active_record/migration/join_table"
|
520
551
|
|
521
552
|
# This must be defined before the inherited hook, below
|
522
553
|
class Current < Migration # :nodoc:
|
@@ -525,10 +556,12 @@ module ActiveRecord
|
|
525
556
|
def self.inherited(subclass) # :nodoc:
|
526
557
|
super
|
527
558
|
if subclass.superclass == Migration
|
559
|
+
major = ActiveRecord::VERSION::MAJOR
|
560
|
+
minor = ActiveRecord::VERSION::MINOR
|
528
561
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
529
|
-
"Please specify the
|
562
|
+
"Please specify the Active Record release the migration was written for:\n" \
|
530
563
|
"\n" \
|
531
|
-
" class #{subclass} < ActiveRecord::Migration[
|
564
|
+
" class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
|
532
565
|
end
|
533
566
|
end
|
534
567
|
|
@@ -545,21 +578,36 @@ module ActiveRecord
|
|
545
578
|
# This class is used to verify that all migrations have been run before
|
546
579
|
# loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
|
547
580
|
class CheckPending
|
548
|
-
def initialize(app)
|
581
|
+
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
549
582
|
@app = app
|
550
|
-
@
|
583
|
+
@needs_check = true
|
584
|
+
@mutex = Mutex.new
|
585
|
+
@file_watcher = file_watcher
|
551
586
|
end
|
552
587
|
|
553
588
|
def call(env)
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
589
|
+
@mutex.synchronize do
|
590
|
+
@watcher ||= build_watcher do
|
591
|
+
@needs_check = true
|
592
|
+
ActiveRecord::Migration.check_pending!(connection)
|
593
|
+
@needs_check = false
|
594
|
+
end
|
595
|
+
|
596
|
+
if @needs_check
|
597
|
+
@watcher.execute
|
598
|
+
else
|
599
|
+
@watcher.execute_if_updated
|
600
|
+
end
|
558
601
|
end
|
602
|
+
|
559
603
|
@app.call(env)
|
560
604
|
end
|
561
605
|
|
562
606
|
private
|
607
|
+
def build_watcher(&block)
|
608
|
+
paths = Array(connection.migration_context.migrations_paths)
|
609
|
+
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
610
|
+
end
|
563
611
|
|
564
612
|
def connection
|
565
613
|
ActiveRecord::Base.connection
|
@@ -580,22 +628,30 @@ module ActiveRecord
|
|
580
628
|
end
|
581
629
|
|
582
630
|
def load_schema_if_pending!
|
583
|
-
|
631
|
+
current_db_config = Base.connection_db_config
|
632
|
+
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
|
633
|
+
|
634
|
+
needs_update = !all_configs.all? do |db_config|
|
635
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
|
636
|
+
end
|
637
|
+
|
638
|
+
if needs_update
|
584
639
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
585
640
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
586
641
|
FileUtils.cd(root) do
|
587
|
-
current_config = Base.connection_config
|
588
642
|
Base.clear_all_connections!
|
589
643
|
system("bin/rails db:test:prepare")
|
590
|
-
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
591
|
-
Base.establish_connection(current_config)
|
592
644
|
end
|
593
|
-
check_pending!
|
594
645
|
end
|
646
|
+
|
647
|
+
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
648
|
+
Base.establish_connection(current_db_config)
|
649
|
+
|
650
|
+
check_pending!
|
595
651
|
end
|
596
652
|
|
597
653
|
def maintain_test_schema! # :nodoc:
|
598
|
-
if ActiveRecord
|
654
|
+
if ActiveRecord.maintain_test_schema
|
599
655
|
suppress_messages { load_schema_if_pending! }
|
600
656
|
end
|
601
657
|
end
|
@@ -603,6 +659,7 @@ module ActiveRecord
|
|
603
659
|
def method_missing(name, *args, &block) # :nodoc:
|
604
660
|
nearest_delegate.send(name, *args, &block)
|
605
661
|
end
|
662
|
+
ruby2_keywords(:method_missing)
|
606
663
|
|
607
664
|
def migrate(direction)
|
608
665
|
new.migrate direction
|
@@ -641,7 +698,7 @@ module ActiveRecord
|
|
641
698
|
# and create the table 'apples' on the way up, and the reverse
|
642
699
|
# on the way down.
|
643
700
|
#
|
644
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
701
|
+
# class FixTLMigration < ActiveRecord::Migration[7.0]
|
645
702
|
# def change
|
646
703
|
# revert do
|
647
704
|
# create_table(:horses) do |t|
|
@@ -658,9 +715,9 @@ module ActiveRecord
|
|
658
715
|
# Or equivalently, if +TenderloveMigration+ is defined as in the
|
659
716
|
# documentation for Migration:
|
660
717
|
#
|
661
|
-
# require_relative
|
718
|
+
# require_relative "20121212123456_tenderlove_migration"
|
662
719
|
#
|
663
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
720
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.0]
|
664
721
|
# def change
|
665
722
|
# revert TenderloveMigration
|
666
723
|
#
|
@@ -671,21 +728,19 @@ module ActiveRecord
|
|
671
728
|
# end
|
672
729
|
#
|
673
730
|
# This command can be nested.
|
674
|
-
def revert(*migration_classes)
|
731
|
+
def revert(*migration_classes, &block)
|
675
732
|
run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
|
676
733
|
if block_given?
|
677
734
|
if connection.respond_to? :revert
|
678
|
-
connection.revert
|
735
|
+
connection.revert(&block)
|
679
736
|
else
|
680
|
-
recorder =
|
737
|
+
recorder = command_recorder
|
681
738
|
@connection = recorder
|
682
739
|
suppress_messages do
|
683
|
-
connection.revert
|
740
|
+
connection.revert(&block)
|
684
741
|
end
|
685
742
|
@connection = recorder.delegate
|
686
|
-
recorder.
|
687
|
-
send(cmd, *args, &block)
|
688
|
-
end
|
743
|
+
recorder.replay(self)
|
689
744
|
end
|
690
745
|
end
|
691
746
|
end
|
@@ -713,7 +768,7 @@ module ActiveRecord
|
|
713
768
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
714
769
|
# even when migrating down:
|
715
770
|
#
|
716
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
771
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.0]
|
717
772
|
# def change
|
718
773
|
# add_column :users, :first_name, :string
|
719
774
|
# add_column :users, :last_name, :string
|
@@ -741,7 +796,7 @@ module ActiveRecord
|
|
741
796
|
# In the following example, the new column +published+ will be given
|
742
797
|
# the value +true+ for all existing records.
|
743
798
|
#
|
744
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
799
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.0]
|
745
800
|
# def change
|
746
801
|
# add_column :posts, :published, :boolean, default: false
|
747
802
|
# up_only do
|
@@ -749,8 +804,8 @@ module ActiveRecord
|
|
749
804
|
# end
|
750
805
|
# end
|
751
806
|
# end
|
752
|
-
def up_only
|
753
|
-
execute_block
|
807
|
+
def up_only(&block)
|
808
|
+
execute_block(&block) unless reverting?
|
754
809
|
end
|
755
810
|
|
756
811
|
# Runs the given migration classes.
|
@@ -814,7 +869,7 @@ module ActiveRecord
|
|
814
869
|
change
|
815
870
|
end
|
816
871
|
else
|
817
|
-
|
872
|
+
public_send(direction)
|
818
873
|
end
|
819
874
|
ensure
|
820
875
|
@connection = nil
|
@@ -830,10 +885,14 @@ module ActiveRecord
|
|
830
885
|
write "== %s %s" % [text, "=" * length]
|
831
886
|
end
|
832
887
|
|
888
|
+
# Takes a message argument and outputs it as is.
|
889
|
+
# A second boolean argument can be passed to specify whether to indent or not.
|
833
890
|
def say(message, subitem = false)
|
834
891
|
write "#{subitem ? " ->" : "--"} #{message}"
|
835
892
|
end
|
836
893
|
|
894
|
+
# Outputs text along with how long it took to run its block.
|
895
|
+
# If the block returns an integer it assumes it is the number of rows affected.
|
837
896
|
def say_with_time(message)
|
838
897
|
say(message)
|
839
898
|
result = nil
|
@@ -843,6 +902,7 @@ module ActiveRecord
|
|
843
902
|
result
|
844
903
|
end
|
845
904
|
|
905
|
+
# Takes a block as an argument and suppresses any output generated by the block.
|
846
906
|
def suppress_messages
|
847
907
|
save, self.verbose = verbose, false
|
848
908
|
yield
|
@@ -861,7 +921,7 @@ module ActiveRecord
|
|
861
921
|
unless connection.respond_to? :revert
|
862
922
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
863
923
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
864
|
-
if
|
924
|
+
if method == :rename_table ||
|
865
925
|
(method == :remove_foreign_key && !arguments.second.is_a?(Hash))
|
866
926
|
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
867
927
|
end
|
@@ -871,21 +931,23 @@ module ActiveRecord
|
|
871
931
|
connection.send(method, *arguments, &block)
|
872
932
|
end
|
873
933
|
end
|
934
|
+
ruby2_keywords(:method_missing)
|
874
935
|
|
875
936
|
def copy(destination, sources, options = {})
|
876
937
|
copied = []
|
938
|
+
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
877
939
|
|
878
940
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
879
941
|
|
880
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
|
942
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
881
943
|
last = destination_migrations.last
|
882
944
|
sources.each do |scope, path|
|
883
|
-
source_migrations = ActiveRecord::MigrationContext.new(path).migrations
|
945
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
884
946
|
|
885
947
|
source_migrations.each do |migration|
|
886
948
|
source = File.binread(migration.filename)
|
887
949
|
inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
|
888
|
-
magic_comments = ""
|
950
|
+
magic_comments = +""
|
889
951
|
loop do
|
890
952
|
# If we have a magic comment in the original migration,
|
891
953
|
# insert our comment after the first newline(end of the magic comment line)
|
@@ -895,6 +957,12 @@ module ActiveRecord
|
|
895
957
|
magic_comments << magic_comment; ""
|
896
958
|
end || break
|
897
959
|
end
|
960
|
+
|
961
|
+
if !magic_comments.empty? && source.start_with?("\n")
|
962
|
+
magic_comments << "\n"
|
963
|
+
source = source[1..-1]
|
964
|
+
end
|
965
|
+
|
898
966
|
source = "#{magic_comments}#{inserted_comment}#{source}"
|
899
967
|
|
900
968
|
if duplicate = destination_migrations.detect { |m| m.name == migration.name }
|
@@ -932,7 +1000,7 @@ module ActiveRecord
|
|
932
1000
|
|
933
1001
|
# Determines the version number of the next migration.
|
934
1002
|
def next_migration_number(number)
|
935
|
-
if ActiveRecord
|
1003
|
+
if ActiveRecord.timestamped_migrations
|
936
1004
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
937
1005
|
else
|
938
1006
|
SchemaMigration.normalize_migration_number(number)
|
@@ -941,7 +1009,7 @@ module ActiveRecord
|
|
941
1009
|
|
942
1010
|
# Builds a hash for use in ActiveRecord::Migration#proper_table_name using
|
943
1011
|
# the Active Record object's table_name prefix and suffix
|
944
|
-
def table_name_options(config = ActiveRecord::Base)
|
1012
|
+
def table_name_options(config = ActiveRecord::Base) # :nodoc:
|
945
1013
|
{
|
946
1014
|
table_name_prefix: config.table_name_prefix,
|
947
1015
|
table_name_suffix: config.table_name_suffix
|
@@ -956,6 +1024,10 @@ module ActiveRecord
|
|
956
1024
|
yield
|
957
1025
|
end
|
958
1026
|
end
|
1027
|
+
|
1028
|
+
def command_recorder
|
1029
|
+
CommandRecorder.new(connection)
|
1030
|
+
end
|
959
1031
|
end
|
960
1032
|
|
961
1033
|
# MigrationProxy is used to defer loading of the actual migration classes
|
@@ -970,41 +1042,49 @@ module ActiveRecord
|
|
970
1042
|
File.basename(filename)
|
971
1043
|
end
|
972
1044
|
|
973
|
-
def mtime
|
974
|
-
File.mtime filename
|
975
|
-
end
|
976
|
-
|
977
1045
|
delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
|
978
1046
|
|
979
1047
|
private
|
980
|
-
|
981
1048
|
def migration
|
982
1049
|
@migration ||= load_migration
|
983
1050
|
end
|
984
1051
|
|
985
1052
|
def load_migration
|
986
|
-
|
1053
|
+
Object.send(:remove_const, name) rescue nil
|
1054
|
+
|
1055
|
+
load(File.expand_path(filename))
|
987
1056
|
name.constantize.new(name, version)
|
988
1057
|
end
|
989
1058
|
end
|
990
1059
|
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
class MigrationContext # :nodoc:
|
1002
|
-
attr_reader :migrations_paths
|
1060
|
+
# MigrationContext sets the context in which a migration is run.
|
1061
|
+
#
|
1062
|
+
# A migration context requires the path to the migrations is set
|
1063
|
+
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
1064
|
+
# class can be provided. For most applications, +SchemaMigration+ is
|
1065
|
+
# sufficient. Multiple database applications need a +SchemaMigration+
|
1066
|
+
# per primary database.
|
1067
|
+
class MigrationContext
|
1068
|
+
attr_reader :migrations_paths, :schema_migration
|
1003
1069
|
|
1004
|
-
def initialize(migrations_paths)
|
1070
|
+
def initialize(migrations_paths, schema_migration = SchemaMigration)
|
1005
1071
|
@migrations_paths = migrations_paths
|
1072
|
+
@schema_migration = schema_migration
|
1006
1073
|
end
|
1007
1074
|
|
1075
|
+
# Runs the migrations in the +migrations_path+.
|
1076
|
+
#
|
1077
|
+
# If +target_version+ is +nil+, +migrate+ will run +up+.
|
1078
|
+
#
|
1079
|
+
# If the +current_version+ and +target_version+ are both
|
1080
|
+
# 0 then an empty array will be returned and no migrations
|
1081
|
+
# will be run.
|
1082
|
+
#
|
1083
|
+
# If the +current_version+ in the schema is greater than
|
1084
|
+
# the +target_version+, then +down+ will be run.
|
1085
|
+
#
|
1086
|
+
# If none of the conditions are met, +up+ will be run with
|
1087
|
+
# the +target_version+.
|
1008
1088
|
def migrate(target_version = nil, &block)
|
1009
1089
|
case
|
1010
1090
|
when target_version.nil?
|
@@ -1018,72 +1098,64 @@ module ActiveRecord
|
|
1018
1098
|
end
|
1019
1099
|
end
|
1020
1100
|
|
1021
|
-
def rollback(steps = 1)
|
1101
|
+
def rollback(steps = 1) # :nodoc:
|
1022
1102
|
move(:down, steps)
|
1023
1103
|
end
|
1024
1104
|
|
1025
|
-
def forward(steps = 1)
|
1105
|
+
def forward(steps = 1) # :nodoc:
|
1026
1106
|
move(:up, steps)
|
1027
1107
|
end
|
1028
1108
|
|
1029
|
-
def up(target_version = nil)
|
1109
|
+
def up(target_version = nil, &block) # :nodoc:
|
1030
1110
|
selected_migrations = if block_given?
|
1031
|
-
migrations.select
|
1111
|
+
migrations.select(&block)
|
1032
1112
|
else
|
1033
1113
|
migrations
|
1034
1114
|
end
|
1035
1115
|
|
1036
|
-
Migrator.new(:up, selected_migrations, target_version).migrate
|
1116
|
+
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1037
1117
|
end
|
1038
1118
|
|
1039
|
-
def down(target_version = nil)
|
1119
|
+
def down(target_version = nil, &block) # :nodoc:
|
1040
1120
|
selected_migrations = if block_given?
|
1041
|
-
migrations.select
|
1121
|
+
migrations.select(&block)
|
1042
1122
|
else
|
1043
1123
|
migrations
|
1044
1124
|
end
|
1045
1125
|
|
1046
|
-
Migrator.new(:down, selected_migrations, target_version).migrate
|
1126
|
+
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1047
1127
|
end
|
1048
1128
|
|
1049
|
-
def run(direction, target_version)
|
1050
|
-
Migrator.new(direction, migrations, target_version).run
|
1129
|
+
def run(direction, target_version) # :nodoc:
|
1130
|
+
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1051
1131
|
end
|
1052
1132
|
|
1053
|
-
def open
|
1054
|
-
Migrator.new(:up, migrations,
|
1133
|
+
def open # :nodoc:
|
1134
|
+
Migrator.new(:up, migrations, schema_migration)
|
1055
1135
|
end
|
1056
1136
|
|
1057
|
-
def get_all_versions
|
1058
|
-
if
|
1059
|
-
|
1137
|
+
def get_all_versions # :nodoc:
|
1138
|
+
if schema_migration.table_exists?
|
1139
|
+
schema_migration.all_versions.map(&:to_i)
|
1060
1140
|
else
|
1061
1141
|
[]
|
1062
1142
|
end
|
1063
1143
|
end
|
1064
1144
|
|
1065
|
-
def current_version
|
1145
|
+
def current_version # :nodoc:
|
1066
1146
|
get_all_versions.max || 0
|
1067
1147
|
rescue ActiveRecord::NoDatabaseError
|
1068
1148
|
end
|
1069
1149
|
|
1070
|
-
def needs_migration?
|
1071
|
-
|
1150
|
+
def needs_migration? # :nodoc:
|
1151
|
+
pending_migration_versions.size > 0
|
1072
1152
|
end
|
1073
1153
|
|
1074
|
-
def
|
1075
|
-
migrations.
|
1154
|
+
def pending_migration_versions # :nodoc:
|
1155
|
+
migrations.collect(&:version) - get_all_versions
|
1076
1156
|
end
|
1077
1157
|
|
1078
|
-
def
|
1079
|
-
migrations.last || NullMigration.new
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
def parse_migration_filename(filename) # :nodoc:
|
1083
|
-
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1084
|
-
end
|
1085
|
-
|
1086
|
-
def migrations
|
1158
|
+
def migrations # :nodoc:
|
1087
1159
|
migrations = migration_files.map do |file|
|
1088
1160
|
version, name, scope = parse_migration_filename(file)
|
1089
1161
|
raise IllegalMigrationNameError.new(file) unless version
|
@@ -1096,38 +1168,34 @@ module ActiveRecord
|
|
1096
1168
|
migrations.sort_by(&:version)
|
1097
1169
|
end
|
1098
1170
|
|
1099
|
-
def migrations_status
|
1100
|
-
db_list =
|
1171
|
+
def migrations_status # :nodoc:
|
1172
|
+
db_list = schema_migration.normalized_versions
|
1101
1173
|
|
1102
|
-
file_list = migration_files.
|
1174
|
+
file_list = migration_files.filter_map do |file|
|
1103
1175
|
version, name, scope = parse_migration_filename(file)
|
1104
1176
|
raise IllegalMigrationNameError.new(file) unless version
|
1105
|
-
version =
|
1177
|
+
version = schema_migration.normalize_migration_number(version)
|
1106
1178
|
status = db_list.delete(version) ? "up" : "down"
|
1107
1179
|
[status, version, (name + scope).humanize]
|
1108
|
-
end
|
1180
|
+
end
|
1109
1181
|
|
1110
1182
|
db_list.map! do |version|
|
1111
1183
|
["up", version, "********** NO FILE **********"]
|
1112
1184
|
end
|
1113
1185
|
|
1114
|
-
(db_list + file_list).sort_by { |_, version, _| version }
|
1115
|
-
end
|
1116
|
-
|
1117
|
-
def migration_files
|
1118
|
-
paths = Array(migrations_paths)
|
1119
|
-
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1186
|
+
(db_list + file_list).sort_by { |_, version, _| version.to_i }
|
1120
1187
|
end
|
1121
1188
|
|
1122
|
-
def current_environment
|
1189
|
+
def current_environment # :nodoc:
|
1123
1190
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1124
1191
|
end
|
1125
1192
|
|
1126
|
-
def protected_environment?
|
1193
|
+
def protected_environment? # :nodoc:
|
1127
1194
|
ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
|
1128
1195
|
end
|
1129
1196
|
|
1130
|
-
def last_stored_environment
|
1197
|
+
def last_stored_environment # :nodoc:
|
1198
|
+
return nil unless ActiveRecord::InternalMetadata.enabled?
|
1131
1199
|
return nil if current_version == 0
|
1132
1200
|
raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
|
1133
1201
|
|
@@ -1137,8 +1205,17 @@ module ActiveRecord
|
|
1137
1205
|
end
|
1138
1206
|
|
1139
1207
|
private
|
1208
|
+
def migration_files
|
1209
|
+
paths = Array(migrations_paths)
|
1210
|
+
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
def parse_migration_filename(filename)
|
1214
|
+
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1215
|
+
end
|
1216
|
+
|
1140
1217
|
def move(direction, steps)
|
1141
|
-
migrator = Migrator.new(direction, migrations)
|
1218
|
+
migrator = Migrator.new(direction, migrations, schema_migration)
|
1142
1219
|
|
1143
1220
|
if current_version != 0 && !migrator.current_migration
|
1144
1221
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1153,7 +1230,7 @@ module ActiveRecord
|
|
1153
1230
|
|
1154
1231
|
finish = migrator.migrations[start_index + steps]
|
1155
1232
|
version = finish ? finish.version : 0
|
1156
|
-
|
1233
|
+
public_send(direction, version)
|
1157
1234
|
end
|
1158
1235
|
end
|
1159
1236
|
|
@@ -1161,30 +1238,24 @@ module ActiveRecord
|
|
1161
1238
|
class << self
|
1162
1239
|
attr_accessor :migrations_paths
|
1163
1240
|
|
1164
|
-
def migrations_path=(path)
|
1165
|
-
ActiveSupport::Deprecation.warn \
|
1166
|
-
"`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
|
1167
|
-
"You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
|
1168
|
-
self.migrations_paths = [path]
|
1169
|
-
end
|
1170
|
-
|
1171
1241
|
# For cases where a table doesn't exist like loading from schema cache
|
1172
1242
|
def current_version
|
1173
|
-
MigrationContext.new(migrations_paths).current_version
|
1243
|
+
MigrationContext.new(migrations_paths, SchemaMigration).current_version
|
1174
1244
|
end
|
1175
1245
|
end
|
1176
1246
|
|
1177
1247
|
self.migrations_paths = ["db/migrate"]
|
1178
1248
|
|
1179
|
-
def initialize(direction, migrations, target_version = nil)
|
1249
|
+
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1180
1250
|
@direction = direction
|
1181
1251
|
@target_version = target_version
|
1182
1252
|
@migrated_versions = nil
|
1183
1253
|
@migrations = migrations
|
1254
|
+
@schema_migration = schema_migration
|
1184
1255
|
|
1185
1256
|
validate(@migrations)
|
1186
1257
|
|
1187
|
-
|
1258
|
+
@schema_migration.create_table
|
1188
1259
|
ActiveRecord::InternalMetadata.create_table
|
1189
1260
|
end
|
1190
1261
|
|
@@ -1238,16 +1309,15 @@ module ActiveRecord
|
|
1238
1309
|
end
|
1239
1310
|
|
1240
1311
|
def load_migrated
|
1241
|
-
@migrated_versions = Set.new(
|
1312
|
+
@migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
|
1242
1313
|
end
|
1243
1314
|
|
1244
1315
|
private
|
1245
|
-
|
1246
1316
|
# Used for running a specific migration.
|
1247
1317
|
def run_without_lock
|
1248
1318
|
migration = migrations.detect { |m| m.version == @target_version }
|
1249
1319
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1250
|
-
result = execute_migration_in_transaction(migration
|
1320
|
+
result = execute_migration_in_transaction(migration)
|
1251
1321
|
|
1252
1322
|
record_environment
|
1253
1323
|
result
|
@@ -1259,10 +1329,7 @@ module ActiveRecord
|
|
1259
1329
|
raise UnknownMigrationVersionError.new(@target_version)
|
1260
1330
|
end
|
1261
1331
|
|
1262
|
-
result = runnable.each
|
1263
|
-
execute_migration_in_transaction(migration, @direction)
|
1264
|
-
end
|
1265
|
-
|
1332
|
+
result = runnable.each(&method(:execute_migration_in_transaction))
|
1266
1333
|
record_environment
|
1267
1334
|
result
|
1268
1335
|
end
|
@@ -1282,18 +1349,18 @@ module ActiveRecord
|
|
1282
1349
|
@target_version && @target_version != 0 && !target
|
1283
1350
|
end
|
1284
1351
|
|
1285
|
-
def execute_migration_in_transaction(migration
|
1352
|
+
def execute_migration_in_transaction(migration)
|
1286
1353
|
return if down? && !migrated.include?(migration.version.to_i)
|
1287
1354
|
return if up? && migrated.include?(migration.version.to_i)
|
1288
1355
|
|
1289
1356
|
Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
|
1290
1357
|
|
1291
1358
|
ddl_transaction(migration) do
|
1292
|
-
migration.migrate(direction)
|
1359
|
+
migration.migrate(@direction)
|
1293
1360
|
record_version_state_after_migrating(migration.version)
|
1294
1361
|
end
|
1295
1362
|
rescue => e
|
1296
|
-
msg = "An error has occurred, "
|
1363
|
+
msg = +"An error has occurred, "
|
1297
1364
|
msg << "this and " if use_transaction?(migration)
|
1298
1365
|
msg << "all later migrations canceled:\n\n#{e}"
|
1299
1366
|
raise StandardError, msg, e.backtrace
|
@@ -1322,10 +1389,10 @@ module ActiveRecord
|
|
1322
1389
|
def record_version_state_after_migrating(version)
|
1323
1390
|
if down?
|
1324
1391
|
migrated.delete(version)
|
1325
|
-
|
1392
|
+
@schema_migration.delete_by(version: version.to_s)
|
1326
1393
|
else
|
1327
1394
|
migrated << version
|
1328
|
-
|
1395
|
+
@schema_migration.create!(version: version.to_s)
|
1329
1396
|
end
|
1330
1397
|
end
|
1331
1398
|
|
@@ -1338,9 +1405,9 @@ module ActiveRecord
|
|
1338
1405
|
end
|
1339
1406
|
|
1340
1407
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1341
|
-
def ddl_transaction(migration)
|
1408
|
+
def ddl_transaction(migration, &block)
|
1342
1409
|
if use_transaction?(migration)
|
1343
|
-
Base.transaction
|
1410
|
+
Base.transaction(&block)
|
1344
1411
|
else
|
1345
1412
|
yield
|
1346
1413
|
end
|
@@ -1351,24 +1418,36 @@ module ActiveRecord
|
|
1351
1418
|
end
|
1352
1419
|
|
1353
1420
|
def use_advisory_lock?
|
1354
|
-
Base.connection.
|
1421
|
+
Base.connection.advisory_locks_enabled?
|
1355
1422
|
end
|
1356
1423
|
|
1357
1424
|
def with_advisory_lock
|
1358
1425
|
lock_id = generate_migrator_advisory_lock_id
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
ConcurrentMigrationError
|
1368
|
-
|
1426
|
+
|
1427
|
+
with_advisory_lock_connection do |connection|
|
1428
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
1429
|
+
raise ConcurrentMigrationError unless got_lock
|
1430
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
1431
|
+
yield
|
1432
|
+
ensure
|
1433
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1434
|
+
raise ConcurrentMigrationError.new(
|
1435
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1436
|
+
)
|
1437
|
+
end
|
1369
1438
|
end
|
1370
1439
|
end
|
1371
1440
|
|
1441
|
+
def with_advisory_lock_connection(&block)
|
1442
|
+
pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
1443
|
+
ActiveRecord::Base.connection_db_config
|
1444
|
+
)
|
1445
|
+
|
1446
|
+
pool.with_connection(&block)
|
1447
|
+
ensure
|
1448
|
+
pool&.disconnect!
|
1449
|
+
end
|
1450
|
+
|
1372
1451
|
MIGRATOR_SALT = 2053462845
|
1373
1452
|
def generate_migrator_advisory_lock_id
|
1374
1453
|
db_name_hash = Zlib.crc32(Base.connection.current_database)
|