activerecord 4.2.8 → 6.0.0
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 +612 -1583
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +134 -286
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -88
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -244
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -627
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -188
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -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 +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -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 +10 -5
- 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/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -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 +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +626 -283
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +147 -46
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +330 -197
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -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 +53 -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/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +308 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -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 -3
- 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 +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- 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
- metadata +164 -60
- 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_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- 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/infinity.rb +0 -13
- 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 -58
- 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,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
@@ -14,38 +14,59 @@ module ActiveRecord
|
|
14
14
|
send m, o
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
18
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, :foreign_key_options,
|
19
|
+
to: :@conn, private: true
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def visit_AlterTable(o)
|
24
|
-
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
25
|
-
sql << o.adds.map { |col|
|
26
|
-
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(
|
27
|
-
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(
|
24
|
+
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
25
|
+
sql << o.adds.map { |col| accept col }.join(" ")
|
26
|
+
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
27
|
+
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
28
28
|
end
|
29
29
|
|
30
30
|
def visit_ColumnDefinition(o)
|
31
|
-
sql_type = type_to_sql(o.type, o.
|
32
|
-
column_sql = "#{quote_column_name(o.name)} #{sql_type}"
|
33
|
-
add_column_options!(column_sql, column_options(o)) unless o.primary_key
|
31
|
+
o.sql_type = type_to_sql(o.type, o.options)
|
32
|
+
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
33
|
+
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
34
34
|
column_sql
|
35
35
|
end
|
36
36
|
|
37
|
+
def visit_AddColumnDefinition(o)
|
38
|
+
+"ADD #{accept(o.column)}"
|
39
|
+
end
|
40
|
+
|
37
41
|
def visit_TableDefinition(o)
|
38
|
-
create_sql = "CREATE#{
|
42
|
+
create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
|
43
|
+
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
39
44
|
create_sql << "#{quote_table_name(o.name)} "
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
|
46
|
+
statements = o.columns.map { |c| accept c }
|
47
|
+
statements << accept(o.primary_keys) if o.primary_keys
|
48
|
+
|
49
|
+
if supports_indexes_in_create?
|
50
|
+
statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
|
51
|
+
end
|
52
|
+
|
53
|
+
if supports_foreign_keys?
|
54
|
+
statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
|
55
|
+
end
|
56
|
+
|
57
|
+
create_sql << "(#{statements.join(', ')})" if statements.present?
|
58
|
+
add_table_options!(create_sql, table_options(o))
|
59
|
+
create_sql << " AS #{to_sql(o.as)}" if o.as
|
43
60
|
create_sql
|
44
61
|
end
|
45
62
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
63
|
+
def visit_PrimaryKeyDefinition(o)
|
64
|
+
"PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_ForeignKeyDefinition(o)
|
68
|
+
sql = +<<~SQL
|
69
|
+
CONSTRAINT #{quote_column_name(o.name)}
|
49
70
|
FOREIGN KEY (#{quote_column_name(o.column)})
|
50
71
|
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
51
72
|
SQL
|
@@ -54,34 +75,34 @@ module ActiveRecord
|
|
54
75
|
sql
|
55
76
|
end
|
56
77
|
|
57
|
-
def
|
58
|
-
"
|
78
|
+
def visit_AddForeignKey(o)
|
79
|
+
"ADD #{accept(o)}"
|
59
80
|
end
|
60
81
|
|
61
|
-
def
|
62
|
-
|
63
|
-
column_options[:null] = o.null unless o.null.nil?
|
64
|
-
column_options[:default] = o.default unless o.default.nil?
|
65
|
-
column_options[:column] = o
|
66
|
-
column_options[:first] = o.first
|
67
|
-
column_options[:after] = o.after
|
68
|
-
column_options
|
82
|
+
def visit_DropForeignKey(name)
|
83
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
69
84
|
end
|
70
85
|
|
71
|
-
def
|
72
|
-
|
86
|
+
def table_options(o)
|
87
|
+
table_options = {}
|
88
|
+
table_options[:comment] = o.comment
|
89
|
+
table_options[:options] = o.options
|
90
|
+
table_options
|
73
91
|
end
|
74
92
|
|
75
|
-
def
|
76
|
-
|
93
|
+
def add_table_options!(create_sql, options)
|
94
|
+
if options_sql = options[:options]
|
95
|
+
create_sql << " #{options_sql}"
|
96
|
+
end
|
97
|
+
create_sql
|
77
98
|
end
|
78
99
|
|
79
|
-
def
|
80
|
-
|
100
|
+
def column_options(o)
|
101
|
+
o.options.merge(column: o)
|
81
102
|
end
|
82
103
|
|
83
104
|
def add_column_options!(sql, options)
|
84
|
-
sql << " DEFAULT #{
|
105
|
+
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
85
106
|
# must explicitly check for :null to allow change_column to work on migrations
|
86
107
|
if options[:null] == false
|
87
108
|
sql << " NOT NULL"
|
@@ -89,18 +110,28 @@ module ActiveRecord
|
|
89
110
|
if options[:auto_increment] == true
|
90
111
|
sql << " AUTO_INCREMENT"
|
91
112
|
end
|
113
|
+
if options[:primary_key] == true
|
114
|
+
sql << " PRIMARY KEY"
|
115
|
+
end
|
92
116
|
sql
|
93
117
|
end
|
94
118
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
119
|
+
def to_sql(sql)
|
120
|
+
sql = sql.to_sql if sql.respond_to?(:to_sql)
|
121
|
+
sql
|
122
|
+
end
|
98
123
|
|
99
|
-
|
124
|
+
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
125
|
+
def table_modifier_in_create(o)
|
126
|
+
" TEMPORARY" if o.temporary
|
100
127
|
end
|
101
128
|
|
102
|
-
def
|
103
|
-
|
129
|
+
def foreign_key_in_create(from_table, to_table, options)
|
130
|
+
prefix = ActiveRecord::Base.table_name_prefix
|
131
|
+
suffix = ActiveRecord::Base.table_name_suffix
|
132
|
+
to_table = "#{prefix}#{to_table}#{suffix}"
|
133
|
+
options = foreign_key_options(from_table, to_table, options)
|
134
|
+
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
104
135
|
end
|
105
136
|
|
106
137
|
def action_sql(action, dependency)
|
@@ -109,17 +140,14 @@ module ActiveRecord
|
|
109
140
|
when :cascade then "ON #{action} CASCADE"
|
110
141
|
when :restrict then "ON #{action} RESTRICT"
|
111
142
|
else
|
112
|
-
raise ArgumentError,
|
143
|
+
raise ArgumentError, <<~MSG
|
113
144
|
'#{dependency}' is not supported for :on_update or :on_delete.
|
114
145
|
Supported values are: :nullify, :cascade, :restrict
|
115
146
|
MSG
|
116
147
|
end
|
117
148
|
end
|
118
|
-
|
119
|
-
def type_for_column(column)
|
120
|
-
@conn.lookup_cast_type(column.sql_type)
|
121
|
-
end
|
122
149
|
end
|
123
150
|
end
|
151
|
+
SchemaCreation = AbstractAdapter::SchemaCreation # :nodoc:
|
124
152
|
end
|
125
153
|
end
|
@@ -1,31 +1,77 @@
|
|
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
|
+
private
|
37
|
+
def concise_options(options)
|
38
|
+
if columns.size == options.size && options.values.uniq.size == 1
|
39
|
+
options.values.first
|
40
|
+
else
|
41
|
+
options
|
42
|
+
end
|
43
|
+
end
|
12
44
|
end
|
13
45
|
|
14
46
|
# Abstract representation of a column definition. Instances of this type
|
15
47
|
# are typically created by methods in TableDefinition, and added to the
|
16
48
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
17
49
|
# for generating a number of table creation or table changing SQL statements.
|
18
|
-
|
19
|
-
|
50
|
+
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
20
51
|
def primary_key?
|
21
|
-
|
52
|
+
options[:primary_key]
|
22
53
|
end
|
23
|
-
end
|
24
54
|
|
25
|
-
|
55
|
+
[:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
|
56
|
+
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
57
|
+
def #{option_name}
|
58
|
+
options[:#{option_name}]
|
59
|
+
end
|
60
|
+
|
61
|
+
def #{option_name}=(value)
|
62
|
+
options[:#{option_name}] = value
|
63
|
+
end
|
64
|
+
CODE
|
65
|
+
end
|
26
66
|
end
|
27
67
|
|
28
|
-
|
68
|
+
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
69
|
+
|
70
|
+
ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
|
71
|
+
|
72
|
+
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
73
|
+
|
74
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
|
29
75
|
def name
|
30
76
|
options[:name]
|
31
77
|
end
|
@@ -50,31 +96,151 @@ module ActiveRecord
|
|
50
96
|
options[:primary_key] != default_primary_key
|
51
97
|
end
|
52
98
|
|
99
|
+
def validate?
|
100
|
+
options.fetch(:validate, true)
|
101
|
+
end
|
102
|
+
alias validated? validate?
|
103
|
+
|
104
|
+
def export_name_on_schema_dump?
|
105
|
+
!ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
|
106
|
+
end
|
107
|
+
|
108
|
+
def defined_for?(to_table: nil, **options)
|
109
|
+
(to_table.nil? || to_table.to_s == self.to_table) &&
|
110
|
+
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
111
|
+
end
|
112
|
+
|
53
113
|
private
|
54
|
-
|
55
|
-
|
114
|
+
def default_primary_key
|
115
|
+
"id"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class ReferenceDefinition # :nodoc:
|
120
|
+
def initialize(
|
121
|
+
name,
|
122
|
+
polymorphic: false,
|
123
|
+
index: true,
|
124
|
+
foreign_key: false,
|
125
|
+
type: :bigint,
|
126
|
+
**options
|
127
|
+
)
|
128
|
+
@name = name
|
129
|
+
@polymorphic = polymorphic
|
130
|
+
@index = index
|
131
|
+
@foreign_key = foreign_key
|
132
|
+
@type = type
|
133
|
+
@options = options
|
134
|
+
|
135
|
+
if polymorphic && foreign_key
|
136
|
+
raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
|
137
|
+
end
|
56
138
|
end
|
139
|
+
|
140
|
+
def add_to(table)
|
141
|
+
columns.each do |column_options|
|
142
|
+
table.column(*column_options)
|
143
|
+
end
|
144
|
+
|
145
|
+
if index
|
146
|
+
table.index(column_names, index_options)
|
147
|
+
end
|
148
|
+
|
149
|
+
if foreign_key
|
150
|
+
table.foreign_key(foreign_table_name, foreign_key_options)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
|
156
|
+
|
157
|
+
def as_options(value)
|
158
|
+
value.is_a?(Hash) ? value : {}
|
159
|
+
end
|
160
|
+
|
161
|
+
def polymorphic_options
|
162
|
+
as_options(polymorphic).merge(options.slice(:null, :first, :after))
|
163
|
+
end
|
164
|
+
|
165
|
+
def index_options
|
166
|
+
as_options(index)
|
167
|
+
end
|
168
|
+
|
169
|
+
def foreign_key_options
|
170
|
+
as_options(foreign_key).merge(column: column_name)
|
171
|
+
end
|
172
|
+
|
173
|
+
def columns
|
174
|
+
result = [[column_name, type, options]]
|
175
|
+
if polymorphic
|
176
|
+
result.unshift(["#{name}_type", :string, polymorphic_options])
|
177
|
+
end
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
def column_name
|
182
|
+
"#{name}_id"
|
183
|
+
end
|
184
|
+
|
185
|
+
def column_names
|
186
|
+
columns.map(&:first)
|
187
|
+
end
|
188
|
+
|
189
|
+
def foreign_table_name
|
190
|
+
foreign_key_options.fetch(:to_table) do
|
191
|
+
Base.pluralize_table_names ? name.to_s.pluralize : name
|
192
|
+
end
|
193
|
+
end
|
57
194
|
end
|
58
195
|
|
59
|
-
module
|
60
|
-
|
61
|
-
return if options.key?(:null)
|
196
|
+
module ColumnMethods
|
197
|
+
extend ActiveSupport::Concern
|
62
198
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
199
|
+
# Appends a primary key definition to the table definition.
|
200
|
+
# Can be called multiple times, but this is probably not a good idea.
|
201
|
+
def primary_key(name, type = :primary_key, **options)
|
202
|
+
column(name, type, options.merge(primary_key: true))
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# :method: column
|
207
|
+
# :call-seq: column(name, type, **options)
|
208
|
+
#
|
209
|
+
# Appends a column or columns of a specified type.
|
210
|
+
#
|
211
|
+
# t.string(:goat)
|
212
|
+
# t.string(:goat, :sheep)
|
213
|
+
#
|
214
|
+
# See TableDefinition#column
|
215
|
+
|
216
|
+
included do
|
217
|
+
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
218
|
+
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
219
|
+
|
220
|
+
alias :numeric :decimal
|
221
|
+
end
|
222
|
+
|
223
|
+
class_methods do
|
224
|
+
private def define_column_methods(*column_types) # :nodoc:
|
225
|
+
column_types.each do |column_type|
|
226
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
227
|
+
def #{column_type}(*names, **options)
|
228
|
+
raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
|
229
|
+
names.each { |name| column(name, :#{column_type}, options) }
|
230
|
+
end
|
231
|
+
RUBY
|
232
|
+
end
|
233
|
+
end
|
68
234
|
end
|
69
235
|
end
|
70
236
|
|
71
237
|
# Represents the schema of an SQL table in an abstract way. This class
|
72
238
|
# provides methods for manipulating the schema representation.
|
73
239
|
#
|
74
|
-
# Inside migration files, the +t+ object in
|
240
|
+
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
75
241
|
# is actually of this type:
|
76
242
|
#
|
77
|
-
# class SomeMigration < ActiveRecord::Migration
|
243
|
+
# class SomeMigration < ActiveRecord::Migration[5.0]
|
78
244
|
# def up
|
79
245
|
# create_table :foo do |t|
|
80
246
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -86,125 +252,65 @@ module ActiveRecord
|
|
86
252
|
# end
|
87
253
|
# end
|
88
254
|
#
|
89
|
-
# The table definitions
|
90
|
-
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
91
255
|
class TableDefinition
|
92
|
-
include
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
256
|
+
include ColumnMethods
|
257
|
+
|
258
|
+
attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
|
259
|
+
|
260
|
+
def initialize(
|
261
|
+
conn,
|
262
|
+
name,
|
263
|
+
temporary: false,
|
264
|
+
if_not_exists: false,
|
265
|
+
options: nil,
|
266
|
+
as: nil,
|
267
|
+
comment: nil,
|
268
|
+
**
|
269
|
+
)
|
270
|
+
@conn = conn
|
100
271
|
@columns_hash = {}
|
101
|
-
@indexes =
|
272
|
+
@indexes = []
|
102
273
|
@foreign_keys = []
|
103
|
-
@
|
274
|
+
@primary_keys = nil
|
104
275
|
@temporary = temporary
|
276
|
+
@if_not_exists = if_not_exists
|
105
277
|
@options = options
|
106
278
|
@as = as
|
107
279
|
@name = name
|
280
|
+
@comment = comment
|
108
281
|
end
|
109
282
|
|
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))
|
283
|
+
def primary_keys(name = nil) # :nodoc:
|
284
|
+
@primary_keys = PrimaryKeyDefinition.new(name) if name
|
285
|
+
@primary_keys
|
116
286
|
end
|
117
287
|
|
288
|
+
# Returns an array of ColumnDefinition objects for the columns of the table.
|
289
|
+
def columns; @columns_hash.values; end
|
290
|
+
|
118
291
|
# Returns a ColumnDefinition for the column with name +name+.
|
119
292
|
def [](name)
|
120
293
|
@columns_hash[name.to_s]
|
121
294
|
end
|
122
295
|
|
123
296
|
# 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.
|
297
|
+
# See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
|
298
|
+
# for available options.
|
299
|
+
#
|
300
|
+
# Additional options are:
|
148
301
|
# * <tt>:index</tt> -
|
149
302
|
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
|
150
303
|
#
|
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
304
|
# This method returns <tt>self</tt>.
|
178
305
|
#
|
179
306
|
# == Examples
|
180
|
-
# # Assuming +td+ is an instance of TableDefinition
|
181
|
-
# td.column(:granted, :boolean)
|
182
|
-
# # granted BOOLEAN
|
183
|
-
#
|
184
|
-
# td.column(:picture, :binary, limit: 2.megabytes)
|
185
|
-
# # => picture BLOB(2097152)
|
186
|
-
#
|
187
|
-
# td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
|
188
|
-
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
189
307
|
#
|
190
|
-
# td
|
191
|
-
#
|
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
|
308
|
+
# # Assuming +td+ is an instance of TableDefinition
|
309
|
+
# td.column(:granted, :boolean, index: true)
|
204
310
|
#
|
205
311
|
# == Short-hand examples
|
206
312
|
#
|
207
|
-
# Instead of calling
|
313
|
+
# Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
|
208
314
|
# They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
|
209
315
|
# in a single statement.
|
210
316
|
#
|
@@ -236,7 +342,8 @@ module ActiveRecord
|
|
236
342
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
237
343
|
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
|
238
344
|
# 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
|
345
|
+
# will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
|
346
|
+
# So what can be written like this:
|
240
347
|
#
|
241
348
|
# create_table :taggings do |t|
|
242
349
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
@@ -250,16 +357,20 @@ module ActiveRecord
|
|
250
357
|
#
|
251
358
|
# create_table :taggings do |t|
|
252
359
|
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
253
|
-
# t.references :tagger, polymorphic: true
|
254
|
-
# t.references :taggable, polymorphic: { default: 'Photo' }
|
360
|
+
# t.references :tagger, polymorphic: true
|
361
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }, index: false
|
255
362
|
# end
|
256
|
-
def column(name, type, options
|
363
|
+
def column(name, type, **options)
|
257
364
|
name = name.to_s
|
258
|
-
type = type.to_sym
|
365
|
+
type = type.to_sym if type
|
259
366
|
options = options.dup
|
260
367
|
|
261
|
-
if @columns_hash[name]
|
262
|
-
|
368
|
+
if @columns_hash[name]
|
369
|
+
if @columns_hash[name].primary_key?
|
370
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
371
|
+
else
|
372
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
373
|
+
end
|
263
374
|
end
|
264
375
|
|
265
376
|
index_options = options.delete(:index)
|
@@ -268,37 +379,35 @@ module ActiveRecord
|
|
268
379
|
self
|
269
380
|
end
|
270
381
|
|
382
|
+
# remove the column +name+ from the table.
|
383
|
+
# remove_column(:account_id)
|
271
384
|
def remove_column(name)
|
272
385
|
@columns_hash.delete name.to_s
|
273
386
|
end
|
274
387
|
|
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
388
|
# Adds index options to the indexes hash, keyed by column name
|
284
389
|
# This is primarily used to track indexes that need to be created after the table
|
285
390
|
#
|
286
391
|
# index(:account_id, name: 'index_projects_on_account_id')
|
287
392
|
def index(column_name, options = {})
|
288
|
-
indexes[column_name
|
393
|
+
indexes << [column_name, options]
|
289
394
|
end
|
290
395
|
|
291
396
|
def foreign_key(table_name, options = {}) # :nodoc:
|
292
|
-
foreign_keys
|
397
|
+
foreign_keys << [table_name, options]
|
293
398
|
end
|
294
399
|
|
295
400
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
296
|
-
# <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
|
401
|
+
# <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
297
402
|
#
|
298
403
|
# t.timestamps null: false
|
299
|
-
def timestamps(
|
300
|
-
options =
|
301
|
-
|
404
|
+
def timestamps(**options)
|
405
|
+
options[:null] = false if options[:null].nil?
|
406
|
+
|
407
|
+
if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
408
|
+
options[:precision] = 6
|
409
|
+
end
|
410
|
+
|
302
411
|
column(:created_at, :datetime, options)
|
303
412
|
column(:updated_at, :datetime, options)
|
304
413
|
end
|
@@ -307,61 +416,42 @@ module ActiveRecord
|
|
307
416
|
#
|
308
417
|
# t.references(:user)
|
309
418
|
# t.belongs_to(:supplier, foreign_key: true)
|
419
|
+
# t.belongs_to(:supplier, foreign_key: true, type: :integer)
|
310
420
|
#
|
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
|
421
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
422
|
+
def references(*args, **options)
|
423
|
+
args.each do |ref_name|
|
424
|
+
ReferenceDefinition.new(ref_name, options).add_to(self)
|
331
425
|
end
|
332
426
|
end
|
333
427
|
alias :belongs_to :references
|
334
428
|
|
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)
|
429
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
430
|
+
if integer_like_primary_key?(type, options)
|
431
|
+
type = integer_like_primary_key_type(type, options)
|
340
432
|
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
|
433
|
+
type = aliased_types(type.to_s, type)
|
434
|
+
options[:primary_key] ||= type == :primary_key
|
435
|
+
options[:null] = false if options[:primary_key]
|
436
|
+
create_column_definition(name, type, options)
|
351
437
|
end
|
352
438
|
|
353
439
|
private
|
354
|
-
|
355
|
-
|
356
|
-
|
440
|
+
def create_column_definition(name, type, options)
|
441
|
+
ColumnDefinition.new(name, type, options)
|
442
|
+
end
|
357
443
|
|
358
|
-
|
359
|
-
|
360
|
-
|
444
|
+
def aliased_types(name, fallback)
|
445
|
+
"timestamp" == name ? :datetime : fallback
|
446
|
+
end
|
361
447
|
|
362
|
-
|
363
|
-
|
364
|
-
|
448
|
+
def integer_like_primary_key?(type, options)
|
449
|
+
options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
|
450
|
+
end
|
451
|
+
|
452
|
+
def integer_like_primary_key_type(type, options)
|
453
|
+
type
|
454
|
+
end
|
365
455
|
end
|
366
456
|
|
367
457
|
class AlterTable # :nodoc:
|
@@ -389,16 +479,17 @@ module ActiveRecord
|
|
389
479
|
def add_column(name, type, options)
|
390
480
|
name = name.to_s
|
391
481
|
type = type.to_sym
|
392
|
-
@adds << @td.new_column_definition(name, type, options)
|
482
|
+
@adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
|
393
483
|
end
|
394
484
|
end
|
395
485
|
|
396
486
|
# Represents an SQL table in an abstract way for updating a table.
|
397
|
-
# Also see TableDefinition and SchemaStatements#create_table
|
487
|
+
# Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
|
398
488
|
#
|
399
489
|
# Available transformations are:
|
400
490
|
#
|
401
491
|
# change_table :table do |t|
|
492
|
+
# t.primary_key
|
402
493
|
# t.column
|
403
494
|
# t.index
|
404
495
|
# t.rename_index
|
@@ -411,15 +502,21 @@ module ActiveRecord
|
|
411
502
|
# t.string
|
412
503
|
# t.text
|
413
504
|
# t.integer
|
505
|
+
# t.bigint
|
414
506
|
# t.float
|
415
507
|
# t.decimal
|
508
|
+
# t.numeric
|
416
509
|
# t.datetime
|
417
510
|
# t.timestamp
|
418
511
|
# t.time
|
419
512
|
# t.date
|
420
513
|
# t.binary
|
421
514
|
# t.boolean
|
515
|
+
# t.foreign_key
|
516
|
+
# t.json
|
517
|
+
# t.virtual
|
422
518
|
# t.remove
|
519
|
+
# t.remove_foreign_key
|
423
520
|
# t.remove_references
|
424
521
|
# t.remove_belongs_to
|
425
522
|
# t.remove_index
|
@@ -427,6 +524,8 @@ module ActiveRecord
|
|
427
524
|
# end
|
428
525
|
#
|
429
526
|
class Table
|
527
|
+
include ColumnMethods
|
528
|
+
|
430
529
|
attr_reader :name
|
431
530
|
|
432
531
|
def initialize(table_name, base)
|
@@ -435,33 +534,44 @@ module ActiveRecord
|
|
435
534
|
end
|
436
535
|
|
437
536
|
# Adds a new column to the named table.
|
438
|
-
# See TableDefinition#column for details of the options you can use.
|
439
537
|
#
|
440
|
-
# ====== Creating a simple column
|
441
538
|
# t.column(:name, :string)
|
442
|
-
|
539
|
+
#
|
540
|
+
# See TableDefinition#column for details of the options you can use.
|
541
|
+
def column(column_name, type, **options)
|
542
|
+
index_options = options.delete(:index)
|
443
543
|
@base.add_column(name, column_name, type, options)
|
544
|
+
index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
444
545
|
end
|
445
546
|
|
446
|
-
# Checks to see if a column exists.
|
547
|
+
# Checks to see if a column exists.
|
548
|
+
#
|
549
|
+
# t.string(:name) unless t.column_exists?(:name, :string)
|
550
|
+
#
|
551
|
+
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
|
447
552
|
def column_exists?(column_name, type = nil, options = {})
|
448
553
|
@base.column_exists?(name, column_name, type, options)
|
449
554
|
end
|
450
555
|
|
451
556
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
452
|
-
# an Array of Symbols.
|
557
|
+
# an Array of Symbols.
|
453
558
|
#
|
454
|
-
# ====== Creating a simple index
|
455
559
|
# t.index(:name)
|
456
|
-
# ====== Creating a unique index
|
457
560
|
# t.index([:branch_id, :party_id], unique: true)
|
458
|
-
# ====== Creating a named index
|
459
561
|
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
562
|
+
#
|
563
|
+
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
|
460
564
|
def index(column_name, options = {})
|
461
565
|
@base.add_index(name, column_name, options)
|
462
566
|
end
|
463
567
|
|
464
|
-
# Checks to see if an index exists.
|
568
|
+
# Checks to see if an index exists.
|
569
|
+
#
|
570
|
+
# unless t.index_exists?(:branch_id)
|
571
|
+
# t.index(:branch_id)
|
572
|
+
# end
|
573
|
+
#
|
574
|
+
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
465
575
|
def index_exists?(column_name, options = {})
|
466
576
|
@base.index_exists?(name, column_name, options)
|
467
577
|
end
|
@@ -469,52 +579,59 @@ module ActiveRecord
|
|
469
579
|
# Renames the given index on the table.
|
470
580
|
#
|
471
581
|
# t.rename_index(:user_id, :account_id)
|
582
|
+
#
|
583
|
+
# See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
|
472
584
|
def rename_index(index_name, new_index_name)
|
473
585
|
@base.rename_index(name, index_name, new_index_name)
|
474
586
|
end
|
475
587
|
|
476
|
-
# Adds timestamps (+created_at+ and +updated_at+) columns to the table.
|
588
|
+
# Adds timestamps (+created_at+ and +updated_at+) columns to the table.
|
589
|
+
#
|
590
|
+
# t.timestamps(null: false)
|
477
591
|
#
|
478
|
-
#
|
592
|
+
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
|
479
593
|
def timestamps(options = {})
|
480
594
|
@base.add_timestamps(name, options)
|
481
595
|
end
|
482
596
|
|
483
597
|
# Changes the column's definition according to the new options.
|
484
|
-
# See TableDefinition#column for details of the options you can use.
|
485
598
|
#
|
486
599
|
# t.change(:name, :string, limit: 80)
|
487
600
|
# t.change(:description, :text)
|
601
|
+
#
|
602
|
+
# See TableDefinition#column for details of the options you can use.
|
488
603
|
def change(column_name, type, options = {})
|
489
604
|
@base.change_column(name, column_name, type, options)
|
490
605
|
end
|
491
606
|
|
492
|
-
# Sets a new default value for a column.
|
607
|
+
# Sets a new default value for a column.
|
493
608
|
#
|
494
609
|
# t.change_default(:qualification, 'new')
|
495
610
|
# t.change_default(:authorized, 1)
|
496
|
-
|
497
|
-
|
611
|
+
# t.change_default(:status, from: nil, to: "draft")
|
612
|
+
#
|
613
|
+
# See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
|
614
|
+
def change_default(column_name, default_or_changes)
|
615
|
+
@base.change_column_default(name, column_name, default_or_changes)
|
498
616
|
end
|
499
617
|
|
500
618
|
# Removes the column(s) from the table definition.
|
501
619
|
#
|
502
620
|
# t.remove(:qualification)
|
503
621
|
# t.remove(:qualification, :experience)
|
622
|
+
#
|
623
|
+
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
|
504
624
|
def remove(*column_names)
|
505
625
|
@base.remove_columns(name, *column_names)
|
506
626
|
end
|
507
627
|
|
508
628
|
# Removes the given index from the table.
|
509
629
|
#
|
510
|
-
#
|
511
|
-
# t.remove_index :
|
512
|
-
#
|
513
|
-
#
|
514
|
-
#
|
515
|
-
# t.remove_index column: [:branch_id, :party_id]
|
516
|
-
# ====== Remove the index named by_branch_party in the table_name table
|
517
|
-
# t.remove_index name: :by_branch_party
|
630
|
+
# t.remove_index(:branch_id)
|
631
|
+
# t.remove_index(column: [:branch_id, :party_id])
|
632
|
+
# t.remove_index(name: :by_branch_party)
|
633
|
+
#
|
634
|
+
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
|
518
635
|
def remove_index(options = {})
|
519
636
|
@base.remove_index(name, options)
|
520
637
|
end
|
@@ -522,6 +639,8 @@ module ActiveRecord
|
|
522
639
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
523
640
|
#
|
524
641
|
# t.remove_timestamps
|
642
|
+
#
|
643
|
+
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
|
525
644
|
def remove_timestamps(options = {})
|
526
645
|
@base.remove_timestamps(name, options)
|
527
646
|
end
|
@@ -529,6 +648,8 @@ module ActiveRecord
|
|
529
648
|
# Renames a column.
|
530
649
|
#
|
531
650
|
# t.rename(:description, :name)
|
651
|
+
#
|
652
|
+
# See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
|
532
653
|
def rename(column_name, new_column_name)
|
533
654
|
@base.rename_column(name, column_name, new_column_name)
|
534
655
|
end
|
@@ -538,9 +659,8 @@ module ActiveRecord
|
|
538
659
|
# t.references(:user)
|
539
660
|
# t.belongs_to(:supplier, foreign_key: true)
|
540
661
|
#
|
541
|
-
# See SchemaStatements#add_reference for details of the options you can use.
|
542
|
-
def references(*args)
|
543
|
-
options = args.extract_options!
|
662
|
+
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
|
663
|
+
def references(*args, **options)
|
544
664
|
args.each do |ref_name|
|
545
665
|
@base.add_reference(name, ref_name, options)
|
546
666
|
end
|
@@ -548,37 +668,46 @@ module ActiveRecord
|
|
548
668
|
alias :belongs_to :references
|
549
669
|
|
550
670
|
# Removes a reference. Optionally removes a +type+ column.
|
551
|
-
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
552
671
|
#
|
553
672
|
# t.remove_references(:user)
|
554
673
|
# t.remove_belongs_to(:supplier, polymorphic: true)
|
555
674
|
#
|
556
|
-
# See SchemaStatements#remove_reference
|
557
|
-
def remove_references(*args)
|
558
|
-
options = args.extract_options!
|
675
|
+
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
|
676
|
+
def remove_references(*args, **options)
|
559
677
|
args.each do |ref_name|
|
560
678
|
@base.remove_reference(name, ref_name, options)
|
561
679
|
end
|
562
680
|
end
|
563
681
|
alias :remove_belongs_to :remove_references
|
564
682
|
|
565
|
-
# Adds a
|
683
|
+
# Adds a foreign key to the table using a supplied table name.
|
566
684
|
#
|
567
|
-
# t.
|
568
|
-
# t.
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
@base.add_column(name, column_name, column_type, options)
|
574
|
-
end
|
575
|
-
end
|
685
|
+
# t.foreign_key(:authors)
|
686
|
+
# t.foreign_key(:authors, column: :author_id, primary_key: "id")
|
687
|
+
#
|
688
|
+
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
|
689
|
+
def foreign_key(*args)
|
690
|
+
@base.add_foreign_key(name, *args)
|
576
691
|
end
|
577
692
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
693
|
+
# Removes the given foreign key from the table.
|
694
|
+
#
|
695
|
+
# t.remove_foreign_key(:authors)
|
696
|
+
# t.remove_foreign_key(column: :author_id)
|
697
|
+
#
|
698
|
+
# See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
|
699
|
+
def remove_foreign_key(*args)
|
700
|
+
@base.remove_foreign_key(name, *args)
|
701
|
+
end
|
702
|
+
|
703
|
+
# Checks to see if a foreign key exists.
|
704
|
+
#
|
705
|
+
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
|
706
|
+
#
|
707
|
+
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
|
708
|
+
def foreign_key_exists?(*args)
|
709
|
+
@base.foreign_key_exists?(name, *args)
|
710
|
+
end
|
582
711
|
end
|
583
712
|
end
|
584
713
|
end
|