activerecord 5.2.8 → 7.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,8 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require "active_record/migration/join_table"
         
     | 
| 
       4 
3 
     | 
    
         
             
            require "active_support/core_ext/string/access"
         
     | 
| 
       5 
     | 
    
         
            -
            require " 
     | 
| 
      
 4 
     | 
    
         
            +
            require "openssl"
         
     | 
| 
       6 
5 
     | 
    
         | 
| 
       7 
6 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       8 
7 
     | 
    
         
             
              module ConnectionAdapters # :nodoc:
         
     | 
| 
         @@ -30,7 +29,7 @@ module ActiveRecord 
     | 
|
| 
       30 
29 
     | 
    
         
             
                    table_name[0...table_alias_length].tr(".", "_")
         
     | 
| 
       31 
30 
     | 
    
         
             
                  end
         
     | 
| 
       32 
31 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                  # Returns the relation names  
     | 
| 
      
 32 
     | 
    
         
            +
                  # Returns the relation names usable to back Active Record models.
         
     | 
| 
       34 
33 
     | 
    
         
             
                  # For most adapters this means all #tables and #views.
         
     | 
| 
       35 
34 
     | 
    
         
             
                  def data_sources
         
     | 
| 
       36 
35 
     | 
    
         
             
                    query_values(data_source_sql, "SCHEMA")
         
     | 
| 
         @@ -97,10 +96,14 @@ module ActiveRecord 
     | 
|
| 
       97 
96 
     | 
    
         
             
                  #   # Check an index with a custom name exists
         
     | 
| 
       98 
97 
     | 
    
         
             
                  #   index_exists?(:suppliers, :company_id, name: "idx_company_id")
         
     | 
| 
       99 
98 
     | 
    
         
             
                  #
         
     | 
