activerecord 4.2.9 → 6.1.4.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 +964 -1382
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +40 -15
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +162 -69
- data/lib/active_record/associations/association_scope.rb +105 -130
- data/lib/active_record/associations/belongs_to_association.rb +83 -65
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -37
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +148 -287
- data/lib/active_record/associations/collection_proxy.rb +252 -150
- data/lib/active_record/associations/foreign_association.rb +23 -1
- data/lib/active_record/associations/has_many_association.rb +56 -98
- data/lib/active_record/associations/has_many_through_association.rb +68 -89
- data/lib/active_record/associations/has_one_association.rb +73 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
- 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/join_dependency.rb +174 -169
- data/lib/active_record/associations/preloader/association.rb +108 -115
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +97 -94
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +39 -19
- data/lib/active_record/associations.rb +1845 -1598
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
- data/lib/active_record/attribute_methods/dirty.rb +168 -148
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
- data/lib/active_record/attribute_methods/write.rb +24 -55
- data/lib/active_record/attribute_methods.rb +149 -154
- data/lib/active_record/attributes.rb +234 -78
- data/lib/active_record/autosave_association.rb +133 -60
- data/lib/active_record/base.rb +46 -46
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
- data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
- 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 +31 -20
- 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 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- 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 +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
- data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- 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 +322 -373
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +458 -241
- data/lib/active_record/counter_cache.rb +70 -49
- 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/database_configurations.rb +272 -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 -106
- data/lib/active_record/enum.rb +211 -92
- data/lib/active_record/errors.rb +224 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +33 -14
- 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 +275 -500
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +62 -0
- data/lib/active_record/legacy_yaml_adapter.rb +27 -5
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +98 -92
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +295 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +673 -325
- data/lib/active_record/model_schema.rb +418 -113
- data/lib/active_record/nested_attributes.rb +263 -224
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +572 -136
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +170 -51
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +523 -199
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +454 -291
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +324 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +316 -242
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +95 -103
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +136 -122
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -413
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -20
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -343
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -23
- data/lib/active_record/scoping/default.rb +96 -83
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +128 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +364 -130
- data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
- data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +182 -163
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +27 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +63 -56
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -29
- 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/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 +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +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 +70 -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/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/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- 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 +172 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- 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 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,31 +1,91 @@
|
|
1
|
-
|
2
|
-
require 'set'
|
3
|
-
require 'bigdecimal'
|
4
|
-
require 'bigdecimal/util'
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
3
|
module ActiveRecord
|
7
4
|
module ConnectionAdapters #:nodoc:
|
8
5
|
# Abstract representation of an index definition on a table. Instances of
|
9
6
|
# this type are typically created and returned by methods in database
|
10
|
-
# adapters. e.g. ActiveRecord::ConnectionAdapters::
|
11
|
-
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
|
12
52
|
end
|
13
53
|
|
14
54
|
# Abstract representation of a column definition. Instances of this type
|
15
55
|
# are typically created by methods in TableDefinition, and added to the
|
16
56
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
17
57
|
# for generating a number of table creation or table changing SQL statements.
|
18
|
-
|
19
|
-
|
58
|
+
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
20
59
|
def primary_key?
|
21
|
-
|
60
|
+
options[:primary_key]
|
22
61
|
end
|
23
|
-
end
|
24
62
|
|
25
|
-
|
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
|
68
|
+
|
69
|
+
def #{option_name}=(value)
|
70
|
+
options[:#{option_name}] = value
|
71
|
+
end
|
72
|
+
CODE
|
73
|
+
end
|
74
|
+
|
75
|
+
def aliased_types(name, fallback)
|
76
|
+
"timestamp" == name ? :datetime : fallback
|
77
|
+
end
|
26
78
|
end
|
27
79
|
|
28
|
-
|
80
|
+
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
81
|
+
|
82
|
+
ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
|
83
|
+
|
84
|
+
CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
|
85
|
+
|
86
|
+
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
87
|
+
|
88
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
|
29
89
|
def name
|
30
90
|
options[:name]
|
31
91
|
end
|
@@ -50,31 +110,174 @@ module ActiveRecord
|
|
50
110
|
options[:primary_key] != default_primary_key
|
51
111
|
end
|
52
112
|
|
113
|
+
def validate?
|
114
|
+
options.fetch(:validate, true)
|
115
|
+
end
|
116
|
+
alias validated? validate?
|
117
|
+
|
118
|
+
def export_name_on_schema_dump?
|
119
|
+
!ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
|
120
|
+
end
|
121
|
+
|
122
|
+
def defined_for?(to_table: nil, validate: nil, **options)
|
123
|
+
(to_table.nil? || to_table.to_s == self.to_table) &&
|
124
|
+
(validate.nil? || validate == options.fetch(:validate, validate)) &&
|
125
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
126
|
+
end
|
127
|
+
|
53
128
|
private
|
54
|
-
|
55
|
-
|
129
|
+
def default_primary_key
|
130
|
+
"id"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
|
135
|
+
def name
|
136
|
+
options[:name]
|
137
|
+
end
|
138
|
+
|
139
|
+
def validate?
|
140
|
+
options.fetch(:validate, true)
|
141
|
+
end
|
142
|
+
alias validated? validate?
|
143
|
+
|
144
|
+
def export_name_on_schema_dump?
|
145
|
+
!ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class ReferenceDefinition # :nodoc:
|
150
|
+
def initialize(
|
151
|
+
name,
|
152
|
+
polymorphic: false,
|
153
|
+
index: true,
|
154
|
+
foreign_key: false,
|
155
|
+
type: :bigint,
|
156
|
+
**options
|
157
|
+
)
|
158
|
+
@name = name
|
159
|
+
@polymorphic = polymorphic
|
160
|
+
@index = index
|
161
|
+
@foreign_key = foreign_key
|
162
|
+
@type = type
|
163
|
+
@options = options
|
164
|
+
|
165
|
+
if polymorphic && foreign_key
|
166
|
+
raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_to(table)
|
171
|
+
columns.each do |name, type, options|
|
172
|
+
table.column(name, type, **options)
|
173
|
+
end
|
174
|
+
|
175
|
+
if index
|
176
|
+
table.index(column_names, **index_options(table.name))
|
177
|
+
end
|
178
|
+
|
179
|
+
if foreign_key
|
180
|
+
table.foreign_key(foreign_table_name, **foreign_key_options)
|
181
|
+
end
|
56
182
|
end
|
183
|
+
|
184
|
+
private
|
185
|
+
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
186
|
+
|
187
|
+
def as_options(value)
|
188
|
+
value.is_a?(Hash) ? value : {}
|
189
|
+
end
|
190
|
+
|
191
|
+
def polymorphic_options
|
192
|
+
as_options(polymorphic).merge(options.slice(:null, :first, :after))
|
193
|
+
end
|
194
|
+
|
195
|
+
def polymorphic_index_name(table_name)
|
196
|
+
"index_#{table_name}_on_#{name}"
|
197
|
+
end
|
198
|
+
|
199
|
+
def index_options(table_name)
|
200
|
+
index_options = as_options(index)
|
201
|
+
index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
|
202
|
+
index_options
|
203
|
+
end
|
204
|
+
|
205
|
+
def foreign_key_options
|
206
|
+
as_options(foreign_key).merge(column: column_name)
|
207
|
+
end
|
208
|
+
|
209
|
+
def columns
|
210
|
+
result = [[column_name, type, options]]
|
211
|
+
if polymorphic
|
212
|
+
result.unshift(["#{name}_type", :string, polymorphic_options])
|
213
|
+
end
|
214
|
+
result
|
215
|
+
end
|
216
|
+
|
217
|
+
def column_name
|
218
|
+
"#{name}_id"
|
219
|
+
end
|
220
|
+
|
221
|
+
def column_names
|
222
|
+
columns.map(&:first)
|
223
|
+
end
|
224
|
+
|
225
|
+
def foreign_table_name
|
226
|
+
foreign_key_options.fetch(:to_table) do
|
227
|
+
Base.pluralize_table_names ? name.to_s.pluralize : name
|
228
|
+
end
|
229
|
+
end
|
57
230
|
end
|
58
231
|
|
59
|
-
module
|
60
|
-
|
61
|
-
return if options.key?(:null)
|
232
|
+
module ColumnMethods
|
233
|
+
extend ActiveSupport::Concern
|
62
234
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
235
|
+
# Appends a primary key definition to the table definition.
|
236
|
+
# Can be called multiple times, but this is probably not a good idea.
|
237
|
+
def primary_key(name, type = :primary_key, **options)
|
238
|
+
column(name, type, **options.merge(primary_key: true))
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# :method: column
|
243
|
+
# :call-seq: column(name, type, **options)
|
244
|
+
#
|
245
|
+
# Appends a column or columns of a specified type.
|
246
|
+
#
|
247
|
+
# t.string(:goat)
|
248
|
+
# t.string(:goat, :sheep)
|
249
|
+
#
|
250
|
+
# See TableDefinition#column
|
251
|
+
|
252
|
+
included do
|
253
|
+
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
254
|
+
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
255
|
+
|
256
|
+
alias :numeric :decimal
|
257
|
+
end
|
258
|
+
|
259
|
+
class_methods do
|
260
|
+
def define_column_methods(*column_types) # :nodoc:
|
261
|
+
column_types.each do |column_type|
|
262
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
263
|
+
def #{column_type}(*names, **options)
|
264
|
+
raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
|
265
|
+
names.each { |name| column(name, :#{column_type}, **options) }
|
266
|
+
end
|
267
|
+
RUBY
|
268
|
+
end
|
269
|
+
end
|
270
|
+
private :define_column_methods
|
68
271
|
end
|
69
272
|
end
|
70
273
|
|
71
274
|
# Represents the schema of an SQL table in an abstract way. This class
|
72
275
|
# provides methods for manipulating the schema representation.
|
73
276
|
#
|
74
|
-
# Inside migration files, the +t+ object in
|
277
|
+
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
75
278
|
# is actually of this type:
|
76
279
|
#
|
77
|
-
# class SomeMigration < ActiveRecord::Migration
|
280
|
+
# class SomeMigration < ActiveRecord::Migration[6.0]
|
78
281
|
# def up
|
79
282
|
# create_table :foo do |t|
|
80
283
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -86,125 +289,66 @@ module ActiveRecord
|
|
86
289
|
# end
|
87
290
|
# end
|
88
291
|
#
|
89
|
-
# The table definitions
|
90
|
-
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
91
292
|
class TableDefinition
|
92
|
-
include
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
293
|
+
include ColumnMethods
|
294
|
+
|
295
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
|
296
|
+
|
297
|
+
def initialize(
|
298
|
+
conn,
|
299
|
+
name,
|
300
|
+
temporary: false,
|
301
|
+
if_not_exists: false,
|
302
|
+
options: nil,
|
303
|
+
as: nil,
|
304
|
+
comment: nil,
|
305
|
+
**
|
306
|
+
)
|
307
|
+
@conn = conn
|
100
308
|
@columns_hash = {}
|
101
|
-
@indexes =
|
309
|
+
@indexes = []
|
102
310
|
@foreign_keys = []
|
103
|
-
@
|
311
|
+
@primary_keys = nil
|
312
|
+
@check_constraints = []
|
104
313
|
@temporary = temporary
|
314
|
+
@if_not_exists = if_not_exists
|
105
315
|
@options = options
|
106
316
|
@as = as
|
107
317
|
@name = name
|
318
|
+
@comment = comment
|
108
319
|
end
|
109
320
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
# Can be called multiple times, but this is probably not a good idea.
|
114
|
-
def primary_key(name, type = :primary_key, options = {})
|
115
|
-
column(name, type, options.merge(:primary_key => true))
|
321
|
+
def primary_keys(name = nil) # :nodoc:
|
322
|
+
@primary_keys = PrimaryKeyDefinition.new(name) if name
|
323
|
+
@primary_keys
|
116
324
|
end
|
117
325
|
|
326
|
+
# Returns an array of ColumnDefinition objects for the columns of the table.
|
327
|
+
def columns; @columns_hash.values; end
|
328
|
+
|
118
329
|
# Returns a ColumnDefinition for the column with name +name+.
|
119
330
|
def [](name)
|
120
331
|
@columns_hash[name.to_s]
|
121
332
|
end
|
122
333
|
|
123
334
|
# Instantiates a new column for the table.
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
129
|
-
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
130
|
-
#
|
131
|
-
# You may use a type not in this list as long as it is supported by your
|
132
|
-
# database (for example, "polygon" in MySQL), but this will not be database
|
133
|
-
# agnostic and should usually be avoided.
|
134
|
-
#
|
135
|
-
# Available options are (none of these exists by default):
|
136
|
-
# * <tt>:limit</tt> -
|
137
|
-
# Requests a maximum column length. This is number of characters for <tt>:string</tt> and
|
138
|
-
# <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
|
139
|
-
# * <tt>:default</tt> -
|
140
|
-
# The column's default value. Use nil for NULL.
|
141
|
-
# * <tt>:null</tt> -
|
142
|
-
# Allows or disallows +NULL+ values in the column. This option could
|
143
|
-
# have been named <tt>:null_allowed</tt>.
|
144
|
-
# * <tt>:precision</tt> -
|
145
|
-
# Specifies the precision for a <tt>:decimal</tt> column.
|
146
|
-
# * <tt>:scale</tt> -
|
147
|
-
# Specifies the scale for a <tt>:decimal</tt> column.
|
335
|
+
# See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
|
336
|
+
# for available options.
|
337
|
+
#
|
338
|
+
# Additional options are:
|
148
339
|
# * <tt>:index</tt> -
|
149
340
|
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
|
150
341
|
#
|
151
|
-
# Note: The precision is the total number of significant digits
|
152
|
-
# and the scale is the number of digits that can be stored following
|
153
|
-
# the decimal point. For example, the number 123.45 has a precision of 5
|
154
|
-
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
155
|
-
# range from -999.99 to 999.99.
|
156
|
-
#
|
157
|
-
# Please be aware of different RDBMS implementations behavior with
|
158
|
-
# <tt>:decimal</tt> columns:
|
159
|
-
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
|
160
|
-
# <tt>:precision</tt>, and makes no comments about the requirements of
|
161
|
-
# <tt>:precision</tt>.
|
162
|
-
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
|
163
|
-
# Default is (10,0).
|
164
|
-
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
165
|
-
# <tt>:scale</tt> [0..infinity]. No default.
|
166
|
-
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
|
167
|
-
# Internal storage as strings. No default.
|
168
|
-
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
169
|
-
# but the maximum supported <tt>:precision</tt> is 16. No default.
|
170
|
-
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
|
171
|
-
# Default is (38,0).
|
172
|
-
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
173
|
-
# Default unknown.
|
174
|
-
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
175
|
-
# Default (38,0).
|
176
|
-
#
|
177
342
|
# This method returns <tt>self</tt>.
|
178
343
|
#
|
179
344
|
# == Examples
|
180
|
-
# # Assuming +td+ is an instance of TableDefinition
|
181
|
-
# td.column(:granted, :boolean)
|
182
|
-
# # granted BOOLEAN
|
183
345
|
#
|
184
|
-
# td
|
185
|
-
#
|
186
|
-
#
|
187
|
-
# td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
|
188
|
-
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
189
|
-
#
|
190
|
-
# td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
|
191
|
-
# # => bill_gates_money DECIMAL(15,2)
|
192
|
-
#
|
193
|
-
# td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
|
194
|
-
# # => sensor_reading DECIMAL(30,20)
|
195
|
-
#
|
196
|
-
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
197
|
-
# # probably wouldn't hurt to include it.
|
198
|
-
# td.column(:huge_integer, :decimal, precision: 30)
|
199
|
-
# # => huge_integer DECIMAL(30)
|
200
|
-
#
|
201
|
-
# # Defines a column with a database-specific type.
|
202
|
-
# td.column(:foo, 'polygon')
|
203
|
-
# # => foo polygon
|
346
|
+
# # Assuming +td+ is an instance of TableDefinition
|
347
|
+
# td.column(:granted, :boolean, index: true)
|
204
348
|
#
|
205
349
|
# == Short-hand examples
|
206
350
|
#
|
207
|
-
# Instead of calling
|
351
|
+
# Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
|
208
352
|
# They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
|
209
353
|
# in a single statement.
|
210
354
|
#
|
@@ -236,7 +380,8 @@ module ActiveRecord
|
|
236
380
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
237
381
|
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
|
238
382
|
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
|
239
|
-
# will also create an index, similar to calling
|
383
|
+
# will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
|
384
|
+
# So what can be written like this:
|
240
385
|
#
|
241
386
|
# create_table :taggings do |t|
|
242
387
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
@@ -250,130 +395,122 @@ module ActiveRecord
|
|
250
395
|
#
|
251
396
|
# create_table :taggings do |t|
|
252
397
|
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
253
|
-
# t.references :tagger, polymorphic: true
|
254
|
-
# t.references :taggable, polymorphic: { default: 'Photo' }
|
398
|
+
# t.references :tagger, polymorphic: true
|
399
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
255
400
|
# end
|
256
|
-
def column(name, type,
|
401
|
+
def column(name, type, index: nil, **options)
|
257
402
|
name = name.to_s
|
258
|
-
type = type.to_sym
|
259
|
-
|
403
|
+
type = type.to_sym if type
|
404
|
+
|
405
|
+
if @columns_hash[name]
|
406
|
+
if @columns_hash[name].primary_key?
|
407
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
408
|
+
else
|
409
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
@columns_hash[name] = new_column_definition(name, type, **options)
|
260
414
|
|
261
|
-
if
|
262
|
-
|
415
|
+
if index
|
416
|
+
index_options = index.is_a?(Hash) ? index : {}
|
417
|
+
index(name, **index_options)
|
263
418
|
end
|
264
419
|
|
265
|
-
index_options = options.delete(:index)
|
266
|
-
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
267
|
-
@columns_hash[name] = new_column_definition(name, type, options)
|
268
420
|
self
|
269
421
|
end
|
270
422
|
|
423
|
+
# remove the column +name+ from the table.
|
424
|
+
# remove_column(:account_id)
|
271
425
|
def remove_column(name)
|
272
426
|
@columns_hash.delete name.to_s
|
273
427
|
end
|
274
428
|
|
275
|
-
[:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
276
|
-
define_method column_type do |*args|
|
277
|
-
options = args.extract_options!
|
278
|
-
column_names = args
|
279
|
-
column_names.each { |name| column(name, column_type, options) }
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
429
|
# Adds index options to the indexes hash, keyed by column name
|
284
430
|
# This is primarily used to track indexes that need to be created after the table
|
285
431
|
#
|
286
432
|
# index(:account_id, name: 'index_projects_on_account_id')
|
287
|
-
def index(column_name, options
|
288
|
-
indexes[column_name
|
433
|
+
def index(column_name, **options)
|
434
|
+
indexes << [column_name, options]
|
289
435
|
end
|
290
436
|
|
291
|
-
def foreign_key(table_name, options
|
292
|
-
foreign_keys
|
437
|
+
def foreign_key(table_name, **options) # :nodoc:
|
438
|
+
foreign_keys << [table_name, options]
|
439
|
+
end
|
440
|
+
|
441
|
+
def check_constraint(expression, **options)
|
442
|
+
check_constraints << [expression, options]
|
293
443
|
end
|
294
444
|
|
295
445
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
296
|
-
# <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
|
446
|
+
# <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
297
447
|
#
|
298
448
|
# t.timestamps null: false
|
299
|
-
def timestamps(
|
300
|
-
options =
|
301
|
-
|
302
|
-
|
303
|
-
|
449
|
+
def timestamps(**options)
|
450
|
+
options[:null] = false if options[:null].nil?
|
451
|
+
|
452
|
+
if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
453
|
+
options[:precision] = 6
|
454
|
+
end
|
455
|
+
|
456
|
+
column(:created_at, :datetime, **options)
|
457
|
+
column(:updated_at, :datetime, **options)
|
304
458
|
end
|
305
459
|
|
306
460
|
# Adds a reference.
|
307
461
|
#
|
308
462
|
# t.references(:user)
|
309
463
|
# t.belongs_to(:supplier, foreign_key: true)
|
464
|
+
# t.belongs_to(:supplier, foreign_key: true, type: :integer)
|
310
465
|
#
|
311
|
-
# See SchemaStatements#add_reference for details of the options you can use.
|
312
|
-
def references(*args)
|
313
|
-
|
314
|
-
|
315
|
-
index_options = options.delete(:index)
|
316
|
-
foreign_key_options = options.delete(:foreign_key)
|
317
|
-
type = options.delete(:type) || :integer
|
318
|
-
|
319
|
-
if polymorphic && foreign_key_options
|
320
|
-
raise ArgumentError, "Cannot add a foreign key on a polymorphic relation"
|
321
|
-
end
|
322
|
-
|
323
|
-
args.each do |col|
|
324
|
-
column("#{col}_id", type, options)
|
325
|
-
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
326
|
-
index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
327
|
-
if foreign_key_options
|
328
|
-
to_table = Base.pluralize_table_names ? col.to_s.pluralize : col.to_s
|
329
|
-
foreign_key(to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
|
330
|
-
end
|
466
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
467
|
+
def references(*args, **options)
|
468
|
+
args.each do |ref_name|
|
469
|
+
ReferenceDefinition.new(ref_name, **options).add_to(self)
|
331
470
|
end
|
332
471
|
end
|
333
472
|
alias :belongs_to :references
|
334
473
|
|
335
|
-
def new_column_definition(name, type, options) # :nodoc:
|
336
|
-
|
337
|
-
|
338
|
-
limit = options.fetch(:limit) do
|
339
|
-
native[type][:limit] if native[type].is_a?(Hash)
|
474
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
475
|
+
if integer_like_primary_key?(type, options)
|
476
|
+
type = integer_like_primary_key_type(type, options)
|
340
477
|
end
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
column.default = options[:default]
|
346
|
-
column.null = options[:null]
|
347
|
-
column.first = options[:first]
|
348
|
-
column.after = options[:after]
|
349
|
-
column.primary_key = type == :primary_key || options[:primary_key]
|
350
|
-
column
|
478
|
+
type = aliased_types(type.to_s, type)
|
479
|
+
options[:primary_key] ||= type == :primary_key
|
480
|
+
options[:null] = false if options[:primary_key]
|
481
|
+
create_column_definition(name, type, options)
|
351
482
|
end
|
352
483
|
|
353
484
|
private
|
354
|
-
|
355
|
-
|
356
|
-
|
485
|
+
def create_column_definition(name, type, options)
|
486
|
+
ColumnDefinition.new(name, type, options)
|
487
|
+
end
|
357
488
|
|
358
|
-
|
359
|
-
|
360
|
-
|
489
|
+
def aliased_types(name, fallback)
|
490
|
+
"timestamp" == name ? :datetime : fallback
|
491
|
+
end
|
361
492
|
|
362
|
-
|
363
|
-
|
364
|
-
|
493
|
+
def integer_like_primary_key?(type, options)
|
494
|
+
options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
|
495
|
+
end
|
496
|
+
|
497
|
+
def integer_like_primary_key_type(type, options)
|
498
|
+
type
|
499
|
+
end
|
365
500
|
end
|
366
501
|
|
367
502
|
class AlterTable # :nodoc:
|
368
503
|
attr_reader :adds
|
369
|
-
attr_reader :foreign_key_adds
|
370
|
-
attr_reader :
|
504
|
+
attr_reader :foreign_key_adds, :foreign_key_drops
|
505
|
+
attr_reader :check_constraint_adds, :check_constraint_drops
|
371
506
|
|
372
507
|
def initialize(td)
|
373
508
|
@td = td
|
374
509
|
@adds = []
|
375
510
|
@foreign_key_adds = []
|
376
511
|
@foreign_key_drops = []
|
512
|
+
@check_constraint_adds = []
|
513
|
+
@check_constraint_drops = []
|
377
514
|
end
|
378
515
|
|
379
516
|
def name; @td.name; end
|
@@ -386,47 +523,67 @@ module ActiveRecord
|
|
386
523
|
@foreign_key_drops << name
|
387
524
|
end
|
388
525
|
|
389
|
-
def
|
526
|
+
def add_check_constraint(expression, options)
|
527
|
+
@check_constraint_adds << CheckConstraintDefinition.new(name, expression, options)
|
528
|
+
end
|
529
|
+
|
530
|
+
def drop_check_constraint(constraint_name)
|
531
|
+
@check_constraint_drops << constraint_name
|
532
|
+
end
|
533
|
+
|
534
|
+
def add_column(name, type, **options)
|
390
535
|
name = name.to_s
|
391
536
|
type = type.to_sym
|
392
|
-
@adds << @td.new_column_definition(name, type, options)
|
537
|
+
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
|
393
538
|
end
|
394
539
|
end
|
395
540
|
|
396
541
|
# Represents an SQL table in an abstract way for updating a table.
|
397
|
-
# Also see TableDefinition and SchemaStatements#create_table
|
542
|
+
# Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
|
398
543
|
#
|
399
544
|
# Available transformations are:
|
400
545
|
#
|
401
546
|
# change_table :table do |t|
|
547
|
+
# t.primary_key
|
402
548
|
# t.column
|
403
549
|
# t.index
|
404
550
|
# t.rename_index
|
405
551
|
# t.timestamps
|
406
552
|
# t.change
|
407
553
|
# t.change_default
|
554
|
+
# t.change_null
|
408
555
|
# t.rename
|
409
556
|
# t.references
|
410
557
|
# t.belongs_to
|
558
|
+
# t.check_constraint
|
411
559
|
# t.string
|
412
560
|
# t.text
|
413
561
|
# t.integer
|
562
|
+
# t.bigint
|
414
563
|
# t.float
|
415
564
|
# t.decimal
|
565
|
+
# t.numeric
|
416
566
|
# t.datetime
|
417
567
|
# t.timestamp
|
418
568
|
# t.time
|
419
569
|
# t.date
|
420
570
|
# t.binary
|
421
571
|
# t.boolean
|
572
|
+
# t.foreign_key
|
573
|
+
# t.json
|
574
|
+
# t.virtual
|
422
575
|
# t.remove
|
576
|
+
# t.remove_foreign_key
|
423
577
|
# t.remove_references
|
424
578
|
# t.remove_belongs_to
|
425
579
|
# t.remove_index
|
580
|
+
# t.remove_check_constraint
|
426
581
|
# t.remove_timestamps
|
427
582
|
# end
|
428
583
|
#
|
429
584
|
class Table
|
585
|
+
include ColumnMethods
|
586
|
+
|
430
587
|
attr_reader :name
|
431
588
|
|
432
589
|
def initialize(table_name, base)
|
@@ -435,33 +592,46 @@ module ActiveRecord
|
|
435
592
|
end
|
436
593
|
|
437
594
|
# Adds a new column to the named table.
|
438
|
-
# See TableDefinition#column for details of the options you can use.
|
439
595
|
#
|
440
|
-
# ====== Creating a simple column
|
441
596
|
# t.column(:name, :string)
|
442
|
-
|
443
|
-
|
597
|
+
#
|
598
|
+
# See TableDefinition#column for details of the options you can use.
|
599
|
+
def column(column_name, type, index: nil, **options)
|
600
|
+
@base.add_column(name, column_name, type, **options)
|
601
|
+
if index
|
602
|
+
index_options = index.is_a?(Hash) ? index : {}
|
603
|
+
index(column_name, **index_options)
|
604
|
+
end
|
444
605
|
end
|
445
606
|
|
446
|
-
# Checks to see if a column exists.
|
447
|
-
|
448
|
-
|
607
|
+
# Checks to see if a column exists.
|
608
|
+
#
|
609
|
+
# t.string(:name) unless t.column_exists?(:name, :string)
|
610
|
+
#
|
611
|
+
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
|
612
|
+
def column_exists?(column_name, type = nil, **options)
|
613
|
+
@base.column_exists?(name, column_name, type, **options)
|
449
614
|
end
|
450
615
|
|
451
616
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
452
|
-
# an Array of Symbols.
|
617
|
+
# an Array of Symbols.
|
453
618
|
#
|
454
|
-
# ====== Creating a simple index
|
455
619
|
# t.index(:name)
|
456
|
-
# ====== Creating a unique index
|
457
620
|
# t.index([:branch_id, :party_id], unique: true)
|
458
|
-
# ====== Creating a named index
|
459
621
|
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
460
|
-
|
461
|
-
|
622
|
+
#
|
623
|
+
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
|
624
|
+
def index(column_name, **options)
|
625
|
+
@base.add_index(name, column_name, **options)
|
462
626
|
end
|
463
627
|
|
464
|
-
# Checks to see if an index exists.
|
628
|
+
# Checks to see if an index exists.
|
629
|
+
#
|
630
|
+
# unless t.index_exists?(:branch_id)
|
631
|
+
# t.index(:branch_id)
|
632
|
+
# end
|
633
|
+
#
|
634
|
+
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
465
635
|
def index_exists?(column_name, options = {})
|
466
636
|
@base.index_exists?(name, column_name, options)
|
467
637
|
end
|
@@ -469,66 +639,88 @@ module ActiveRecord
|
|
469
639
|
# Renames the given index on the table.
|
470
640
|
#
|
471
641
|
# t.rename_index(:user_id, :account_id)
|
642
|
+
#
|
643
|
+
# See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
|
472
644
|
def rename_index(index_name, new_index_name)
|
473
645
|
@base.rename_index(name, index_name, new_index_name)
|
474
646
|
end
|
475
647
|
|
476
|
-
# Adds timestamps (+created_at+ and +updated_at+) columns to the table.
|
648
|
+
# Adds timestamps (+created_at+ and +updated_at+) columns to the table.
|
649
|
+
#
|
650
|
+
# t.timestamps(null: false)
|
477
651
|
#
|
478
|
-
#
|
479
|
-
def timestamps(options
|
480
|
-
@base.add_timestamps(name, options)
|
652
|
+
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
653
|
+
def timestamps(**options)
|
654
|
+
@base.add_timestamps(name, **options)
|
481
655
|
end
|
482
656
|
|
483
657
|
# Changes the column's definition according to the new options.
|
484
|
-
# See TableDefinition#column for details of the options you can use.
|
485
658
|
#
|
486
659
|
# t.change(:name, :string, limit: 80)
|
487
660
|
# t.change(:description, :text)
|
488
|
-
|
489
|
-
|
661
|
+
#
|
662
|
+
# See TableDefinition#column for details of the options you can use.
|
663
|
+
def change(column_name, type, **options)
|
664
|
+
@base.change_column(name, column_name, type, **options)
|
490
665
|
end
|
491
666
|
|
492
|
-
# Sets a new default value for a column.
|
667
|
+
# Sets a new default value for a column.
|
493
668
|
#
|
494
669
|
# t.change_default(:qualification, 'new')
|
495
670
|
# t.change_default(:authorized, 1)
|
496
|
-
|
497
|
-
|
671
|
+
# t.change_default(:status, from: nil, to: "draft")
|
672
|
+
#
|
673
|
+
# See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
|
674
|
+
def change_default(column_name, default_or_changes)
|
675
|
+
@base.change_column_default(name, column_name, default_or_changes)
|
676
|
+
end
|
677
|
+
|
678
|
+
# Sets or removes a NOT NULL constraint on a column.
|
679
|
+
#
|
680
|
+
# t.change_null(:qualification, true)
|
681
|
+
# t.change_null(:qualification, false, 0)
|
682
|
+
#
|
683
|
+
# See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
|
684
|
+
def change_null(column_name, null, default = nil)
|
685
|
+
@base.change_column_null(name, column_name, null, default)
|
498
686
|
end
|
499
687
|
|
500
688
|
# Removes the column(s) from the table definition.
|
501
689
|
#
|
502
690
|
# t.remove(:qualification)
|
503
691
|
# t.remove(:qualification, :experience)
|
504
|
-
|
505
|
-
|
692
|
+
#
|
693
|
+
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
|
694
|
+
def remove(*column_names, **options)
|
695
|
+
@base.remove_columns(name, *column_names, **options)
|
506
696
|
end
|
507
697
|
|
508
698
|
# Removes the given index from the table.
|
509
699
|
#
|
510
|
-
#
|
511
|
-
# t.remove_index :
|
512
|
-
#
|
513
|
-
# t.remove_index
|
514
|
-
#
|
515
|
-
#
|
516
|
-
|
517
|
-
|
518
|
-
def remove_index(options = {})
|
519
|
-
@base.remove_index(name, options)
|
700
|
+
# t.remove_index(:branch_id)
|
701
|
+
# t.remove_index(column: [:branch_id, :party_id])
|
702
|
+
# t.remove_index(name: :by_branch_party)
|
703
|
+
# t.remove_index(:branch_id, name: :by_branch_party)
|
704
|
+
#
|
705
|
+
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
|
706
|
+
def remove_index(column_name = nil, **options)
|
707
|
+
@base.remove_index(name, column_name, **options)
|
520
708
|
end
|
521
709
|
|
522
710
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
523
711
|
#
|
524
712
|
# t.remove_timestamps
|
525
|
-
|
526
|
-
|
713
|
+
#
|
714
|
+
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
|
715
|
+
def remove_timestamps(**options)
|
716
|
+
@base.remove_timestamps(name, **options)
|
527
717
|
end
|
528
718
|
|
529
719
|
# Renames a column.
|
530
720
|
#
|
531
721
|
# t.rename(:description, :name)
|
722
|
+
#
|
723
|
+
# See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
|
532
724
|
def rename(column_name, new_column_name)
|
533
725
|
@base.rename_column(name, column_name, new_column_name)
|
534
726
|
end
|
@@ -538,47 +730,73 @@ module ActiveRecord
|
|
538
730
|
# t.references(:user)
|
539
731
|
# t.belongs_to(:supplier, foreign_key: true)
|
540
732
|
#
|
541
|
-
# See SchemaStatements#add_reference for details of the options you can use.
|
542
|
-
def references(*args)
|
543
|
-
options = args.extract_options!
|
733
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
734
|
+
def references(*args, **options)
|
544
735
|
args.each do |ref_name|
|
545
|
-
@base.add_reference(name, ref_name, options)
|
736
|
+
@base.add_reference(name, ref_name, **options)
|
546
737
|
end
|
547
738
|
end
|
548
739
|
alias :belongs_to :references
|
549
740
|
|
550
741
|
# Removes a reference. Optionally removes a +type+ column.
|
551
|
-
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
552
742
|
#
|
553
743
|
# t.remove_references(:user)
|
554
744
|
# t.remove_belongs_to(:supplier, polymorphic: true)
|
555
745
|
#
|
556
|
-
# See SchemaStatements#remove_reference
|
557
|
-
def remove_references(*args)
|
558
|
-
options = args.extract_options!
|
746
|
+
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
|
747
|
+
def remove_references(*args, **options)
|
559
748
|
args.each do |ref_name|
|
560
|
-
@base.remove_reference(name, ref_name, options)
|
749
|
+
@base.remove_reference(name, ref_name, **options)
|
561
750
|
end
|
562
751
|
end
|
563
752
|
alias :remove_belongs_to :remove_references
|
564
753
|
|
565
|
-
# Adds a
|
754
|
+
# Adds a foreign key to the table using a supplied table name.
|
566
755
|
#
|
567
|
-
# t.
|
568
|
-
# t.
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
@base.add_column(name, column_name, column_type, options)
|
574
|
-
end
|
575
|
-
end
|
756
|
+
# t.foreign_key(:authors)
|
757
|
+
# t.foreign_key(:authors, column: :author_id, primary_key: "id")
|
758
|
+
#
|
759
|
+
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
|
760
|
+
def foreign_key(*args, **options)
|
761
|
+
@base.add_foreign_key(name, *args, **options)
|
576
762
|
end
|
577
763
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
764
|
+
# Removes the given foreign key from the table.
|
765
|
+
#
|
766
|
+
# t.remove_foreign_key(:authors)
|
767
|
+
# t.remove_foreign_key(column: :author_id)
|
768
|
+
#
|
769
|
+
# See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
|
770
|
+
def remove_foreign_key(*args, **options)
|
771
|
+
@base.remove_foreign_key(name, *args, **options)
|
772
|
+
end
|
773
|
+
|
774
|
+
# Checks to see if a foreign key exists.
|
775
|
+
#
|
776
|
+
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
|
777
|
+
#
|
778
|
+
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
|
779
|
+
def foreign_key_exists?(*args, **options)
|
780
|
+
@base.foreign_key_exists?(name, *args, **options)
|
781
|
+
end
|
782
|
+
|
783
|
+
# Adds a check constraint.
|
784
|
+
#
|
785
|
+
# t.check_constraint("price > 0", name: "price_check")
|
786
|
+
#
|
787
|
+
# See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
|
788
|
+
def check_constraint(*args)
|
789
|
+
@base.add_check_constraint(name, *args)
|
790
|
+
end
|
791
|
+
|
792
|
+
# Removes the given check constraint from the table.
|
793
|
+
#
|
794
|
+
# t.remove_check_constraint(name: "price_check")
|
795
|
+
#
|
796
|
+
# See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
|
797
|
+
def remove_check_constraint(*args)
|
798
|
+
@base.remove_check_constraint(name, *args)
|
799
|
+
end
|
582
800
|
end
|
583
801
|
end
|
584
802
|
end
|