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