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