activerecord 6.0.0 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +996 -594
- data/MIT-LICENSE +1 -1
- data/README.rdoc +34 -34
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +22 -20
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +41 -30
- data/lib/active_record/associations/association.rb +106 -41
- data/lib/active_record/associations/association_scope.rb +30 -21
- data/lib/active_record/associations/belongs_to_association.rb +69 -14
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
- data/lib/active_record/associations/builder/association.rb +39 -6
- data/lib/active_record/associations/builder/belongs_to.rb +47 -17
- data/lib/active_record/associations/builder/collection_association.rb +14 -6
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
- data/lib/active_record/associations/builder/has_many.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +13 -16
- data/lib/active_record/associations/builder/singular_association.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +90 -53
- data/lib/active_record/associations/collection_proxy.rb +54 -19
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +21 -1
- data/lib/active_record/associations/has_many_association.rb +41 -10
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +33 -9
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +97 -54
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +237 -54
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +51 -17
- data/lib/active_record/associations/preloader.rb +55 -121
- data/lib/active_record/associations/singular_association.rb +16 -4
- data/lib/active_record/associations/through_association.rb +26 -15
- data/lib/active_record/associations.rb +454 -440
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +11 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +75 -34
- data/lib/active_record/attribute_methods/primary_key.rb +53 -31
- data/lib/active_record/attribute_methods/query.rb +31 -22
- data/lib/active_record/attribute_methods/read.rb +16 -17
- data/lib/active_record/attribute_methods/serialization.rb +177 -35
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
- data/lib/active_record/attribute_methods/write.rb +16 -28
- data/lib/active_record/attribute_methods.rb +227 -100
- data/lib/active_record/attributes.rb +94 -56
- data/lib/active_record/autosave_association.rb +119 -73
- data/lib/active_record/base.rb +31 -21
- data/lib/active_record/callbacks.rb +168 -55
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -25
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
- data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
- data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
- data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
- data/lib/active_record/connection_adapters/column.rb +28 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
- data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +243 -115
- data/lib/active_record/core.rb +481 -199
- data/lib/active_record/counter_cache.rb +69 -32
- data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
- data/lib/active_record/database_configurations/database_config.rb +77 -10
- data/lib/active_record/database_configurations/hash_config.rb +148 -26
- data/lib/active_record/database_configurations/url_config.rb +44 -45
- data/lib/active_record/database_configurations.rb +190 -114
- data/lib/active_record/delegated_type.rb +279 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +5 -6
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +171 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +224 -73
- data/lib/active_record/errors.rb +254 -36
- data/lib/active_record/explain.rb +30 -17
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +15 -6
- data/lib/active_record/fixture_set/render_context.rb +3 -1
- data/lib/active_record/fixture_set/table_row.rb +88 -16
- data/lib/active_record/fixture_set/table_rows.rb +4 -5
- data/lib/active_record/fixtures.rb +229 -116
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +121 -48
- data/lib/active_record/insert_all.rb +178 -29
- data/lib/active_record/integration.rb +16 -14
- data/lib/active_record/internal_metadata.rb +132 -21
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +64 -33
- data/lib/active_record/locking/pessimistic.rb +21 -8
- data/lib/active_record/log_subscriber.rb +61 -30
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
- data/lib/active_record/middleware/database_selector.rb +25 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +160 -55
- data/lib/active_record/migration/compatibility.rb +286 -43
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +421 -193
- data/lib/active_record/model_schema.rb +217 -125
- data/lib/active_record/nested_attributes.rb +62 -27
- data/lib/active_record/no_touching.rb +4 -4
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +322 -319
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -15
- data/lib/active_record/query_logs.rb +193 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +54 -14
- data/lib/active_record/railtie.rb +250 -72
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +312 -197
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +45 -3
- data/lib/active_record/reflection.rb +389 -146
- data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
- data/lib/active_record/relation/batches.rb +214 -73
- data/lib/active_record/relation/calculations.rb +379 -124
- data/lib/active_record/relation/delegation.rb +36 -23
- data/lib/active_record/relation/finder_methods.rb +159 -49
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +41 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +79 -53
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +1156 -279
- data/lib/active_record/relation/record_fetch_warning.rb +12 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -9
- data/lib/active_record/relation/where_clause.rb +100 -66
- data/lib/active_record/relation.rb +829 -194
- data/lib/active_record/result.rb +76 -56
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +86 -47
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +140 -33
- data/lib/active_record/schema_migration.rb +74 -29
- data/lib/active_record/scoping/default.rb +73 -19
- data/lib/active_record/scoping/named.rb +10 -28
- data/lib/active_record/scoping.rb +65 -35
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +34 -8
- data/lib/active_record/serialization.rb +11 -4
- data/lib/active_record/signed_id.rb +138 -0
- data/lib/active_record/statement_cache.rb +26 -10
- data/lib/active_record/store.rb +19 -14
- data/lib/active_record/suppressor.rb +15 -17
- data/lib/active_record/table_metadata.rb +46 -36
- data/lib/active_record/tasks/database_tasks.rb +371 -205
- data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +189 -104
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +35 -25
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +31 -27
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +131 -99
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +33 -18
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +11 -6
- data/lib/active_record/type/time.rb +14 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +7 -2
- data/lib/active_record/type_caster/connection.rb +4 -5
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -8
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +88 -18
- data/lib/active_record/validations.rb +15 -8
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +446 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +4 -8
- data/lib/arel/collectors/bind.rb +8 -1
- data/lib/arel/collectors/composite.rb +15 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/crud.rb +30 -22
- data/lib/arel/delete_manager.rb +23 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +82 -9
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +22 -10
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +14 -13
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +122 -11
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/table_alias.rb +11 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes/update_statement.rb +11 -4
- data/lib/arel/nodes.rb +10 -3
- data/lib/arel/predications.rb +31 -28
- data/lib/arel/select_manager.rb +18 -9
- data/lib/arel/table.rb +21 -10
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +25 -5
- data/lib/arel/visitors/dot.rb +94 -90
- data/lib/arel/visitors/mysql.rb +34 -6
- data/lib/arel/visitors/postgresql.rb +5 -16
- data/lib/arel/visitors/sqlite.rb +25 -1
- data/lib/arel/visitors/to_sql.rb +227 -81
- data/lib/arel/visitors/visitor.rb +2 -3
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +37 -15
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +117 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/null_relation.rb +0 -68
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
module ActiveRecord
|
|
4
|
-
module ConnectionAdapters
|
|
5
|
+
module ConnectionAdapters # :nodoc:
|
|
5
6
|
# Abstract representation of an index definition on a table. Instances of
|
|
6
7
|
# this type are typically created and returned by methods in database
|
|
7
8
|
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
|
8
9
|
class IndexDefinition # :nodoc:
|
|
9
|
-
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
|
|
10
|
+
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :include, :nulls_not_distinct, :comment, :valid
|
|
10
11
|
|
|
11
12
|
def initialize(
|
|
12
13
|
table, name,
|
|
@@ -18,7 +19,10 @@ module ActiveRecord
|
|
|
18
19
|
where: nil,
|
|
19
20
|
type: nil,
|
|
20
21
|
using: nil,
|
|
21
|
-
|
|
22
|
+
include: nil,
|
|
23
|
+
nulls_not_distinct: nil,
|
|
24
|
+
comment: nil,
|
|
25
|
+
valid: true
|
|
22
26
|
)
|
|
23
27
|
@table = table
|
|
24
28
|
@name = name
|
|
@@ -30,7 +34,32 @@ module ActiveRecord
|
|
|
30
34
|
@where = where
|
|
31
35
|
@type = type
|
|
32
36
|
@using = using
|
|
37
|
+
@include = include
|
|
38
|
+
@nulls_not_distinct = nulls_not_distinct
|
|
33
39
|
@comment = comment
|
|
40
|
+
@valid = valid
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def valid?
|
|
44
|
+
@valid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def column_options
|
|
48
|
+
{
|
|
49
|
+
length: lengths,
|
|
50
|
+
order: orders,
|
|
51
|
+
opclass: opclasses,
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def defined_for?(columns = nil, name: nil, unique: nil, valid: nil, include: nil, nulls_not_distinct: nil, **options)
|
|
56
|
+
columns = options[:column] if columns.blank?
|
|
57
|
+
(columns.nil? || Array(self.columns) == Array(columns).map(&:to_s)) &&
|
|
58
|
+
(name.nil? || self.name == name.to_s) &&
|
|
59
|
+
(unique.nil? || self.unique == unique) &&
|
|
60
|
+
(valid.nil? || self.valid == valid) &&
|
|
61
|
+
(include.nil? || Array(self.include) == Array(include).map(&:to_s)) &&
|
|
62
|
+
(nulls_not_distinct.nil? || self.nulls_not_distinct == nulls_not_distinct)
|
|
34
63
|
end
|
|
35
64
|
|
|
36
65
|
private
|
|
@@ -48,11 +77,24 @@ module ActiveRecord
|
|
|
48
77
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
|
49
78
|
# for generating a number of table creation or table changing SQL statements.
|
|
50
79
|
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
|
80
|
+
self::OPTION_NAMES = [
|
|
81
|
+
:limit,
|
|
82
|
+
:precision,
|
|
83
|
+
:scale,
|
|
84
|
+
:default,
|
|
85
|
+
:null,
|
|
86
|
+
:collation,
|
|
87
|
+
:comment,
|
|
88
|
+
:primary_key,
|
|
89
|
+
:if_exists,
|
|
90
|
+
:if_not_exists
|
|
91
|
+
]
|
|
92
|
+
|
|
51
93
|
def primary_key?
|
|
52
94
|
options[:primary_key]
|
|
53
95
|
end
|
|
54
96
|
|
|
55
|
-
|
|
97
|
+
(self::OPTION_NAMES - [:primary_key]).each do |option_name|
|
|
56
98
|
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
|
57
99
|
def #{option_name}
|
|
58
100
|
options[:#{option_name}]
|
|
@@ -63,15 +105,23 @@ module ActiveRecord
|
|
|
63
105
|
end
|
|
64
106
|
CODE
|
|
65
107
|
end
|
|
108
|
+
|
|
109
|
+
def aliased_types(name, fallback)
|
|
110
|
+
"timestamp" == name ? :datetime : fallback
|
|
111
|
+
end
|
|
66
112
|
end
|
|
67
113
|
|
|
68
114
|
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
|
69
115
|
|
|
70
|
-
ChangeColumnDefinition = Struct.new(:column, :name)
|
|
116
|
+
ChangeColumnDefinition = Struct.new(:column, :name) # :nodoc:
|
|
117
|
+
|
|
118
|
+
ChangeColumnDefaultDefinition = Struct.new(:column, :default) # :nodoc:
|
|
119
|
+
|
|
120
|
+
CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
|
|
71
121
|
|
|
72
122
|
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
|
73
123
|
|
|
74
|
-
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do
|
|
124
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do # :nodoc:
|
|
75
125
|
def name
|
|
76
126
|
options[:name]
|
|
77
127
|
end
|
|
@@ -92,6 +142,10 @@ module ActiveRecord
|
|
|
92
142
|
options[:on_update]
|
|
93
143
|
end
|
|
94
144
|
|
|
145
|
+
def deferrable
|
|
146
|
+
options[:deferrable]
|
|
147
|
+
end
|
|
148
|
+
|
|
95
149
|
def custom_primary_key?
|
|
96
150
|
options[:primary_key] != default_primary_key
|
|
97
151
|
end
|
|
@@ -105,9 +159,12 @@ module ActiveRecord
|
|
|
105
159
|
!ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
|
|
106
160
|
end
|
|
107
161
|
|
|
108
|
-
def defined_for?(to_table: nil, **options)
|
|
162
|
+
def defined_for?(to_table: nil, validate: nil, **options)
|
|
163
|
+
options = options.slice(*self.options.keys)
|
|
164
|
+
|
|
109
165
|
(to_table.nil? || to_table.to_s == self.to_table) &&
|
|
110
|
-
|
|
166
|
+
(validate.nil? || validate == self.options.fetch(:validate, validate)) &&
|
|
167
|
+
options.all? { |k, v| Array(self.options[k]).map(&:to_s) == Array(v).map(&:to_s) }
|
|
111
168
|
end
|
|
112
169
|
|
|
113
170
|
private
|
|
@@ -116,6 +173,29 @@ module ActiveRecord
|
|
|
116
173
|
end
|
|
117
174
|
end
|
|
118
175
|
|
|
176
|
+
CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
|
|
177
|
+
def name
|
|
178
|
+
options[:name]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def validate?
|
|
182
|
+
options.fetch(:validate, true)
|
|
183
|
+
end
|
|
184
|
+
alias validated? validate?
|
|
185
|
+
|
|
186
|
+
def export_name_on_schema_dump?
|
|
187
|
+
!ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def defined_for?(name:, expression: nil, validate: nil, **options)
|
|
191
|
+
options = options.slice(*self.options.keys)
|
|
192
|
+
|
|
193
|
+
self.name == name.to_s &&
|
|
194
|
+
(validate.nil? || validate == self.options.fetch(:validate, validate)) &&
|
|
195
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
119
199
|
class ReferenceDefinition # :nodoc:
|
|
120
200
|
def initialize(
|
|
121
201
|
name,
|
|
@@ -137,17 +217,31 @@ module ActiveRecord
|
|
|
137
217
|
end
|
|
138
218
|
end
|
|
139
219
|
|
|
220
|
+
def add(table_name, connection)
|
|
221
|
+
columns.each do |name, type, options|
|
|
222
|
+
connection.add_column(table_name, name, type, **options)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
if index
|
|
226
|
+
connection.add_index(table_name, column_names, **index_options(table_name))
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
if foreign_key
|
|
230
|
+
connection.add_foreign_key(table_name, foreign_table_name, **foreign_key_options)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
140
234
|
def add_to(table)
|
|
141
|
-
columns.each do |
|
|
142
|
-
table.column(
|
|
235
|
+
columns.each do |name, type, options|
|
|
236
|
+
table.column(name, type, **options)
|
|
143
237
|
end
|
|
144
238
|
|
|
145
239
|
if index
|
|
146
|
-
table.index(column_names, index_options)
|
|
240
|
+
table.index(column_names, **index_options(table.name))
|
|
147
241
|
end
|
|
148
242
|
|
|
149
243
|
if foreign_key
|
|
150
|
-
table.foreign_key(foreign_table_name, foreign_key_options)
|
|
244
|
+
table.foreign_key(foreign_table_name, **foreign_key_options)
|
|
151
245
|
end
|
|
152
246
|
end
|
|
153
247
|
|
|
@@ -158,16 +252,30 @@ module ActiveRecord
|
|
|
158
252
|
value.is_a?(Hash) ? value : {}
|
|
159
253
|
end
|
|
160
254
|
|
|
255
|
+
def conditional_options
|
|
256
|
+
options.slice(:if_exists, :if_not_exists)
|
|
257
|
+
end
|
|
258
|
+
|
|
161
259
|
def polymorphic_options
|
|
162
|
-
as_options(polymorphic).merge(options.slice(:null, :first, :after))
|
|
260
|
+
as_options(polymorphic).merge(conditional_options).merge(options.slice(:null, :first, :after))
|
|
163
261
|
end
|
|
164
262
|
|
|
165
|
-
def
|
|
166
|
-
|
|
263
|
+
def polymorphic_index_name(table_name)
|
|
264
|
+
"index_#{table_name}_on_#{name}"
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def index_options(table_name)
|
|
268
|
+
index_options = as_options(index).merge(conditional_options)
|
|
269
|
+
|
|
270
|
+
# legacy reference index names are used on versions 6.0 and earlier
|
|
271
|
+
return index_options if options[:_uses_legacy_reference_index_name]
|
|
272
|
+
|
|
273
|
+
index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
|
|
274
|
+
index_options
|
|
167
275
|
end
|
|
168
276
|
|
|
169
277
|
def foreign_key_options
|
|
170
|
-
as_options(foreign_key).merge(column: column_name)
|
|
278
|
+
as_options(foreign_key).merge(column: column_name, **conditional_options)
|
|
171
279
|
end
|
|
172
280
|
|
|
173
281
|
def columns
|
|
@@ -199,7 +307,7 @@ module ActiveRecord
|
|
|
199
307
|
# Appends a primary key definition to the table definition.
|
|
200
308
|
# Can be called multiple times, but this is probably not a good idea.
|
|
201
309
|
def primary_key(name, type = :primary_key, **options)
|
|
202
|
-
column(name, type, options.merge(primary_key: true))
|
|
310
|
+
column(name, type, **options.merge(primary_key: true))
|
|
203
311
|
end
|
|
204
312
|
|
|
205
313
|
##
|
|
@@ -217,30 +325,34 @@ module ActiveRecord
|
|
|
217
325
|
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
|
218
326
|
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
|
219
327
|
|
|
328
|
+
alias :blob :binary
|
|
220
329
|
alias :numeric :decimal
|
|
221
330
|
end
|
|
222
331
|
|
|
223
332
|
class_methods do
|
|
224
|
-
|
|
333
|
+
def define_column_methods(*column_types) # :nodoc:
|
|
225
334
|
column_types.each do |column_type|
|
|
226
335
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
227
336
|
def #{column_type}(*names, **options)
|
|
228
337
|
raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
|
|
229
|
-
names.each { |name| column(name, :#{column_type}, options) }
|
|
338
|
+
names.each { |name| column(name, :#{column_type}, **options) }
|
|
230
339
|
end
|
|
231
340
|
RUBY
|
|
232
341
|
end
|
|
233
342
|
end
|
|
343
|
+
private :define_column_methods
|
|
234
344
|
end
|
|
235
345
|
end
|
|
236
346
|
|
|
347
|
+
# = Active Record Connection Adapters \Table \Definition
|
|
348
|
+
#
|
|
237
349
|
# Represents the schema of an SQL table in an abstract way. This class
|
|
238
350
|
# provides methods for manipulating the schema representation.
|
|
239
351
|
#
|
|
240
352
|
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
|
241
353
|
# is actually of this type:
|
|
242
354
|
#
|
|
243
|
-
# class SomeMigration < ActiveRecord::Migration[
|
|
355
|
+
# class SomeMigration < ActiveRecord::Migration[7.2]
|
|
244
356
|
# def up
|
|
245
357
|
# create_table :foo do |t|
|
|
246
358
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
|
@@ -255,7 +367,7 @@ module ActiveRecord
|
|
|
255
367
|
class TableDefinition
|
|
256
368
|
include ColumnMethods
|
|
257
369
|
|
|
258
|
-
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
|
|
370
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
|
|
259
371
|
|
|
260
372
|
def initialize(
|
|
261
373
|
conn,
|
|
@@ -272,6 +384,7 @@ module ActiveRecord
|
|
|
272
384
|
@indexes = []
|
|
273
385
|
@foreign_keys = []
|
|
274
386
|
@primary_keys = nil
|
|
387
|
+
@check_constraints = []
|
|
275
388
|
@temporary = temporary
|
|
276
389
|
@if_not_exists = if_not_exists
|
|
277
390
|
@options = options
|
|
@@ -280,6 +393,23 @@ module ActiveRecord
|
|
|
280
393
|
@comment = comment
|
|
281
394
|
end
|
|
282
395
|
|
|
396
|
+
def set_primary_key(table_name, id, primary_key, **options)
|
|
397
|
+
if id && !as
|
|
398
|
+
pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
|
|
399
|
+
|
|
400
|
+
if id.is_a?(Hash)
|
|
401
|
+
options.merge!(id.except(:type))
|
|
402
|
+
id = id.fetch(:type, :primary_key)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
if pk.is_a?(Array)
|
|
406
|
+
primary_keys(pk)
|
|
407
|
+
else
|
|
408
|
+
primary_key(pk, id, **options)
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
283
413
|
def primary_keys(name = nil) # :nodoc:
|
|
284
414
|
@primary_keys = PrimaryKeyDefinition.new(name) if name
|
|
285
415
|
@primary_keys
|
|
@@ -305,7 +435,7 @@ module ActiveRecord
|
|
|
305
435
|
#
|
|
306
436
|
# == Examples
|
|
307
437
|
#
|
|
308
|
-
# # Assuming
|
|
438
|
+
# # Assuming `td` is an instance of TableDefinition
|
|
309
439
|
# td.column(:granted, :boolean, index: true)
|
|
310
440
|
#
|
|
311
441
|
# == Short-hand examples
|
|
@@ -360,22 +490,18 @@ module ActiveRecord
|
|
|
360
490
|
# t.references :tagger, polymorphic: true
|
|
361
491
|
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
|
362
492
|
# end
|
|
363
|
-
def column(name, type, **options)
|
|
493
|
+
def column(name, type, index: nil, **options)
|
|
364
494
|
name = name.to_s
|
|
365
495
|
type = type.to_sym if type
|
|
366
|
-
options = options.dup
|
|
367
496
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
497
|
+
raise_on_duplicate_column(name)
|
|
498
|
+
@columns_hash[name] = new_column_definition(name, type, **options)
|
|
499
|
+
|
|
500
|
+
if index
|
|
501
|
+
index_options = index.is_a?(Hash) ? index : {}
|
|
502
|
+
index(name, **index_options)
|
|
374
503
|
end
|
|
375
504
|
|
|
376
|
-
index_options = options.delete(:index)
|
|
377
|
-
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
|
378
|
-
@columns_hash[name] = new_column_definition(name, type, options)
|
|
379
505
|
self
|
|
380
506
|
end
|
|
381
507
|
|
|
@@ -389,12 +515,16 @@ module ActiveRecord
|
|
|
389
515
|
# This is primarily used to track indexes that need to be created after the table
|
|
390
516
|
#
|
|
391
517
|
# index(:account_id, name: 'index_projects_on_account_id')
|
|
392
|
-
def index(column_name, options
|
|
518
|
+
def index(column_name, **options)
|
|
393
519
|
indexes << [column_name, options]
|
|
394
520
|
end
|
|
395
521
|
|
|
396
|
-
def foreign_key(
|
|
397
|
-
foreign_keys <<
|
|
522
|
+
def foreign_key(to_table, **options)
|
|
523
|
+
foreign_keys << new_foreign_key_definition(to_table, options)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def check_constraint(expression, **options)
|
|
527
|
+
check_constraints << new_check_constraint_definition(expression, options)
|
|
398
528
|
end
|
|
399
529
|
|
|
400
530
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
|
@@ -408,8 +538,8 @@ module ActiveRecord
|
|
|
408
538
|
options[:precision] = 6
|
|
409
539
|
end
|
|
410
540
|
|
|
411
|
-
column(:created_at, :datetime, options)
|
|
412
|
-
column(:updated_at, :datetime, options)
|
|
541
|
+
column(:created_at, :datetime, **options)
|
|
542
|
+
column(:updated_at, :datetime, **options)
|
|
413
543
|
end
|
|
414
544
|
|
|
415
545
|
# Adds a reference.
|
|
@@ -421,7 +551,7 @@ module ActiveRecord
|
|
|
421
551
|
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
|
422
552
|
def references(*args, **options)
|
|
423
553
|
args.each do |ref_name|
|
|
424
|
-
ReferenceDefinition.new(ref_name, options).add_to(self)
|
|
554
|
+
ReferenceDefinition.new(ref_name, **options).add_to(self)
|
|
425
555
|
end
|
|
426
556
|
end
|
|
427
557
|
alias :belongs_to :references
|
|
@@ -431,13 +561,41 @@ module ActiveRecord
|
|
|
431
561
|
type = integer_like_primary_key_type(type, options)
|
|
432
562
|
end
|
|
433
563
|
type = aliased_types(type.to_s, type)
|
|
564
|
+
|
|
565
|
+
if @conn.supports_datetime_with_precision?
|
|
566
|
+
if type == :datetime && !options.key?(:precision)
|
|
567
|
+
options[:precision] = 6
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
434
571
|
options[:primary_key] ||= type == :primary_key
|
|
435
572
|
options[:null] = false if options[:primary_key]
|
|
436
573
|
create_column_definition(name, type, options)
|
|
437
574
|
end
|
|
438
575
|
|
|
576
|
+
def new_foreign_key_definition(to_table, options) # :nodoc:
|
|
577
|
+
prefix = ActiveRecord::Base.table_name_prefix
|
|
578
|
+
suffix = ActiveRecord::Base.table_name_suffix
|
|
579
|
+
to_table = "#{prefix}#{to_table}#{suffix}"
|
|
580
|
+
options = @conn.foreign_key_options(name, to_table, options)
|
|
581
|
+
ForeignKeyDefinition.new(name, to_table, options)
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def new_check_constraint_definition(expression, options) # :nodoc:
|
|
585
|
+
options = @conn.check_constraint_options(name, expression, options)
|
|
586
|
+
CheckConstraintDefinition.new(name, expression, options)
|
|
587
|
+
end
|
|
588
|
+
|
|
439
589
|
private
|
|
590
|
+
def valid_column_definition_options
|
|
591
|
+
@conn.valid_column_definition_options
|
|
592
|
+
end
|
|
593
|
+
|
|
440
594
|
def create_column_definition(name, type, options)
|
|
595
|
+
unless options[:_skip_validate_options]
|
|
596
|
+
options.except(:_uses_legacy_reference_index_name, :_skip_validate_options).assert_valid_keys(valid_column_definition_options)
|
|
597
|
+
end
|
|
598
|
+
|
|
441
599
|
ColumnDefinition.new(name, type, options)
|
|
442
600
|
end
|
|
443
601
|
|
|
@@ -452,37 +610,59 @@ module ActiveRecord
|
|
|
452
610
|
def integer_like_primary_key_type(type, options)
|
|
453
611
|
type
|
|
454
612
|
end
|
|
613
|
+
|
|
614
|
+
def raise_on_duplicate_column(name)
|
|
615
|
+
if @columns_hash[name]
|
|
616
|
+
if @columns_hash[name].primary_key?
|
|
617
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}' on '#{@name}'. To define a custom primary key, pass { id: false } to create_table."
|
|
618
|
+
else
|
|
619
|
+
raise ArgumentError, "you can't define an already defined column '#{name}' on '#{@name}'."
|
|
620
|
+
end
|
|
621
|
+
end
|
|
622
|
+
end
|
|
455
623
|
end
|
|
456
624
|
|
|
457
625
|
class AlterTable # :nodoc:
|
|
458
626
|
attr_reader :adds
|
|
459
|
-
attr_reader :foreign_key_adds
|
|
460
|
-
attr_reader :
|
|
627
|
+
attr_reader :foreign_key_adds, :foreign_key_drops
|
|
628
|
+
attr_reader :check_constraint_adds, :check_constraint_drops
|
|
461
629
|
|
|
462
630
|
def initialize(td)
|
|
463
631
|
@td = td
|
|
464
632
|
@adds = []
|
|
465
633
|
@foreign_key_adds = []
|
|
466
634
|
@foreign_key_drops = []
|
|
635
|
+
@check_constraint_adds = []
|
|
636
|
+
@check_constraint_drops = []
|
|
467
637
|
end
|
|
468
638
|
|
|
469
639
|
def name; @td.name; end
|
|
470
640
|
|
|
471
641
|
def add_foreign_key(to_table, options)
|
|
472
|
-
@foreign_key_adds <<
|
|
642
|
+
@foreign_key_adds << @td.new_foreign_key_definition(to_table, options)
|
|
473
643
|
end
|
|
474
644
|
|
|
475
645
|
def drop_foreign_key(name)
|
|
476
646
|
@foreign_key_drops << name
|
|
477
647
|
end
|
|
478
648
|
|
|
479
|
-
def
|
|
649
|
+
def add_check_constraint(expression, options)
|
|
650
|
+
@check_constraint_adds << @td.new_check_constraint_definition(expression, options)
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
def drop_check_constraint(constraint_name)
|
|
654
|
+
@check_constraint_drops << constraint_name
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
def add_column(name, type, **options)
|
|
480
658
|
name = name.to_s
|
|
481
659
|
type = type.to_sym
|
|
482
|
-
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
|
|
660
|
+
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
|
|
483
661
|
end
|
|
484
662
|
end
|
|
485
663
|
|
|
664
|
+
# = Active Record Connection Adapters \Table
|
|
665
|
+
#
|
|
486
666
|
# Represents an SQL table in an abstract way for updating a table.
|
|
487
667
|
# Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
|
|
488
668
|
#
|
|
@@ -496,9 +676,11 @@ module ActiveRecord
|
|
|
496
676
|
# t.timestamps
|
|
497
677
|
# t.change
|
|
498
678
|
# t.change_default
|
|
679
|
+
# t.change_null
|
|
499
680
|
# t.rename
|
|
500
681
|
# t.references
|
|
501
682
|
# t.belongs_to
|
|
683
|
+
# t.check_constraint
|
|
502
684
|
# t.string
|
|
503
685
|
# t.text
|
|
504
686
|
# t.integer
|
|
@@ -511,6 +693,7 @@ module ActiveRecord
|
|
|
511
693
|
# t.time
|
|
512
694
|
# t.date
|
|
513
695
|
# t.binary
|
|
696
|
+
# t.blob
|
|
514
697
|
# t.boolean
|
|
515
698
|
# t.foreign_key
|
|
516
699
|
# t.json
|
|
@@ -520,6 +703,7 @@ module ActiveRecord
|
|
|
520
703
|
# t.remove_references
|
|
521
704
|
# t.remove_belongs_to
|
|
522
705
|
# t.remove_index
|
|
706
|
+
# t.remove_check_constraint
|
|
523
707
|
# t.remove_timestamps
|
|
524
708
|
# end
|
|
525
709
|
#
|
|
@@ -538,10 +722,13 @@ module ActiveRecord
|
|
|
538
722
|
# t.column(:name, :string)
|
|
539
723
|
#
|
|
540
724
|
# See TableDefinition#column for details of the options you can use.
|
|
541
|
-
def column(column_name, type, **options)
|
|
542
|
-
|
|
543
|
-
@base.add_column(name, column_name, type, options)
|
|
544
|
-
|
|
725
|
+
def column(column_name, type, index: nil, **options)
|
|
726
|
+
raise_on_if_exist_options(options)
|
|
727
|
+
@base.add_column(name, column_name, type, **options)
|
|
728
|
+
if index
|
|
729
|
+
index_options = index.is_a?(Hash) ? index : {}
|
|
730
|
+
index(column_name, **index_options)
|
|
731
|
+
end
|
|
545
732
|
end
|
|
546
733
|
|
|
547
734
|
# Checks to see if a column exists.
|
|
@@ -549,8 +736,8 @@ module ActiveRecord
|
|
|
549
736
|
# t.string(:name) unless t.column_exists?(:name, :string)
|
|
550
737
|
#
|
|
551
738
|
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
|
|
552
|
-
def column_exists?(column_name, type = nil, options
|
|
553
|
-
@base.column_exists?(name, column_name, type, options)
|
|
739
|
+
def column_exists?(column_name, type = nil, **options)
|
|
740
|
+
@base.column_exists?(name, column_name, type, **options)
|
|
554
741
|
end
|
|
555
742
|
|
|
556
743
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
|
@@ -561,8 +748,9 @@ module ActiveRecord
|
|
|
561
748
|
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
|
562
749
|
#
|
|
563
750
|
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
|
|
564
|
-
def index(column_name, options
|
|
565
|
-
|
|
751
|
+
def index(column_name, **options)
|
|
752
|
+
raise_on_if_exist_options(options)
|
|
753
|
+
@base.add_index(name, column_name, **options)
|
|
566
754
|
end
|
|
567
755
|
|
|
568
756
|
# Checks to see if an index exists.
|
|
@@ -572,8 +760,8 @@ module ActiveRecord
|
|
|
572
760
|
# end
|
|
573
761
|
#
|
|
574
762
|
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
|
575
|
-
def index_exists?(column_name, options
|
|
576
|
-
@base.index_exists?(name, column_name, options)
|
|
763
|
+
def index_exists?(column_name, **options)
|
|
764
|
+
@base.index_exists?(name, column_name, **options)
|
|
577
765
|
end
|
|
578
766
|
|
|
579
767
|
# Renames the given index on the table.
|
|
@@ -590,8 +778,9 @@ module ActiveRecord
|
|
|
590
778
|
# t.timestamps(null: false)
|
|
591
779
|
#
|
|
592
780
|
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
|
593
|
-
def timestamps(options
|
|
594
|
-
|
|
781
|
+
def timestamps(**options)
|
|
782
|
+
raise_on_if_exist_options(options)
|
|
783
|
+
@base.add_timestamps(name, **options)
|
|
595
784
|
end
|
|
596
785
|
|
|
597
786
|
# Changes the column's definition according to the new options.
|
|
@@ -600,8 +789,9 @@ module ActiveRecord
|
|
|
600
789
|
# t.change(:description, :text)
|
|
601
790
|
#
|
|
602
791
|
# See TableDefinition#column for details of the options you can use.
|
|
603
|
-
def change(column_name, type, options
|
|
604
|
-
|
|
792
|
+
def change(column_name, type, **options)
|
|
793
|
+
raise_on_if_exist_options(options)
|
|
794
|
+
@base.change_column(name, column_name, type, **options)
|
|
605
795
|
end
|
|
606
796
|
|
|
607
797
|
# Sets a new default value for a column.
|
|
@@ -615,14 +805,25 @@ module ActiveRecord
|
|
|
615
805
|
@base.change_column_default(name, column_name, default_or_changes)
|
|
616
806
|
end
|
|
617
807
|
|
|
808
|
+
# Sets or removes a NOT NULL constraint on a column.
|
|
809
|
+
#
|
|
810
|
+
# t.change_null(:qualification, true)
|
|
811
|
+
# t.change_null(:qualification, false, 0)
|
|
812
|
+
#
|
|
813
|
+
# See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
|
|
814
|
+
def change_null(column_name, null, default = nil)
|
|
815
|
+
@base.change_column_null(name, column_name, null, default)
|
|
816
|
+
end
|
|
817
|
+
|
|
618
818
|
# Removes the column(s) from the table definition.
|
|
619
819
|
#
|
|
620
820
|
# t.remove(:qualification)
|
|
621
821
|
# t.remove(:qualification, :experience)
|
|
622
822
|
#
|
|
623
823
|
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
|
|
624
|
-
def remove(*column_names)
|
|
625
|
-
|
|
824
|
+
def remove(*column_names, **options)
|
|
825
|
+
raise_on_if_exist_options(options)
|
|
826
|
+
@base.remove_columns(name, *column_names, **options)
|
|
626
827
|
end
|
|
627
828
|
|
|
628
829
|
# Removes the given index from the table.
|
|
@@ -630,10 +831,12 @@ module ActiveRecord
|
|
|
630
831
|
# t.remove_index(:branch_id)
|
|
631
832
|
# t.remove_index(column: [:branch_id, :party_id])
|
|
632
833
|
# t.remove_index(name: :by_branch_party)
|
|
834
|
+
# t.remove_index(:branch_id, name: :by_branch_party)
|
|
633
835
|
#
|
|
634
836
|
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
|
|
635
|
-
def remove_index(
|
|
636
|
-
|
|
837
|
+
def remove_index(column_name = nil, **options)
|
|
838
|
+
raise_on_if_exist_options(options)
|
|
839
|
+
@base.remove_index(name, column_name, **options)
|
|
637
840
|
end
|
|
638
841
|
|
|
639
842
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
|
@@ -641,8 +844,8 @@ module ActiveRecord
|
|
|
641
844
|
# t.remove_timestamps
|
|
642
845
|
#
|
|
643
846
|
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
|
|
644
|
-
def remove_timestamps(options
|
|
645
|
-
@base.remove_timestamps(name, options)
|
|
847
|
+
def remove_timestamps(**options)
|
|
848
|
+
@base.remove_timestamps(name, **options)
|
|
646
849
|
end
|
|
647
850
|
|
|
648
851
|
# Renames a column.
|
|
@@ -661,8 +864,9 @@ module ActiveRecord
|
|
|
661
864
|
#
|
|
662
865
|
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
|
663
866
|
def references(*args, **options)
|
|
867
|
+
raise_on_if_exist_options(options)
|
|
664
868
|
args.each do |ref_name|
|
|
665
|
-
@base.add_reference(name, ref_name, options)
|
|
869
|
+
@base.add_reference(name, ref_name, **options)
|
|
666
870
|
end
|
|
667
871
|
end
|
|
668
872
|
alias :belongs_to :references
|
|
@@ -674,8 +878,9 @@ module ActiveRecord
|
|
|
674
878
|
#
|
|
675
879
|
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
|
|
676
880
|
def remove_references(*args, **options)
|
|
881
|
+
raise_on_if_exist_options(options)
|
|
677
882
|
args.each do |ref_name|
|
|
678
|
-
@base.remove_reference(name, ref_name, options)
|
|
883
|
+
@base.remove_reference(name, ref_name, **options)
|
|
679
884
|
end
|
|
680
885
|
end
|
|
681
886
|
alias :remove_belongs_to :remove_references
|
|
@@ -686,8 +891,9 @@ module ActiveRecord
|
|
|
686
891
|
# t.foreign_key(:authors, column: :author_id, primary_key: "id")
|
|
687
892
|
#
|
|
688
893
|
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
|
|
689
|
-
def foreign_key(*args)
|
|
690
|
-
|
|
894
|
+
def foreign_key(*args, **options)
|
|
895
|
+
raise_on_if_exist_options(options)
|
|
896
|
+
@base.add_foreign_key(name, *args, **options)
|
|
691
897
|
end
|
|
692
898
|
|
|
693
899
|
# Removes the given foreign key from the table.
|
|
@@ -696,8 +902,9 @@ module ActiveRecord
|
|
|
696
902
|
# t.remove_foreign_key(column: :author_id)
|
|
697
903
|
#
|
|
698
904
|
# See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
|
|
699
|
-
def remove_foreign_key(*args)
|
|
700
|
-
|
|
905
|
+
def remove_foreign_key(*args, **options)
|
|
906
|
+
raise_on_if_exist_options(options)
|
|
907
|
+
@base.remove_foreign_key(name, *args, **options)
|
|
701
908
|
end
|
|
702
909
|
|
|
703
910
|
# Checks to see if a foreign key exists.
|
|
@@ -705,9 +912,54 @@ module ActiveRecord
|
|
|
705
912
|
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
|
|
706
913
|
#
|
|
707
914
|
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
|
|
708
|
-
def foreign_key_exists?(*args)
|
|
709
|
-
@base.foreign_key_exists?(name, *args)
|
|
915
|
+
def foreign_key_exists?(*args, **options)
|
|
916
|
+
@base.foreign_key_exists?(name, *args, **options)
|
|
710
917
|
end
|
|
918
|
+
|
|
919
|
+
# Adds a check constraint.
|
|
920
|
+
#
|
|
921
|
+
# t.check_constraint("price > 0", name: "price_check")
|
|
922
|
+
#
|
|
923
|
+
# See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
|
|
924
|
+
def check_constraint(*args, **options)
|
|
925
|
+
@base.add_check_constraint(name, *args, **options)
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
# Removes the given check constraint from the table.
|
|
929
|
+
#
|
|
930
|
+
# t.remove_check_constraint(name: "price_check")
|
|
931
|
+
#
|
|
932
|
+
# See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
|
|
933
|
+
def remove_check_constraint(*args, **options)
|
|
934
|
+
@base.remove_check_constraint(name, *args, **options)
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
# Checks if a check_constraint exists on a table.
|
|
938
|
+
#
|
|
939
|
+
# unless t.check_constraint_exists?(name: "price_check")
|
|
940
|
+
# t.check_constraint("price > 0", name: "price_check")
|
|
941
|
+
# end
|
|
942
|
+
#
|
|
943
|
+
# See {connection.check_constraint_exists?}[rdoc-ref:SchemaStatements#check_constraint_exists?]
|
|
944
|
+
def check_constraint_exists?(*args, **options)
|
|
945
|
+
@base.check_constraint_exists?(name, *args, **options)
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
private
|
|
949
|
+
def raise_on_if_exist_options(options)
|
|
950
|
+
unrecognized_option = options.keys.find do |key|
|
|
951
|
+
key == :if_exists || key == :if_not_exists
|
|
952
|
+
end
|
|
953
|
+
if unrecognized_option
|
|
954
|
+
conditional = unrecognized_option == :if_exists ? "if" : "unless"
|
|
955
|
+
message = <<~TXT
|
|
956
|
+
Option #{unrecognized_option} will be ignored. If you are calling an expression like
|
|
957
|
+
`t.column(.., #{unrecognized_option}: true)` from inside a change_table block, try a
|
|
958
|
+
conditional clause instead, as in `t.column(..) #{conditional} t.column_exists?(..)`
|
|
959
|
+
TXT
|
|
960
|
+
raise ArgumentError.new(message)
|
|
961
|
+
end
|
|
962
|
+
end
|
|
711
963
|
end
|
|
712
964
|
end
|
|
713
965
|
end
|