| 
       100 
     | 
    
         
            -
                  def index_exists?(table_name, column_name, options 
     | 
| 
       101 
     | 
    
         
            -
                    column_names = Array(column_name).map(&:to_s)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  def index_exists?(table_name, column_name, **options)
         
     | 
| 
       102 
100 
     | 
    
         
             
                    checks = []
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    if column_name.present?
         
     | 
| 
      
 103 
     | 
    
         
            +
                      column_names = Array(column_name).map(&:to_s)
         
     | 
| 
      
 104 
     | 
    
         
            +
                      checks << lambda { |i| Array(i.columns) == column_names }
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
       104 
107 
     | 
    
         
             
                    checks << lambda { |i| i.unique } if options[:unique]
         
     | 
| 
       105 
108 
     | 
    
         
             
                    checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
         
     | 
| 
       106 
109 
     | 
    
         | 
| 
         @@ -121,6 +124,9 @@ module ActiveRecord 
     | 
|
| 
       121 
124 
     | 
    
         
             
                  #   column_exists?(:suppliers, :name)
         
     | 
| 
       122 
125 
     | 
    
         
             
                  #
         
     | 
| 
       123 
126 
     | 
    
         
             
                  #   # Check a column exists of a particular type
         
     | 
| 
      
 127 
     | 
    
         
            +
                  #   #
         
     | 
| 
      
 128 
     | 
    
         
            +
                  #   # This works for standard non-casted types (eg. string) but is unreliable
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #   # for types that may get cast to something else (eg. char, bigint).
         
     | 
| 
       124 
130 
     | 
    
         
             
                  #   column_exists?(:suppliers, :name, :string)
         
     | 
| 
       125 
131 
     | 
    
         
             
                  #
         
     | 
| 
       126 
132 
     | 
    
         
             
                  #   # Check a column exists with a specific definition
         
     | 
| 
         @@ -129,11 +135,11 @@ module ActiveRecord 
     | 
|
| 
       129 
135 
     | 
    
         
             
                  #   column_exists?(:suppliers, :name, :string, null: false)
         
     | 
| 
       130 
136 
     | 
    
         
             
                  #   column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
         
     | 
| 
       131 
137 
     | 
    
         
             
                  #
         
     | 
| 
       132 
     | 
    
         
            -
                  def column_exists?(table_name, column_name, type = nil, options 
     | 
| 
      
 138 
     | 
    
         
            +
                  def column_exists?(table_name, column_name, type = nil, **options)
         
     | 
| 
       133 
139 
     | 
    
         
             
                    column_name = column_name.to_s
         
     | 
| 
       134 
140 
     | 
    
         
             
                    checks = []
         
     | 
| 
       135 
141 
     | 
    
         
             
                    checks << lambda { |c| c.name == column_name }
         
     | 
| 
       136 
     | 
    
         
            -
                    checks << lambda { |c| c.type == type } if type
         
     | 
| 
      
 142 
     | 
    
         
            +
                    checks << lambda { |c| c.type == type.to_sym rescue nil } if type
         
     | 
| 
       137 
143 
     | 
    
         
             
                    column_options_keys.each do |attr|
         
     | 
| 
       138 
144 
     | 
    
         
             
                      checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
         
     | 
| 
       139 
145 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -205,19 +211,22 @@ module ActiveRecord 
     | 
|
| 
       205 
211 
     | 
    
         
             
                  #   Set to true to drop the table before creating it.
         
     | 
| 
       206 
212 
     | 
    
         
             
                  #   Set to +:cascade+ to drop dependent objects as well.
         
     | 
| 
       207 
213 
     | 
    
         
             
                  #   Defaults to false.
         
     | 
| 
      
 214 
     | 
    
         
            +
                  # [<tt>:if_not_exists</tt>]
         
     | 
| 
      
 215 
     | 
    
         
            +
                  #   Set to true to avoid raising an error when the table already exists.
         
     | 
| 
      
 216 
     | 
    
         
            +
                  #   Defaults to false.
         
     | 
| 
       208 
217 
     | 
    
         
             
                  # [<tt>:as</tt>]
         
     | 
| 
       209 
218 
     | 
    
         
             
                  #   SQL to use to generate the table. When this option is used, the block is
         
     | 
| 
       210 
219 
     | 
    
         
             
                  #   ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
         
     | 
| 
       211 
220 
     | 
    
         
             
                  #
         
     | 
| 
       212 
221 
     | 
    
         
             
                  # ====== Add a backend specific option to the generated SQL (MySQL)
         
     | 
| 
       213 
222 
     | 
    
         
             
                  #
         
     | 
| 
       214 
     | 
    
         
            -
                  #   create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET= 
     | 
| 
      
 223 
     | 
    
         
            +
                  #   create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
         
     | 
| 
       215 
224 
     | 
    
         
             
                  #
         
     | 
| 
       216 
225 
     | 
    
         
             
                  # generates:
         
     | 
| 
       217 
226 
     | 
    
         
             
                  #
         
     | 
| 
       218 
227 
     | 
    
         
             
                  #   CREATE TABLE suppliers (
         
     | 
| 
       219 
228 
     | 
    
         
             
                  #     id bigint auto_increment PRIMARY KEY
         
     | 
| 
       220 
     | 
    
         
            -
                  #   ) ENGINE=InnoDB DEFAULT CHARSET= 
     | 
| 
      
 229 
     | 
    
         
            +
                  #   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
         
     | 
| 
       221 
230 
     | 
    
         
             
                  #
         
     | 
| 
       222 
231 
     | 
    
         
             
                  # ====== Rename the primary key column
         
     | 
| 
       223 
232 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -287,37 +296,44 @@ module ActiveRecord 
     | 
|
| 
       287 
296 
     | 
    
         
             
                  #     SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
         
     | 
| 
       288 
297 
     | 
    
         
             
                  #
         
     | 
| 
       289 
298 
     | 
    
         
             
                  # See also TableDefinition#column for details on how to create columns.
         
     | 
| 
       290 
     | 
    
         
            -
                  def create_table(table_name,  
     | 
| 
       291 
     | 
    
         
            -
                    td = create_table_definition 
     | 
| 
      
 299 
     | 
    
         
            +
                  def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
         
     | 
| 
      
 300 
     | 
    
         
            +
                    td = create_table_definition(table_name, **extract_table_options!(options))
         
     | 
| 
       292 
301 
     | 
    
         | 
| 
       293 
     | 
    
         
            -
                    if  
     | 
| 
       294 
     | 
    
         
            -
                      pk =  
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
      
 302 
     | 
    
         
            +
                    if id && !td.as
         
     | 
| 
      
 303 
     | 
    
         
            +
                      pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
                      if id.is_a?(Hash)
         
     | 
| 
      
 306 
     | 
    
         
            +
                        options.merge!(id.except(:type))
         
     | 
| 
      
 307 
     | 
    
         
            +
                        id = id.fetch(:type, :primary_key)
         
     | 
| 
       296 
308 
     | 
    
         
             
                      end
         
     | 
| 
       297 
309 
     | 
    
         | 
| 
       298 
310 
     | 
    
         
             
                      if pk.is_a?(Array)
         
     | 
| 
       299 
311 
     | 
    
         
             
                        td.primary_keys pk
         
     | 
| 
       300 
312 
     | 
    
         
             
                      else
         
     | 
| 
       301 
     | 
    
         
            -
                        td.primary_key pk,  
     | 
| 
      
 313 
     | 
    
         
            +
                        td.primary_key pk, id, **options
         
     | 
| 
       302 
314 
     | 
    
         
             
                      end
         
     | 
| 
       303 
315 
     | 
    
         
             
                    end
         
     | 
| 
       304 
316 
     | 
    
         | 
| 
       305 
317 
     | 
    
         
             
                    yield td if block_given?
         
     | 
| 
       306 
318 
     | 
    
         | 
| 
       307 
     | 
    
         
            -
                    if  
     | 
| 
       308 
     | 
    
         
            -
                      drop_table(table_name,  
     | 
| 
      
 319 
     | 
    
         
            +
                    if force
         
     | 
| 
      
 320 
     | 
    
         
            +
                      drop_table(table_name, force: force, if_exists: true)
         
     | 
| 
      
 321 
     | 
    
         
            +
                    else
         
     | 
| 
      
 322 
     | 
    
         
            +
                      schema_cache.clear_data_source_cache!(table_name.to_s)
         
     | 
| 
       309 
323 
     | 
    
         
             
                    end
         
     | 
| 
       310 
324 
     | 
    
         | 
| 
       311 
325 
     | 
    
         
             
                    result = execute schema_creation.accept td
         
     | 
| 
       312 
326 
     | 
    
         | 
| 
       313 
327 
     | 
    
         
             
                    unless supports_indexes_in_create?
         
     | 
| 
       314 
328 
     | 
    
         
             
                      td.indexes.each do |column_name, index_options|
         
     | 
| 
       315 
     | 
    
         
            -
                        add_index(table_name, column_name, index_options)
         
     | 
| 
      
 329 
     | 
    
         
            +
                        add_index(table_name, column_name, **index_options, if_not_exists: td.if_not_exists)
         
     | 
| 
       316 
330 
     | 
    
         
             
                      end
         
     | 
| 
       317 
331 
     | 
    
         
             
                    end
         
     | 
| 
       318 
332 
     | 
    
         | 
| 
       319 
333 
     | 
    
         
             
                    if supports_comments? && !supports_comments_in_create?
         
     | 
| 
       320 
     | 
    
         
            -
                       
     | 
| 
      
 334 
     | 
    
         
            +
                      if table_comment = td.comment.presence
         
     | 
| 
      
 335 
     | 
    
         
            +
                        change_table_comment(table_name, table_comment)
         
     | 
| 
      
 336 
     | 
    
         
            +
                      end
         
     | 
| 
       321 
337 
     | 
    
         | 
| 
       322 
338 
     | 
    
         
             
                      td.columns.each do |column|
         
     | 
| 
       323 
339 
     | 
    
         
             
                        change_column_comment(table_name, column.name, column.comment) if column.comment.present?
         
     | 
| 
         @@ -372,9 +388,9 @@ module ActiveRecord 
     | 
|
| 
       372 
388 
     | 
    
         | 
| 
       373 
389 
     | 
    
         
             
                    t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
         
     | 
| 
       374 
390 
     | 
    
         | 
| 
       375 
     | 
    
         
            -
                    create_table(join_table_name, options.merge!(id: false)) do |td|
         
     | 
| 
       376 
     | 
    
         
            -
                      td.references t1_ref, column_options
         
     | 
| 
       377 
     | 
    
         
            -
                      td.references t2_ref, column_options
         
     | 
| 
      
 391 
     | 
    
         
            +
                    create_table(join_table_name, **options.merge!(id: false)) do |td|
         
     | 
| 
      
 392 
     | 
    
         
            +
                      td.references t1_ref, **column_options
         
     | 
| 
      
 393 
     | 
    
         
            +
                      td.references t2_ref, **column_options
         
     | 
| 
       378 
394 
     | 
    
         
             
                      yield td if block_given?
         
     | 
| 
       379 
395 
     | 
    
         
             
                    end
         
     | 
| 
       380 
396 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -385,7 +401,7 @@ module ActiveRecord 
     | 
|
| 
       385 
401 
     | 
    
         
             
                  # Although this command ignores the block if one is given, it can be helpful
         
     | 
| 
       386 
402 
     | 
    
         
             
                  # to provide one in a migration's +change+ method so it can be reverted.
         
     | 
| 
       387 
403 
     | 
    
         
             
                  # In that case, the block will be used by #create_join_table.
         
     | 
| 
       388 
     | 
    
         
            -
                  def drop_join_table(table_1, table_2, options 
     | 
| 
      
 404 
     | 
    
         
            +
                  def drop_join_table(table_1, table_2, **options)
         
     | 
| 
       389 
405 
     | 
    
         
             
                    join_table_name = find_join_table_name(table_1, table_2, options)
         
     | 
| 
       390 
406 
     | 
    
         
             
                    drop_table(join_table_name)
         
     | 
| 
       391 
407 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -414,6 +430,12 @@ module ActiveRecord 
     | 
|
| 
       414 
430 
     | 
    
         
             
                  #     t.column :name, :string, limit: 60
         
     | 
| 
       415 
431 
     | 
    
         
             
                  #   end
         
     | 
| 
       416 
432 
     | 
    
         
             
                  #
         
     | 
| 
      
 433 
     | 
    
         
            +
                  # ====== Change type of a column
         
     | 
| 
      
 434 
     | 
    
         
            +
                  #
         
     | 
| 
      
 435 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 436 
     | 
    
         
            +
                  #     t.change :metadata, :json
         
     | 
| 
      
 437 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 438 
     | 
    
         
            +
                  #
         
     | 
| 
       417 
439 
     | 
    
         
             
                  # ====== Add 2 integer columns
         
     | 
| 
       418 
440 
     | 
    
         
             
                  #
         
     | 
| 
       419 
441 
     | 
    
         
             
                  #   change_table(:suppliers) do |t|
         
     | 
| 
         @@ -462,7 +484,7 @@ module ActiveRecord 
     | 
|
| 
       462 
484 
     | 
    
         
             
                  #  end
         
     | 
| 
       463 
485 
     | 
    
         
             
                  #
         
     | 
| 
       464 
486 
     | 
    
         
             
                  # See also Table for details on all of the various column transformations.
         
     | 
| 
       465 
     | 
    
         
            -
                  def change_table(table_name, options 
     | 
| 
      
 487 
     | 
    
         
            +
                  def change_table(table_name, **options)
         
     | 
| 
       466 
488 
     | 
    
         
             
                    if supports_bulk_alter? && options[:bulk]
         
     | 
| 
       467 
489 
     | 
    
         
             
                      recorder = ActiveRecord::Migration::CommandRecorder.new(self)
         
     | 
| 
       468 
490 
     | 
    
         
             
                      yield update_table_definition(table_name, recorder)
         
     | 
| 
         @@ -492,38 +514,53 @@ module ActiveRecord 
     | 
|
| 
       492 
514 
     | 
    
         
             
                  # Although this command ignores most +options+ and the block if one is given,
         
     | 
| 
       493 
515 
     | 
    
         
             
                  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
         
     | 
| 
       494 
516 
     | 
    
         
             
                  # In that case, +options+ and the block will be used by #create_table.
         
     | 
| 
       495 
     | 
    
         
            -
                  def drop_table(table_name, options 
     | 
| 
      
 517 
     | 
    
         
            +
                  def drop_table(table_name, **options)
         
     | 
| 
      
 518 
     | 
    
         
            +
                    schema_cache.clear_data_source_cache!(table_name.to_s)
         
     | 
| 
       496 
519 
     | 
    
         
             
                    execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
         
     | 
| 
       497 
520 
     | 
    
         
             
                  end
         
     | 
| 
       498 
521 
     | 
    
         | 
| 
       499 
522 
     | 
    
         
             
                  # Add a new +type+ column named +column_name+ to +table_name+.
         
     | 
| 
       500 
523 
     | 
    
         
             
                  #
         
     | 
| 
      
 524 
     | 
    
         
            +
                  # See {ActiveRecord::ConnectionAdapters::TableDefinition.column}[rdoc-ref:ActiveRecord::ConnectionAdapters::TableDefinition#column].
         
     | 
| 
      
 525 
     | 
    
         
            +
                  #
         
     | 
| 
       501 
526 
     | 
    
         
             
                  # The +type+ parameter is normally one of the migrations native types,
         
     | 
| 
       502 
527 
     | 
    
         
             
                  # which is one of the following:
         
     | 
| 
       503 
528 
     | 
    
         
             
                  # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
         
     | 
| 
       504 
529 
     | 
    
         
             
                  # <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
         
     | 
| 
       505 
530 
     | 
    
         
             
                  # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
         
     | 
| 
       506 
     | 
    
         
            -
                  # <tt>:binary</tt>, <tt>:boolean</tt>.
         
     | 
| 
      
 531 
     | 
    
         
            +
                  # <tt>:binary</tt>, <tt>:blob</tt>, <tt>:boolean</tt>.
         
     | 
| 
       507 
532 
     | 
    
         
             
                  #
         
     | 
| 
       508 
533 
     | 
    
         
             
                  # You may use a type not in this list as long as it is supported by your
         
     | 
| 
       509 
534 
     | 
    
         
             
                  # database (for example, "polygon" in MySQL), but this will not be database
         
     | 
| 
       510 
535 
     | 
    
         
             
                  # agnostic and should usually be avoided.
         
     | 
| 
       511 
536 
     | 
    
         
             
                  #
         
     | 
| 
       512 
537 
     | 
    
         
             
                  # Available options are (none of these exists by default):
         
     | 
| 
      
 538 
     | 
    
         
            +
                  # * <tt>:comment</tt> -
         
     | 
| 
      
 539 
     | 
    
         
            +
                  #   Specifies the comment for the column. This option is ignored by some backends.
         
     | 
| 
      
 540 
     | 
    
         
            +
                  # * <tt>:collation</tt> -
         
     | 
| 
      
 541 
     | 
    
         
            +
                  #   Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column.
         
     | 
| 
      
 542 
     | 
    
         
            +
                  #   If not specified, the column will have the same collation as the table.
         
     | 
| 
      
 543 
     | 
    
         
            +
                  # * <tt>:default</tt> -
         
     | 
| 
      
 544 
     | 
    
         
            +
                  #   The column's default value. Use +nil+ for +NULL+.
         
     | 
| 
       513 
545 
     | 
    
         
             
                  # * <tt>:limit</tt> -
         
     | 
| 
       514 
546 
     | 
    
         
             
                  #   Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
         
     | 
| 
       515 
     | 
    
         
            -
                  #   and number of bytes for <tt>:text</tt>, <tt>:binary</tt 
     | 
| 
      
 547 
     | 
    
         
            +
                  #   and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, <tt>:blob</tt>, and <tt>:integer</tt> columns.
         
     | 
| 
       516 
548 
     | 
    
         
             
                  #   This option is ignored by some backends.
         
     | 
| 
       517 
     | 
    
         
            -
                  # * <tt>:default</tt> -
         
     | 
| 
       518 
     | 
    
         
            -
                  #   The column's default value. Use +nil+ for +NULL+.
         
     | 
| 
       519 
549 
     | 
    
         
             
                  # * <tt>:null</tt> -
         
     | 
| 
       520 
550 
     | 
    
         
             
                  #   Allows or disallows +NULL+ values in the column.
         
     | 
| 
       521 
551 
     | 
    
         
             
                  # * <tt>:precision</tt> -
         
     | 
| 
       522 
     | 
    
         
            -
                  #   Specifies the precision for the <tt>:decimal</tt 
     | 
| 
      
 552 
     | 
    
         
            +
                  #   Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
         
     | 
| 
      
 553 
     | 
    
         
            +
                  #   <tt>:datetime</tt>, and <tt>:time</tt> columns.
         
     | 
| 
       523 
554 
     | 
    
         
             
                  # * <tt>:scale</tt> -
         
     | 
| 
       524 
555 
     | 
    
         
             
                  #   Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
         
     | 
| 
      
 556 
     | 
    
         
            +
                  # * <tt>:collation</tt> -
         
     | 
| 
      
 557 
     | 
    
         
            +
                  #   Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
         
     | 
| 
      
 558 
     | 
    
         
            +
                  #   column will have the same collation as the table.
         
     | 
| 
       525 
559 
     | 
    
         
             
                  # * <tt>:comment</tt> -
         
     | 
| 
       526 
560 
     | 
    
         
             
                  #   Specifies the comment for the column. This option is ignored by some backends.
         
     | 
| 
      
 561 
     | 
    
         
            +
                  # * <tt>:if_not_exists</tt> -
         
     | 
| 
      
 562 
     | 
    
         
            +
                  #   Specifies if the column already exists to not try to re-add it. This will avoid
         
     | 
| 
      
 563 
     | 
    
         
            +
                  #   duplicate column errors.
         
     | 
| 
       527 
564 
     | 
    
         
             
                  #
         
     | 
| 
       528 
565 
     | 
    
         
             
                  # Note: The precision is the total number of significant digits,
         
     | 
| 
       529 
566 
     | 
    
         
             
                  # and the scale is the number of digits that can be stored following
         
     | 
| 
         @@ -544,8 +581,6 @@ module ActiveRecord 
     | 
|
| 
       544 
581 
     | 
    
         
             
                  #   but the maximum supported <tt>:precision</tt> is 16. No default.
         
     | 
| 
       545 
582 
     | 
    
         
             
                  # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
         
     | 
| 
       546 
583 
     | 
    
         
             
                  #   Default is (38,0).
         
     | 
| 
       547 
     | 
    
         
            -
                  # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
         
     | 
| 
       548 
     | 
    
         
            -
                  #   Default unknown.
         
     | 
| 
       549 
584 
     | 
    
         
             
                  # * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
         
     | 
| 
       550 
585 
     | 
    
         
             
                  #   Default (38,0).
         
     | 
| 
       551 
586 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -575,21 +610,43 @@ module ActiveRecord 
     | 
|
| 
       575 
610 
     | 
    
         
             
                  #  # Defines a column with a database-specific type.
         
     | 
| 
       576 
611 
     | 
    
         
             
                  #  add_column(:shapes, :triangle, 'polygon')
         
     | 
| 
       577 
612 
     | 
    
         
             
                  #  # ALTER TABLE "shapes" ADD "triangle" polygon
         
     | 
| 
       578 
     | 
    
         
            -
                   
     | 
| 
      
 613 
     | 
    
         
            +
                  #
         
     | 
| 
      
 614 
     | 
    
         
            +
                  #  # Ignores the method call if the column exists
         
     | 
| 
      
 615 
     | 
    
         
            +
                  #  add_column(:shapes, :triangle, 'polygon', if_not_exists: true)
         
     | 
| 
      
 616 
     | 
    
         
            +
                  def add_column(table_name, column_name, type, **options)
         
     | 
| 
      
 617 
     | 
    
         
            +
                    return if options[:if_not_exists] == true && column_exists?(table_name, column_name)
         
     | 
| 
      
 618 
     | 
    
         
            +
             
     | 
| 
      
 619 
     | 
    
         
            +
                    if supports_datetime_with_precision?
         
     | 
| 
      
 620 
     | 
    
         
            +
                      if type == :datetime && !options.key?(:precision)
         
     | 
| 
      
 621 
     | 
    
         
            +
                        options[:precision] = 6
         
     | 
| 
      
 622 
     | 
    
         
            +
                      end
         
     | 
| 
      
 623 
     | 
    
         
            +
                    end
         
     | 
| 
      
 624 
     | 
    
         
            +
             
     | 
| 
       579 
625 
     | 
    
         
             
                    at = create_alter_table table_name
         
     | 
| 
       580 
     | 
    
         
            -
                    at.add_column(column_name, type, options)
         
     | 
| 
      
 626 
     | 
    
         
            +
                    at.add_column(column_name, type, **options)
         
     | 
| 
       581 
627 
     | 
    
         
             
                    execute schema_creation.accept at
         
     | 
| 
       582 
628 
     | 
    
         
             
                  end
         
     | 
| 
       583 
629 
     | 
    
         | 
| 
      
 630 
     | 
    
         
            +
                  def add_columns(table_name, *column_names, type:, **options) # :nodoc:
         
     | 
| 
      
 631 
     | 
    
         
            +
                    column_names.each do |column_name|
         
     | 
| 
      
 632 
     | 
    
         
            +
                      add_column(table_name, column_name, type, **options)
         
     | 
| 
      
 633 
     | 
    
         
            +
                    end
         
     | 
| 
      
 634 
     | 
    
         
            +
                  end
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
       584 
636 
     | 
    
         
             
                  # Removes the given columns from the table definition.
         
     | 
| 
       585 
637 
     | 
    
         
             
                  #
         
     | 
| 
       586 
638 
     | 
    
         
             
                  #   remove_columns(:suppliers, :qualification, :experience)
         
     | 
| 
       587 
639 
     | 
    
         
             
                  #
         
     | 
| 
       588 
     | 
    
         
            -
                   
     | 
| 
       589 
     | 
    
         
            -
             
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
             
     | 
| 
      
 640 
     | 
    
         
            +
                  # +type+ and other column options can be passed to make migration reversible.
         
     | 
| 
      
 641 
     | 
    
         
            +
                  #
         
     | 
| 
      
 642 
     | 
    
         
            +
                  #    remove_columns(:suppliers, :qualification, :experience, type: :string, null: false)
         
     | 
| 
      
 643 
     | 
    
         
            +
                  def remove_columns(table_name, *column_names, type: nil, **options)
         
     | 
| 
      
 644 
     | 
    
         
            +
                    if column_names.empty?
         
     | 
| 
      
 645 
     | 
    
         
            +
                      raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)")
         
     | 
| 
       592 
646 
     | 
    
         
             
                    end
         
     | 
| 
      
 647 
     | 
    
         
            +
             
     | 
| 
      
 648 
     | 
    
         
            +
                    remove_column_fragments = remove_columns_for_alter(table_name, *column_names, type: type, **options)
         
     | 
| 
      
 649 
     | 
    
         
            +
                    execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_fragments.join(', ')}"
         
     | 
| 
       593 
650 
     | 
    
         
             
                  end
         
     | 
| 
       594 
651 
     | 
    
         | 
| 
       595 
652 
     | 
    
         
             
                  # Removes the column from the table definition.
         
     | 
| 
         @@ -599,8 +656,18 @@ module ActiveRecord 
     | 
|
| 
       599 
656 
     | 
    
         
             
                  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
         
     | 
| 
       600 
657 
     | 
    
         
             
                  # to provide these in a migration's +change+ method so it can be reverted.
         
     | 
| 
       601 
658 
     | 
    
         
             
                  # In that case, +type+ and +options+ will be used by #add_column.
         
     | 
| 
       602 
     | 
    
         
            -
                   
     | 
| 
       603 
     | 
    
         
            -
             
     | 
| 
      
 659 
     | 
    
         
            +
                  # Depending on the database you're using, indexes using this column may be
         
     | 
| 
      
 660 
     | 
    
         
            +
                  # automatically removed or modified to remove this column from the index.
         
     | 
| 
      
 661 
     | 
    
         
            +
                  #
         
     | 
| 
      
 662 
     | 
    
         
            +
                  # If the options provided include an +if_exists+ key, it will be used to check if the
         
     | 
| 
      
 663 
     | 
    
         
            +
                  # column does not exist. This will silently ignore the migration rather than raising
         
     | 
| 
      
 664 
     | 
    
         
            +
                  # if the column was already used.
         
     | 
| 
      
 665 
     | 
    
         
            +
                  #
         
     | 
| 
      
 666 
     | 
    
         
            +
                  #   remove_column(:suppliers, :qualification, if_exists: true)
         
     | 
| 
      
 667 
     | 
    
         
            +
                  def remove_column(table_name, column_name, type = nil, **options)
         
     | 
| 
      
 668 
     | 
    
         
            +
                    return if options[:if_exists] == true && !column_exists?(table_name, column_name)
         
     | 
| 
      
 669 
     | 
    
         
            +
             
     | 
| 
      
 670 
     | 
    
         
            +
                    execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, **options)}"
         
     | 
| 
       604 
671 
     | 
    
         
             
                  end
         
     | 
| 
       605 
672 
     | 
    
         | 
| 
       606 
673 
     | 
    
         
             
                  # Changes the column's definition according to the new options.
         
     | 
| 
         @@ -609,7 +676,7 @@ module ActiveRecord 
     | 
|
| 
       609 
676 
     | 
    
         
             
                  #   change_column(:suppliers, :name, :string, limit: 80)
         
     | 
| 
       610 
677 
     | 
    
         
             
                  #   change_column(:accounts, :description, :text)
         
     | 
| 
       611 
678 
     | 
    
         
             
                  #
         
     | 
| 
       612 
     | 
    
         
            -
                  def change_column(table_name, column_name, type, options 
     | 
| 
      
 679 
     | 
    
         
            +
                  def change_column(table_name, column_name, type, **options)
         
     | 
| 
       613 
680 
     | 
    
         
             
                    raise NotImplementedError, "change_column is not implemented"
         
     | 
| 
       614 
681 
     | 
    
         
             
                  end
         
     | 
| 
       615 
682 
     | 
    
         | 
| 
         @@ -671,7 +738,17 @@ module ActiveRecord 
     | 
|
| 
       671 
738 
     | 
    
         
             
                  #
         
     | 
| 
       672 
739 
     | 
    
         
             
                  # generates:
         
     | 
| 
       673 
740 
     | 
    
         
             
                  #
         
     | 
| 
       674 
     | 
    
         
            -
                  #   CREATE INDEX  
     | 
| 
      
 741 
     | 
    
         
            +
                  #   CREATE INDEX index_suppliers_on_name ON suppliers(name)
         
     | 
| 
      
 742 
     | 
    
         
            +
                  #
         
     | 
| 
      
 743 
     | 
    
         
            +
                  # ====== Creating a index which already exists
         
     | 
| 
      
 744 
     | 
    
         
            +
                  #
         
     | 
| 
      
 745 
     | 
    
         
            +
                  #   add_index(:suppliers, :name, if_not_exists: true)
         
     | 
| 
      
 746 
     | 
    
         
            +
                  #
         
     | 
| 
      
 747 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 748 
     | 
    
         
            +
                  #
         
     | 
| 
      
 749 
     | 
    
         
            +
                  #   CREATE INDEX IF NOT EXISTS index_suppliers_on_name ON suppliers(name)
         
     | 
| 
      
 750 
     | 
    
         
            +
                  #
         
     | 
| 
      
 751 
     | 
    
         
            +
                  # Note: Not supported by MySQL.
         
     | 
| 
       675 
752 
     | 
    
         
             
                  #
         
     | 
| 
       676 
753 
     | 
    
         
             
                  # ====== Creating a unique index
         
     | 
| 
       677 
754 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -679,7 +756,7 @@ module ActiveRecord 
     | 
|
| 
       679 
756 
     | 
    
         
             
                  #
         
     | 
| 
       680 
757 
     | 
    
         
             
                  # generates:
         
     | 
| 
       681 
758 
     | 
    
         
             
                  #
         
     | 
| 
       682 
     | 
    
         
            -
                  #   CREATE UNIQUE INDEX  
     | 
| 
      
 759 
     | 
    
         
            +
                  #   CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id)
         
     | 
| 
       683 
760 
     | 
    
         
             
                  #
         
     | 
| 
       684 
761 
     | 
    
         
             
                  # ====== Creating a named index
         
     | 
| 
       685 
762 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -705,11 +782,11 @@ module ActiveRecord 
     | 
|
| 
       705 
782 
     | 
    
         
             
                  #
         
     | 
| 
       706 
783 
     | 
    
         
             
                  #   CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
         
     | 
| 
       707 
784 
     | 
    
         
             
                  #
         
     | 
| 
       708 
     | 
    
         
            -
                  # Note:  
     | 
| 
      
 785 
     | 
    
         
            +
                  # Note: only supported by MySQL
         
     | 
| 
       709 
786 
     | 
    
         
             
                  #
         
     | 
| 
       710 
787 
     | 
    
         
             
                  # ====== Creating an index with a sort order (desc or asc, asc is the default)
         
     | 
| 
       711 
788 
     | 
    
         
             
                  #
         
     | 
| 
       712 
     | 
    
         
            -
                  #   add_index(:accounts, [:branch_id, :party_id, :surname], order: {branch_id: :desc, party_id: :asc})
         
     | 
| 
      
 789 
     | 
    
         
            +
                  #   add_index(:accounts, [:branch_id, :party_id, :surname], name: 'by_branch_desc_party', order: {branch_id: :desc, party_id: :asc})
         
     | 
| 
       713 
790 
     | 
    
         
             
                  #
         
     | 
| 
       714 
791 
     | 
    
         
             
                  # generates:
         
     | 
| 
       715 
792 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -725,7 +802,7 @@ module ActiveRecord 
     | 
|
| 
       725 
802 
     | 
    
         
             
                  #
         
     | 
| 
       726 
803 
     | 
    
         
             
                  #   CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
         
     | 
| 
       727 
804 
     | 
    
         
             
                  #
         
     | 
| 
       728 
     | 
    
         
            -
                  # Note: Partial indexes are only supported for PostgreSQL and SQLite 
     | 
| 
      
 805 
     | 
    
         
            +
                  # Note: Partial indexes are only supported for PostgreSQL and SQLite.
         
     | 
| 
       729 
806 
     | 
    
         
             
                  #
         
     | 
| 
       730 
807 
     | 
    
         
             
                  # ====== Creating an index with a specific method
         
     | 
| 
       731 
808 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -760,9 +837,22 @@ module ActiveRecord 
     | 
|
| 
       760 
837 
     | 
    
         
             
                  #   CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
         
     | 
| 
       761 
838 
     | 
    
         
             
                  #
         
     | 
| 
       762 
839 
     | 
    
         
             
                  # Note: only supported by MySQL.
         
     | 
| 
       763 
     | 
    
         
            -
                   
     | 
| 
       764 
     | 
    
         
            -
             
     | 
| 
       765 
     | 
    
         
            -
             
     | 
| 
      
 840 
     | 
    
         
            +
                  #
         
     | 
| 
      
 841 
     | 
    
         
            +
                  # ====== Creating an index with a specific algorithm
         
     | 
| 
      
 842 
     | 
    
         
            +
                  #
         
     | 
| 
      
 843 
     | 
    
         
            +
                  #  add_index(:developers, :name, algorithm: :concurrently)
         
     | 
| 
      
 844 
     | 
    
         
            +
                  #  # CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
         
     | 
| 
      
 845 
     | 
    
         
            +
                  #
         
     | 
| 
      
 846 
     | 
    
         
            +
                  # Note: only supported by PostgreSQL.
         
     | 
| 
      
 847 
     | 
    
         
            +
                  #
         
     | 
| 
      
 848 
     | 
    
         
            +
                  # Concurrently adding an index is not supported in a transaction.
         
     | 
| 
      
 849 
     | 
    
         
            +
                  #
         
     | 
| 
      
 850 
     | 
    
         
            +
                  # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
         
     | 
| 
      
 851 
     | 
    
         
            +
                  def add_index(table_name, column_name, **options)
         
     | 
| 
      
 852 
     | 
    
         
            +
                    index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
         
     | 
| 
      
 853 
     | 
    
         
            +
             
     | 
| 
      
 854 
     | 
    
         
            +
                    create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
         
     | 
| 
      
 855 
     | 
    
         
            +
                    execute schema_creation.accept(create_index)
         
     | 
| 
       766 
856 
     | 
    
         
             
                  end
         
     | 
| 
       767 
857 
     | 
    
         | 
| 
       768 
858 
     | 
    
         
             
                  # Removes the given index from the table.
         
     | 
| 
         @@ -783,8 +873,29 @@ module ActiveRecord 
     | 
|
| 
       783 
873 
     | 
    
         
             
                  #
         
     | 
| 
       784 
874 
     | 
    
         
             
                  #   remove_index :accounts, name: :by_branch_party
         
     | 
| 
       785 
875 
     | 
    
         
             
                  #
         
     | 
| 
       786 
     | 
    
         
            -
                   
     | 
| 
       787 
     | 
    
         
            -
             
     | 
| 
      
 876 
     | 
    
         
            +
                  # Removes the index on +branch_id+ named +by_branch_party+ in the +accounts+ table.
         
     | 
| 
      
 877 
     | 
    
         
            +
                  #
         
     | 
| 
      
 878 
     | 
    
         
            +
                  #   remove_index :accounts, :branch_id, name: :by_branch_party
         
     | 
| 
      
 879 
     | 
    
         
            +
                  #
         
     | 
| 
      
 880 
     | 
    
         
            +
                  # Checks if the index exists before trying to remove it. Will silently ignore indexes that
         
     | 
| 
      
 881 
     | 
    
         
            +
                  # don't exist.
         
     | 
| 
      
 882 
     | 
    
         
            +
                  #
         
     | 
| 
      
 883 
     | 
    
         
            +
                  #   remove_index :accounts, if_exists: true
         
     | 
| 
      
 884 
     | 
    
         
            +
                  #
         
     | 
| 
      
 885 
     | 
    
         
            +
                  # Removes the index named +by_branch_party+ in the +accounts+ table +concurrently+.
         
     | 
| 
      
 886 
     | 
    
         
            +
                  #
         
     | 
| 
      
 887 
     | 
    
         
            +
                  #   remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
         
     | 
| 
      
 888 
     | 
    
         
            +
                  #
         
     | 
| 
      
 889 
     | 
    
         
            +
                  # Note: only supported by PostgreSQL.
         
     | 
| 
      
 890 
     | 
    
         
            +
                  #
         
     | 
| 
      
 891 
     | 
    
         
            +
                  # Concurrently removing an index is not supported in a transaction.
         
     | 
| 
      
 892 
     | 
    
         
            +
                  #
         
     | 
| 
      
 893 
     | 
    
         
            +
                  # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
         
     | 
| 
      
 894 
     | 
    
         
            +
                  def remove_index(table_name, column_name = nil, **options)
         
     | 
| 
      
 895 
     | 
    
         
            +
                    return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
         
     | 
| 
      
 896 
     | 
    
         
            +
             
     | 
| 
      
 897 
     | 
    
         
            +
                    index_name = index_name_for_remove(table_name, column_name, options)
         
     | 
| 
      
 898 
     | 
    
         
            +
             
     | 
| 
       788 
899 
     | 
    
         
             
                    execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
         
     | 
| 
       789 
900 
     | 
    
         
             
                  end
         
     | 
| 
       790 
901 
     | 
    
         | 
| 
         @@ -795,6 +906,8 @@ module ActiveRecord 
     | 
|
| 
       795 
906 
     | 
    
         
             
                  #   rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
         
     | 
| 
       796 
907 
     | 
    
         
             
                  #
         
     | 
| 
       797 
908 
     | 
    
         
             
                  def rename_index(table_name, old_name, new_name)
         
     | 
| 
      
 909 
     | 
    
         
            +
                    old_name = old_name.to_s
         
     | 
| 
      
 910 
     | 
    
         
            +
                    new_name = new_name.to_s
         
     | 
| 
       798 
911 
     | 
    
         
             
                    validate_index_length!(table_name, new_name)
         
     | 
| 
       799 
912 
     | 
    
         | 
| 
       800 
913 
     | 
    
         
             
                    # this is a naive implementation; some DBs may support this more efficiently (PostgreSQL, for instance)
         
     | 
| 
         @@ -804,7 +917,7 @@ module ActiveRecord 
     | 
|
| 
       804 
917 
     | 
    
         
             
                    remove_index(table_name, name: old_name)
         
     | 
| 
       805 
918 
     | 
    
         
             
                  end
         
     | 
| 
       806 
919 
     | 
    
         | 
| 
       807 
     | 
    
         
            -
                  def index_name(table_name, options)  
     | 
| 
      
 920 
     | 
    
         
            +
                  def index_name(table_name, options) # :nodoc:
         
     | 
| 
       808 
921 
     | 
    
         
             
                    if Hash === options
         
     | 
| 
       809 
922 
     | 
    
         
             
                      if options[:column]
         
     | 
| 
       810 
923 
     | 
    
         
             
                        "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
         
     | 
| 
         @@ -836,23 +949,25 @@ module ActiveRecord 
     | 
|
| 
       836 
949 
     | 
    
         
             
                  #   Add an appropriate index. Defaults to true.
         
     | 
| 
       837 
950 
     | 
    
         
             
                  #   See #add_index for usage of this option.
         
     | 
| 
       838 
951 
     | 
    
         
             
                  # [<tt>:foreign_key</tt>]
         
     | 
| 
       839 
     | 
    
         
            -
                  #   Add an appropriate foreign key constraint. Defaults to false 
     | 
| 
      
 952 
     | 
    
         
            +
                  #   Add an appropriate foreign key constraint. Defaults to false, pass true
         
     | 
| 
      
 953 
     | 
    
         
            +
                  #   to add. In case the join table can't be inferred from the association
         
     | 
| 
      
 954 
     | 
    
         
            +
                  #   pass <tt>:to_table</tt> with the appropriate table name.
         
     | 
| 
       840 
955 
     | 
    
         
             
                  # [<tt>:polymorphic</tt>]
         
     | 
| 
       841 
956 
     | 
    
         
             
                  #   Whether an additional +_type+ column should be added. Defaults to false.
         
     | 
| 
       842 
957 
     | 
    
         
             
                  # [<tt>:null</tt>]
         
     | 
| 
       843 
958 
     | 
    
         
             
                  #   Whether the column allows nulls. Defaults to true.
         
     | 
| 
       844 
959 
     | 
    
         
             
                  #
         
     | 
| 
       845 
     | 
    
         
            -
                  # ====== Create a user_id bigint column
         
     | 
| 
      
 960 
     | 
    
         
            +
                  # ====== Create a user_id bigint column without an index
         
     | 
| 
       846 
961 
     | 
    
         
             
                  #
         
     | 
| 
       847 
     | 
    
         
            -
                  #   add_reference(:products, :user)
         
     | 
| 
      
 962 
     | 
    
         
            +
                  #   add_reference(:products, :user, index: false)
         
     | 
| 
       848 
963 
     | 
    
         
             
                  #
         
     | 
| 
       849 
964 
     | 
    
         
             
                  # ====== Create a user_id string column
         
     | 
| 
       850 
965 
     | 
    
         
             
                  #
         
     | 
| 
       851 
966 
     | 
    
         
             
                  #   add_reference(:products, :user, type: :string)
         
     | 
| 
       852 
967 
     | 
    
         
             
                  #
         
     | 
| 
       853 
     | 
    
         
            -
                  # ====== Create supplier_id, supplier_type columns 
     | 
| 
      
 968 
     | 
    
         
            +
                  # ====== Create supplier_id, supplier_type columns
         
     | 
| 
       854 
969 
     | 
    
         
             
                  #
         
     | 
| 
       855 
     | 
    
         
            -
                  #   add_reference(:products, :supplier, polymorphic: true 
     | 
| 
      
 970 
     | 
    
         
            +
                  #   add_reference(:products, :supplier, polymorphic: true)
         
     | 
| 
       856 
971 
     | 
    
         
             
                  #
         
     | 
| 
       857 
972 
     | 
    
         
             
                  # ====== Create a supplier_id column with a unique index
         
     | 
| 
       858 
973 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -868,10 +983,10 @@ module ActiveRecord 
     | 
|
| 
       868 
983 
     | 
    
         
             
                  #
         
     | 
| 
       869 
984 
     | 
    
         
             
                  # ====== Create a supplier_id column and a foreign key to the firms table
         
     | 
| 
       870 
985 
     | 
    
         
             
                  #
         
     | 
| 
       871 
     | 
    
         
            -
                  #   add_reference(:products, :supplier, foreign_key: {to_table: :firms})
         
     | 
| 
      
 986 
     | 
    
         
            +
                  #   add_reference(:products, :supplier, foreign_key: { to_table: :firms })
         
     | 
| 
       872 
987 
     | 
    
         
             
                  #
         
     | 
| 
       873 
988 
     | 
    
         
             
                  def add_reference(table_name, ref_name, **options)
         
     | 
| 
       874 
     | 
    
         
            -
                    ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
         
     | 
| 
      
 989 
     | 
    
         
            +
                    ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
         
     | 
| 
       875 
990 
     | 
    
         
             
                  end
         
     | 
| 
       876 
991 
     | 
    
         
             
                  alias :add_belongs_to :add_reference
         
     | 
| 
       877 
992 
     | 
    
         | 
| 
         @@ -880,7 +995,7 @@ module ActiveRecord 
     | 
|
| 
       880 
995 
     | 
    
         
             
                  #
         
     | 
| 
       881 
996 
     | 
    
         
             
                  # ====== Remove the reference
         
     | 
| 
       882 
997 
     | 
    
         
             
                  #
         
     | 
| 
       883 
     | 
    
         
            -
                  #   remove_reference(:products, :user, index:  
     | 
| 
      
 998 
     | 
    
         
            +
                  #   remove_reference(:products, :user, index: false)
         
     | 
| 
       884 
999 
     | 
    
         
             
                  #
         
     | 
| 
       885 
1000 
     | 
    
         
             
                  # ====== Remove polymorphic reference
         
     | 
| 
       886 
1001 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -888,7 +1003,7 @@ module ActiveRecord 
     | 
|
| 
       888 
1003 
     | 
    
         
             
                  #
         
     | 
| 
       889 
1004 
     | 
    
         
             
                  # ====== Remove the reference with a foreign key
         
     | 
| 
       890 
1005 
     | 
    
         
             
                  #
         
     | 
| 
       891 
     | 
    
         
            -
                  #   remove_reference(:products, :user,  
     | 
| 
      
 1006 
     | 
    
         
            +
                  #   remove_reference(:products, :user, foreign_key: true)
         
     | 
| 
       892 
1007 
     | 
    
         
             
                  #
         
     | 
| 
       893 
1008 
     | 
    
         
             
                  def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
         
     | 
| 
       894 
1009 
     | 
    
         
             
                    if foreign_key
         
     | 
| 
         @@ -899,7 +1014,7 @@ module ActiveRecord 
     | 
|
| 
       899 
1014 
     | 
    
         
             
                        foreign_key_options = { to_table: reference_name }
         
     | 
| 
       900 
1015 
     | 
    
         
             
                      end
         
     | 
| 
       901 
1016 
     | 
    
         
             
                      foreign_key_options[:column] ||= "#{ref_name}_id"
         
     | 
| 
       902 
     | 
    
         
            -
                      remove_foreign_key(table_name, foreign_key_options)
         
     | 
| 
      
 1017 
     | 
    
         
            +
                      remove_foreign_key(table_name, **foreign_key_options)
         
     | 
| 
       903 
1018 
     | 
    
         
             
                    end
         
     | 
| 
       904 
1019 
     | 
    
         | 
| 
       905 
1020 
     | 
    
         
             
                    remove_column(table_name, "#{ref_name}_id")
         
     | 
| 
         @@ -928,6 +1043,10 @@ module ActiveRecord 
     | 
|
| 
       928 
1043 
     | 
    
         
             
                  #
         
     | 
| 
       929 
1044 
     | 
    
         
             
                  #   ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")
         
     | 
| 
       930 
1045 
     | 
    
         
             
                  #
         
     | 
| 
      
 1046 
     | 
    
         
            +
                  # ====== Creating a foreign key, ignoring method call if the foreign key exists
         
     | 
| 
      
 1047 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1048 
     | 
    
         
            +
                  #  add_foreign_key(:articles, :authors, if_not_exists: true)
         
     | 
| 
      
 1049 
     | 
    
         
            +
                  #
         
     | 
| 
       931 
1050 
     | 
    
         
             
                  # ====== Creating a foreign key on a specific column
         
     | 
| 
       932 
1051 
     | 
    
         
             
                  #
         
     | 
| 
       933 
1052 
     | 
    
         
             
                  #   add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
         
     | 
| 
         @@ -955,10 +1074,17 @@ module ActiveRecord 
     | 
|
| 
       955 
1074 
     | 
    
         
             
                  #   Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
         
     | 
| 
       956 
1075 
     | 
    
         
             
                  # [<tt>:on_update</tt>]
         
     | 
| 
       957 
1076 
     | 
    
         
             
                  #   Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
         
     | 
| 
      
 1077 
     | 
    
         
            +
                  # [<tt>:if_not_exists</tt>]
         
     | 
| 
      
 1078 
     | 
    
         
            +
                  #   Specifies if the foreign key already exists to not try to re-add it. This will avoid
         
     | 
| 
      
 1079 
     | 
    
         
            +
                  #   duplicate column errors.
         
     | 
| 
       958 
1080 
     | 
    
         
             
                  # [<tt>:validate</tt>]
         
     | 
| 
       959 
     | 
    
         
            -
                  #   ( 
     | 
| 
       960 
     | 
    
         
            -
                   
     | 
| 
      
 1081 
     | 
    
         
            +
                  #   (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
         
     | 
| 
      
 1082 
     | 
    
         
            +
                  # [<tt>:deferrable</tt>]
         
     | 
| 
      
 1083 
     | 
    
         
            +
                  #   (PostgreSQL only) Specify whether or not the foreign key should be deferrable. Valid values are booleans or
         
     | 
| 
      
 1084 
     | 
    
         
            +
                  #   +:deferred+ or +:immediate+ to specify the default behavior. Defaults to +false+.
         
     | 
| 
      
 1085 
     | 
    
         
            +
                  def add_foreign_key(from_table, to_table, **options)
         
     | 
| 
       961 
1086 
     | 
    
         
             
                    return unless supports_foreign_keys?
         
     | 
| 
      
 1087 
     | 
    
         
            +
                    return if options[:if_not_exists] == true && foreign_key_exists?(from_table, to_table)
         
     | 
| 
       962 
1088 
     | 
    
         | 
| 
       963 
1089 
     | 
    
         
             
                    options = foreign_key_options(from_table, to_table, options)
         
     | 
| 
       964 
1090 
     | 
    
         
             
                    at = create_alter_table from_table
         
     | 
| 
         @@ -980,15 +1106,28 @@ module ActiveRecord 
     | 
|
| 
       980 
1106 
     | 
    
         
             
                  #
         
     | 
| 
       981 
1107 
     | 
    
         
             
                  #   remove_foreign_key :accounts, column: :owner_id
         
     | 
| 
       982 
1108 
     | 
    
         
             
                  #
         
     | 
| 
      
 1109 
     | 
    
         
            +
                  # Removes the foreign key on +accounts.owner_id+.
         
     | 
| 
      
 1110 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1111 
     | 
    
         
            +
                  #   remove_foreign_key :accounts, to_table: :owners
         
     | 
| 
      
 1112 
     | 
    
         
            +
                  #
         
     | 
| 
       983 
1113 
     | 
    
         
             
                  # Removes the foreign key named +special_fk_name+ on the +accounts+ table.
         
     | 
| 
       984 
1114 
     | 
    
         
             
                  #
         
     | 
| 
       985 
1115 
     | 
    
         
             
                  #   remove_foreign_key :accounts, name: :special_fk_name
         
     | 
| 
       986 
1116 
     | 
    
         
             
                  #
         
     | 
| 
       987 
     | 
    
         
            -
                  #  
     | 
| 
       988 
     | 
    
         
            -
                   
     | 
| 
      
 1117 
     | 
    
         
            +
                  # Checks if the foreign key exists before trying to remove it. Will silently ignore indexes that
         
     | 
| 
      
 1118 
     | 
    
         
            +
                  # don't exist.
         
     | 
| 
      
 1119 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1120 
     | 
    
         
            +
                  #   remove_foreign_key :accounts, :branches, if_exists: true
         
     | 
| 
      
 1121 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1122 
     | 
    
         
            +
                  # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
         
     | 
| 
      
 1123 
     | 
    
         
            +
                  # with an addition of
         
     | 
| 
      
 1124 
     | 
    
         
            +
                  # [<tt>:to_table</tt>]
         
     | 
| 
      
 1125 
     | 
    
         
            +
                  #   The name of the table that contains the referenced primary key.
         
     | 
| 
      
 1126 
     | 
    
         
            +
                  def remove_foreign_key(from_table, to_table = nil, **options)
         
     | 
| 
       989 
1127 
     | 
    
         
             
                    return unless supports_foreign_keys?
         
     | 
| 
      
 1128 
     | 
    
         
            +
                    return if options[:if_exists] == true && !foreign_key_exists?(from_table, to_table)
         
     | 
| 
       990 
1129 
     | 
    
         | 
| 
       991 
     | 
    
         
            -
                    fk_name_to_delete = foreign_key_for!(from_table,  
     | 
| 
      
 1130 
     | 
    
         
            +
                    fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
         
     | 
| 
       992 
1131 
     | 
    
         | 
| 
       993 
1132 
     | 
    
         
             
                    at = create_alter_table from_table
         
     | 
| 
       994 
1133 
     | 
    
         
             
                    at.drop_foreign_key fk_name_to_delete
         
     | 
| 
         @@ -1007,14 +1146,12 @@ module ActiveRecord 
     | 
|
| 
       1007 
1146 
     | 
    
         
             
                  #   # Checks to see if a foreign key with a custom name exists.
         
     | 
| 
       1008 
1147 
     | 
    
         
             
                  #   foreign_key_exists?(:accounts, name: "special_fk_name")
         
     | 
| 
       1009 
1148 
     | 
    
         
             
                  #
         
     | 
| 
       1010 
     | 
    
         
            -
                  def foreign_key_exists?(from_table,  
     | 
| 
       1011 
     | 
    
         
            -
                    foreign_key_for(from_table,  
     | 
| 
      
 1149 
     | 
    
         
            +
                  def foreign_key_exists?(from_table, to_table = nil, **options)
         
     | 
| 
      
 1150 
     | 
    
         
            +
                    foreign_key_for(from_table, to_table: to_table, **options).present?
         
     | 
| 
       1012 
1151 
     | 
    
         
             
                  end
         
     | 
| 
       1013 
1152 
     | 
    
         | 
| 
       1014 
1153 
     | 
    
         
             
                  def foreign_key_column_for(table_name) # :nodoc:
         
     | 
| 
       1015 
     | 
    
         
            -
                     
     | 
| 
       1016 
     | 
    
         
            -
                    suffix = Base.table_name_suffix
         
     | 
| 
       1017 
     | 
    
         
            -
                    name = table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
         
     | 
| 
      
 1154 
     | 
    
         
            +
                    name = strip_table_name_prefix_and_suffix(table_name)
         
     | 
| 
       1018 
1155 
     | 
    
         
             
                    "#{name.singularize}_id"
         
     | 
| 
       1019 
1156 
     | 
    
         
             
                  end
         
     | 
| 
       1020 
1157 
     | 
    
         | 
| 
         @@ -1025,8 +1162,62 @@ module ActiveRecord 
     | 
|
| 
       1025 
1162 
     | 
    
         
             
                    options
         
     | 
| 
       1026 
1163 
     | 
    
         
             
                  end
         
     | 
| 
       1027 
1164 
     | 
    
         | 
| 
       1028 
     | 
    
         
            -
                   
     | 
| 
       1029 
     | 
    
         
            -
             
     | 
| 
      
 1165 
     | 
    
         
            +
                  # Returns an array of check constraints for the given table.
         
     | 
| 
      
 1166 
     | 
    
         
            +
                  # The check constraints are represented as CheckConstraintDefinition objects.
         
     | 
| 
      
 1167 
     | 
    
         
            +
                  def check_constraints(table_name)
         
     | 
| 
      
 1168 
     | 
    
         
            +
                    raise NotImplementedError
         
     | 
| 
      
 1169 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1170 
     | 
    
         
            +
             
     | 
| 
      
 1171 
     | 
    
         
            +
                  # Adds a new check constraint to the table. +expression+ is a String
         
     | 
| 
      
 1172 
     | 
    
         
            +
                  # representation of verifiable boolean condition.
         
     | 
| 
      
 1173 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1174 
     | 
    
         
            +
                  #   add_check_constraint :products, "price > 0", name: "price_check"
         
     | 
| 
      
 1175 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1176 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 1177 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1178 
     | 
    
         
            +
                  #   ALTER TABLE "products" ADD CONSTRAINT price_check CHECK (price > 0)
         
     | 
| 
      
 1179 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1180 
     | 
    
         
            +
                  # The +options+ hash can include the following keys:
         
     | 
| 
      
 1181 
     | 
    
         
            +
                  # [<tt>:name</tt>]
         
     | 
| 
      
 1182 
     | 
    
         
            +
                  #   The constraint name. Defaults to <tt>chk_rails_<identifier></tt>.
         
     | 
| 
      
 1183 
     | 
    
         
            +
                  # [<tt>:validate</tt>]
         
     | 
| 
      
 1184 
     | 
    
         
            +
                  #   (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
         
     | 
| 
      
 1185 
     | 
    
         
            +
                  def add_check_constraint(table_name, expression, **options)
         
     | 
| 
      
 1186 
     | 
    
         
            +
                    return unless supports_check_constraints?
         
     | 
| 
      
 1187 
     | 
    
         
            +
             
     | 
| 
      
 1188 
     | 
    
         
            +
                    options = check_constraint_options(table_name, expression, options)
         
     | 
| 
      
 1189 
     | 
    
         
            +
                    at = create_alter_table(table_name)
         
     | 
| 
      
 1190 
     | 
    
         
            +
                    at.add_check_constraint(expression, options)
         
     | 
| 
      
 1191 
     | 
    
         
            +
             
     | 
| 
      
 1192 
     | 
    
         
            +
                    execute schema_creation.accept(at)
         
     | 
| 
      
 1193 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1194 
     | 
    
         
            +
             
     | 
| 
      
 1195 
     | 
    
         
            +
                  def check_constraint_options(table_name, expression, options) # :nodoc:
         
     | 
| 
      
 1196 
     | 
    
         
            +
                    options = options.dup
         
     | 
| 
      
 1197 
     | 
    
         
            +
                    options[:name] ||= check_constraint_name(table_name, expression: expression, **options)
         
     | 
| 
      
 1198 
     | 
    
         
            +
                    options
         
     | 
| 
      
 1199 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1200 
     | 
    
         
            +
             
     | 
| 
      
 1201 
     | 
    
         
            +
                  # Removes the given check constraint from the table.
         
     | 
| 
      
 1202 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1203 
     | 
    
         
            +
                  #   remove_check_constraint :products, name: "price_check"
         
     | 
| 
      
 1204 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1205 
     | 
    
         
            +
                  # The +expression+ parameter will be ignored if present. It can be helpful
         
     | 
| 
      
 1206 
     | 
    
         
            +
                  # to provide this in a migration's +change+ method so it can be reverted.
         
     | 
| 
      
 1207 
     | 
    
         
            +
                  # In that case, +expression+ will be used by #add_check_constraint.
         
     | 
| 
      
 1208 
     | 
    
         
            +
                  def remove_check_constraint(table_name, expression = nil, **options)
         
     | 
| 
      
 1209 
     | 
    
         
            +
                    return unless supports_check_constraints?
         
     | 
| 
      
 1210 
     | 
    
         
            +
             
     | 
| 
      
 1211 
     | 
    
         
            +
                    chk_name_to_delete = check_constraint_for!(table_name, expression: expression, **options).name
         
     | 
| 
      
 1212 
     | 
    
         
            +
             
     | 
| 
      
 1213 
     | 
    
         
            +
                    at = create_alter_table(table_name)
         
     | 
| 
      
 1214 
     | 
    
         
            +
                    at.drop_check_constraint(chk_name_to_delete)
         
     | 
| 
      
 1215 
     | 
    
         
            +
             
     | 
| 
      
 1216 
     | 
    
         
            +
                    execute schema_creation.accept(at)
         
     | 
| 
      
 1217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1218 
     | 
    
         
            +
             
     | 
| 
      
 1219 
     | 
    
         
            +
                  def dump_schema_information # :nodoc:
         
     | 
| 
      
 1220 
     | 
    
         
            +
                    versions = schema_migration.all_versions
         
     | 
| 
       1030 
1221 
     | 
    
         
             
                    insert_versions_sql(versions) if versions.any?
         
     | 
| 
       1031 
1222 
     | 
    
         
             
                  end
         
     | 
| 
       1032 
1223 
     | 
    
         | 
| 
         @@ -1034,15 +1225,12 @@ module ActiveRecord 
     | 
|
| 
       1034 
1225 
     | 
    
         
             
                    { primary_key: true }
         
     | 
| 
       1035 
1226 
     | 
    
         
             
                  end
         
     | 
| 
       1036 
1227 
     | 
    
         | 
| 
       1037 
     | 
    
         
            -
                  def assume_migrated_upto_version(version 
     | 
| 
       1038 
     | 
    
         
            -
                    migrations_paths = Array(migrations_paths)
         
     | 
| 
      
 1228 
     | 
    
         
            +
                  def assume_migrated_upto_version(version)
         
     | 
| 
       1039 
1229 
     | 
    
         
             
                    version = version.to_i
         
     | 
| 
       1040 
     | 
    
         
            -
                    sm_table = quote_table_name( 
     | 
| 
      
 1230 
     | 
    
         
            +
                    sm_table = quote_table_name(schema_migration.table_name)
         
     | 
| 
       1041 
1231 
     | 
    
         | 
| 
       1042 
     | 
    
         
            -
                    migrated =  
     | 
| 
       1043 
     | 
    
         
            -
                    versions = migration_context. 
     | 
| 
       1044 
     | 
    
         
            -
                      migration_context.parse_migration_filename(file).first.to_i
         
     | 
| 
       1045 
     | 
    
         
            -
                    end
         
     | 
| 
      
 1232 
     | 
    
         
            +
                    migrated = migration_context.get_all_versions
         
     | 
| 
      
 1233 
     | 
    
         
            +
                    versions = migration_context.migrations.map(&:version)
         
     | 
| 
       1046 
1234 
     | 
    
         | 
| 
       1047 
1235 
     | 
    
         
             
                    unless migrated.include?(version)
         
     | 
| 
       1048 
1236 
     | 
    
         
             
                      execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
         
     | 
| 
         @@ -1053,13 +1241,7 @@ module ActiveRecord 
     | 
|
| 
       1053 
1241 
     | 
    
         
             
                      if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
         
     | 
| 
       1054 
1242 
     | 
    
         
             
                        raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
         
     | 
| 
       1055 
1243 
     | 
    
         
             
                      end
         
     | 
| 
       1056 
     | 
    
         
            -
                       
     | 
| 
       1057 
     | 
    
         
            -
                        execute insert_versions_sql(inserting)
         
     | 
| 
       1058 
     | 
    
         
            -
                      else
         
     | 
| 
       1059 
     | 
    
         
            -
                        inserting.each do |v|
         
     | 
| 
       1060 
     | 
    
         
            -
                          execute insert_versions_sql(v)
         
     | 
| 
       1061 
     | 
    
         
            -
                        end
         
     | 
| 
       1062 
     | 
    
         
            -
                      end
         
     | 
| 
      
 1244 
     | 
    
         
            +
                      execute insert_versions_sql(inserting)
         
     | 
| 
       1063 
1245 
     | 
    
         
             
                    end
         
     | 
| 
       1064 
1246 
     | 
    
         
             
                  end
         
     | 
| 
       1065 
1247 
     | 
    
         | 
| 
         @@ -1085,7 +1267,7 @@ module ActiveRecord 
     | 
|
| 
       1085 
1267 
     | 
    
         
             
                        if (0..6) === precision
         
     | 
| 
       1086 
1268 
     | 
    
         
             
                          column_type_sql << "(#{precision})"
         
     | 
| 
       1087 
1269 
     | 
    
         
             
                        else
         
     | 
| 
       1088 
     | 
    
         
            -
                          raise 
     | 
| 
      
 1270 
     | 
    
         
            +
                          raise ArgumentError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6"
         
     | 
| 
       1089 
1271 
     | 
    
         
             
                        end
         
     | 
| 
       1090 
1272 
     | 
    
         
             
                      elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
         
     | 
| 
       1091 
1273 
     | 
    
         
             
                        column_type_sql << "(#{limit})"
         
     | 
| 
         @@ -1107,61 +1289,90 @@ module ActiveRecord 
     | 
|
| 
       1107 
1289 
     | 
    
         
             
                    columns
         
     | 
| 
       1108 
1290 
     | 
    
         
             
                  end
         
     | 
| 
       1109 
1291 
     | 
    
         | 
| 
      
 1292 
     | 
    
         
            +
                  def distinct_relation_for_primary_key(relation) # :nodoc:
         
     | 
| 
      
 1293 
     | 
    
         
            +
                    values = columns_for_distinct(
         
     | 
| 
      
 1294 
     | 
    
         
            +
                      visitor.compile(relation.table[relation.primary_key]),
         
     | 
| 
      
 1295 
     | 
    
         
            +
                      relation.order_values
         
     | 
| 
      
 1296 
     | 
    
         
            +
                    )
         
     | 
| 
      
 1297 
     | 
    
         
            +
             
     | 
| 
      
 1298 
     | 
    
         
            +
                    limited = relation.reselect(values).distinct!
         
     | 
| 
      
 1299 
     | 
    
         
            +
                    limited_ids = select_rows(limited.arel, "SQL").map(&:last)
         
     | 
| 
      
 1300 
     | 
    
         
            +
             
     | 
| 
      
 1301 
     | 
    
         
            +
                    if limited_ids.empty?
         
     | 
| 
      
 1302 
     | 
    
         
            +
                      relation.none!
         
     | 
| 
      
 1303 
     | 
    
         
            +
                    else
         
     | 
| 
      
 1304 
     | 
    
         
            +
                      relation.where!(relation.primary_key => limited_ids)
         
     | 
| 
      
 1305 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1306 
     | 
    
         
            +
             
     | 
| 
      
 1307 
     | 
    
         
            +
                    relation.limit_value = relation.offset_value = nil
         
     | 
| 
      
 1308 
     | 
    
         
            +
                    relation
         
     | 
| 
      
 1309 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1310 
     | 
    
         
            +
             
     | 
| 
       1110 
1311 
     | 
    
         
             
                  # Adds timestamps (+created_at+ and +updated_at+) columns to +table_name+.
         
     | 
| 
       1111 
1312 
     | 
    
         
             
                  # Additional options (like +:null+) are forwarded to #add_column.
         
     | 
| 
       1112 
1313 
     | 
    
         
             
                  #
         
     | 
| 
       1113 
1314 
     | 
    
         
             
                  #   add_timestamps(:suppliers, null: true)
         
     | 
| 
       1114 
1315 
     | 
    
         
             
                  #
         
     | 
| 
       1115 
     | 
    
         
            -
                  def add_timestamps(table_name, options 
     | 
| 
      
 1316 
     | 
    
         
            +
                  def add_timestamps(table_name, **options)
         
     | 
| 
       1116 
1317 
     | 
    
         
             
                    options[:null] = false if options[:null].nil?
         
     | 
| 
       1117 
1318 
     | 
    
         | 
| 
       1118 
     | 
    
         
            -
                     
     | 
| 
       1119 
     | 
    
         
            -
             
     | 
| 
      
 1319 
     | 
    
         
            +
                    if !options.key?(:precision) && supports_datetime_with_precision?
         
     | 
| 
      
 1320 
     | 
    
         
            +
                      options[:precision] = 6
         
     | 
| 
      
 1321 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1322 
     | 
    
         
            +
             
     | 
| 
      
 1323 
     | 
    
         
            +
                    add_column table_name, :created_at, :datetime, **options
         
     | 
| 
      
 1324 
     | 
    
         
            +
                    add_column table_name, :updated_at, :datetime, **options
         
     | 
| 
       1120 
1325 
     | 
    
         
             
                  end
         
     | 
| 
       1121 
1326 
     | 
    
         | 
| 
       1122 
1327 
     | 
    
         
             
                  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
         
     | 
| 
       1123 
1328 
     | 
    
         
             
                  #
         
     | 
| 
       1124 
1329 
     | 
    
         
             
                  #  remove_timestamps(:suppliers)
         
     | 
| 
       1125 
1330 
     | 
    
         
             
                  #
         
     | 
| 
       1126 
     | 
    
         
            -
                  def remove_timestamps(table_name, options 
     | 
| 
       1127 
     | 
    
         
            -
                     
     | 
| 
       1128 
     | 
    
         
            -
                    remove_column table_name, :created_at
         
     | 
| 
      
 1331 
     | 
    
         
            +
                  def remove_timestamps(table_name, **options)
         
     | 
| 
      
 1332 
     | 
    
         
            +
                    remove_columns table_name, :updated_at, :created_at
         
     | 
| 
       1129 
1333 
     | 
    
         
             
                  end
         
     | 
| 
       1130 
1334 
     | 
    
         | 
| 
       1131 
     | 
    
         
            -
                  def update_table_definition(table_name, base)  
     | 
| 
      
 1335 
     | 
    
         
            +
                  def update_table_definition(table_name, base) # :nodoc:
         
     | 
| 
       1132 
1336 
     | 
    
         
             
                    Table.new(table_name, base)
         
     | 
| 
       1133 
1337 
     | 
    
         
             
                  end
         
     | 
| 
       1134 
1338 
     | 
    
         | 
| 
       1135 
     | 
    
         
            -
                  def add_index_options(table_name, column_name,  
     | 
| 
       1136 
     | 
    
         
            -
                     
     | 
| 
      
 1339 
     | 
    
         
            +
                  def add_index_options(table_name, column_name, name: nil, if_not_exists: false, internal: false, **options) # :nodoc:
         
     | 
| 
      
 1340 
     | 
    
         
            +
                    options.assert_valid_keys(:unique, :length, :order, :opclass, :where, :type, :using, :comment, :algorithm)
         
     | 
| 
       1137 
1341 
     | 
    
         | 
| 
       1138 
     | 
    
         
            -
                     
     | 
| 
      
 1342 
     | 
    
         
            +
                    column_names = index_column_names(column_name)
         
     | 
| 
       1139 
1343 
     | 
    
         | 
| 
       1140 
     | 
    
         
            -
                     
     | 
| 
       1141 
     | 
    
         
            -
                    index_type ||= options[:unique] ? "UNIQUE" : ""
         
     | 
| 
       1142 
     | 
    
         
            -
                    index_name = options[:name].to_s if options.key?(:name)
         
     | 
| 
      
 1344 
     | 
    
         
            +
                    index_name = name&.to_s
         
     | 
| 
       1143 
1345 
     | 
    
         
             
                    index_name ||= index_name(table_name, column_names)
         
     | 
| 
       1144 
1346 
     | 
    
         | 
| 
       1145 
     | 
    
         
            -
                     
     | 
| 
       1146 
     | 
    
         
            -
             
     | 
| 
       1147 
     | 
    
         
            -
             
     | 
| 
       1148 
     | 
    
         
            -
                       
     | 
| 
       1149 
     | 
    
         
            -
             
     | 
| 
       1150 
     | 
    
         
            -
             
     | 
| 
       1151 
     | 
    
         
            -
             
     | 
| 
       1152 
     | 
    
         
            -
             
     | 
| 
       1153 
     | 
    
         
            -
             
     | 
| 
       1154 
     | 
    
         
            -
                       
     | 
| 
       1155 
     | 
    
         
            -
             
     | 
| 
      
 1347 
     | 
    
         
            +
                    validate_index_length!(table_name, index_name, internal)
         
     | 
| 
      
 1348 
     | 
    
         
            +
             
     | 
| 
      
 1349 
     | 
    
         
            +
                    index = IndexDefinition.new(
         
     | 
| 
      
 1350 
     | 
    
         
            +
                      table_name, index_name,
         
     | 
| 
      
 1351 
     | 
    
         
            +
                      options[:unique],
         
     | 
| 
      
 1352 
     | 
    
         
            +
                      column_names,
         
     | 
| 
      
 1353 
     | 
    
         
            +
                      lengths: options[:length] || {},
         
     | 
| 
      
 1354 
     | 
    
         
            +
                      orders: options[:order] || {},
         
     | 
| 
      
 1355 
     | 
    
         
            +
                      opclasses: options[:opclass] || {},
         
     | 
| 
      
 1356 
     | 
    
         
            +
                      where: options[:where],
         
     | 
| 
      
 1357 
     | 
    
         
            +
                      type: options[:type],
         
     | 
| 
      
 1358 
     | 
    
         
            +
                      using: options[:using],
         
     | 
| 
      
 1359 
     | 
    
         
            +
                      comment: options[:comment]
         
     | 
| 
      
 1360 
     | 
    
         
            +
                    )
         
     | 
| 
      
 1361 
     | 
    
         
            +
             
     | 
| 
      
 1362 
     | 
    
         
            +
                    [index, index_algorithm(options[:algorithm]), if_not_exists]
         
     | 
| 
      
 1363 
     | 
    
         
            +
                  end
         
     | 
| 
       1156 
1364 
     | 
    
         | 
| 
       1157 
     | 
    
         
            -
             
     | 
| 
      
 1365 
     | 
    
         
            +
                  def index_algorithm(algorithm) # :nodoc:
         
     | 
| 
      
 1366 
     | 
    
         
            +
                    index_algorithms.fetch(algorithm) do
         
     | 
| 
      
 1367 
     | 
    
         
            +
                      raise ArgumentError, "Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}"
         
     | 
| 
      
 1368 
     | 
    
         
            +
                    end if algorithm
         
     | 
| 
      
 1369 
     | 
    
         
            +
                  end
         
     | 
| 
       1158 
1370 
     | 
    
         | 
| 
       1159 
     | 
    
         
            -
             
     | 
| 
       1160 
     | 
    
         
            -
             
     | 
| 
      
 1371 
     | 
    
         
            +
                  def quoted_columns_for_index(column_names, options) # :nodoc:
         
     | 
| 
      
 1372 
     | 
    
         
            +
                    quoted_columns = column_names.each_with_object({}) do |name, result|
         
     | 
| 
      
 1373 
     | 
    
         
            +
                      result[name.to_sym] = quote_column_name(name).dup
         
     | 
| 
       1161 
1374 
     | 
    
         
             
                    end
         
     | 
| 
       1162 
     | 
    
         
            -
                     
     | 
| 
       1163 
     | 
    
         
            -
             
     | 
| 
       1164 
     | 
    
         
            -
                    [index_name, index_type, index_columns, index_options, algorithm, using, comment]
         
     | 
| 
      
 1375 
     | 
    
         
            +
                    add_options_for_index_columns(quoted_columns, **options).values.join(", ")
         
     | 
| 
       1165 
1376 
     | 
    
         
             
                  end
         
     | 
| 
       1166 
1377 
     | 
    
         | 
| 
       1167 
1378 
     | 
    
         
             
                  def options_include_default?(options)
         
     | 
| 
         @@ -1169,12 +1380,22 @@ module ActiveRecord 
     | 
|
| 
       1169 
1380 
     | 
    
         
             
                  end
         
     | 
| 
       1170 
1381 
     | 
    
         | 
| 
       1171 
1382 
     | 
    
         
             
                  # Changes the comment for a table or removes it if +nil+.
         
     | 
| 
       1172 
     | 
    
         
            -
                   
     | 
| 
      
 1383 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1384 
     | 
    
         
            +
                  # Passing a hash containing +:from+ and +:to+ will make this change
         
     | 
| 
      
 1385 
     | 
    
         
            +
                  # reversible in migration:
         
     | 
| 
      
 1386 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1387 
     | 
    
         
            +
                  #   change_table_comment(:posts, from: "old_comment", to: "new_comment")
         
     | 
| 
      
 1388 
     | 
    
         
            +
                  def change_table_comment(table_name, comment_or_changes)
         
     | 
| 
       1173 
1389 
     | 
    
         
             
                    raise NotImplementedError, "#{self.class} does not support changing table comments"
         
     | 
| 
       1174 
1390 
     | 
    
         
             
                  end
         
     | 
| 
       1175 
1391 
     | 
    
         | 
| 
       1176 
1392 
     | 
    
         
             
                  # Changes the comment for a column or removes it if +nil+.
         
     | 
| 
       1177 
     | 
    
         
            -
                   
     | 
| 
      
 1393 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1394 
     | 
    
         
            +
                  # Passing a hash containing +:from+ and +:to+ will make this change
         
     | 
| 
      
 1395 
     | 
    
         
            +
                  # reversible in migration:
         
     | 
| 
      
 1396 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1397 
     | 
    
         
            +
                  #   change_column_comment(:posts, :state, from: "old_comment", to: "new_comment")
         
     | 
| 
      
 1398 
     | 
    
         
            +
                  def change_column_comment(table_name, column_name, comment_or_changes)
         
     | 
| 
       1178 
1399 
     | 
    
         
             
                    raise NotImplementedError, "#{self.class} does not support changing column comments"
         
     | 
| 
       1179 
1400 
     | 
    
         
             
                  end
         
     | 
| 
       1180 
1401 
     | 
    
         | 
| 
         @@ -1206,32 +1427,27 @@ module ActiveRecord 
     | 
|
| 
       1206 
1427 
     | 
    
         
             
                    # the PostgreSQL adapter for supporting operator classes.
         
     | 
| 
       1207 
1428 
     | 
    
         
             
                    def add_options_for_index_columns(quoted_columns, **options)
         
     | 
| 
       1208 
1429 
     | 
    
         
             
                      if supports_index_sort_order?
         
     | 
| 
       1209 
     | 
    
         
            -
                        quoted_columns = add_index_sort_order(quoted_columns, options)
         
     | 
| 
      
 1430 
     | 
    
         
            +
                        quoted_columns = add_index_sort_order(quoted_columns, **options)
         
     | 
| 
       1210 
1431 
     | 
    
         
             
                      end
         
     | 
| 
       1211 
1432 
     | 
    
         | 
| 
       1212 
1433 
     | 
    
         
             
                      quoted_columns
         
     | 
| 
       1213 
1434 
     | 
    
         
             
                    end
         
     | 
| 
       1214 
1435 
     | 
    
         | 
| 
       1215 
     | 
    
         
            -
                    def  
     | 
| 
       1216 
     | 
    
         
            -
                      return [ 
     | 
| 
       1217 
     | 
    
         
            -
             
     | 
| 
       1218 
     | 
    
         
            -
                      quoted_columns = Hash[column_names.map { |name| [name.to_sym, quote_column_name(name).dup] }]
         
     | 
| 
       1219 
     | 
    
         
            -
                      add_options_for_index_columns(quoted_columns, options).values
         
     | 
| 
       1220 
     | 
    
         
            -
                    end
         
     | 
| 
       1221 
     | 
    
         
            -
             
     | 
| 
       1222 
     | 
    
         
            -
                    def index_name_for_remove(table_name, options = {})
         
     | 
| 
       1223 
     | 
    
         
            -
                      return options[:name] if can_remove_index_by_name?(options)
         
     | 
| 
      
 1436 
     | 
    
         
            +
                    def index_name_for_remove(table_name, column_name, options)
         
     | 
| 
      
 1437 
     | 
    
         
            +
                      return options[:name] if can_remove_index_by_name?(column_name, options)
         
     | 
| 
       1224 
1438 
     | 
    
         | 
| 
       1225 
1439 
     | 
    
         
             
                      checks = []
         
     | 
| 
       1226 
1440 
     | 
    
         | 
| 
       1227 
     | 
    
         
            -
                      if options. 
     | 
| 
       1228 
     | 
    
         
            -
                         
     | 
| 
       1229 
     | 
    
         
            -
                        column_names =  
     | 
| 
      
 1441 
     | 
    
         
            +
                      if !options.key?(:name) && expression_column_name?(column_name)
         
     | 
| 
      
 1442 
     | 
    
         
            +
                        options[:name] = index_name(table_name, column_name)
         
     | 
| 
      
 1443 
     | 
    
         
            +
                        column_names = []
         
     | 
| 
       1230 
1444 
     | 
    
         
             
                      else
         
     | 
| 
       1231 
     | 
    
         
            -
                        column_names = index_column_names(options)
         
     | 
| 
      
 1445 
     | 
    
         
            +
                        column_names = index_column_names(column_name || options[:column])
         
     | 
| 
       1232 
1446 
     | 
    
         
             
                      end
         
     | 
| 
       1233 
1447 
     | 
    
         | 
| 
       1234 
     | 
    
         
            -
                      if  
     | 
| 
      
 1448 
     | 
    
         
            +
                      checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
         
     | 
| 
      
 1449 
     | 
    
         
            +
             
     | 
| 
      
 1450 
     | 
    
         
            +
                      if column_names.present? && !(options.key?(:name) && expression_column_name?(column_names))
         
     | 
| 
       1235 
1451 
     | 
    
         
             
                        checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
         
     | 
| 
       1236 
1452 
     | 
    
         
             
                      end
         
     | 
| 
       1237 
1453 
     | 
    
         | 
| 
         @@ -1275,14 +1491,18 @@ module ActiveRecord 
     | 
|
| 
       1275 
1491 
     | 
    
         
             
                      SchemaCreation.new(self)
         
     | 
| 
       1276 
1492 
     | 
    
         
             
                    end
         
     | 
| 
       1277 
1493 
     | 
    
         | 
| 
       1278 
     | 
    
         
            -
                    def create_table_definition( 
     | 
| 
       1279 
     | 
    
         
            -
                      TableDefinition.new( 
     | 
| 
      
 1494 
     | 
    
         
            +
                    def create_table_definition(name, **options)
         
     | 
| 
      
 1495 
     | 
    
         
            +
                      TableDefinition.new(self, name, **options)
         
     | 
| 
       1280 
1496 
     | 
    
         
             
                    end
         
     | 
| 
       1281 
1497 
     | 
    
         | 
| 
       1282 
1498 
     | 
    
         
             
                    def create_alter_table(name)
         
     | 
| 
       1283 
1499 
     | 
    
         
             
                      AlterTable.new create_table_definition(name)
         
     | 
| 
       1284 
1500 
     | 
    
         
             
                    end
         
     | 
| 
       1285 
1501 
     | 
    
         | 
| 
      
 1502 
     | 
    
         
            +
                    def extract_table_options!(options)
         
     | 
| 
      
 1503 
     | 
    
         
            +
                      options.extract!(:temporary, :if_not_exists, :options, :as, :comment, :charset, :collation)
         
     | 
| 
      
 1504 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1505 
     | 
    
         
            +
             
     | 
| 
       1286 
1506 
     | 
    
         
             
                    def fetch_type_metadata(sql_type)
         
     | 
| 
       1287 
1507 
     | 
    
         
             
                      cast_type = lookup_cast_type(sql_type)
         
     | 
| 
       1288 
1508 
     | 
    
         
             
                      SqlTypeMetadata.new(
         
     | 
| 
         @@ -1295,7 +1515,7 @@ module ActiveRecord 
     | 
|
| 
       1295 
1515 
     | 
    
         
             
                    end
         
     | 
| 
       1296 
1516 
     | 
    
         | 
| 
       1297 
1517 
     | 
    
         
             
                    def index_column_names(column_names)
         
     | 
| 
       1298 
     | 
    
         
            -
                      if  
     | 
| 
      
 1518 
     | 
    
         
            +
                      if expression_column_name?(column_names)
         
     | 
| 
       1299 
1519 
     | 
    
         
             
                        column_names
         
     | 
| 
       1300 
1520 
     | 
    
         
             
                      else
         
     | 
| 
       1301 
1521 
     | 
    
         
             
                        Array(column_names)
         
     | 
| 
         @@ -1303,30 +1523,41 @@ module ActiveRecord 
     | 
|
| 
       1303 
1523 
     | 
    
         
             
                    end
         
     | 
| 
       1304 
1524 
     | 
    
         | 
| 
       1305 
1525 
     | 
    
         
             
                    def index_name_options(column_names)
         
     | 
| 
       1306 
     | 
    
         
            -
                      if  
     | 
| 
      
 1526 
     | 
    
         
            +
                      if expression_column_name?(column_names)
         
     | 
| 
       1307 
1527 
     | 
    
         
             
                        column_names = column_names.scan(/\w+/).join("_")
         
     | 
| 
       1308 
1528 
     | 
    
         
             
                      end
         
     | 
| 
       1309 
1529 
     | 
    
         | 
| 
       1310 
1530 
     | 
    
         
             
                      { column: column_names }
         
     | 
| 
       1311 
1531 
     | 
    
         
             
                    end
         
     | 
| 
       1312 
1532 
     | 
    
         | 
| 
      
 1533 
     | 
    
         
            +
                    # Try to identify whether the given column name is an expression
         
     | 
| 
      
 1534 
     | 
    
         
            +
                    def expression_column_name?(column_name)
         
     | 
| 
      
 1535 
     | 
    
         
            +
                      column_name.is_a?(String) && /\W/.match?(column_name)
         
     | 
| 
      
 1536 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1537 
     | 
    
         
            +
             
     | 
| 
      
 1538 
     | 
    
         
            +
                    def strip_table_name_prefix_and_suffix(table_name)
         
     | 
| 
      
 1539 
     | 
    
         
            +
                      prefix = Base.table_name_prefix
         
     | 
| 
      
 1540 
     | 
    
         
            +
                      suffix = Base.table_name_suffix
         
     | 
| 
      
 1541 
     | 
    
         
            +
                      table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
         
     | 
| 
      
 1542 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1543 
     | 
    
         
            +
             
     | 
| 
       1313 
1544 
     | 
    
         
             
                    def foreign_key_name(table_name, options)
         
     | 
| 
       1314 
1545 
     | 
    
         
             
                      options.fetch(:name) do
         
     | 
| 
       1315 
1546 
     | 
    
         
             
                        identifier = "#{table_name}_#{options.fetch(:column)}_fk"
         
     | 
| 
       1316 
     | 
    
         
            -
                        hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
         
     | 
| 
      
 1547 
     | 
    
         
            +
                        hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
         
     | 
| 
       1317 
1548 
     | 
    
         | 
| 
       1318 
1549 
     | 
    
         
             
                        "fk_rails_#{hashed_identifier}"
         
     | 
| 
       1319 
1550 
     | 
    
         
             
                      end
         
     | 
| 
       1320 
1551 
     | 
    
         
             
                    end
         
     | 
| 
       1321 
1552 
     | 
    
         | 
| 
       1322 
     | 
    
         
            -
                    def foreign_key_for(from_table,  
     | 
| 
      
 1553 
     | 
    
         
            +
                    def foreign_key_for(from_table, **options)
         
     | 
| 
       1323 
1554 
     | 
    
         
             
                      return unless supports_foreign_keys?
         
     | 
| 
       1324 
     | 
    
         
            -
                      foreign_keys(from_table).detect { |fk| fk.defined_for?  
     | 
| 
      
 1555 
     | 
    
         
            +
                      foreign_keys(from_table).detect { |fk| fk.defined_for?(**options) }
         
     | 
| 
       1325 
1556 
     | 
    
         
             
                    end
         
     | 
| 
       1326 
1557 
     | 
    
         | 
| 
       1327 
     | 
    
         
            -
                    def foreign_key_for!(from_table,  
     | 
| 
       1328 
     | 
    
         
            -
                      foreign_key_for(from_table,  
     | 
| 
       1329 
     | 
    
         
            -
                        raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{ 
     | 
| 
      
 1558 
     | 
    
         
            +
                    def foreign_key_for!(from_table, to_table: nil, **options)
         
     | 
| 
      
 1559 
     | 
    
         
            +
                      foreign_key_for(from_table, to_table: to_table, **options) ||
         
     | 
| 
      
 1560 
     | 
    
         
            +
                        raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
         
     | 
| 
       1330 
1561 
     | 
    
         
             
                    end
         
     | 
| 
       1331 
1562 
     | 
    
         | 
| 
       1332 
1563 
     | 
    
         
             
                    def extract_foreign_key_action(specifier)
         
     | 
| 
         @@ -1337,11 +1568,30 @@ module ActiveRecord 
     | 
|
| 
       1337 
1568 
     | 
    
         
             
                      end
         
     | 
| 
       1338 
1569 
     | 
    
         
             
                    end
         
     | 
| 
       1339 
1570 
     | 
    
         | 
| 
       1340 
     | 
    
         
            -
                    def  
     | 
| 
       1341 
     | 
    
         
            -
                       
     | 
| 
      
 1571 
     | 
    
         
            +
                    def check_constraint_name(table_name, **options)
         
     | 
| 
      
 1572 
     | 
    
         
            +
                      options.fetch(:name) do
         
     | 
| 
      
 1573 
     | 
    
         
            +
                        expression = options.fetch(:expression)
         
     | 
| 
      
 1574 
     | 
    
         
            +
                        identifier = "#{table_name}_#{expression}_chk"
         
     | 
| 
      
 1575 
     | 
    
         
            +
                        hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
         
     | 
| 
       1342 
1576 
     | 
    
         | 
| 
       1343 
     | 
    
         
            -
             
     | 
| 
       1344 
     | 
    
         
            -
             
     | 
| 
      
 1577 
     | 
    
         
            +
                        "chk_rails_#{hashed_identifier}"
         
     | 
| 
      
 1578 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1579 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1580 
     | 
    
         
            +
             
     | 
| 
      
 1581 
     | 
    
         
            +
                    def check_constraint_for(table_name, **options)
         
     | 
| 
      
 1582 
     | 
    
         
            +
                      return unless supports_check_constraints?
         
     | 
| 
      
 1583 
     | 
    
         
            +
                      chk_name = check_constraint_name(table_name, **options)
         
     | 
| 
      
 1584 
     | 
    
         
            +
                      check_constraints(table_name).detect { |chk| chk.name == chk_name }
         
     | 
| 
      
 1585 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1586 
     | 
    
         
            +
             
     | 
| 
      
 1587 
     | 
    
         
            +
                    def check_constraint_for!(table_name, expression: nil, **options)
         
     | 
| 
      
 1588 
     | 
    
         
            +
                      check_constraint_for(table_name, expression: expression, **options) ||
         
     | 
| 
      
 1589 
     | 
    
         
            +
                        raise(ArgumentError, "Table '#{table_name}' has no check constraint for #{expression || options}")
         
     | 
| 
      
 1590 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1591 
     | 
    
         
            +
             
     | 
| 
      
 1592 
     | 
    
         
            +
                    def validate_index_length!(table_name, new_name, internal = false)
         
     | 
| 
      
 1593 
     | 
    
         
            +
                      if new_name.length > index_name_length
         
     | 
| 
      
 1594 
     | 
    
         
            +
                        raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
         
     | 
| 
       1345 
1595 
     | 
    
         
             
                      end
         
     | 
| 
       1346 
1596 
     | 
    
         
             
                    end
         
     | 
| 
       1347 
1597 
     | 
    
         | 
| 
         @@ -1352,30 +1602,77 @@ module ActiveRecord 
     | 
|
| 
       1352 
1602 
     | 
    
         
             
                        default_or_changes
         
     | 
| 
       1353 
1603 
     | 
    
         
             
                      end
         
     | 
| 
       1354 
1604 
     | 
    
         
             
                    end
         
     | 
| 
      
 1605 
     | 
    
         
            +
                    alias :extract_new_comment_value :extract_new_default_value
         
     | 
| 
      
 1606 
     | 
    
         
            +
             
     | 
| 
      
 1607 
     | 
    
         
            +
                    def can_remove_index_by_name?(column_name, options)
         
     | 
| 
      
 1608 
     | 
    
         
            +
                      column_name.nil? && options.key?(:name) && options.except(:name, :algorithm).empty?
         
     | 
| 
      
 1609 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1610 
     | 
    
         
            +
             
     | 
| 
      
 1611 
     | 
    
         
            +
                    def bulk_change_table(table_name, operations)
         
     | 
| 
      
 1612 
     | 
    
         
            +
                      sql_fragments = []
         
     | 
| 
      
 1613 
     | 
    
         
            +
                      non_combinable_operations = []
         
     | 
| 
      
 1614 
     | 
    
         
            +
             
     | 
| 
      
 1615 
     | 
    
         
            +
                      operations.each do |command, args|
         
     | 
| 
      
 1616 
     | 
    
         
            +
                        table, arguments = args.shift, args
         
     | 
| 
      
 1617 
     | 
    
         
            +
                        method = :"#{command}_for_alter"
         
     | 
| 
      
 1618 
     | 
    
         
            +
             
     | 
| 
      
 1619 
     | 
    
         
            +
                        if respond_to?(method, true)
         
     | 
| 
      
 1620 
     | 
    
         
            +
                          sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
         
     | 
| 
      
 1621 
     | 
    
         
            +
                          sql_fragments << sqls
         
     | 
| 
      
 1622 
     | 
    
         
            +
                          non_combinable_operations.concat(procs)
         
     | 
| 
      
 1623 
     | 
    
         
            +
                        else
         
     | 
| 
      
 1624 
     | 
    
         
            +
                          execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
         
     | 
| 
      
 1625 
     | 
    
         
            +
                          non_combinable_operations.each(&:call)
         
     | 
| 
      
 1626 
     | 
    
         
            +
                          sql_fragments = []
         
     | 
| 
      
 1627 
     | 
    
         
            +
                          non_combinable_operations = []
         
     | 
| 
      
 1628 
     | 
    
         
            +
                          send(command, table, *arguments)
         
     | 
| 
      
 1629 
     | 
    
         
            +
                        end
         
     | 
| 
      
 1630 
     | 
    
         
            +
                      end
         
     | 
| 
       1355 
1631 
     | 
    
         | 
| 
       1356 
     | 
    
         
            -
             
     | 
| 
       1357 
     | 
    
         
            -
                       
     | 
| 
      
 1632 
     | 
    
         
            +
                      execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
         
     | 
| 
      
 1633 
     | 
    
         
            +
                      non_combinable_operations.each(&:call)
         
     | 
| 
       1358 
1634 
     | 
    
         
             
                    end
         
     | 
| 
       1359 
1635 
     | 
    
         | 
| 
       1360 
     | 
    
         
            -
                    def add_column_for_alter(table_name, column_name, type, options 
     | 
| 
      
 1636 
     | 
    
         
            +
                    def add_column_for_alter(table_name, column_name, type, **options)
         
     | 
| 
       1361 
1637 
     | 
    
         
             
                      td = create_table_definition(table_name)
         
     | 
| 
       1362 
     | 
    
         
            -
                      cd = td.new_column_definition(column_name, type, options)
         
     | 
| 
      
 1638 
     | 
    
         
            +
                      cd = td.new_column_definition(column_name, type, **options)
         
     | 
| 
       1363 
1639 
     | 
    
         
             
                      schema_creation.accept(AddColumnDefinition.new(cd))
         
     | 
| 
       1364 
1640 
     | 
    
         
             
                    end
         
     | 
| 
       1365 
1641 
     | 
    
         | 
| 
       1366 
     | 
    
         
            -
                    def  
     | 
| 
      
 1642 
     | 
    
         
            +
                    def rename_column_sql(table_name, column_name, new_column_name)
         
     | 
| 
      
 1643 
     | 
    
         
            +
                      "RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
         
     | 
| 
      
 1644 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1645 
     | 
    
         
            +
             
     | 
| 
      
 1646 
     | 
    
         
            +
                    def remove_column_for_alter(table_name, column_name, type = nil, **options)
         
     | 
| 
       1367 
1647 
     | 
    
         
             
                      "DROP COLUMN #{quote_column_name(column_name)}"
         
     | 
| 
       1368 
1648 
     | 
    
         
             
                    end
         
     | 
| 
       1369 
1649 
     | 
    
         | 
| 
       1370 
     | 
    
         
            -
                    def remove_columns_for_alter(table_name, *column_names)
         
     | 
| 
      
 1650 
     | 
    
         
            +
                    def remove_columns_for_alter(table_name, *column_names, **options)
         
     | 
| 
       1371 
1651 
     | 
    
         
             
                      column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
         
     | 
| 
       1372 
1652 
     | 
    
         
             
                    end
         
     | 
| 
       1373 
1653 
     | 
    
         | 
| 
      
 1654 
     | 
    
         
            +
                    def add_timestamps_for_alter(table_name, **options)
         
     | 
| 
      
 1655 
     | 
    
         
            +
                      options[:null] = false if options[:null].nil?
         
     | 
| 
      
 1656 
     | 
    
         
            +
             
     | 
| 
      
 1657 
     | 
    
         
            +
                      if !options.key?(:precision) && supports_datetime_with_precision?
         
     | 
| 
      
 1658 
     | 
    
         
            +
                        options[:precision] = 6
         
     | 
| 
      
 1659 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1660 
     | 
    
         
            +
             
     | 
| 
      
 1661 
     | 
    
         
            +
                      [
         
     | 
| 
      
 1662 
     | 
    
         
            +
                        add_column_for_alter(table_name, :created_at, :datetime, **options),
         
     | 
| 
      
 1663 
     | 
    
         
            +
                        add_column_for_alter(table_name, :updated_at, :datetime, **options)
         
     | 
| 
      
 1664 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 1665 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1666 
     | 
    
         
            +
             
     | 
| 
      
 1667 
     | 
    
         
            +
                    def remove_timestamps_for_alter(table_name, **options)
         
     | 
| 
      
 1668 
     | 
    
         
            +
                      remove_columns_for_alter(table_name, :updated_at, :created_at)
         
     | 
| 
      
 1669 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1670 
     | 
    
         
            +
             
     | 
| 
       1374 
1671 
     | 
    
         
             
                    def insert_versions_sql(versions)
         
     | 
| 
       1375 
     | 
    
         
            -
                      sm_table = quote_table_name( 
     | 
| 
      
 1672 
     | 
    
         
            +
                      sm_table = quote_table_name(schema_migration.table_name)
         
     | 
| 
       1376 
1673 
     | 
    
         | 
| 
       1377 
1674 
     | 
    
         
             
                      if versions.is_a?(Array)
         
     | 
| 
       1378 
     | 
    
         
            -
                        sql = "INSERT INTO #{sm_table} (version) VALUES\n" 
     | 
| 
      
 1675 
     | 
    
         
            +
                        sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
         
     | 
| 
       1379 
1676 
     | 
    
         
             
                        sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
         
     | 
| 
       1380 
1677 
     | 
    
         
             
                        sql << ";\n\n"
         
     | 
| 
       1381 
1678 
     | 
    
         
             
                        sql
         
     |