activerecord 5.0.7.2 → 6.1.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 +4 -4
- data/CHANGELOG.md +829 -2015
- data/MIT-LICENSE +3 -1
- data/README.rdoc +11 -9
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -29
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +30 -18
- data/lib/active_record/associations.rb +1714 -1596
- data/lib/active_record/associations/alias_tracker.rb +36 -42
- data/lib/active_record/associations/association.rb +143 -68
- data/lib/active_record/associations/association_scope.rb +98 -94
- data/lib/active_record/associations/belongs_to_association.rb +76 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +27 -28
- data/lib/active_record/associations/builder/belongs_to.rb +52 -60
- data/lib/active_record/associations/builder/collection_association.rb +12 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
- data/lib/active_record/associations/builder/has_many.rb +10 -2
- data/lib/active_record/associations/builder/has_one.rb +35 -2
- data/lib/active_record/associations/builder/singular_association.rb +5 -1
- data/lib/active_record/associations/collection_association.rb +104 -259
- data/lib/active_record/associations/collection_proxy.rb +169 -125
- data/lib/active_record/associations/foreign_association.rb +22 -0
- data/lib/active_record/associations/has_many_association.rb +46 -31
- data/lib/active_record/associations/has_many_through_association.rb +66 -46
- data/lib/active_record/associations/has_one_association.rb +71 -52
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +169 -180
- data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +97 -104
- data/lib/active_record/associations/preloader/association.rb +109 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/attribute_assignment.rb +55 -60
- data/lib/active_record/attribute_methods.rb +111 -141
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
- data/lib/active_record/attribute_methods/dirty.rb +172 -112
- data/lib/active_record/attribute_methods/primary_key.rb +88 -91
- data/lib/active_record/attribute_methods/query.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +18 -50
- data/lib/active_record/attribute_methods/serialization.rb +38 -10
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
- data/lib/active_record/attribute_methods/write.rb +25 -32
- data/lib/active_record/attributes.rb +69 -31
- data/lib/active_record/autosave_association.rb +102 -66
- data/lib/active_record/base.rb +16 -25
- data/lib/active_record/callbacks.rb +202 -43
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -12
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
- data/lib/active_record/connection_adapters/column.rb +55 -13
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- 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 +6 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -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 +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -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 +18 -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/quoting.rb +98 -38
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
- data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
- 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 +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +287 -45
- data/lib/active_record/core.rb +385 -181
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +122 -47
- data/lib/active_record/errors.rb +153 -22
- data/lib/active_record/explain.rb +13 -8
- 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 +20 -22
- 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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +246 -507
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +168 -95
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +114 -25
- data/lib/active_record/internal_metadata.rb +30 -24
- data/lib/active_record/legacy_yaml_adapter.rb +11 -5
- data/lib/active_record/locking/optimistic.rb +81 -85
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +68 -31
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +439 -342
- data/lib/active_record/migration/command_recorder.rb +152 -98
- data/lib/active_record/migration/compatibility.rb +229 -60
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +230 -122
- data/lib/active_record/nested_attributes.rb +213 -203
- data/lib/active_record/no_touching.rb +11 -2
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +471 -97
- data/lib/active_record/query_cache.rb +23 -12
- data/lib/active_record/querying.rb +43 -25
- data/lib/active_record/railtie.rb +155 -43
- 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 +507 -195
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +245 -269
- data/lib/active_record/relation.rb +475 -324
- data/lib/active_record/relation/batches.rb +125 -72
- data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
- data/lib/active_record/relation/calculations.rb +267 -171
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +238 -248
- data/lib/active_record/relation/from_clause.rb +7 -9
- data/lib/active_record/relation/merger.rb +95 -77
- data/lib/active_record/relation/predicate_builder.rb +109 -110
- data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +654 -374
- data/lib/active_record/relation/record_fetch_warning.rb +8 -6
- data/lib/active_record/relation/spawn_methods.rb +15 -14
- data/lib/active_record/relation/where_clause.rb +171 -109
- data/lib/active_record/result.rb +88 -51
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +73 -100
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +101 -69
- data/lib/active_record/schema_migration.rb +16 -12
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +39 -30
- data/lib/active_record/secure_token.rb +19 -9
- data/lib/active_record/serialization.rb +7 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +80 -29
- data/lib/active_record/store.rb +122 -42
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +51 -39
- data/lib/active_record/tasks/database_tasks.rb +332 -115
- data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
- data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +26 -24
- data/lib/active_record/transactions.rb +121 -184
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +29 -17
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- 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 -4
- 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 +20 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -13
- data/lib/active_record/type_caster/map.rb +10 -6
- data/lib/active_record/validations.rb +8 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +52 -45
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +54 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -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 +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.rb +70 -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 +45 -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/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -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 +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/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -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.rb +22 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
- 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 → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +141 -57
- 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.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_decorators.rb +0 -67
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
- 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/base_handler.rb +0 -17
- 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/relation/where_clause_factory.rb +0 -38
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
module Savepoints
|
@@ -6,15 +8,15 @@ module ActiveRecord
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def create_savepoint(name = current_savepoint_name)
|
9
|
-
execute("SAVEPOINT #{name}")
|
11
|
+
execute("SAVEPOINT #{name}", "TRANSACTION")
|
10
12
|
end
|
11
13
|
|
12
14
|
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
13
|
-
execute("ROLLBACK TO SAVEPOINT #{name}")
|
15
|
+
execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
|
14
16
|
end
|
15
17
|
|
16
18
|
def release_savepoint(name = current_savepoint_name)
|
17
|
-
execute("RELEASE SAVEPOINT #{name}")
|
19
|
+
execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -1,147 +1,189 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class SchemaCreation # :nodoc:
|
6
|
+
def initialize(conn)
|
7
|
+
@conn = conn
|
8
|
+
@cache = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def accept(o)
|
12
|
+
m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
|
13
|
+
send m, o
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
17
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, :foreign_key_options,
|
18
|
+
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?, :check_constraint_options,
|
19
|
+
to: :@conn, private: true
|
20
|
+
|
21
|
+
private
|
22
|
+
def visit_AlterTable(o)
|
23
|
+
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
24
|
+
sql << o.adds.map { |col| accept col }.join(" ")
|
25
|
+
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
26
|
+
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
27
|
+
sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
|
28
|
+
sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
|
29
|
+
end
|
30
|
+
|
31
|
+
def visit_ColumnDefinition(o)
|
32
|
+
o.sql_type = type_to_sql(o.type, **o.options)
|
33
|
+
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
34
|
+
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
35
|
+
column_sql
|
10
36
|
end
|
11
37
|
|
12
|
-
def
|
13
|
-
|
14
|
-
send m, o
|
38
|
+
def visit_AddColumnDefinition(o)
|
39
|
+
+"ADD #{accept(o.column)}"
|
15
40
|
end
|
16
41
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
42
|
+
def visit_TableDefinition(o)
|
43
|
+
create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
|
44
|
+
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
45
|
+
create_sql << "#{quote_table_name(o.name)} "
|
21
46
|
|
22
|
-
|
47
|
+
statements = o.columns.map { |c| accept c }
|
48
|
+
statements << accept(o.primary_keys) if o.primary_keys
|
23
49
|
|
24
|
-
|
25
|
-
|
26
|
-
sql << o.adds.map { |col| accept col }.join(' ')
|
27
|
-
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(' ')
|
28
|
-
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(' ')
|
50
|
+
if supports_indexes_in_create?
|
51
|
+
statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
|
29
52
|
end
|
30
53
|
|
31
|
-
|
32
|
-
o.
|
33
|
-
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
34
|
-
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
35
|
-
column_sql
|
54
|
+
if supports_foreign_keys?
|
55
|
+
statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
|
36
56
|
end
|
37
57
|
|
38
|
-
|
39
|
-
|
58
|
+
if supports_check_constraints?
|
59
|
+
statements.concat(o.check_constraints.map { |expression, options| check_constraint_in_create(o.name, expression, options) })
|
40
60
|
end
|
41
61
|
|
42
|
-
|
43
|
-
|
62
|
+
create_sql << "(#{statements.join(', ')})" if statements.present?
|
63
|
+
add_table_options!(create_sql, o)
|
64
|
+
create_sql << " AS #{to_sql(o.as)}" if o.as
|
65
|
+
create_sql
|
66
|
+
end
|
44
67
|
|
45
|
-
|
46
|
-
|
68
|
+
def visit_PrimaryKeyDefinition(o)
|
69
|
+
"PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
|
70
|
+
end
|
47
71
|
|
48
|
-
|
49
|
-
|
50
|
-
|
72
|
+
def visit_ForeignKeyDefinition(o)
|
73
|
+
sql = +<<~SQL
|
74
|
+
CONSTRAINT #{quote_column_name(o.name)}
|
75
|
+
FOREIGN KEY (#{quote_column_name(o.column)})
|
76
|
+
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
77
|
+
SQL
|
78
|
+
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
79
|
+
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
80
|
+
sql
|
81
|
+
end
|
51
82
|
|
52
|
-
|
53
|
-
|
54
|
-
|
83
|
+
def visit_AddForeignKey(o)
|
84
|
+
"ADD #{accept(o)}"
|
85
|
+
end
|
55
86
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
create_sql
|
60
|
-
end
|
87
|
+
def visit_DropForeignKey(name)
|
88
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
89
|
+
end
|
61
90
|
|
62
|
-
|
63
|
-
|
64
|
-
|
91
|
+
def visit_CreateIndexDefinition(o)
|
92
|
+
index = o.index
|
93
|
+
|
94
|
+
sql = ["CREATE"]
|
95
|
+
sql << "UNIQUE" if index.unique
|
96
|
+
sql << "INDEX"
|
97
|
+
sql << "IF NOT EXISTS" if o.if_not_exists
|
98
|
+
sql << o.algorithm if o.algorithm
|
99
|
+
sql << index.type if index.type
|
100
|
+
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
101
|
+
sql << "USING #{index.using}" if supports_index_using? && index.using
|
102
|
+
sql << "(#{quoted_columns(index)})"
|
103
|
+
sql << "WHERE #{index.where}" if supports_partial_index? && index.where
|
104
|
+
|
105
|
+
sql.join(" ")
|
106
|
+
end
|
65
107
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
FOREIGN KEY (#{quote_column_name(o.column)})
|
70
|
-
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
71
|
-
SQL
|
72
|
-
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
73
|
-
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
74
|
-
sql
|
75
|
-
end
|
108
|
+
def visit_CheckConstraintDefinition(o)
|
109
|
+
"CONSTRAINT #{o.name} CHECK (#{o.expression})"
|
110
|
+
end
|
76
111
|
|
77
|
-
|
78
|
-
|
79
|
-
|
112
|
+
def visit_AddCheckConstraint(o)
|
113
|
+
"ADD #{accept(o)}"
|
114
|
+
end
|
80
115
|
|
81
|
-
|
82
|
-
|
83
|
-
|
116
|
+
def visit_DropCheckConstraint(name)
|
117
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
118
|
+
end
|
84
119
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
table_options[:options] = o.options
|
89
|
-
table_options
|
90
|
-
end
|
120
|
+
def quoted_columns(o)
|
121
|
+
String === o.columns ? o.columns : quoted_columns_for_index(o.columns, o.column_options)
|
122
|
+
end
|
91
123
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
end
|
124
|
+
def supports_index_using?
|
125
|
+
true
|
126
|
+
end
|
97
127
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
column_options[:column] = o
|
103
|
-
column_options[:first] = o.first
|
104
|
-
column_options[:after] = o.after
|
105
|
-
column_options[:auto_increment] = o.auto_increment
|
106
|
-
column_options[:primary_key] = o.primary_key
|
107
|
-
column_options[:collation] = o.collation
|
108
|
-
column_options[:comment] = o.comment
|
109
|
-
column_options
|
110
|
-
end
|
128
|
+
def add_table_options!(create_sql, o)
|
129
|
+
create_sql << " #{o.options}" if o.options
|
130
|
+
create_sql
|
131
|
+
end
|
111
132
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
if options[:null] == false
|
116
|
-
sql << " NOT NULL"
|
117
|
-
end
|
118
|
-
if options[:auto_increment] == true
|
119
|
-
sql << " AUTO_INCREMENT"
|
120
|
-
end
|
121
|
-
if options[:primary_key] == true
|
122
|
-
sql << " PRIMARY KEY"
|
123
|
-
end
|
124
|
-
sql
|
125
|
-
end
|
133
|
+
def column_options(o)
|
134
|
+
o.options.merge(column: o)
|
135
|
+
end
|
126
136
|
|
127
|
-
|
128
|
-
|
129
|
-
|
137
|
+
def add_column_options!(sql, options)
|
138
|
+
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
139
|
+
# must explicitly check for :null to allow change_column to work on migrations
|
140
|
+
if options[:null] == false
|
141
|
+
sql << " NOT NULL"
|
142
|
+
end
|
143
|
+
if options[:auto_increment] == true
|
144
|
+
sql << " AUTO_INCREMENT"
|
130
145
|
end
|
146
|
+
if options[:primary_key] == true
|
147
|
+
sql << " PRIMARY KEY"
|
148
|
+
end
|
149
|
+
sql
|
150
|
+
end
|
131
151
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
152
|
+
def to_sql(sql)
|
153
|
+
sql = sql.to_sql if sql.respond_to?(:to_sql)
|
154
|
+
sql
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
158
|
+
def table_modifier_in_create(o)
|
159
|
+
" TEMPORARY" if o.temporary
|
160
|
+
end
|
161
|
+
|
162
|
+
def foreign_key_in_create(from_table, to_table, options)
|
163
|
+
prefix = ActiveRecord::Base.table_name_prefix
|
164
|
+
suffix = ActiveRecord::Base.table_name_suffix
|
165
|
+
to_table = "#{prefix}#{to_table}#{suffix}"
|
166
|
+
options = foreign_key_options(from_table, to_table, options)
|
167
|
+
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
168
|
+
end
|
169
|
+
|
170
|
+
def check_constraint_in_create(table_name, expression, options)
|
171
|
+
options = check_constraint_options(table_name, expression, options)
|
172
|
+
accept CheckConstraintDefinition.new(table_name, expression, options)
|
173
|
+
end
|
174
|
+
|
175
|
+
def action_sql(action, dependency)
|
176
|
+
case dependency
|
177
|
+
when :nullify then "ON #{action} SET NULL"
|
178
|
+
when :cascade then "ON #{action} CASCADE"
|
179
|
+
when :restrict then "ON #{action} RESTRICT"
|
180
|
+
else
|
181
|
+
raise ArgumentError, <<~MSG
|
182
|
+
'#{dependency}' is not supported for :on_update or :on_delete.
|
183
|
+
Supported values are: :nullify, :cascade, :restrict
|
184
|
+
MSG
|
143
185
|
end
|
144
|
-
|
186
|
+
end
|
145
187
|
end
|
146
188
|
end
|
147
189
|
end
|
@@ -1,32 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters #:nodoc:
|
3
5
|
# Abstract representation of an index definition on a table. Instances of
|
4
6
|
# this type are typically created and returned by methods in database
|
5
|
-
# adapters. e.g. ActiveRecord::ConnectionAdapters::
|
6
|
-
class IndexDefinition
|
7
|
+
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
8
|
+
class IndexDefinition # :nodoc:
|
9
|
+
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
table, name,
|
13
|
+
unique = false,
|
14
|
+
columns = [],
|
15
|
+
lengths: {},
|
16
|
+
orders: {},
|
17
|
+
opclasses: {},
|
18
|
+
where: nil,
|
19
|
+
type: nil,
|
20
|
+
using: nil,
|
21
|
+
comment: nil
|
22
|
+
)
|
23
|
+
@table = table
|
24
|
+
@name = name
|
25
|
+
@unique = unique
|
26
|
+
@columns = columns
|
27
|
+
@lengths = concise_options(lengths)
|
28
|
+
@orders = concise_options(orders)
|
29
|
+
@opclasses = concise_options(opclasses)
|
30
|
+
@where = where
|
31
|
+
@type = type
|
32
|
+
@using = using
|
33
|
+
@comment = comment
|
34
|
+
end
|
35
|
+
|
36
|
+
def column_options
|
37
|
+
{
|
38
|
+
length: lengths,
|
39
|
+
order: orders,
|
40
|
+
opclass: opclasses,
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def concise_options(options)
|
46
|
+
if columns.size == options.size && options.values.uniq.size == 1
|
47
|
+
options.values.first
|
48
|
+
else
|
49
|
+
options
|
50
|
+
end
|
51
|
+
end
|
7
52
|
end
|
8
53
|
|
9
54
|
# Abstract representation of a column definition. Instances of this type
|
10
55
|
# are typically created by methods in TableDefinition, and added to the
|
11
56
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
12
57
|
# for generating a number of table creation or table changing SQL statements.
|
13
|
-
|
14
|
-
|
58
|
+
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
15
59
|
def primary_key?
|
16
|
-
|
60
|
+
options[:primary_key]
|
17
61
|
end
|
18
|
-
end
|
19
62
|
|
20
|
-
|
21
|
-
|
63
|
+
[:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
|
64
|
+
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
65
|
+
def #{option_name}
|
66
|
+
options[:#{option_name}]
|
67
|
+
end
|
22
68
|
|
23
|
-
|
69
|
+
def #{option_name}=(value)
|
70
|
+
options[:#{option_name}] = value
|
71
|
+
end
|
72
|
+
CODE
|
73
|
+
end
|
24
74
|
end
|
25
75
|
|
26
|
-
|
27
|
-
|
76
|
+
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
77
|
+
|
78
|
+
ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
|
79
|
+
|
80
|
+
CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
|
81
|
+
|
82
|
+
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
28
83
|
|
29
|
-
|
84
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
|
30
85
|
def name
|
31
86
|
options[:name]
|
32
87
|
end
|
@@ -51,18 +106,39 @@ module ActiveRecord
|
|
51
106
|
options[:primary_key] != default_primary_key
|
52
107
|
end
|
53
108
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
109
|
+
def validate?
|
110
|
+
options.fetch(:validate, true)
|
111
|
+
end
|
112
|
+
alias validated? validate?
|
113
|
+
|
114
|
+
def export_name_on_schema_dump?
|
115
|
+
!ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
|
116
|
+
end
|
117
|
+
|
118
|
+
def defined_for?(to_table: nil, validate: nil, **options)
|
119
|
+
(to_table.nil? || to_table.to_s == self.to_table) &&
|
120
|
+
(validate.nil? || validate == options.fetch(:validate, validate)) &&
|
121
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
61
122
|
end
|
62
123
|
|
63
124
|
private
|
64
|
-
|
65
|
-
|
125
|
+
def default_primary_key
|
126
|
+
"id"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
|
131
|
+
def name
|
132
|
+
options[:name]
|
133
|
+
end
|
134
|
+
|
135
|
+
def validate?
|
136
|
+
options.fetch(:validate, true)
|
137
|
+
end
|
138
|
+
alias validated? validate?
|
139
|
+
|
140
|
+
def export_name_on_schema_dump?
|
141
|
+
!ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
|
66
142
|
end
|
67
143
|
end
|
68
144
|
|
@@ -72,7 +148,7 @@ module ActiveRecord
|
|
72
148
|
polymorphic: false,
|
73
149
|
index: true,
|
74
150
|
foreign_key: false,
|
75
|
-
type: :
|
151
|
+
type: :bigint,
|
76
152
|
**options
|
77
153
|
)
|
78
154
|
@name = name
|
@@ -88,98 +164,107 @@ module ActiveRecord
|
|
88
164
|
end
|
89
165
|
|
90
166
|
def add_to(table)
|
91
|
-
columns.each do |
|
92
|
-
table.column(
|
167
|
+
columns.each do |name, type, options|
|
168
|
+
table.column(name, type, **options)
|
93
169
|
end
|
94
170
|
|
95
171
|
if index
|
96
|
-
table.index(column_names, index_options)
|
172
|
+
table.index(column_names, **index_options(table.name))
|
97
173
|
end
|
98
174
|
|
99
175
|
if foreign_key
|
100
|
-
table.foreign_key(foreign_table_name, foreign_key_options)
|
176
|
+
table.foreign_key(foreign_table_name, **foreign_key_options)
|
101
177
|
end
|
102
178
|
end
|
103
179
|
|
104
|
-
protected
|
105
|
-
|
106
|
-
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
107
|
-
|
108
180
|
private
|
181
|
+
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
109
182
|
|
110
|
-
|
111
|
-
|
112
|
-
|
183
|
+
def as_options(value)
|
184
|
+
value.is_a?(Hash) ? value : {}
|
185
|
+
end
|
113
186
|
|
114
|
-
|
115
|
-
|
116
|
-
|
187
|
+
def polymorphic_options
|
188
|
+
as_options(polymorphic).merge(options.slice(:null, :first, :after))
|
189
|
+
end
|
117
190
|
|
118
|
-
|
119
|
-
|
120
|
-
|
191
|
+
def polymorphic_index_name(table_name)
|
192
|
+
"index_#{table_name}_on_#{name}"
|
193
|
+
end
|
121
194
|
|
122
|
-
|
123
|
-
|
124
|
-
|
195
|
+
def index_options(table_name)
|
196
|
+
index_options = as_options(index)
|
197
|
+
index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
|
198
|
+
index_options
|
199
|
+
end
|
125
200
|
|
126
|
-
|
127
|
-
|
128
|
-
if polymorphic
|
129
|
-
result.unshift(["#{name}_type", :string, polymorphic_options])
|
201
|
+
def foreign_key_options
|
202
|
+
as_options(foreign_key).merge(column: column_name)
|
130
203
|
end
|
131
|
-
result
|
132
|
-
end
|
133
204
|
|
134
|
-
|
135
|
-
|
136
|
-
|
205
|
+
def columns
|
206
|
+
result = [[column_name, type, options]]
|
207
|
+
if polymorphic
|
208
|
+
result.unshift(["#{name}_type", :string, polymorphic_options])
|
209
|
+
end
|
210
|
+
result
|
211
|
+
end
|
137
212
|
|
138
|
-
|
139
|
-
|
140
|
-
|
213
|
+
def column_name
|
214
|
+
"#{name}_id"
|
215
|
+
end
|
141
216
|
|
142
|
-
|
143
|
-
|
144
|
-
|
217
|
+
def column_names
|
218
|
+
columns.map(&:first)
|
219
|
+
end
|
220
|
+
|
221
|
+
def foreign_table_name
|
222
|
+
foreign_key_options.fetch(:to_table) do
|
223
|
+
Base.pluralize_table_names ? name.to_s.pluralize : name
|
224
|
+
end
|
145
225
|
end
|
146
|
-
end
|
147
226
|
end
|
148
227
|
|
149
228
|
module ColumnMethods
|
229
|
+
extend ActiveSupport::Concern
|
230
|
+
|
150
231
|
# Appends a primary key definition to the table definition.
|
151
232
|
# Can be called multiple times, but this is probably not a good idea.
|
152
233
|
def primary_key(name, type = :primary_key, **options)
|
153
|
-
column(name, type, options.merge(primary_key: true))
|
234
|
+
column(name, type, **options.merge(primary_key: true))
|
154
235
|
end
|
155
236
|
|
237
|
+
##
|
238
|
+
# :method: column
|
239
|
+
# :call-seq: column(name, type, **options)
|
240
|
+
#
|
156
241
|
# Appends a column or columns of a specified type.
|
157
242
|
#
|
158
243
|
# t.string(:goat)
|
159
244
|
# t.string(:goat, :sheep)
|
160
245
|
#
|
161
246
|
# See TableDefinition#column
|
162
|
-
|
163
|
-
|
164
|
-
:binary,
|
165
|
-
|
166
|
-
|
167
|
-
:
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
:
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
247
|
+
|
248
|
+
included do
|
249
|
+
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
250
|
+
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
251
|
+
|
252
|
+
alias :numeric :decimal
|
253
|
+
end
|
254
|
+
|
255
|
+
class_methods do
|
256
|
+
def define_column_methods(*column_types) # :nodoc:
|
257
|
+
column_types.each do |column_type|
|
258
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
259
|
+
def #{column_type}(*names, **options)
|
260
|
+
raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
|
261
|
+
names.each { |name| column(name, :#{column_type}, **options) }
|
262
|
+
end
|
263
|
+
RUBY
|
179
264
|
end
|
180
|
-
|
265
|
+
end
|
266
|
+
private :define_column_methods
|
181
267
|
end
|
182
|
-
alias_method :numeric, :decimal
|
183
268
|
end
|
184
269
|
|
185
270
|
# Represents the schema of an SQL table in an abstract way. This class
|
@@ -188,7 +273,7 @@ module ActiveRecord
|
|
188
273
|
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
189
274
|
# is actually of this type:
|
190
275
|
#
|
191
|
-
# class SomeMigration < ActiveRecord::Migration[
|
276
|
+
# class SomeMigration < ActiveRecord::Migration[6.0]
|
192
277
|
# def up
|
193
278
|
# create_table :foo do |t|
|
194
279
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -203,15 +288,26 @@ module ActiveRecord
|
|
203
288
|
class TableDefinition
|
204
289
|
include ColumnMethods
|
205
290
|
|
206
|
-
|
207
|
-
attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
|
291
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
|
208
292
|
|
209
|
-
def initialize(
|
293
|
+
def initialize(
|
294
|
+
conn,
|
295
|
+
name,
|
296
|
+
temporary: false,
|
297
|
+
if_not_exists: false,
|
298
|
+
options: nil,
|
299
|
+
as: nil,
|
300
|
+
comment: nil,
|
301
|
+
**
|
302
|
+
)
|
303
|
+
@conn = conn
|
210
304
|
@columns_hash = {}
|
211
305
|
@indexes = []
|
212
306
|
@foreign_keys = []
|
213
307
|
@primary_keys = nil
|
308
|
+
@check_constraints = []
|
214
309
|
@temporary = temporary
|
310
|
+
@if_not_exists = if_not_exists
|
215
311
|
@options = options
|
216
312
|
@as = as
|
217
313
|
@name = name
|
@@ -295,21 +391,28 @@ module ActiveRecord
|
|
295
391
|
#
|
296
392
|
# create_table :taggings do |t|
|
297
393
|
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
298
|
-
# t.references :tagger, polymorphic: true
|
299
|
-
# t.references :taggable, polymorphic: { default: 'Photo' }
|
394
|
+
# t.references :tagger, polymorphic: true
|
395
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
300
396
|
# end
|
301
|
-
def column(name, type,
|
397
|
+
def column(name, type, index: nil, **options)
|
302
398
|
name = name.to_s
|
303
399
|
type = type.to_sym if type
|
304
|
-
options = options.dup
|
305
400
|
|
306
|
-
if @columns_hash[name]
|
307
|
-
|
401
|
+
if @columns_hash[name]
|
402
|
+
if @columns_hash[name].primary_key?
|
403
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
404
|
+
else
|
405
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
@columns_hash[name] = new_column_definition(name, type, **options)
|
410
|
+
|
411
|
+
if index
|
412
|
+
index_options = index.is_a?(Hash) ? index : {}
|
413
|
+
index(name, **index_options)
|
308
414
|
end
|
309
415
|
|
310
|
-
index_options = options.delete(:index)
|
311
|
-
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
312
|
-
@columns_hash[name] = new_column_definition(name, type, options)
|
313
416
|
self
|
314
417
|
end
|
315
418
|
|
@@ -323,81 +426,87 @@ module ActiveRecord
|
|
323
426
|
# This is primarily used to track indexes that need to be created after the table
|
324
427
|
#
|
325
428
|
# index(:account_id, name: 'index_projects_on_account_id')
|
326
|
-
def index(column_name, options
|
429
|
+
def index(column_name, **options)
|
327
430
|
indexes << [column_name, options]
|
328
431
|
end
|
329
432
|
|
330
|
-
def foreign_key(table_name, options
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
433
|
+
def foreign_key(table_name, **options) # :nodoc:
|
434
|
+
foreign_keys << [table_name, options]
|
435
|
+
end
|
436
|
+
|
437
|
+
def check_constraint(expression, **options)
|
438
|
+
check_constraints << [expression, options]
|
335
439
|
end
|
336
440
|
|
337
441
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
338
442
|
# <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
339
443
|
#
|
340
444
|
# t.timestamps null: false
|
341
|
-
def timestamps(
|
342
|
-
options = args.extract_options!
|
343
|
-
|
445
|
+
def timestamps(**options)
|
344
446
|
options[:null] = false if options[:null].nil?
|
345
447
|
|
346
|
-
|
347
|
-
|
448
|
+
if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
449
|
+
options[:precision] = 6
|
450
|
+
end
|
451
|
+
|
452
|
+
column(:created_at, :datetime, **options)
|
453
|
+
column(:updated_at, :datetime, **options)
|
348
454
|
end
|
349
455
|
|
350
456
|
# Adds a reference.
|
351
457
|
#
|
352
458
|
# t.references(:user)
|
353
459
|
# t.belongs_to(:supplier, foreign_key: true)
|
460
|
+
# t.belongs_to(:supplier, foreign_key: true, type: :integer)
|
354
461
|
#
|
355
462
|
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
356
463
|
def references(*args, **options)
|
357
|
-
args.each do |
|
358
|
-
ReferenceDefinition.new(
|
464
|
+
args.each do |ref_name|
|
465
|
+
ReferenceDefinition.new(ref_name, **options).add_to(self)
|
359
466
|
end
|
360
467
|
end
|
361
468
|
alias :belongs_to :references
|
362
469
|
|
363
|
-
def new_column_definition(name, type, options) # :nodoc:
|
470
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
471
|
+
if integer_like_primary_key?(type, options)
|
472
|
+
type = integer_like_primary_key_type(type, options)
|
473
|
+
end
|
364
474
|
type = aliased_types(type.to_s, type)
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
column.precision = options[:precision]
|
369
|
-
column.scale = options[:scale]
|
370
|
-
column.default = options[:default]
|
371
|
-
column.null = options[:null]
|
372
|
-
column.first = options[:first]
|
373
|
-
column.after = options[:after]
|
374
|
-
column.auto_increment = options[:auto_increment]
|
375
|
-
column.primary_key = type == :primary_key || options[:primary_key]
|
376
|
-
column.collation = options[:collation]
|
377
|
-
column.comment = options[:comment]
|
378
|
-
column
|
475
|
+
options[:primary_key] ||= type == :primary_key
|
476
|
+
options[:null] = false if options[:primary_key]
|
477
|
+
create_column_definition(name, type, options)
|
379
478
|
end
|
380
479
|
|
381
480
|
private
|
382
|
-
|
383
|
-
|
384
|
-
|
481
|
+
def create_column_definition(name, type, options)
|
482
|
+
ColumnDefinition.new(name, type, options)
|
483
|
+
end
|
385
484
|
|
386
|
-
|
387
|
-
|
388
|
-
|
485
|
+
def aliased_types(name, fallback)
|
486
|
+
"timestamp" == name ? :datetime : fallback
|
487
|
+
end
|
488
|
+
|
489
|
+
def integer_like_primary_key?(type, options)
|
490
|
+
options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
|
491
|
+
end
|
492
|
+
|
493
|
+
def integer_like_primary_key_type(type, options)
|
494
|
+
type
|
495
|
+
end
|
389
496
|
end
|
390
497
|
|
391
498
|
class AlterTable # :nodoc:
|
392
499
|
attr_reader :adds
|
393
|
-
attr_reader :foreign_key_adds
|
394
|
-
attr_reader :
|
500
|
+
attr_reader :foreign_key_adds, :foreign_key_drops
|
501
|
+
attr_reader :check_constraint_adds, :check_constraint_drops
|
395
502
|
|
396
503
|
def initialize(td)
|
397
504
|
@td = td
|
398
505
|
@adds = []
|
399
506
|
@foreign_key_adds = []
|
400
507
|
@foreign_key_drops = []
|
508
|
+
@check_constraint_adds = []
|
509
|
+
@check_constraint_drops = []
|
401
510
|
end
|
402
511
|
|
403
512
|
def name; @td.name; end
|
@@ -410,10 +519,18 @@ module ActiveRecord
|
|
410
519
|
@foreign_key_drops << name
|
411
520
|
end
|
412
521
|
|
413
|
-
def
|
522
|
+
def add_check_constraint(expression, options)
|
523
|
+
@check_constraint_adds << CheckConstraintDefinition.new(name, expression, options)
|
524
|
+
end
|
525
|
+
|
526
|
+
def drop_check_constraint(constraint_name)
|
527
|
+
@check_constraint_drops << constraint_name
|
528
|
+
end
|
529
|
+
|
530
|
+
def add_column(name, type, **options)
|
414
531
|
name = name.to_s
|
415
532
|
type = type.to_sym
|
416
|
-
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
|
533
|
+
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
|
417
534
|
end
|
418
535
|
end
|
419
536
|
|
@@ -430,9 +547,11 @@ module ActiveRecord
|
|
430
547
|
# t.timestamps
|
431
548
|
# t.change
|
432
549
|
# t.change_default
|
550
|
+
# t.change_null
|
433
551
|
# t.rename
|
434
552
|
# t.references
|
435
553
|
# t.belongs_to
|
554
|
+
# t.check_constraint
|
436
555
|
# t.string
|
437
556
|
# t.text
|
438
557
|
# t.integer
|
@@ -446,10 +565,15 @@ module ActiveRecord
|
|
446
565
|
# t.date
|
447
566
|
# t.binary
|
448
567
|
# t.boolean
|
568
|
+
# t.foreign_key
|
569
|
+
# t.json
|
570
|
+
# t.virtual
|
449
571
|
# t.remove
|
572
|
+
# t.remove_foreign_key
|
450
573
|
# t.remove_references
|
451
574
|
# t.remove_belongs_to
|
452
575
|
# t.remove_index
|
576
|
+
# t.remove_check_constraint
|
453
577
|
# t.remove_timestamps
|
454
578
|
# end
|
455
579
|
#
|
@@ -468,17 +592,21 @@ module ActiveRecord
|
|
468
592
|
# t.column(:name, :string)
|
469
593
|
#
|
470
594
|
# See TableDefinition#column for details of the options you can use.
|
471
|
-
def column(column_name, type,
|
472
|
-
@base.add_column(name, column_name, type, options)
|
595
|
+
def column(column_name, type, index: nil, **options)
|
596
|
+
@base.add_column(name, column_name, type, **options)
|
597
|
+
if index
|
598
|
+
index_options = index.is_a?(Hash) ? index : {}
|
599
|
+
index(column_name, **index_options)
|
600
|
+
end
|
473
601
|
end
|
474
602
|
|
475
603
|
# Checks to see if a column exists.
|
476
604
|
#
|
477
|
-
#
|
605
|
+
# t.string(:name) unless t.column_exists?(:name, :string)
|
478
606
|
#
|
479
607
|
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
|
480
|
-
def column_exists?(column_name, type = nil, options
|
481
|
-
@base.column_exists?(name, column_name, type, options)
|
608
|
+
def column_exists?(column_name, type = nil, **options)
|
609
|
+
@base.column_exists?(name, column_name, type, **options)
|
482
610
|
end
|
483
611
|
|
484
612
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
@@ -489,15 +617,15 @@ module ActiveRecord
|
|
489
617
|
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
490
618
|
#
|
491
619
|
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
|
492
|
-
def index(column_name, options
|
493
|
-
@base.add_index(name, column_name, options)
|
620
|
+
def index(column_name, **options)
|
621
|
+
@base.add_index(name, column_name, **options)
|
494
622
|
end
|
495
623
|
|
496
624
|
# Checks to see if an index exists.
|
497
625
|
#
|
498
|
-
#
|
499
|
-
#
|
500
|
-
#
|
626
|
+
# unless t.index_exists?(:branch_id)
|
627
|
+
# t.index(:branch_id)
|
628
|
+
# end
|
501
629
|
#
|
502
630
|
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
503
631
|
def index_exists?(column_name, options = {})
|
@@ -518,8 +646,8 @@ module ActiveRecord
|
|
518
646
|
# t.timestamps(null: false)
|
519
647
|
#
|
520
648
|
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
521
|
-
def timestamps(options
|
522
|
-
@base.add_timestamps(name, options)
|
649
|
+
def timestamps(**options)
|
650
|
+
@base.add_timestamps(name, **options)
|
523
651
|
end
|
524
652
|
|
525
653
|
# Changes the column's definition according to the new options.
|
@@ -528,8 +656,8 @@ module ActiveRecord
|
|
528
656
|
# t.change(:description, :text)
|
529
657
|
#
|
530
658
|
# See TableDefinition#column for details of the options you can use.
|
531
|
-
def change(column_name, type, options
|
532
|
-
@base.change_column(name, column_name, type, options)
|
659
|
+
def change(column_name, type, **options)
|
660
|
+
@base.change_column(name, column_name, type, **options)
|
533
661
|
end
|
534
662
|
|
535
663
|
# Sets a new default value for a column.
|
@@ -543,14 +671,24 @@ module ActiveRecord
|
|
543
671
|
@base.change_column_default(name, column_name, default_or_changes)
|
544
672
|
end
|
545
673
|
|
674
|
+
# Sets or removes a NOT NULL constraint on a column.
|
675
|
+
#
|
676
|
+
# t.change_null(:qualification, true)
|
677
|
+
# t.change_null(:qualification, false, 0)
|
678
|
+
#
|
679
|
+
# See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
|
680
|
+
def change_null(column_name, null, default = nil)
|
681
|
+
@base.change_column_null(name, column_name, null, default)
|
682
|
+
end
|
683
|
+
|
546
684
|
# Removes the column(s) from the table definition.
|
547
685
|
#
|
548
686
|
# t.remove(:qualification)
|
549
687
|
# t.remove(:qualification, :experience)
|
550
688
|
#
|
551
689
|
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
|
552
|
-
def remove(*column_names)
|
553
|
-
@base.remove_columns(name, *column_names)
|
690
|
+
def remove(*column_names, **options)
|
691
|
+
@base.remove_columns(name, *column_names, **options)
|
554
692
|
end
|
555
693
|
|
556
694
|
# Removes the given index from the table.
|
@@ -558,10 +696,11 @@ module ActiveRecord
|
|
558
696
|
# t.remove_index(:branch_id)
|
559
697
|
# t.remove_index(column: [:branch_id, :party_id])
|
560
698
|
# t.remove_index(name: :by_branch_party)
|
699
|
+
# t.remove_index(:branch_id, name: :by_branch_party)
|
561
700
|
#
|
562
701
|
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
|
563
|
-
def remove_index(
|
564
|
-
@base.remove_index(name, options)
|
702
|
+
def remove_index(column_name = nil, **options)
|
703
|
+
@base.remove_index(name, column_name, **options)
|
565
704
|
end
|
566
705
|
|
567
706
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
@@ -569,8 +708,8 @@ module ActiveRecord
|
|
569
708
|
# t.remove_timestamps
|
570
709
|
#
|
571
710
|
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
|
572
|
-
def remove_timestamps(options
|
573
|
-
@base.remove_timestamps(name, options)
|
711
|
+
def remove_timestamps(**options)
|
712
|
+
@base.remove_timestamps(name, **options)
|
574
713
|
end
|
575
714
|
|
576
715
|
# Renames a column.
|
@@ -588,10 +727,9 @@ module ActiveRecord
|
|
588
727
|
# t.belongs_to(:supplier, foreign_key: true)
|
589
728
|
#
|
590
729
|
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
591
|
-
def references(*args)
|
592
|
-
options = args.extract_options!
|
730
|
+
def references(*args, **options)
|
593
731
|
args.each do |ref_name|
|
594
|
-
@base.add_reference(name, ref_name, options)
|
732
|
+
@base.add_reference(name, ref_name, **options)
|
595
733
|
end
|
596
734
|
end
|
597
735
|
alias :belongs_to :references
|
@@ -602,30 +740,58 @@ module ActiveRecord
|
|
602
740
|
# t.remove_belongs_to(:supplier, polymorphic: true)
|
603
741
|
#
|
604
742
|
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
|
605
|
-
def remove_references(*args)
|
606
|
-
options = args.extract_options!
|
743
|
+
def remove_references(*args, **options)
|
607
744
|
args.each do |ref_name|
|
608
|
-
@base.remove_reference(name, ref_name, options)
|
745
|
+
@base.remove_reference(name, ref_name, **options)
|
609
746
|
end
|
610
747
|
end
|
611
748
|
alias :remove_belongs_to :remove_references
|
612
749
|
|
613
|
-
# Adds a foreign key.
|
750
|
+
# Adds a foreign key to the table using a supplied table name.
|
614
751
|
#
|
615
|
-
#
|
752
|
+
# t.foreign_key(:authors)
|
753
|
+
# t.foreign_key(:authors, column: :author_id, primary_key: "id")
|
616
754
|
#
|
617
755
|
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
|
618
|
-
def foreign_key(*args)
|
619
|
-
@base.add_foreign_key(name, *args)
|
756
|
+
def foreign_key(*args, **options)
|
757
|
+
@base.add_foreign_key(name, *args, **options)
|
758
|
+
end
|
759
|
+
|
760
|
+
# Removes the given foreign key from the table.
|
761
|
+
#
|
762
|
+
# t.remove_foreign_key(:authors)
|
763
|
+
# t.remove_foreign_key(column: :author_id)
|
764
|
+
#
|
765
|
+
# See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
|
766
|
+
def remove_foreign_key(*args, **options)
|
767
|
+
@base.remove_foreign_key(name, *args, **options)
|
620
768
|
end
|
621
769
|
|
622
770
|
# Checks to see if a foreign key exists.
|
623
771
|
#
|
624
|
-
#
|
772
|
+
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
|
625
773
|
#
|
626
774
|
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
|
627
|
-
def foreign_key_exists?(*args)
|
628
|
-
@base.foreign_key_exists?(name, *args)
|
775
|
+
def foreign_key_exists?(*args, **options)
|
776
|
+
@base.foreign_key_exists?(name, *args, **options)
|
777
|
+
end
|
778
|
+
|
779
|
+
# Adds a check constraint.
|
780
|
+
#
|
781
|
+
# t.check_constraint("price > 0", name: "price_check")
|
782
|
+
#
|
783
|
+
# See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
|
784
|
+
def check_constraint(*args)
|
785
|
+
@base.add_check_constraint(name, *args)
|
786
|
+
end
|
787
|
+
|
788
|
+
# Removes the given check constraint from the table.
|
789
|
+
#
|
790
|
+
# t.remove_check_constraint(name: "price_check")
|
791
|
+
#
|
792
|
+
# See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
|
793
|
+
def remove_check_constraint(*args)
|
794
|
+
@base.remove_check_constraint(name, *args)
|
629
795
|
end
|
630
796
|
end
|
631
797
|
end
|