activerecord 5.2.8 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1393 -587
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +10 -9
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +122 -47
- data/lib/active_record/associations/association_scope.rb +24 -24
- data/lib/active_record/associations/belongs_to_association.rb +67 -49
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
- data/lib/active_record/associations/builder/association.rb +52 -23
- data/lib/active_record/associations/builder/belongs_to.rb +44 -61
- data/lib/active_record/associations/builder/collection_association.rb +17 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +10 -3
- data/lib/active_record/associations/builder/has_one.rb +35 -3
- data/lib/active_record/associations/builder/singular_association.rb +5 -3
- data/lib/active_record/associations/collection_association.rb +59 -50
- data/lib/active_record/associations/collection_proxy.rb +32 -23
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +27 -14
- data/lib/active_record/associations/has_many_through_association.rb +26 -19
- data/lib/active_record/associations/has_one_association.rb +52 -37
- data/lib/active_record/associations/has_one_through_association.rb +6 -6
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +97 -62
- data/lib/active_record/associations/preloader/association.rb +220 -60
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +85 -40
- data/lib/active_record/associations/preloader.rb +44 -105
- data/lib/active_record/associations/singular_association.rb +9 -17
- data/lib/active_record/associations/through_association.rb +4 -4
- data/lib/active_record/associations.rb +207 -66
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
- data/lib/active_record/attribute_methods/dirty.rb +141 -47
- data/lib/active_record/attribute_methods/primary_key.rb +22 -27
- data/lib/active_record/attribute_methods/query.rb +6 -10
- data/lib/active_record/attribute_methods/read.rb +15 -55
- data/lib/active_record/attribute_methods/serialization.rb +77 -18
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
- data/lib/active_record/attribute_methods/write.rb +18 -37
- data/lib/active_record/attribute_methods.rb +90 -153
- data/lib/active_record/attributes.rb +38 -12
- data/lib/active_record/autosave_association.rb +50 -50
- data/lib/active_record/base.rb +23 -18
- data/lib/active_record/callbacks.rb +159 -44
- data/lib/active_record/coders/yaml_column.rb +12 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
- data/lib/active_record/connection_adapters/column.rb +33 -11
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
- data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +53 -0
- data/lib/active_record/connection_handling.rb +292 -38
- data/lib/active_record/core.rb +385 -158
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
- data/lib/active_record/database_configurations/database_config.rb +83 -0
- data/lib/active_record/database_configurations/hash_config.rb +154 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +256 -0
- data/lib/active_record/delegated_type.rb +250 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +4 -5
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +130 -51
- data/lib/active_record/errors.rb +129 -23
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +187 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +206 -490
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +104 -37
- data/lib/active_record/insert_all.rb +278 -0
- data/lib/active_record/integration.rb +69 -18
- data/lib/active_record/internal_metadata.rb +24 -9
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +41 -26
- data/lib/active_record/locking/pessimistic.rb +18 -8
- data/lib/active_record/log_subscriber.rb +46 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +82 -0
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +246 -64
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration.rb +266 -187
- data/lib/active_record/model_schema.rb +165 -52
- data/lib/active_record/nested_attributes.rb +17 -19
- data/lib/active_record/no_touching.rb +11 -4
- data/lib/active_record/null_relation.rb +2 -7
- data/lib/active_record/persistence.rb +467 -92
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +51 -24
- data/lib/active_record/railtie.rb +224 -57
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +31 -36
- data/lib/active_record/railties/databases.rake +369 -101
- data/lib/active_record/readonly_attributes.rb +15 -0
- data/lib/active_record/reflection.rb +170 -137
- data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
- data/lib/active_record/relation/batches.rb +46 -37
- data/lib/active_record/relation/calculations.rb +168 -96
- data/lib/active_record/relation/delegation.rb +37 -52
- data/lib/active_record/relation/finder_methods.rb +79 -58
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +50 -51
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -46
- data/lib/active_record/relation/query_attribute.rb +9 -10
- data/lib/active_record/relation/query_methods.rb +685 -208
- data/lib/active_record/relation/record_fetch_warning.rb +9 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -10
- data/lib/active_record/relation/where_clause.rb +108 -64
- data/lib/active_record/relation.rb +515 -151
- data/lib/active_record/result.rb +78 -42
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +29 -44
- data/lib/active_record/schema.rb +37 -31
- data/lib/active_record/schema_dumper.rb +74 -23
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +62 -17
- data/lib/active_record/scoping/named.rb +17 -32
- data/lib/active_record/scoping.rb +70 -41
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +6 -4
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +13 -17
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +352 -94
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +44 -34
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +67 -128
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +34 -19
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +7 -4
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +9 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +2 -3
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +39 -31
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +209 -32
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +71 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +258 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +117 -0
- data/lib/arel/tree_manager.rb +60 -0
- data/lib/arel/update_manager.rb +48 -0
- data/lib/arel/visitors/dot.rb +298 -0
- data/lib/arel/visitors/mysql.rb +99 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +955 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +55 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +162 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
module SchemaStatements
|
7
7
|
# Drops the database specified on the +name+ attribute
|
8
8
|
# and creates it again using the provided +options+.
|
9
|
-
def recreate_database(name, options = {})
|
9
|
+
def recreate_database(name, options = {}) # :nodoc:
|
10
10
|
drop_database(name)
|
11
11
|
create_database(name, options)
|
12
12
|
end
|
@@ -22,8 +22,8 @@ module ActiveRecord
|
|
22
22
|
def create_database(name, options = {})
|
23
23
|
options = { encoding: "utf8" }.merge!(options.symbolize_keys)
|
24
24
|
|
25
|
-
option_string = options.
|
26
|
-
memo
|
25
|
+
option_string = options.each_with_object(+"") do |(key, value), memo|
|
26
|
+
memo << case key
|
27
27
|
when :owner
|
28
28
|
" OWNER = \"#{value}\""
|
29
29
|
when :template
|
@@ -50,11 +50,12 @@ module ActiveRecord
|
|
50
50
|
#
|
51
51
|
# Example:
|
52
52
|
# drop_database 'matt_development'
|
53
|
-
def drop_database(name)
|
53
|
+
def drop_database(name) # :nodoc:
|
54
54
|
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
|
55
55
|
end
|
56
56
|
|
57
|
-
def drop_table(table_name, options
|
57
|
+
def drop_table(table_name, **options) # :nodoc:
|
58
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
58
59
|
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
|
59
60
|
end
|
60
61
|
|
@@ -68,13 +69,13 @@ module ActiveRecord
|
|
68
69
|
table = quoted_scope(table_name)
|
69
70
|
index = quoted_scope(index_name)
|
70
71
|
|
71
|
-
query_value(
|
72
|
+
query_value(<<~SQL, "SCHEMA").to_i > 0
|
72
73
|
SELECT COUNT(*)
|
73
74
|
FROM pg_class t
|
74
75
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
75
76
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
76
77
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
77
|
-
WHERE i.relkind
|
78
|
+
WHERE i.relkind IN ('i', 'I')
|
78
79
|
AND i.relname = #{index[:name]}
|
79
80
|
AND t.relname = #{table[:name]}
|
80
81
|
AND n.nspname = #{index[:schema]}
|
@@ -85,14 +86,14 @@ module ActiveRecord
|
|
85
86
|
def indexes(table_name) # :nodoc:
|
86
87
|
scope = quoted_scope(table_name)
|
87
88
|
|
88
|
-
result = query(
|
89
|
+
result = query(<<~SQL, "SCHEMA")
|
89
90
|
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
|
90
91
|
pg_catalog.obj_description(i.oid, 'pg_class') AS comment
|
91
92
|
FROM pg_class t
|
92
93
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
93
94
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
94
95
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
95
|
-
WHERE i.relkind
|
96
|
+
WHERE i.relkind IN ('i', 'I')
|
96
97
|
AND d.indisprimary = 'f'
|
97
98
|
AND t.relname = #{scope[:name]}
|
98
99
|
AND n.nspname = #{scope[:schema]}
|
@@ -115,7 +116,7 @@ module ActiveRecord
|
|
115
116
|
if indkey.include?(0)
|
116
117
|
columns = expressions
|
117
118
|
else
|
118
|
-
columns = Hash[query(
|
119
|
+
columns = Hash[query(<<~SQL, "SCHEMA")].values_at(*indkey).compact
|
119
120
|
SELECT a.attnum, a.attname
|
120
121
|
FROM pg_attribute a
|
121
122
|
WHERE a.attrelid = #{oid}
|
@@ -158,7 +159,7 @@ module ActiveRecord
|
|
158
159
|
def table_comment(table_name) # :nodoc:
|
159
160
|
scope = quoted_scope(table_name, type: "BASE TABLE")
|
160
161
|
if scope[:name]
|
161
|
-
query_value(
|
162
|
+
query_value(<<~SQL, "SCHEMA")
|
162
163
|
SELECT pg_catalog.obj_description(c.oid, 'pg_class')
|
163
164
|
FROM pg_catalog.pg_class c
|
164
165
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
@@ -196,7 +197,7 @@ module ActiveRecord
|
|
196
197
|
|
197
198
|
# Returns an array of schema names.
|
198
199
|
def schema_names
|
199
|
-
query_values(
|
200
|
+
query_values(<<~SQL, "SCHEMA")
|
200
201
|
SELECT nspname
|
201
202
|
FROM pg_namespace
|
202
203
|
WHERE nspname !~ '^pg_.*'
|
@@ -211,7 +212,7 @@ module ActiveRecord
|
|
211
212
|
end
|
212
213
|
|
213
214
|
# Drops the schema for the given schema name.
|
214
|
-
def drop_schema(schema_name, options
|
215
|
+
def drop_schema(schema_name, **options)
|
215
216
|
execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name)} CASCADE"
|
216
217
|
end
|
217
218
|
|
@@ -243,7 +244,7 @@ module ActiveRecord
|
|
243
244
|
end
|
244
245
|
|
245
246
|
# Returns the sequence name for a table's primary key or some other specified key.
|
246
|
-
def default_sequence_name(table_name, pk = "id")
|
247
|
+
def default_sequence_name(table_name, pk = "id") # :nodoc:
|
247
248
|
result = serial_sequence(table_name, pk)
|
248
249
|
return nil unless result
|
249
250
|
Utils.extract_schema_qualified_name(result).to_s
|
@@ -256,7 +257,7 @@ module ActiveRecord
|
|
256
257
|
end
|
257
258
|
|
258
259
|
# Sets the sequence of a table's primary key to the specified value.
|
259
|
-
def set_pk_sequence!(table, value)
|
260
|
+
def set_pk_sequence!(table, value) # :nodoc:
|
260
261
|
pk, sequence = pk_and_sequence_for(table)
|
261
262
|
|
262
263
|
if pk
|
@@ -271,7 +272,7 @@ module ActiveRecord
|
|
271
272
|
end
|
272
273
|
|
273
274
|
# Resets the sequence of a table's primary key to the maximum value.
|
274
|
-
def reset_pk_sequence!(table, pk = nil, sequence = nil)
|
275
|
+
def reset_pk_sequence!(table, pk = nil, sequence = nil) # :nodoc:
|
275
276
|
unless pk && sequence
|
276
277
|
default_pk, default_sequence = pk_and_sequence_for(table)
|
277
278
|
|
@@ -287,7 +288,7 @@ module ActiveRecord
|
|
287
288
|
quoted_sequence = quote_table_name(sequence)
|
288
289
|
max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
|
289
290
|
if max_pk.nil?
|
290
|
-
if
|
291
|
+
if database_version >= 100000
|
291
292
|
minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
|
292
293
|
else
|
293
294
|
minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
|
@@ -299,10 +300,10 @@ module ActiveRecord
|
|
299
300
|
end
|
300
301
|
|
301
302
|
# Returns a table's primary key and belonging sequence.
|
302
|
-
def pk_and_sequence_for(table)
|
303
|
+
def pk_and_sequence_for(table) # :nodoc:
|
303
304
|
# First try looking for a sequence with a dependency on the
|
304
305
|
# given table's primary key.
|
305
|
-
result = query(
|
306
|
+
result = query(<<~SQL, "SCHEMA")[0]
|
306
307
|
SELECT attr.attname, nsp.nspname, seq.relname
|
307
308
|
FROM pg_class seq,
|
308
309
|
pg_attribute attr,
|
@@ -319,10 +320,10 @@ module ActiveRecord
|
|
319
320
|
AND cons.contype = 'p'
|
320
321
|
AND dep.classid = 'pg_class'::regclass
|
321
322
|
AND dep.refobjid = #{quote(quote_table_name(table))}::regclass
|
322
|
-
|
323
|
+
SQL
|
323
324
|
|
324
325
|
if result.nil? || result.empty?
|
325
|
-
result = query(
|
326
|
+
result = query(<<~SQL, "SCHEMA")[0]
|
326
327
|
SELECT attr.attname, nsp.nspname,
|
327
328
|
CASE
|
328
329
|
WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL
|
@@ -339,7 +340,7 @@ module ActiveRecord
|
|
339
340
|
WHERE t.oid = #{quote(quote_table_name(table))}::regclass
|
340
341
|
AND cons.contype = 'p'
|
341
342
|
AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
|
342
|
-
|
343
|
+
SQL
|
343
344
|
end
|
344
345
|
|
345
346
|
pk = result.shift
|
@@ -353,7 +354,7 @@ module ActiveRecord
|
|
353
354
|
end
|
354
355
|
|
355
356
|
def primary_keys(table_name) # :nodoc:
|
356
|
-
query_values(
|
357
|
+
query_values(<<~SQL, "SCHEMA")
|
357
358
|
SELECT a.attname
|
358
359
|
FROM (
|
359
360
|
SELECT indrelid, indkey, generate_subscripts(indkey, 1) idx
|
@@ -368,31 +369,6 @@ module ActiveRecord
|
|
368
369
|
SQL
|
369
370
|
end
|
370
371
|
|
371
|
-
def bulk_change_table(table_name, operations)
|
372
|
-
sql_fragments = []
|
373
|
-
non_combinable_operations = []
|
374
|
-
|
375
|
-
operations.each do |command, args|
|
376
|
-
table, arguments = args.shift, args
|
377
|
-
method = :"#{command}_for_alter"
|
378
|
-
|
379
|
-
if respond_to?(method, true)
|
380
|
-
sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
|
381
|
-
sql_fragments << sqls
|
382
|
-
non_combinable_operations.concat(procs)
|
383
|
-
else
|
384
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
385
|
-
non_combinable_operations.each(&:call)
|
386
|
-
sql_fragments = []
|
387
|
-
non_combinable_operations = []
|
388
|
-
send(command, table, *arguments)
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
393
|
-
non_combinable_operations.each(&:call)
|
394
|
-
end
|
395
|
-
|
396
372
|
# Renames a table.
|
397
373
|
# Also renames a table's primary key sequence if the sequence name exists and
|
398
374
|
# matches the Active Record default.
|
@@ -401,6 +377,8 @@ module ActiveRecord
|
|
401
377
|
# rename_table('octopuses', 'octopi')
|
402
378
|
def rename_table(table_name, new_name)
|
403
379
|
clear_cache!
|
380
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
381
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
404
382
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
405
383
|
pk, seq = pk_and_sequence_for(new_name)
|
406
384
|
if pk
|
@@ -415,15 +393,15 @@ module ActiveRecord
|
|
415
393
|
rename_table_indexes(table_name, new_name)
|
416
394
|
end
|
417
395
|
|
418
|
-
def add_column(table_name, column_name, type, options
|
396
|
+
def add_column(table_name, column_name, type, **options) # :nodoc:
|
419
397
|
clear_cache!
|
420
398
|
super
|
421
399
|
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
422
400
|
end
|
423
401
|
|
424
|
-
def change_column(table_name, column_name, type, options
|
402
|
+
def change_column(table_name, column_name, type, **options) # :nodoc:
|
425
403
|
clear_cache!
|
426
|
-
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, options)).partition { |v| v.is_a?(String) }
|
404
|
+
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, **options)).partition { |v| v.is_a?(String) }
|
427
405
|
execute "ALTER TABLE #{quote_table_name(table_name)} #{sqls.join(", ")}"
|
428
406
|
procs.each(&:call)
|
429
407
|
end
|
@@ -433,7 +411,7 @@ module ActiveRecord
|
|
433
411
|
execute "ALTER TABLE #{quote_table_name(table_name)} #{change_column_default_for_alter(table_name, column_name, default_or_changes)}"
|
434
412
|
end
|
435
413
|
|
436
|
-
def change_column_null(table_name, column_name, null, default = nil)
|
414
|
+
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
|
437
415
|
clear_cache!
|
438
416
|
unless null || default.nil?
|
439
417
|
column = column_for(table_name, column_name)
|
@@ -443,35 +421,40 @@ module ActiveRecord
|
|
443
421
|
end
|
444
422
|
|
445
423
|
# Adds comment for given table column or drops it if +comment+ is a +nil+
|
446
|
-
def change_column_comment(table_name, column_name,
|
424
|
+
def change_column_comment(table_name, column_name, comment_or_changes) # :nodoc:
|
447
425
|
clear_cache!
|
426
|
+
comment = extract_new_comment_value(comment_or_changes)
|
448
427
|
execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS #{quote(comment)}"
|
449
428
|
end
|
450
429
|
|
451
430
|
# Adds comment for given table or drops it if +comment+ is a +nil+
|
452
|
-
def change_table_comment(table_name,
|
431
|
+
def change_table_comment(table_name, comment_or_changes) # :nodoc:
|
453
432
|
clear_cache!
|
433
|
+
comment = extract_new_comment_value(comment_or_changes)
|
454
434
|
execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS #{quote(comment)}"
|
455
435
|
end
|
456
436
|
|
457
437
|
# Renames a column in a table.
|
458
|
-
def rename_column(table_name, column_name, new_column_name)
|
438
|
+
def rename_column(table_name, column_name, new_column_name) # :nodoc:
|
459
439
|
clear_cache!
|
460
|
-
execute
|
440
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}")
|
461
441
|
rename_column_indexes(table_name, column_name, new_column_name)
|
462
442
|
end
|
463
443
|
|
464
|
-
def add_index(table_name, column_name, options
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
444
|
+
def add_index(table_name, column_name, **options) # :nodoc:
|
445
|
+
index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
|
446
|
+
|
447
|
+
create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
|
448
|
+
result = execute schema_creation.accept(create_index)
|
449
|
+
|
450
|
+
execute "COMMENT ON INDEX #{quote_column_name(index.name)} IS #{quote(index.comment)}" if index.comment
|
451
|
+
result
|
469
452
|
end
|
470
453
|
|
471
|
-
def remove_index(table_name,
|
454
|
+
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
472
455
|
table = Utils.extract_schema_qualified_name(table_name.to_s)
|
473
456
|
|
474
|
-
if options.
|
457
|
+
if options.key?(:name)
|
475
458
|
provided_index = Utils.extract_schema_qualified_name(options[:name].to_s)
|
476
459
|
|
477
460
|
options[:name] = provided_index.identifier
|
@@ -482,14 +465,11 @@ module ActiveRecord
|
|
482
465
|
end
|
483
466
|
end
|
484
467
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
end
|
491
|
-
end
|
492
|
-
execute "DROP INDEX #{algorithm} #{quote_table_name(index_to_remove)}"
|
468
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
469
|
+
|
470
|
+
index_to_remove = PostgreSQL::Name.new(table.schema, index_name_for_remove(table.to_s, column_name, options))
|
471
|
+
|
472
|
+
execute "DROP INDEX #{index_algorithm(options[:algorithm])} #{quote_table_name(index_to_remove)}"
|
493
473
|
end
|
494
474
|
|
495
475
|
# Renames an index of a table. Raises error if length of new
|
@@ -502,8 +482,8 @@ module ActiveRecord
|
|
502
482
|
|
503
483
|
def foreign_keys(table_name)
|
504
484
|
scope = quoted_scope(table_name)
|
505
|
-
fk_info = exec_query(
|
506
|
-
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid
|
485
|
+
fk_info = exec_query(<<~SQL, "SCHEMA")
|
486
|
+
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred
|
507
487
|
FROM pg_constraint c
|
508
488
|
JOIN pg_class t1 ON c.conrelid = t1.oid
|
509
489
|
JOIN pg_class t2 ON c.confrelid = t2.oid
|
@@ -525,6 +505,8 @@ module ActiveRecord
|
|
525
505
|
|
526
506
|
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
527
507
|
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
508
|
+
options[:deferrable] = extract_foreign_key_deferrable(row["deferrable"], row["deferred"])
|
509
|
+
|
528
510
|
options[:validate] = row["valid"]
|
529
511
|
|
530
512
|
ForeignKeyDefinition.new(table_name, row["to_table"], options)
|
@@ -539,8 +521,30 @@ module ActiveRecord
|
|
539
521
|
query_values(data_source_sql(table_name, type: "FOREIGN TABLE"), "SCHEMA").any? if table_name.present?
|
540
522
|
end
|
541
523
|
|
524
|
+
def check_constraints(table_name) # :nodoc:
|
525
|
+
scope = quoted_scope(table_name)
|
526
|
+
|
527
|
+
check_info = exec_query(<<-SQL, "SCHEMA")
|
528
|
+
SELECT conname, pg_get_constraintdef(c.oid, true) AS constraintdef, c.convalidated AS valid
|
529
|
+
FROM pg_constraint c
|
530
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
531
|
+
WHERE c.contype = 'c'
|
532
|
+
AND t.relname = #{scope[:name]}
|
533
|
+
SQL
|
534
|
+
|
535
|
+
check_info.map do |row|
|
536
|
+
options = {
|
537
|
+
name: row["conname"],
|
538
|
+
validate: row["valid"]
|
539
|
+
}
|
540
|
+
expression = row["constraintdef"][/CHECK \((.+)\)/m, 1]
|
541
|
+
|
542
|
+
CheckConstraintDefinition.new(table_name, expression, options)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
542
546
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
543
|
-
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
547
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, enum_type: nil, **) # :nodoc:
|
544
548
|
sql = \
|
545
549
|
case type.to_s
|
546
550
|
when "binary"
|
@@ -548,22 +552,26 @@ module ActiveRecord
|
|
548
552
|
# The hard limit is 1GB, because of a 32-bit size field, and TOAST.
|
549
553
|
case limit
|
550
554
|
when nil, 0..0x3fffffff; super(type)
|
551
|
-
else raise
|
555
|
+
else raise ArgumentError, "No binary type has byte size #{limit}. The limit on binary can be at most 1GB - 1byte."
|
552
556
|
end
|
553
557
|
when "text"
|
554
558
|
# PostgreSQL doesn't support limits on text columns.
|
555
559
|
# The hard limit is 1GB, according to section 8.3 in the manual.
|
556
560
|
case limit
|
557
561
|
when nil, 0..0x3fffffff; super(type)
|
558
|
-
else raise
|
562
|
+
else raise ArgumentError, "No text type has byte size #{limit}. The limit on text can be at most 1GB - 1byte."
|
559
563
|
end
|
560
564
|
when "integer"
|
561
565
|
case limit
|
562
566
|
when 1, 2; "smallint"
|
563
567
|
when nil, 3, 4; "integer"
|
564
568
|
when 5..8; "bigint"
|
565
|
-
else raise
|
569
|
+
else raise ArgumentError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead."
|
566
570
|
end
|
571
|
+
when "enum"
|
572
|
+
raise ArgumentError, "enum_type is required for enums" if enum_type.nil?
|
573
|
+
|
574
|
+
enum_type
|
567
575
|
else
|
568
576
|
super
|
569
577
|
end
|
@@ -574,14 +582,14 @@ module ActiveRecord
|
|
574
582
|
|
575
583
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
576
584
|
# requires that the ORDER BY include the distinct column.
|
577
|
-
def columns_for_distinct(columns, orders)
|
578
|
-
order_columns = orders.
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
+
def columns_for_distinct(columns, orders) # :nodoc:
|
586
|
+
order_columns = orders.compact_blank.map { |s|
|
587
|
+
# Convert Arel node to string
|
588
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
589
|
+
# Remove any ASC/DESC modifiers
|
590
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
591
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
592
|
+
}.compact_blank.map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
585
593
|
|
586
594
|
(order_columns << super).join(", ")
|
587
595
|
end
|
@@ -600,8 +608,6 @@ module ActiveRecord
|
|
600
608
|
#
|
601
609
|
# validate_constraint :accounts, :constraint_name
|
602
610
|
def validate_constraint(table_name, constraint_name)
|
603
|
-
return unless supports_validate_constraints?
|
604
|
-
|
605
611
|
at = create_alter_table table_name
|
606
612
|
at.validate_constraint constraint_name
|
607
613
|
|
@@ -623,21 +629,30 @@ module ActiveRecord
|
|
623
629
|
# validate_foreign_key :accounts, name: :special_fk_name
|
624
630
|
#
|
625
631
|
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
|
626
|
-
def validate_foreign_key(from_table,
|
627
|
-
|
628
|
-
|
629
|
-
fk_name_to_validate = foreign_key_for!(from_table, options_or_to_table).name
|
632
|
+
def validate_foreign_key(from_table, to_table = nil, **options)
|
633
|
+
fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
|
630
634
|
|
631
635
|
validate_constraint from_table, fk_name_to_validate
|
632
636
|
end
|
633
637
|
|
638
|
+
# Validates the given check constraint.
|
639
|
+
#
|
640
|
+
# validate_check_constraint :products, name: "price_check"
|
641
|
+
#
|
642
|
+
# The +options+ hash accepts the same keys as add_check_constraint[rdoc-ref:ConnectionAdapters::SchemaStatements#add_check_constraint].
|
643
|
+
def validate_check_constraint(table_name, **options)
|
644
|
+
chk_name_to_validate = check_constraint_for!(table_name, **options).name
|
645
|
+
|
646
|
+
validate_constraint table_name, chk_name_to_validate
|
647
|
+
end
|
648
|
+
|
634
649
|
private
|
635
650
|
def schema_creation
|
636
651
|
PostgreSQL::SchemaCreation.new(self)
|
637
652
|
end
|
638
653
|
|
639
|
-
def create_table_definition(
|
640
|
-
PostgreSQL::TableDefinition.new(
|
654
|
+
def create_table_definition(name, **options)
|
655
|
+
PostgreSQL::TableDefinition.new(self, name, **options)
|
641
656
|
end
|
642
657
|
|
643
658
|
def create_alter_table(name)
|
@@ -645,21 +660,30 @@ module ActiveRecord
|
|
645
660
|
end
|
646
661
|
|
647
662
|
def new_column_from_field(table_name, field)
|
648
|
-
column_name, type, default, notnull, oid, fmod, collation, comment = field
|
663
|
+
column_name, type, default, notnull, oid, fmod, collation, comment, attgenerated = field
|
649
664
|
type_metadata = fetch_type_metadata(column_name, type, oid.to_i, fmod.to_i)
|
650
665
|
default_value = extract_value_from_default(default)
|
651
|
-
default_function = extract_default_function(default_value, default)
|
652
666
|
|
653
|
-
|
667
|
+
if attgenerated.present?
|
668
|
+
default_function = default
|
669
|
+
else
|
670
|
+
default_function = extract_default_function(default_value, default)
|
671
|
+
end
|
672
|
+
|
673
|
+
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
|
674
|
+
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
675
|
+
end
|
676
|
+
|
677
|
+
PostgreSQL::Column.new(
|
654
678
|
column_name,
|
655
679
|
default_value,
|
656
680
|
type_metadata,
|
657
681
|
!notnull,
|
658
|
-
table_name,
|
659
682
|
default_function,
|
660
|
-
collation,
|
683
|
+
collation: collation,
|
661
684
|
comment: comment.presence,
|
662
|
-
|
685
|
+
serial: serial,
|
686
|
+
generated: attgenerated
|
663
687
|
)
|
664
688
|
end
|
665
689
|
|
@@ -672,7 +696,23 @@ module ActiveRecord
|
|
672
696
|
precision: cast_type.precision,
|
673
697
|
scale: cast_type.scale,
|
674
698
|
)
|
675
|
-
|
699
|
+
PostgreSQL::TypeMetadata.new(simple_type, oid: oid, fmod: fmod)
|
700
|
+
end
|
701
|
+
|
702
|
+
def sequence_name_from_parts(table_name, column_name, suffix)
|
703
|
+
over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
|
704
|
+
|
705
|
+
if over_length > 0
|
706
|
+
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
707
|
+
over_length -= column_name.length - column_name_length
|
708
|
+
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
709
|
+
end
|
710
|
+
|
711
|
+
if over_length > 0
|
712
|
+
table_name = table_name[0, table_name.length - over_length]
|
713
|
+
end
|
714
|
+
|
715
|
+
"#{table_name}_#{column_name}_#{suffix}"
|
676
716
|
end
|
677
717
|
|
678
718
|
def extract_foreign_key_action(specifier)
|
@@ -683,14 +723,18 @@ module ActiveRecord
|
|
683
723
|
end
|
684
724
|
end
|
685
725
|
|
686
|
-
def
|
726
|
+
def extract_foreign_key_deferrable(deferrable, deferred)
|
727
|
+
deferrable && (deferred ? :deferred : true)
|
728
|
+
end
|
729
|
+
|
730
|
+
def add_column_for_alter(table_name, column_name, type, **options)
|
687
731
|
return super unless options.key?(:comment)
|
688
732
|
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
689
733
|
end
|
690
734
|
|
691
|
-
def change_column_for_alter(table_name, column_name, type, options
|
735
|
+
def change_column_for_alter(table_name, column_name, type, **options)
|
692
736
|
td = create_table_definition(table_name)
|
693
|
-
cd = td.new_column_definition(column_name, type, options)
|
737
|
+
cd = td.new_column_definition(column_name, type, **options)
|
694
738
|
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
695
739
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
696
740
|
sqls
|
@@ -715,14 +759,6 @@ module ActiveRecord
|
|
715
759
|
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
716
760
|
end
|
717
761
|
|
718
|
-
def add_timestamps_for_alter(table_name, options = {})
|
719
|
-
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
720
|
-
end
|
721
|
-
|
722
|
-
def remove_timestamps_for_alter(table_name, options = {})
|
723
|
-
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
724
|
-
end
|
725
|
-
|
726
762
|
def add_index_opclass(quoted_columns, **options)
|
727
763
|
opclasses = options_for_index_columns(options[:opclass])
|
728
764
|
quoted_columns.each do |name, column|
|
@@ -731,7 +767,7 @@ module ActiveRecord
|
|
731
767
|
end
|
732
768
|
|
733
769
|
def add_options_for_index_columns(quoted_columns, **options)
|
734
|
-
quoted_columns = add_index_opclass(quoted_columns, options)
|
770
|
+
quoted_columns = add_index_opclass(quoted_columns, **options)
|
735
771
|
super
|
736
772
|
end
|
737
773
|
|
@@ -739,7 +775,7 @@ module ActiveRecord
|
|
739
775
|
scope = quoted_scope(name, type: type)
|
740
776
|
scope[:type] ||= "'r','v','m','p','f'" # (r)elation/table, (v)iew, (m)aterialized view, (p)artitioned table, (f)oreign table
|
741
777
|
|
742
|
-
sql = "SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
|
778
|
+
sql = +"SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
|
743
779
|
sql << " WHERE n.nspname = #{scope[:schema]}"
|
744
780
|
sql << " AND c.relname = #{scope[:name]}" if scope[:name]
|
745
781
|
sql << " AND c.relkind IN (#{scope[:type]})"
|
@@ -1,39 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
+
# :stopdoc:
|
4
5
|
module ConnectionAdapters
|
5
|
-
|
6
|
-
|
6
|
+
module PostgreSQL
|
7
|
+
class TypeMetadata < DelegateClass(SqlTypeMetadata)
|
8
|
+
undef to_yaml if method_defined?(:to_yaml)
|
7
9
|
|
8
|
-
|
10
|
+
include Deduplicable
|
9
11
|
|
10
|
-
|
11
|
-
super(type_metadata)
|
12
|
-
@type_metadata = type_metadata
|
13
|
-
@oid = oid
|
14
|
-
@fmod = fmod
|
15
|
-
@array = /\[\]$/.match?(type_metadata.sql_type)
|
16
|
-
end
|
17
|
-
|
18
|
-
def sql_type
|
19
|
-
super.gsub(/\[\]$/, "".freeze)
|
20
|
-
end
|
21
|
-
|
22
|
-
def ==(other)
|
23
|
-
other.is_a?(PostgreSQLTypeMetadata) &&
|
24
|
-
attributes_for_hash == other.attributes_for_hash
|
25
|
-
end
|
26
|
-
alias eql? ==
|
12
|
+
attr_reader :oid, :fmod
|
27
13
|
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
def initialize(type_metadata, oid: nil, fmod: nil)
|
15
|
+
super(type_metadata)
|
16
|
+
@oid = oid
|
17
|
+
@fmod = fmod
|
18
|
+
end
|
31
19
|
|
32
|
-
|
20
|
+
def ==(other)
|
21
|
+
other.is_a?(TypeMetadata) &&
|
22
|
+
__getobj__ == other.__getobj__ &&
|
23
|
+
oid == other.oid &&
|
24
|
+
fmod == other.fmod
|
25
|
+
end
|
26
|
+
alias eql? ==
|
33
27
|
|
34
|
-
def
|
35
|
-
|
28
|
+
def hash
|
29
|
+
TypeMetadata.hash ^
|
30
|
+
__getobj__.hash ^
|
31
|
+
oid.hash ^
|
32
|
+
fmod.hash
|
36
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def deduplicated
|
37
|
+
__setobj__(__getobj__.deduplicate)
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
37
41
|
end
|
42
|
+
PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata
|
38
43
|
end
|
39
44
|
end
|