activerecord 5.0.6 → 6.0.1
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 +5 -5
- data/CHANGELOG.md +638 -2023
- data/MIT-LICENSE +3 -1
- data/README.rdoc +8 -6
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/aggregations.rb +249 -246
- data/lib/active_record/association_relation.rb +24 -13
- data/lib/active_record/associations/alias_tracker.rb +24 -33
- data/lib/active_record/associations/association.rb +119 -56
- data/lib/active_record/associations/association_scope.rb +94 -94
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +80 -252
- data/lib/active_record/associations/collection_proxy.rb +158 -121
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -29
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -176
- data/lib/active_record/associations/preloader/association.rb +84 -125
- data/lib/active_record/associations/preloader/through_association.rb +82 -75
- data/lib/active_record/associations/preloader.rb +90 -102
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +26 -14
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -60
- data/lib/active_record/attribute_decorators.rb +38 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +86 -91
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +21 -49
- data/lib/active_record/attribute_methods/serialization.rb +30 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
- data/lib/active_record/attribute_methods/write.rb +35 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -24
- data/lib/active_record/autosave_association.rb +53 -32
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +63 -33
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
- data/lib/active_record/connection_handling.rb +159 -40
- data/lib/active_record/core.rb +202 -162
- data/lib/active_record/counter_cache.rb +57 -28
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -86
- data/lib/active_record/enum.rb +60 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -3
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +195 -502
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +151 -97
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +15 -18
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +78 -87
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +143 -97
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +367 -300
- data/lib/active_record/model_schema.rb +145 -139
- data/lib/active_record/nested_attributes.rb +214 -201
- data/lib/active_record/no_touching.rb +10 -1
- data/lib/active_record/null_relation.rb +13 -34
- data/lib/active_record/persistence.rb +442 -72
- data/lib/active_record/query_cache.rb +15 -14
- data/lib/active_record/querying.rb +36 -23
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +309 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +211 -249
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +99 -52
- data/lib/active_record/relation/calculations.rb +211 -172
- data/lib/active_record/relation/delegation.rb +67 -65
- data/lib/active_record/relation/finder_methods.rb +208 -247
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +78 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +86 -104
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +458 -329
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +111 -95
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +429 -318
- data/lib/active_record/result.rb +69 -39
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +15 -5
- data/lib/active_record/scoping/default.rb +93 -95
- data/lib/active_record/scoping/named.rb +45 -25
- data/lib/active_record/scoping.rb +20 -19
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +4 -1
- data/lib/active_record/table_metadata.rb +26 -20
- data/lib/active_record/tasks/database_tasks.rb +276 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
- data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +70 -35
- data/lib/active_record/touch_later.rb +7 -4
- data/lib/active_record/transactions.rb +133 -149
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -45
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -8
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +2 -1
- data/lib/active_record/type/type_map.rb +13 -15
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +23 -17
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -4
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -22
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -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/insert_manager.rb +49 -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 +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -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 +41 -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 +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +58 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +133 -50
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -130
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,6 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/migration/join_table"
|
4
|
+
require "active_support/core_ext/string/access"
|
5
|
+
require "active_support/deprecation"
|
6
|
+
require "digest/sha2"
|
4
7
|
|
5
8
|
module ActiveRecord
|
6
9
|
module ConnectionAdapters # :nodoc:
|
@@ -25,12 +28,14 @@ module ActiveRecord
|
|
25
28
|
|
26
29
|
# Truncates a table alias according to the limits of the current adapter.
|
27
30
|
def table_alias_for(table_name)
|
28
|
-
table_name[0...table_alias_length].tr(
|
31
|
+
table_name[0...table_alias_length].tr(".", "_")
|
29
32
|
end
|
30
33
|
|
31
34
|
# Returns the relation names useable to back Active Record models.
|
32
35
|
# For most adapters this means all #tables and #views.
|
33
36
|
def data_sources
|
37
|
+
query_values(data_source_sql, "SCHEMA")
|
38
|
+
rescue NotImplementedError
|
34
39
|
tables | views
|
35
40
|
end
|
36
41
|
|
@@ -39,12 +44,14 @@ module ActiveRecord
|
|
39
44
|
# data_source_exists?(:ebooks)
|
40
45
|
#
|
41
46
|
def data_source_exists?(name)
|
47
|
+
query_values(data_source_sql(name), "SCHEMA").any? if name.present?
|
48
|
+
rescue NotImplementedError
|
42
49
|
data_sources.include?(name.to_s)
|
43
50
|
end
|
44
51
|
|
45
52
|
# Returns an array of table names defined in the database.
|
46
|
-
def tables
|
47
|
-
|
53
|
+
def tables
|
54
|
+
query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
|
48
55
|
end
|
49
56
|
|
50
57
|
# Checks to see if the table +table_name+ exists on the database.
|
@@ -52,12 +59,14 @@ module ActiveRecord
|
|
52
59
|
# table_exists?(:developers)
|
53
60
|
#
|
54
61
|
def table_exists?(table_name)
|
62
|
+
query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
|
63
|
+
rescue NotImplementedError
|
55
64
|
tables.include?(table_name.to_s)
|
56
65
|
end
|
57
66
|
|
58
67
|
# Returns an array of view names defined in the database.
|
59
68
|
def views
|
60
|
-
|
69
|
+
query_values(data_source_sql(type: "VIEW"), "SCHEMA")
|
61
70
|
end
|
62
71
|
|
63
72
|
# Checks to see if the view +view_name+ exists on the database.
|
@@ -65,11 +74,15 @@ module ActiveRecord
|
|
65
74
|
# view_exists?(:ebooks)
|
66
75
|
#
|
67
76
|
def view_exists?(view_name)
|
77
|
+
query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
|
78
|
+
rescue NotImplementedError
|
68
79
|
views.include?(view_name.to_s)
|
69
80
|
end
|
70
81
|
|
71
82
|
# Returns an array of indexes for the given table.
|
72
|
-
|
83
|
+
def indexes(table_name)
|
84
|
+
raise NotImplementedError, "#indexes is not implemented"
|
85
|
+
end
|
73
86
|
|
74
87
|
# Checks to see if an index exists on a table for a given index definition.
|
75
88
|
#
|
@@ -88,17 +101,19 @@ module ActiveRecord
|
|
88
101
|
def index_exists?(table_name, column_name, options = {})
|
89
102
|
column_names = Array(column_name).map(&:to_s)
|
90
103
|
checks = []
|
91
|
-
checks << lambda { |i| i.columns == column_names }
|
104
|
+
checks << lambda { |i| Array(i.columns) == column_names }
|
92
105
|
checks << lambda { |i| i.unique } if options[:unique]
|
93
106
|
checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
|
94
107
|
|
95
108
|
indexes(table_name).any? { |i| checks.all? { |check| check[i] } }
|
96
109
|
end
|
97
110
|
|
98
|
-
# Returns an array of Column objects for the table specified by +table_name+.
|
99
|
-
# See the concrete implementation for details on the expected parameter values.
|
111
|
+
# Returns an array of +Column+ objects for the table specified by +table_name+.
|
100
112
|
def columns(table_name)
|
101
|
-
|
113
|
+
table_name = table_name.to_s
|
114
|
+
column_definitions(table_name).map do |field|
|
115
|
+
new_column_from_field(table_name, field)
|
116
|
+
end
|
102
117
|
end
|
103
118
|
|
104
119
|
# Checks to see if a column exists in a given table.
|
@@ -115,12 +130,12 @@ module ActiveRecord
|
|
115
130
|
# column_exists?(:suppliers, :name, :string, null: false)
|
116
131
|
# column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
|
117
132
|
#
|
118
|
-
def column_exists?(table_name, column_name, type = nil, options
|
133
|
+
def column_exists?(table_name, column_name, type = nil, **options)
|
119
134
|
column_name = column_name.to_s
|
120
135
|
checks = []
|
121
136
|
checks << lambda { |c| c.name == column_name }
|
122
|
-
checks << lambda { |c| c.type == type } if type
|
123
|
-
|
137
|
+
checks << lambda { |c| c.type == type.to_sym rescue nil } if type
|
138
|
+
column_options_keys.each do |attr|
|
124
139
|
checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
|
125
140
|
end
|
126
141
|
|
@@ -174,7 +189,9 @@ module ActiveRecord
|
|
174
189
|
# A Symbol can be used to specify the type of the generated primary key column.
|
175
190
|
# [<tt>:primary_key</tt>]
|
176
191
|
# The name of the primary key, if one is to be added automatically.
|
177
|
-
# Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
|
192
|
+
# Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
|
193
|
+
#
|
194
|
+
# If an array is passed, a composite primary key will be created.
|
178
195
|
#
|
179
196
|
# Note that Active Record models will automatically detect their
|
180
197
|
# primary key. This can be avoided by using
|
@@ -189,19 +206,22 @@ module ActiveRecord
|
|
189
206
|
# Set to true to drop the table before creating it.
|
190
207
|
# Set to +:cascade+ to drop dependent objects as well.
|
191
208
|
# Defaults to false.
|
209
|
+
# [<tt>:if_not_exists</tt>]
|
210
|
+
# Set to true to avoid raising an error when the table already exists.
|
211
|
+
# Defaults to false.
|
192
212
|
# [<tt>:as</tt>]
|
193
213
|
# SQL to use to generate the table. When this option is used, the block is
|
194
214
|
# ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
|
195
215
|
#
|
196
216
|
# ====== Add a backend specific option to the generated SQL (MySQL)
|
197
217
|
#
|
198
|
-
# create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=
|
218
|
+
# create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
|
199
219
|
#
|
200
220
|
# generates:
|
201
221
|
#
|
202
222
|
# CREATE TABLE suppliers (
|
203
|
-
# id
|
204
|
-
# ) ENGINE=InnoDB DEFAULT CHARSET=
|
223
|
+
# id bigint auto_increment PRIMARY KEY
|
224
|
+
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
205
225
|
#
|
206
226
|
# ====== Rename the primary key column
|
207
227
|
#
|
@@ -212,7 +232,7 @@ module ActiveRecord
|
|
212
232
|
# generates:
|
213
233
|
#
|
214
234
|
# CREATE TABLE objects (
|
215
|
-
# guid
|
235
|
+
# guid bigint auto_increment PRIMARY KEY,
|
216
236
|
# name varchar(80)
|
217
237
|
# )
|
218
238
|
#
|
@@ -229,18 +249,35 @@ module ActiveRecord
|
|
229
249
|
# label varchar
|
230
250
|
# )
|
231
251
|
#
|
252
|
+
# ====== Create a composite primary key
|
253
|
+
#
|
254
|
+
# create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
|
255
|
+
# t.belongs_to :product
|
256
|
+
# t.belongs_to :client
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# generates:
|
260
|
+
#
|
261
|
+
# CREATE TABLE order (
|
262
|
+
# product_id bigint NOT NULL,
|
263
|
+
# client_id bigint NOT NULL
|
264
|
+
# );
|
265
|
+
#
|
266
|
+
# ALTER TABLE ONLY "orders"
|
267
|
+
# ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
|
268
|
+
#
|
232
269
|
# ====== Do not add a primary key column
|
233
270
|
#
|
234
271
|
# create_table(:categories_suppliers, id: false) do |t|
|
235
|
-
# t.column :category_id, :
|
236
|
-
# t.column :supplier_id, :
|
272
|
+
# t.column :category_id, :bigint
|
273
|
+
# t.column :supplier_id, :bigint
|
237
274
|
# end
|
238
275
|
#
|
239
276
|
# generates:
|
240
277
|
#
|
241
278
|
# CREATE TABLE categories_suppliers (
|
242
|
-
# category_id
|
243
|
-
# supplier_id
|
279
|
+
# category_id bigint,
|
280
|
+
# supplier_id bigint
|
244
281
|
# )
|
245
282
|
#
|
246
283
|
# ====== Create a temporary table based on a query
|
@@ -254,8 +291,8 @@ module ActiveRecord
|
|
254
291
|
# SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
|
255
292
|
#
|
256
293
|
# See also TableDefinition#column for details on how to create columns.
|
257
|
-
def create_table(table_name,
|
258
|
-
td = create_table_definition
|
294
|
+
def create_table(table_name, **options)
|
295
|
+
td = create_table_definition(table_name, options)
|
259
296
|
|
260
297
|
if options[:id] != false && !options[:as]
|
261
298
|
pk = options.fetch(:primary_key) do
|
@@ -265,14 +302,14 @@ module ActiveRecord
|
|
265
302
|
if pk.is_a?(Array)
|
266
303
|
td.primary_keys pk
|
267
304
|
else
|
268
|
-
td.primary_key pk, options.fetch(:id, :primary_key), options
|
305
|
+
td.primary_key pk, options.fetch(:id, :primary_key), options.except(:comment)
|
269
306
|
end
|
270
307
|
end
|
271
308
|
|
272
309
|
yield td if block_given?
|
273
310
|
|
274
|
-
if options[:force]
|
275
|
-
drop_table(table_name, options)
|
311
|
+
if options[:force]
|
312
|
+
drop_table(table_name, options.merge(if_exists: true))
|
276
313
|
end
|
277
314
|
|
278
315
|
result = execute schema_creation.accept td
|
@@ -284,7 +321,9 @@ module ActiveRecord
|
|
284
321
|
end
|
285
322
|
|
286
323
|
if supports_comments? && !supports_comments_in_create?
|
287
|
-
|
324
|
+
if table_comment = options[:comment].presence
|
325
|
+
change_table_comment(table_name, table_comment)
|
326
|
+
end
|
288
327
|
|
289
328
|
td.columns.each do |column|
|
290
329
|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
|
@@ -300,9 +339,9 @@ module ActiveRecord
|
|
300
339
|
# # Creates a table called 'assemblies_parts' with no id.
|
301
340
|
# create_join_table(:assemblies, :parts)
|
302
341
|
#
|
303
|
-
# You can pass
|
342
|
+
# You can pass an +options+ hash which can include the following keys:
|
304
343
|
# [<tt>:table_name</tt>]
|
305
|
-
# Sets the table name overriding the default
|
344
|
+
# Sets the table name, overriding the default.
|
306
345
|
# [<tt>:column_options</tt>]
|
307
346
|
# Any extra options you want appended to the columns definition.
|
308
347
|
# [<tt>:options</tt>]
|
@@ -328,22 +367,20 @@ module ActiveRecord
|
|
328
367
|
# generates:
|
329
368
|
#
|
330
369
|
# CREATE TABLE assemblies_parts (
|
331
|
-
# assembly_id
|
332
|
-
# part_id
|
370
|
+
# assembly_id bigint NOT NULL,
|
371
|
+
# part_id bigint NOT NULL,
|
333
372
|
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
334
373
|
#
|
335
|
-
def create_join_table(table_1, table_2,
|
374
|
+
def create_join_table(table_1, table_2, column_options: {}, **options)
|
336
375
|
join_table_name = find_join_table_name(table_1, table_2, options)
|
337
376
|
|
338
|
-
column_options
|
339
|
-
column_options.reverse_merge!(null: false)
|
340
|
-
type = column_options.delete(:type) || :integer
|
377
|
+
column_options.reverse_merge!(null: false, index: false)
|
341
378
|
|
342
|
-
|
379
|
+
t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
|
343
380
|
|
344
381
|
create_table(join_table_name, options.merge!(id: false)) do |td|
|
345
|
-
td.
|
346
|
-
td.
|
382
|
+
td.references t1_ref, column_options
|
383
|
+
td.references t2_ref, column_options
|
347
384
|
yield td if block_given?
|
348
385
|
end
|
349
386
|
end
|
@@ -375,6 +412,8 @@ module ActiveRecord
|
|
375
412
|
#
|
376
413
|
# Defaults to false.
|
377
414
|
#
|
415
|
+
# Only supported on the MySQL and PostgreSQL adapter, ignored elsewhere.
|
416
|
+
#
|
378
417
|
# ====== Add a column
|
379
418
|
#
|
380
419
|
# change_table(:suppliers) do |t|
|
@@ -399,7 +438,7 @@ module ActiveRecord
|
|
399
438
|
# t.references :company
|
400
439
|
# end
|
401
440
|
#
|
402
|
-
# Creates a <tt>company_id(
|
441
|
+
# Creates a <tt>company_id(bigint)</tt> column.
|
403
442
|
#
|
404
443
|
# ====== Add a polymorphic foreign key column
|
405
444
|
#
|
@@ -407,7 +446,7 @@ module ActiveRecord
|
|
407
446
|
# t.belongs_to :company, polymorphic: true
|
408
447
|
# end
|
409
448
|
#
|
410
|
-
# Creates <tt>company_type(varchar)</tt> and <tt>company_id(
|
449
|
+
# Creates <tt>company_type(varchar)</tt> and <tt>company_id(bigint)</tt> columns.
|
411
450
|
#
|
412
451
|
# ====== Remove a column
|
413
452
|
#
|
@@ -428,7 +467,7 @@ module ActiveRecord
|
|
428
467
|
# t.remove_index :company_id
|
429
468
|
# end
|
430
469
|
#
|
431
|
-
# See also Table for details on all of the various column
|
470
|
+
# See also Table for details on all of the various column transformations.
|
432
471
|
def change_table(table_name, options = {})
|
433
472
|
if supports_bulk_alter? && options[:bulk]
|
434
473
|
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
|
@@ -478,19 +517,25 @@ module ActiveRecord
|
|
478
517
|
#
|
479
518
|
# Available options are (none of these exists by default):
|
480
519
|
# * <tt>:limit</tt> -
|
481
|
-
# Requests a maximum column length. This is number of characters for a <tt>:string</tt> column
|
482
|
-
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt
|
520
|
+
# Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
|
521
|
+
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
|
522
|
+
# This option is ignored by some backends.
|
483
523
|
# * <tt>:default</tt> -
|
484
|
-
# The column's default value. Use nil for NULL
|
524
|
+
# The column's default value. Use +nil+ for +NULL+.
|
485
525
|
# * <tt>:null</tt> -
|
486
|
-
# Allows or disallows +NULL+ values in the column.
|
487
|
-
# have been named <tt>:null_allowed</tt>.
|
526
|
+
# Allows or disallows +NULL+ values in the column.
|
488
527
|
# * <tt>:precision</tt> -
|
489
|
-
# Specifies the precision for the <tt>:decimal</tt
|
528
|
+
# Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
|
529
|
+
# <tt>:datetime</tt>, and <tt>:time</tt> columns.
|
490
530
|
# * <tt>:scale</tt> -
|
491
531
|
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
532
|
+
# * <tt>:collation</tt> -
|
533
|
+
# Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
|
534
|
+
# column will have the same collation as the table.
|
535
|
+
# * <tt>:comment</tt> -
|
536
|
+
# Specifies the comment for the column. This option is ignored by some backends.
|
492
537
|
#
|
493
|
-
# Note: The precision is the total number of significant digits
|
538
|
+
# Note: The precision is the total number of significant digits,
|
494
539
|
# and the scale is the number of digits that can be stored following
|
495
540
|
# the decimal point. For example, the number 123.45 has a precision of 5
|
496
541
|
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
@@ -511,7 +556,7 @@ module ActiveRecord
|
|
511
556
|
# Default is (38,0).
|
512
557
|
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
513
558
|
# Default unknown.
|
514
|
-
# * SqlServer
|
559
|
+
# * SqlServer: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
515
560
|
# Default (38,0).
|
516
561
|
#
|
517
562
|
# == Examples
|
@@ -533,10 +578,14 @@ module ActiveRecord
|
|
533
578
|
# add_column(:measurements, :huge_integer, :decimal, precision: 30)
|
534
579
|
# # ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
|
535
580
|
#
|
581
|
+
# # Defines a column that stores an array of a type.
|
582
|
+
# add_column(:users, :skills, :text, array: true)
|
583
|
+
# # ALTER TABLE "users" ADD "skills" text[]
|
584
|
+
#
|
536
585
|
# # Defines a column with a database-specific type.
|
537
586
|
# add_column(:shapes, :triangle, 'polygon')
|
538
587
|
# # ALTER TABLE "shapes" ADD "triangle" polygon
|
539
|
-
def add_column(table_name, column_name, type, options
|
588
|
+
def add_column(table_name, column_name, type, **options)
|
540
589
|
at = create_alter_table table_name
|
541
590
|
at.add_column(column_name, type, options)
|
542
591
|
execute schema_creation.accept at
|
@@ -559,9 +608,10 @@ module ActiveRecord
|
|
559
608
|
#
|
560
609
|
# The +type+ and +options+ parameters will be ignored if present. It can be helpful
|
561
610
|
# to provide these in a migration's +change+ method so it can be reverted.
|
562
|
-
# In that case, +type+ and +options+ will be used by add_column.
|
611
|
+
# In that case, +type+ and +options+ will be used by #add_column.
|
612
|
+
# Indexes on the column are automatically removed.
|
563
613
|
def remove_column(table_name, column_name, type = nil, options = {})
|
564
|
-
execute "ALTER TABLE #{quote_table_name(table_name)}
|
614
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
|
565
615
|
end
|
566
616
|
|
567
617
|
# Changes the column's definition according to the new options.
|
@@ -676,7 +726,7 @@ module ActiveRecord
|
|
676
726
|
#
|
677
727
|
# CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
|
678
728
|
#
|
679
|
-
# Note: MySQL
|
729
|
+
# Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).
|
680
730
|
#
|
681
731
|
# ====== Creating a partial index
|
682
732
|
#
|
@@ -699,6 +749,19 @@ module ActiveRecord
|
|
699
749
|
#
|
700
750
|
# Note: only supported by PostgreSQL and MySQL
|
701
751
|
#
|
752
|
+
# ====== Creating an index with a specific operator class
|
753
|
+
#
|
754
|
+
# add_index(:developers, :name, using: 'gist', opclass: :gist_trgm_ops)
|
755
|
+
# # CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
|
756
|
+
#
|
757
|
+
# add_index(:developers, [:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
|
758
|
+
# # CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
|
759
|
+
#
|
760
|
+
# add_index(:developers, [:name, :city], using: 'gist', opclass: :gist_trgm_ops)
|
761
|
+
# # CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
|
762
|
+
#
|
763
|
+
# Note: only supported by PostgreSQL
|
764
|
+
#
|
702
765
|
# ====== Creating an index with a specific type
|
703
766
|
#
|
704
767
|
# add_index(:developers, :name, type: :fulltext)
|
@@ -708,6 +771,17 @@ module ActiveRecord
|
|
708
771
|
# CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
|
709
772
|
#
|
710
773
|
# Note: only supported by MySQL.
|
774
|
+
#
|
775
|
+
# ====== Creating an index with a specific algorithm
|
776
|
+
#
|
777
|
+
# add_index(:developers, :name, algorithm: :concurrently)
|
778
|
+
# # CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
|
779
|
+
#
|
780
|
+
# Note: only supported by PostgreSQL.
|
781
|
+
#
|
782
|
+
# Concurrently adding an index is not supported in a transaction.
|
783
|
+
#
|
784
|
+
# For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
|
711
785
|
def add_index(table_name, column_name, options = {})
|
712
786
|
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
|
713
787
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
|
@@ -731,6 +805,15 @@ module ActiveRecord
|
|
731
805
|
#
|
732
806
|
# remove_index :accounts, name: :by_branch_party
|
733
807
|
#
|
808
|
+
# Removes the index named +by_branch_party+ in the +accounts+ table +concurrently+.
|
809
|
+
#
|
810
|
+
# remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
|
811
|
+
#
|
812
|
+
# Note: only supported by PostgreSQL.
|
813
|
+
#
|
814
|
+
# Concurrently removing an index is not supported in a transaction.
|
815
|
+
#
|
816
|
+
# For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
|
734
817
|
def remove_index(table_name, options = {})
|
735
818
|
index_name = index_name_for_remove(table_name, options)
|
736
819
|
execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
|
@@ -745,7 +828,7 @@ module ActiveRecord
|
|
745
828
|
def rename_index(table_name, old_name, new_name)
|
746
829
|
validate_index_length!(table_name, new_name)
|
747
830
|
|
748
|
-
# this is a naive implementation; some DBs may support this more efficiently (
|
831
|
+
# this is a naive implementation; some DBs may support this more efficiently (PostgreSQL, for instance)
|
749
832
|
old_index_def = indexes(table_name).detect { |i| i.name == old_name }
|
750
833
|
return unless old_index_def
|
751
834
|
add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
|
@@ -767,23 +850,19 @@ module ActiveRecord
|
|
767
850
|
end
|
768
851
|
|
769
852
|
# Verifies the existence of an index with a given name.
|
770
|
-
|
771
|
-
# The default argument is returned if the underlying implementation does not define the indexes method,
|
772
|
-
# as there's no way to determine the correct answer in that case.
|
773
|
-
def index_name_exists?(table_name, index_name, default)
|
774
|
-
return default unless respond_to?(:indexes)
|
853
|
+
def index_name_exists?(table_name, index_name)
|
775
854
|
index_name = index_name.to_s
|
776
855
|
indexes(table_name).detect { |i| i.name == index_name }
|
777
856
|
end
|
778
857
|
|
779
|
-
# Adds a reference. The reference column is
|
858
|
+
# Adds a reference. The reference column is a bigint by default,
|
780
859
|
# the <tt>:type</tt> option can be used to specify a different type.
|
781
860
|
# Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
|
782
861
|
# #add_reference and #add_belongs_to are acceptable.
|
783
862
|
#
|
784
863
|
# The +options+ hash can include the following keys:
|
785
864
|
# [<tt>:type</tt>]
|
786
|
-
# The reference column type. Defaults to +:
|
865
|
+
# The reference column type. Defaults to +:bigint+.
|
787
866
|
# [<tt>:index</tt>]
|
788
867
|
# Add an appropriate index. Defaults to true.
|
789
868
|
# See #add_index for usage of this option.
|
@@ -794,17 +873,17 @@ module ActiveRecord
|
|
794
873
|
# [<tt>:null</tt>]
|
795
874
|
# Whether the column allows nulls. Defaults to true.
|
796
875
|
#
|
797
|
-
# ====== Create a user_id
|
876
|
+
# ====== Create a user_id bigint column without an index
|
798
877
|
#
|
799
|
-
# add_reference(:products, :user)
|
878
|
+
# add_reference(:products, :user, index: false)
|
800
879
|
#
|
801
880
|
# ====== Create a user_id string column
|
802
881
|
#
|
803
882
|
# add_reference(:products, :user, type: :string)
|
804
883
|
#
|
805
|
-
# ====== Create supplier_id, supplier_type columns
|
884
|
+
# ====== Create supplier_id, supplier_type columns
|
806
885
|
#
|
807
|
-
# add_reference(:products, :supplier, polymorphic: true
|
886
|
+
# add_reference(:products, :supplier, polymorphic: true)
|
808
887
|
#
|
809
888
|
# ====== Create a supplier_id column with a unique index
|
810
889
|
#
|
@@ -822,8 +901,8 @@ module ActiveRecord
|
|
822
901
|
#
|
823
902
|
# add_reference(:products, :supplier, foreign_key: {to_table: :firms})
|
824
903
|
#
|
825
|
-
def add_reference(table_name,
|
826
|
-
ReferenceDefinition.new(
|
904
|
+
def add_reference(table_name, ref_name, **options)
|
905
|
+
ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
|
827
906
|
end
|
828
907
|
alias :add_belongs_to :add_reference
|
829
908
|
|
@@ -832,7 +911,7 @@ module ActiveRecord
|
|
832
911
|
#
|
833
912
|
# ====== Remove the reference
|
834
913
|
#
|
835
|
-
# remove_reference(:products, :user, index:
|
914
|
+
# remove_reference(:products, :user, index: false)
|
836
915
|
#
|
837
916
|
# ====== Remove polymorphic reference
|
838
917
|
#
|
@@ -840,7 +919,7 @@ module ActiveRecord
|
|
840
919
|
#
|
841
920
|
# ====== Remove the reference with a foreign key
|
842
921
|
#
|
843
|
-
# remove_reference(:products, :user,
|
922
|
+
# remove_reference(:products, :user, foreign_key: true)
|
844
923
|
#
|
845
924
|
def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
|
846
925
|
if foreign_key
|
@@ -850,7 +929,8 @@ module ActiveRecord
|
|
850
929
|
else
|
851
930
|
foreign_key_options = { to_table: reference_name }
|
852
931
|
end
|
853
|
-
|
932
|
+
foreign_key_options[:column] ||= "#{ref_name}_id"
|
933
|
+
remove_foreign_key(table_name, foreign_key_options)
|
854
934
|
end
|
855
935
|
|
856
936
|
remove_column(table_name, "#{ref_name}_id")
|
@@ -906,6 +986,8 @@ module ActiveRecord
|
|
906
986
|
# Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
907
987
|
# [<tt>:on_update</tt>]
|
908
988
|
# Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
989
|
+
# [<tt>:validate</tt>]
|
990
|
+
# (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
|
909
991
|
def add_foreign_key(from_table, to_table, options = {})
|
910
992
|
return unless supports_foreign_keys?
|
911
993
|
|
@@ -929,15 +1011,22 @@ module ActiveRecord
|
|
929
1011
|
#
|
930
1012
|
# remove_foreign_key :accounts, column: :owner_id
|
931
1013
|
#
|
1014
|
+
# Removes the foreign key on +accounts.owner_id+.
|
1015
|
+
#
|
1016
|
+
# remove_foreign_key :accounts, to_table: :owners
|
1017
|
+
#
|
932
1018
|
# Removes the foreign key named +special_fk_name+ on the +accounts+ table.
|
933
1019
|
#
|
934
1020
|
# remove_foreign_key :accounts, name: :special_fk_name
|
935
1021
|
#
|
936
|
-
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
|
937
|
-
|
1022
|
+
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
|
1023
|
+
# with an addition of
|
1024
|
+
# [<tt>:to_table</tt>]
|
1025
|
+
# The name of the table that contains the referenced primary key.
|
1026
|
+
def remove_foreign_key(from_table, to_table = nil, **options)
|
938
1027
|
return unless supports_foreign_keys?
|
939
1028
|
|
940
|
-
fk_name_to_delete = foreign_key_for!(from_table,
|
1029
|
+
fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
|
941
1030
|
|
942
1031
|
at = create_alter_table from_table
|
943
1032
|
at.drop_foreign_key fk_name_to_delete
|
@@ -947,33 +1036,21 @@ module ActiveRecord
|
|
947
1036
|
|
948
1037
|
# Checks to see if a foreign key exists on a table for a given foreign key definition.
|
949
1038
|
#
|
950
|
-
# #
|
1039
|
+
# # Checks to see if a foreign key exists.
|
951
1040
|
# foreign_key_exists?(:accounts, :branches)
|
952
1041
|
#
|
953
|
-
# #
|
1042
|
+
# # Checks to see if a foreign key on a specified column exists.
|
954
1043
|
# foreign_key_exists?(:accounts, column: :owner_id)
|
955
1044
|
#
|
956
|
-
# #
|
1045
|
+
# # Checks to see if a foreign key with a custom name exists.
|
957
1046
|
# foreign_key_exists?(:accounts, name: "special_fk_name")
|
958
1047
|
#
|
959
|
-
def foreign_key_exists?(from_table,
|
960
|
-
foreign_key_for(from_table,
|
961
|
-
end
|
962
|
-
|
963
|
-
def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc:
|
964
|
-
return unless supports_foreign_keys?
|
965
|
-
foreign_keys(from_table).detect {|fk| fk.defined_for? options_or_to_table }
|
966
|
-
end
|
967
|
-
|
968
|
-
def foreign_key_for!(from_table, options_or_to_table = {}) # :nodoc:
|
969
|
-
foreign_key_for(from_table, options_or_to_table) or \
|
970
|
-
raise ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}"
|
1048
|
+
def foreign_key_exists?(from_table, to_table = nil, **options)
|
1049
|
+
foreign_key_for(from_table, to_table: to_table, **options).present?
|
971
1050
|
end
|
972
1051
|
|
973
1052
|
def foreign_key_column_for(table_name) # :nodoc:
|
974
|
-
|
975
|
-
suffix = Base.table_name_suffix
|
976
|
-
name = table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
|
1053
|
+
name = strip_table_name_prefix_and_suffix(table_name)
|
977
1054
|
"#{name.singularize}_id"
|
978
1055
|
end
|
979
1056
|
|
@@ -984,68 +1061,42 @@ module ActiveRecord
|
|
984
1061
|
options
|
985
1062
|
end
|
986
1063
|
|
987
|
-
def dump_schema_information
|
988
|
-
versions =
|
1064
|
+
def dump_schema_information # :nodoc:
|
1065
|
+
versions = schema_migration.all_versions
|
989
1066
|
insert_versions_sql(versions) if versions.any?
|
990
1067
|
end
|
991
1068
|
|
992
|
-
def insert_versions_sql(versions) # :nodoc:
|
993
|
-
sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
|
994
|
-
|
995
|
-
if versions.is_a?(Array)
|
996
|
-
sql = "INSERT INTO #{sm_table} (version) VALUES\n"
|
997
|
-
sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
|
998
|
-
sql << ";\n\n"
|
999
|
-
sql
|
1000
|
-
else
|
1001
|
-
"INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
|
1002
|
-
end
|
1003
|
-
end
|
1004
|
-
|
1005
|
-
# Should not be called normally, but this operation is non-destructive.
|
1006
|
-
# The migrations module handles this automatically.
|
1007
|
-
def initialize_schema_migrations_table
|
1008
|
-
ActiveRecord::SchemaMigration.create_table
|
1009
|
-
end
|
1010
|
-
|
1011
|
-
def initialize_internal_metadata_table
|
1012
|
-
ActiveRecord::InternalMetadata.create_table
|
1013
|
-
end
|
1014
|
-
|
1015
1069
|
def internal_string_options_for_primary_key # :nodoc:
|
1016
1070
|
{ primary_key: true }
|
1017
1071
|
end
|
1018
1072
|
|
1019
|
-
def assume_migrated_upto_version(version, migrations_paths)
|
1020
|
-
|
1073
|
+
def assume_migrated_upto_version(version, migrations_paths = nil)
|
1074
|
+
unless migrations_paths.nil?
|
1075
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
1076
|
+
Passing migrations_paths to #assume_migrated_upto_version is deprecated and will be removed in Rails 6.1.
|
1077
|
+
MSG
|
1078
|
+
end
|
1079
|
+
|
1021
1080
|
version = version.to_i
|
1022
|
-
sm_table = quote_table_name(
|
1081
|
+
sm_table = quote_table_name(schema_migration.table_name)
|
1023
1082
|
|
1024
|
-
migrated =
|
1025
|
-
versions =
|
1026
|
-
ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
|
1027
|
-
end
|
1083
|
+
migrated = migration_context.get_all_versions
|
1084
|
+
versions = migration_context.migrations.map(&:version)
|
1028
1085
|
|
1029
1086
|
unless migrated.include?(version)
|
1030
1087
|
execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
|
1031
1088
|
end
|
1032
1089
|
|
1033
|
-
inserting = (versions - migrated).select {|v| v < version}
|
1090
|
+
inserting = (versions - migrated).select { |v| v < version }
|
1034
1091
|
if inserting.any?
|
1035
|
-
if (duplicate = inserting.detect {|v| inserting.count(v) > 1})
|
1092
|
+
if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
|
1036
1093
|
raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
|
1037
1094
|
end
|
1038
|
-
|
1039
|
-
execute insert_versions_sql(inserting)
|
1040
|
-
else
|
1041
|
-
inserting.each do |v|
|
1042
|
-
execute insert_versions_sql(v)
|
1043
|
-
end
|
1044
|
-
end
|
1095
|
+
execute insert_versions_sql(inserting)
|
1045
1096
|
end
|
1046
1097
|
end
|
1047
1098
|
|
1048
|
-
def type_to_sql(type, limit
|
1099
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
|
1049
1100
|
type = type.to_sym if type
|
1050
1101
|
if native = native_database_types[type]
|
1051
1102
|
column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
|
@@ -1063,11 +1114,11 @@ module ActiveRecord
|
|
1063
1114
|
raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
|
1064
1115
|
end
|
1065
1116
|
|
1066
|
-
elsif [:datetime, :time].include?(type) && precision ||= native[:precision]
|
1117
|
+
elsif [:datetime, :timestamp, :time, :interval].include?(type) && precision ||= native[:precision]
|
1067
1118
|
if (0..6) === precision
|
1068
1119
|
column_type_sql << "(#{precision})"
|
1069
1120
|
else
|
1070
|
-
raise
|
1121
|
+
raise ArgumentError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6"
|
1071
1122
|
end
|
1072
1123
|
elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
|
1073
1124
|
column_type_sql << "(#{limit})"
|
@@ -1080,7 +1131,7 @@ module ActiveRecord
|
|
1080
1131
|
end
|
1081
1132
|
|
1082
1133
|
# Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
|
1083
|
-
# PostgreSQL, MySQL, and Oracle
|
1134
|
+
# PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they
|
1084
1135
|
# require the order columns appear in the SELECT.
|
1085
1136
|
#
|
1086
1137
|
# columns_for_distinct("posts.id", ["posts.created_at desc"])
|
@@ -1097,6 +1148,10 @@ module ActiveRecord
|
|
1097
1148
|
def add_timestamps(table_name, options = {})
|
1098
1149
|
options[:null] = false if options[:null].nil?
|
1099
1150
|
|
1151
|
+
if !options.key?(:precision) && supports_datetime_with_precision?
|
1152
|
+
options[:precision] = 6
|
1153
|
+
end
|
1154
|
+
|
1100
1155
|
add_column table_name, :created_at, :datetime, options
|
1101
1156
|
add_column table_name, :updated_at, :datetime, options
|
1102
1157
|
end
|
@@ -1117,13 +1172,12 @@ module ActiveRecord
|
|
1117
1172
|
def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
|
1118
1173
|
column_names = index_column_names(column_name)
|
1119
1174
|
|
1120
|
-
options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
|
1175
|
+
options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclass)
|
1121
1176
|
|
1122
1177
|
index_type = options[:type].to_s if options.key?(:type)
|
1123
1178
|
index_type ||= options[:unique] ? "UNIQUE" : ""
|
1124
1179
|
index_name = options[:name].to_s if options.key?(:name)
|
1125
1180
|
index_name ||= index_name(table_name, column_names)
|
1126
|
-
max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
|
1127
1181
|
|
1128
1182
|
if options.key?(:algorithm)
|
1129
1183
|
algorithm = index_algorithms.fetch(options[:algorithm]) {
|
@@ -1137,10 +1191,9 @@ module ActiveRecord
|
|
1137
1191
|
index_options = options[:where] ? " WHERE #{options[:where]}" : ""
|
1138
1192
|
end
|
1139
1193
|
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name, false)
|
1194
|
+
validate_index_length!(table_name, index_name, options.fetch(:internal, false))
|
1195
|
+
|
1196
|
+
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
|
1144
1197
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
|
1145
1198
|
end
|
1146
1199
|
index_columns = quoted_columns_for_index(column_names, options).join(", ")
|
@@ -1153,32 +1206,51 @@ module ActiveRecord
|
|
1153
1206
|
end
|
1154
1207
|
|
1155
1208
|
# Changes the comment for a table or removes it if +nil+.
|
1156
|
-
|
1209
|
+
#
|
1210
|
+
# Passing a hash containing +:from+ and +:to+ will make this change
|
1211
|
+
# reversible in migration:
|
1212
|
+
#
|
1213
|
+
# change_table_comment(:posts, from: "old_comment", to: "new_comment")
|
1214
|
+
def change_table_comment(table_name, comment_or_changes)
|
1157
1215
|
raise NotImplementedError, "#{self.class} does not support changing table comments"
|
1158
1216
|
end
|
1159
1217
|
|
1160
1218
|
# Changes the comment for a column or removes it if +nil+.
|
1161
|
-
|
1219
|
+
#
|
1220
|
+
# Passing a hash containing +:from+ and +:to+ will make this change
|
1221
|
+
# reversible in migration:
|
1222
|
+
#
|
1223
|
+
# change_column_comment(:posts, :state, from: "old_comment", to: "new_comment")
|
1224
|
+
def change_column_comment(table_name, column_name, comment_or_changes)
|
1162
1225
|
raise NotImplementedError, "#{self.class} does not support changing column comments"
|
1163
1226
|
end
|
1164
1227
|
|
1165
|
-
|
1228
|
+
def create_schema_dumper(options) # :nodoc:
|
1229
|
+
SchemaDumper.create(self, options)
|
1230
|
+
end
|
1231
|
+
|
1232
|
+
private
|
1233
|
+
def column_options_keys
|
1234
|
+
[:limit, :precision, :scale, :default, :null, :collation, :comment]
|
1235
|
+
end
|
1166
1236
|
|
1167
1237
|
def add_index_sort_order(quoted_columns, **options)
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
order = order.symbolize_keys
|
1172
|
-
quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
|
1173
|
-
when String
|
1174
|
-
quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
|
1175
|
-
end
|
1238
|
+
orders = options_for_index_columns(options[:order])
|
1239
|
+
quoted_columns.each do |name, column|
|
1240
|
+
column << " #{orders[name].upcase}" if orders[name].present?
|
1176
1241
|
end
|
1242
|
+
end
|
1177
1243
|
|
1178
|
-
|
1244
|
+
def options_for_index_columns(options)
|
1245
|
+
if options.is_a?(Hash)
|
1246
|
+
options.symbolize_keys
|
1247
|
+
else
|
1248
|
+
Hash.new { |hash, column| hash[column] = options }
|
1249
|
+
end
|
1179
1250
|
end
|
1180
1251
|
|
1181
|
-
# Overridden by the MySQL adapter for supporting index lengths
|
1252
|
+
# Overridden by the MySQL adapter for supporting index lengths and by
|
1253
|
+
# the PostgreSQL adapter for supporting operator classes.
|
1182
1254
|
def add_options_for_index_columns(quoted_columns, **options)
|
1183
1255
|
if supports_index_sort_order?
|
1184
1256
|
quoted_columns = add_index_sort_order(quoted_columns, options)
|
@@ -1197,10 +1269,6 @@ module ActiveRecord
|
|
1197
1269
|
def index_name_for_remove(table_name, options = {})
|
1198
1270
|
return options[:name] if can_remove_index_by_name?(options)
|
1199
1271
|
|
1200
|
-
# if the adapter doesn't support the indexes call the best we can do
|
1201
|
-
# is return the default index name for the options provided
|
1202
|
-
return index_name(table_name, options) unless respond_to?(:indexes)
|
1203
|
-
|
1204
1272
|
checks = []
|
1205
1273
|
|
1206
1274
|
if options.is_a?(Hash)
|
@@ -1250,56 +1318,158 @@ module ActiveRecord
|
|
1250
1318
|
end
|
1251
1319
|
end
|
1252
1320
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
end
|
1321
|
+
def schema_creation
|
1322
|
+
SchemaCreation.new(self)
|
1323
|
+
end
|
1257
1324
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1325
|
+
def create_table_definition(*args)
|
1326
|
+
TableDefinition.new(self, *args)
|
1327
|
+
end
|
1261
1328
|
|
1262
|
-
|
1263
|
-
|
1264
|
-
column_names
|
1265
|
-
else
|
1266
|
-
Array(column_names)
|
1329
|
+
def create_alter_table(name)
|
1330
|
+
AlterTable.new create_table_definition(name)
|
1267
1331
|
end
|
1268
|
-
end
|
1269
1332
|
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1333
|
+
def fetch_type_metadata(sql_type)
|
1334
|
+
cast_type = lookup_cast_type(sql_type)
|
1335
|
+
SqlTypeMetadata.new(
|
1336
|
+
sql_type: sql_type,
|
1337
|
+
type: cast_type.type,
|
1338
|
+
limit: cast_type.limit,
|
1339
|
+
precision: cast_type.precision,
|
1340
|
+
scale: cast_type.scale,
|
1341
|
+
)
|
1273
1342
|
end
|
1274
1343
|
|
1275
|
-
|
1276
|
-
|
1344
|
+
def index_column_names(column_names)
|
1345
|
+
if column_names.is_a?(String) && /\W/.match?(column_names)
|
1346
|
+
column_names
|
1347
|
+
else
|
1348
|
+
Array(column_names)
|
1349
|
+
end
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
def index_name_options(column_names)
|
1353
|
+
if column_names.is_a?(String) && /\W/.match?(column_names)
|
1354
|
+
column_names = column_names.scan(/\w+/).join("_")
|
1355
|
+
end
|
1277
1356
|
|
1278
|
-
|
1279
|
-
identifier = "#{table_name}_#{options.fetch(:column)}_fk"
|
1280
|
-
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
1281
|
-
options.fetch(:name) do
|
1282
|
-
"fk_rails_#{hashed_identifier}"
|
1357
|
+
{ column: column_names }
|
1283
1358
|
end
|
1284
|
-
end
|
1285
1359
|
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1360
|
+
def strip_table_name_prefix_and_suffix(table_name)
|
1361
|
+
prefix = Base.table_name_prefix
|
1362
|
+
suffix = Base.table_name_suffix
|
1363
|
+
table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
|
1289
1364
|
end
|
1290
|
-
end
|
1291
1365
|
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1366
|
+
def foreign_key_name(table_name, options)
|
1367
|
+
options.fetch(:name) do
|
1368
|
+
identifier = "#{table_name}_#{options.fetch(:column)}_fk"
|
1369
|
+
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
1370
|
+
|
1371
|
+
"fk_rails_#{hashed_identifier}"
|
1372
|
+
end
|
1297
1373
|
end
|
1298
|
-
end
|
1299
1374
|
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1375
|
+
def foreign_key_for(from_table, **options)
|
1376
|
+
return unless supports_foreign_keys?
|
1377
|
+
foreign_keys(from_table).detect { |fk| fk.defined_for?(options) }
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
def foreign_key_for!(from_table, to_table: nil, **options)
|
1381
|
+
foreign_key_for(from_table, to_table: to_table, **options) ||
|
1382
|
+
raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
def extract_foreign_key_action(specifier)
|
1386
|
+
case specifier
|
1387
|
+
when "CASCADE"; :cascade
|
1388
|
+
when "SET NULL"; :nullify
|
1389
|
+
when "RESTRICT"; :restrict
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
def validate_index_length!(table_name, new_name, internal = false)
|
1394
|
+
max_index_length = internal ? index_name_length : allowed_index_name_length
|
1395
|
+
|
1396
|
+
if new_name.length > max_index_length
|
1397
|
+
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
|
1398
|
+
end
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
def extract_new_default_value(default_or_changes)
|
1402
|
+
if default_or_changes.is_a?(Hash) && default_or_changes.has_key?(:from) && default_or_changes.has_key?(:to)
|
1403
|
+
default_or_changes[:to]
|
1404
|
+
else
|
1405
|
+
default_or_changes
|
1406
|
+
end
|
1407
|
+
end
|
1408
|
+
alias :extract_new_comment_value :extract_new_default_value
|
1409
|
+
|
1410
|
+
def can_remove_index_by_name?(options)
|
1411
|
+
options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
def bulk_change_table(table_name, operations)
|
1415
|
+
sql_fragments = []
|
1416
|
+
non_combinable_operations = []
|
1417
|
+
|
1418
|
+
operations.each do |command, args|
|
1419
|
+
table, arguments = args.shift, args
|
1420
|
+
method = :"#{command}_for_alter"
|
1421
|
+
|
1422
|
+
if respond_to?(method, true)
|
1423
|
+
sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
|
1424
|
+
sql_fragments << sqls
|
1425
|
+
non_combinable_operations.concat(procs)
|
1426
|
+
else
|
1427
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
1428
|
+
non_combinable_operations.each(&:call)
|
1429
|
+
sql_fragments = []
|
1430
|
+
non_combinable_operations = []
|
1431
|
+
send(command, table, *arguments)
|
1432
|
+
end
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
1436
|
+
non_combinable_operations.each(&:call)
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
1440
|
+
td = create_table_definition(table_name)
|
1441
|
+
cd = td.new_column_definition(column_name, type, options)
|
1442
|
+
schema_creation.accept(AddColumnDefinition.new(cd))
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
def remove_column_for_alter(table_name, column_name, type = nil, options = {})
|
1446
|
+
"DROP COLUMN #{quote_column_name(column_name)}"
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
def remove_columns_for_alter(table_name, *column_names)
|
1450
|
+
column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
def insert_versions_sql(versions)
|
1454
|
+
sm_table = quote_table_name(schema_migration.table_name)
|
1455
|
+
|
1456
|
+
if versions.is_a?(Array)
|
1457
|
+
sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
|
1458
|
+
sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
|
1459
|
+
sql << ";\n\n"
|
1460
|
+
sql
|
1461
|
+
else
|
1462
|
+
"INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
|
1463
|
+
end
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
def data_source_sql(name = nil, type: nil)
|
1467
|
+
raise NotImplementedError
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
def quoted_scope(name = nil, type: nil)
|
1471
|
+
raise NotImplementedError
|
1472
|
+
end
|
1303
1473
|
end
|
1304
1474
|
end
|
1305
1475
|
end
|