activerecord 6.0.0 → 7.2.3
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 +4 -4
- data/CHANGELOG.md +996 -594
- data/MIT-LICENSE +1 -1
- data/README.rdoc +34 -34
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +22 -20
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +41 -30
- data/lib/active_record/associations/association.rb +106 -41
- data/lib/active_record/associations/association_scope.rb +30 -21
- data/lib/active_record/associations/belongs_to_association.rb +69 -14
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
- data/lib/active_record/associations/builder/association.rb +39 -6
- data/lib/active_record/associations/builder/belongs_to.rb +47 -17
- data/lib/active_record/associations/builder/collection_association.rb +14 -6
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
- data/lib/active_record/associations/builder/has_many.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +13 -16
- data/lib/active_record/associations/builder/singular_association.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +90 -53
- data/lib/active_record/associations/collection_proxy.rb +54 -19
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +21 -1
- data/lib/active_record/associations/has_many_association.rb +41 -10
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +33 -9
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +97 -54
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +237 -54
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +51 -17
- data/lib/active_record/associations/preloader.rb +55 -121
- data/lib/active_record/associations/singular_association.rb +16 -4
- data/lib/active_record/associations/through_association.rb +26 -15
- data/lib/active_record/associations.rb +454 -440
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +11 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +75 -34
- data/lib/active_record/attribute_methods/primary_key.rb +53 -31
- data/lib/active_record/attribute_methods/query.rb +31 -22
- data/lib/active_record/attribute_methods/read.rb +16 -17
- data/lib/active_record/attribute_methods/serialization.rb +177 -35
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
- data/lib/active_record/attribute_methods/write.rb +16 -28
- data/lib/active_record/attribute_methods.rb +227 -100
- data/lib/active_record/attributes.rb +94 -56
- data/lib/active_record/autosave_association.rb +119 -73
- data/lib/active_record/base.rb +31 -21
- data/lib/active_record/callbacks.rb +168 -55
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -25
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
- data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
- data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
- data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
- data/lib/active_record/connection_adapters/column.rb +28 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
- data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +243 -115
- data/lib/active_record/core.rb +481 -199
- data/lib/active_record/counter_cache.rb +69 -32
- data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
- data/lib/active_record/database_configurations/database_config.rb +77 -10
- data/lib/active_record/database_configurations/hash_config.rb +148 -26
- data/lib/active_record/database_configurations/url_config.rb +44 -45
- data/lib/active_record/database_configurations.rb +190 -114
- data/lib/active_record/delegated_type.rb +279 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +5 -6
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +171 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +224 -73
- data/lib/active_record/errors.rb +254 -36
- data/lib/active_record/explain.rb +30 -17
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +15 -6
- data/lib/active_record/fixture_set/render_context.rb +3 -1
- data/lib/active_record/fixture_set/table_row.rb +88 -16
- data/lib/active_record/fixture_set/table_rows.rb +4 -5
- data/lib/active_record/fixtures.rb +229 -116
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +121 -48
- data/lib/active_record/insert_all.rb +178 -29
- data/lib/active_record/integration.rb +16 -14
- data/lib/active_record/internal_metadata.rb +132 -21
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +64 -33
- data/lib/active_record/locking/pessimistic.rb +21 -8
- data/lib/active_record/log_subscriber.rb +61 -30
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
- data/lib/active_record/middleware/database_selector.rb +25 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +160 -55
- data/lib/active_record/migration/compatibility.rb +286 -43
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +421 -193
- data/lib/active_record/model_schema.rb +217 -125
- data/lib/active_record/nested_attributes.rb +62 -27
- data/lib/active_record/no_touching.rb +4 -4
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +322 -319
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -15
- data/lib/active_record/query_logs.rb +193 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +54 -14
- data/lib/active_record/railtie.rb +250 -72
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +312 -197
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +45 -3
- data/lib/active_record/reflection.rb +389 -146
- data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
- data/lib/active_record/relation/batches.rb +214 -73
- data/lib/active_record/relation/calculations.rb +379 -124
- data/lib/active_record/relation/delegation.rb +36 -23
- data/lib/active_record/relation/finder_methods.rb +159 -49
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +41 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +79 -53
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +1156 -279
- data/lib/active_record/relation/record_fetch_warning.rb +12 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -9
- data/lib/active_record/relation/where_clause.rb +100 -66
- data/lib/active_record/relation.rb +829 -194
- data/lib/active_record/result.rb +76 -56
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +86 -47
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +140 -33
- data/lib/active_record/schema_migration.rb +74 -29
- data/lib/active_record/scoping/default.rb +73 -19
- data/lib/active_record/scoping/named.rb +10 -28
- data/lib/active_record/scoping.rb +65 -35
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +34 -8
- data/lib/active_record/serialization.rb +11 -4
- data/lib/active_record/signed_id.rb +138 -0
- data/lib/active_record/statement_cache.rb +26 -10
- data/lib/active_record/store.rb +19 -14
- data/lib/active_record/suppressor.rb +15 -17
- data/lib/active_record/table_metadata.rb +46 -36
- data/lib/active_record/tasks/database_tasks.rb +371 -205
- data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +189 -104
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +35 -25
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +31 -27
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +131 -99
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +33 -18
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +11 -6
- data/lib/active_record/type/time.rb +14 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +7 -2
- data/lib/active_record/type_caster/connection.rb +4 -5
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -8
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +88 -18
- data/lib/active_record/validations.rb +15 -8
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +446 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +4 -8
- data/lib/arel/collectors/bind.rb +8 -1
- data/lib/arel/collectors/composite.rb +15 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/crud.rb +30 -22
- data/lib/arel/delete_manager.rb +23 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +82 -9
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +22 -10
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +14 -13
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +122 -11
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/table_alias.rb +11 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes/update_statement.rb +11 -4
- data/lib/arel/nodes.rb +10 -3
- data/lib/arel/predications.rb +31 -28
- data/lib/arel/select_manager.rb +18 -9
- data/lib/arel/table.rb +21 -10
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +25 -5
- data/lib/arel/visitors/dot.rb +94 -90
- data/lib/arel/visitors/mysql.rb +34 -6
- data/lib/arel/visitors/postgresql.rb +5 -16
- data/lib/arel/visitors/sqlite.rb +25 -1
- data/lib/arel/visitors/to_sql.rb +227 -81
- data/lib/arel/visitors/visitor.rb +2 -3
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +37 -15
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
- 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 +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +117 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/null_relation.rb +0 -68
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
|
@@ -5,6 +5,8 @@ module ActiveRecord
|
|
|
5
5
|
module ConnectionAdapters
|
|
6
6
|
# An abstract definition of a column in a table.
|
|
7
7
|
class Column
|
|
8
|
+
include Deduplicable
|
|
9
|
+
|
|
8
10
|
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
|
9
11
|
|
|
10
12
|
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
|
@@ -61,6 +63,15 @@ module ActiveRecord
|
|
|
61
63
|
coder["comment"] = @comment
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
# whether the column is auto-populated by the database using a sequence
|
|
67
|
+
def auto_incremented_by_db?
|
|
68
|
+
false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def auto_populated?
|
|
72
|
+
auto_incremented_by_db? || default_function
|
|
73
|
+
end
|
|
74
|
+
|
|
64
75
|
def ==(other)
|
|
65
76
|
other.is_a?(Column) &&
|
|
66
77
|
name == other.name &&
|
|
@@ -76,6 +87,7 @@ module ActiveRecord
|
|
|
76
87
|
def hash
|
|
77
88
|
Column.hash ^
|
|
78
89
|
name.hash ^
|
|
90
|
+
name.encoding.hash ^
|
|
79
91
|
default.hash ^
|
|
80
92
|
sql_type_metadata.hash ^
|
|
81
93
|
null.hash ^
|
|
@@ -83,10 +95,25 @@ module ActiveRecord
|
|
|
83
95
|
collation.hash ^
|
|
84
96
|
comment.hash
|
|
85
97
|
end
|
|
98
|
+
|
|
99
|
+
def virtual?
|
|
100
|
+
false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
def deduplicated
|
|
105
|
+
@name = -name
|
|
106
|
+
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
|
|
107
|
+
@default = -default if default
|
|
108
|
+
@default_function = -default_function if default_function
|
|
109
|
+
@collation = -collation if collation
|
|
110
|
+
@comment = -comment if comment
|
|
111
|
+
super
|
|
112
|
+
end
|
|
86
113
|
end
|
|
87
114
|
|
|
88
115
|
class NullColumn < Column
|
|
89
|
-
def initialize(name)
|
|
116
|
+
def initialize(name, **)
|
|
90
117
|
super(name, nil)
|
|
91
118
|
end
|
|
92
119
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module ConnectionAdapters # :nodoc:
|
|
5
|
+
module Deduplicable
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
def registry
|
|
10
|
+
@registry ||= {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def new(*, **)
|
|
14
|
+
super.deduplicate
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def deduplicate
|
|
19
|
+
self.class.registry[self] ||= deduplicated
|
|
20
|
+
end
|
|
21
|
+
alias :-@ :deduplicate
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def deduplicated
|
|
25
|
+
freeze
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -11,12 +11,13 @@ module ActiveRecord
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def case_sensitive?
|
|
14
|
-
collation &&
|
|
14
|
+
collation && !collation.end_with?("_ci")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def auto_increment?
|
|
18
18
|
extra == "auto_increment"
|
|
19
19
|
end
|
|
20
|
+
alias_method :auto_incremented_by_db?, :auto_increment?
|
|
20
21
|
|
|
21
22
|
def virtual?
|
|
22
23
|
/\b(?:VIRTUAL|STORED|PERSISTENT)\b/.match?(extra)
|
|
@@ -4,130 +4,65 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module MySQL
|
|
6
6
|
module DatabaseStatements
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
unprepared_statement { super }
|
|
11
|
-
else
|
|
12
|
-
super
|
|
13
|
-
end
|
|
14
|
-
@connection.abandon_results!
|
|
15
|
-
result
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def query(sql, name = nil) # :nodoc:
|
|
19
|
-
execute(sql, name).to_a
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
|
|
7
|
+
READ_QUERY = AbstractAdapter.build_read_query_regexp(
|
|
8
|
+
:desc, :describe, :set, :show, :use, :kill
|
|
9
|
+
) # :nodoc:
|
|
23
10
|
private_constant :READ_QUERY
|
|
24
11
|
|
|
12
|
+
# https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_current-timestamp
|
|
13
|
+
# https://dev.mysql.com/doc/refman/5.7/en/date-and-time-type-syntax.html
|
|
14
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP(6)", retryable: true).freeze # :nodoc:
|
|
15
|
+
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
16
|
+
|
|
25
17
|
def write_query?(sql) # :nodoc:
|
|
26
18
|
!READ_QUERY.match?(sql)
|
|
19
|
+
rescue ArgumentError # Invalid encoding
|
|
20
|
+
!READ_QUERY.match?(sql.b)
|
|
27
21
|
end
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
|
33
|
-
end
|
|
23
|
+
def high_precision_current_timestamp
|
|
24
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
25
|
+
end
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
def explain(arel, binds = [], options = [])
|
|
28
|
+
sql = build_explain_clause(options) + " " + to_sql(arel, binds)
|
|
29
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
30
|
+
result = internal_exec_query(sql, "EXPLAIN", binds)
|
|
31
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
|
|
40
34
|
end
|
|
41
35
|
|
|
42
|
-
def
|
|
43
|
-
if
|
|
44
|
-
execute_and_free(sql, name) do |result|
|
|
45
|
-
if result
|
|
46
|
-
ActiveRecord::Result.new(result.fields, result.to_a)
|
|
47
|
-
else
|
|
48
|
-
ActiveRecord::Result.new([], [])
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
else
|
|
52
|
-
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
|
53
|
-
if result
|
|
54
|
-
ActiveRecord::Result.new(result.fields, result.to_a)
|
|
55
|
-
else
|
|
56
|
-
ActiveRecord::Result.new([], [])
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
36
|
+
def build_explain_clause(options = [])
|
|
37
|
+
return "EXPLAIN" if options.empty?
|
|
61
38
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
end
|
|
39
|
+
explain_clause = "EXPLAIN #{options.join(" ").upcase}"
|
|
40
|
+
|
|
41
|
+
if analyze_without_explain? && explain_clause.include?("ANALYZE")
|
|
42
|
+
explain_clause.sub("EXPLAIN ", "")
|
|
67
43
|
else
|
|
68
|
-
|
|
44
|
+
explain_clause
|
|
69
45
|
end
|
|
70
46
|
end
|
|
71
|
-
alias :exec_update :exec_delete
|
|
72
47
|
|
|
73
48
|
private
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
49
|
+
# https://mariadb.com/kb/en/analyze-statement/
|
|
50
|
+
def analyze_without_explain?
|
|
51
|
+
mariadb? && database_version >= "10.1.0"
|
|
77
52
|
end
|
|
78
53
|
|
|
79
54
|
def default_insert_value(column)
|
|
80
55
|
super unless column.auto_increment?
|
|
81
56
|
end
|
|
82
57
|
|
|
83
|
-
def
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def supports_set_server_option?
|
|
88
|
-
@connection.respond_to?(:set_server_option)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def build_truncate_statements(*table_names)
|
|
92
|
-
if table_names.size == 1
|
|
93
|
-
super.first
|
|
58
|
+
def returning_column_values(result)
|
|
59
|
+
if supports_insert_returning?
|
|
60
|
+
result.rows.first
|
|
94
61
|
else
|
|
95
62
|
super
|
|
96
63
|
end
|
|
97
64
|
end
|
|
98
65
|
|
|
99
|
-
def multi_statements_enabled?(flags)
|
|
100
|
-
if flags.is_a?(Array)
|
|
101
|
-
flags.include?("MULTI_STATEMENTS")
|
|
102
|
-
else
|
|
103
|
-
(flags & Mysql2::Client::MULTI_STATEMENTS) != 0
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def with_multi_statements
|
|
108
|
-
previous_flags = @config[:flags]
|
|
109
|
-
|
|
110
|
-
unless multi_statements_enabled?(previous_flags)
|
|
111
|
-
if supports_set_server_option?
|
|
112
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
|
113
|
-
else
|
|
114
|
-
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
|
115
|
-
reconnect!
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
yield
|
|
120
|
-
ensure
|
|
121
|
-
unless multi_statements_enabled?(previous_flags)
|
|
122
|
-
if supports_set_server_option?
|
|
123
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
|
124
|
-
else
|
|
125
|
-
@config[:flags] = previous_flags
|
|
126
|
-
reconnect!
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
66
|
def combine_multi_statements(total_sql)
|
|
132
67
|
total_sql.each_with_object([]) do |sql, total_sql_chunks|
|
|
133
68
|
previous_packet = total_sql_chunks.last
|
|
@@ -154,46 +89,6 @@ module ActiveRecord
|
|
|
154
89
|
def max_allowed_packet
|
|
155
90
|
@max_allowed_packet ||= show_variable("max_allowed_packet")
|
|
156
91
|
end
|
|
157
|
-
|
|
158
|
-
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
|
159
|
-
if preventing_writes? && write_query?(sql)
|
|
160
|
-
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
materialize_transactions
|
|
164
|
-
|
|
165
|
-
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
|
166
|
-
# made since we established the connection
|
|
167
|
-
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
|
168
|
-
|
|
169
|
-
type_casted_binds = type_casted_binds(binds)
|
|
170
|
-
|
|
171
|
-
log(sql, name, binds, type_casted_binds) do
|
|
172
|
-
if cache_stmt
|
|
173
|
-
stmt = @statements[sql] ||= @connection.prepare(sql)
|
|
174
|
-
else
|
|
175
|
-
stmt = @connection.prepare(sql)
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
begin
|
|
179
|
-
result = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
|
180
|
-
stmt.execute(*type_casted_binds)
|
|
181
|
-
end
|
|
182
|
-
rescue Mysql2::Error => e
|
|
183
|
-
if cache_stmt
|
|
184
|
-
@statements.delete(sql)
|
|
185
|
-
else
|
|
186
|
-
stmt.close
|
|
187
|
-
end
|
|
188
|
-
raise e
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
ret = yield stmt, result
|
|
192
|
-
result.free if result
|
|
193
|
-
stmt.close unless cache_stmt
|
|
194
|
-
ret
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
92
|
end
|
|
198
93
|
end
|
|
199
94
|
end
|
|
@@ -37,7 +37,6 @@ module ActiveRecord
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
private
|
|
40
|
-
|
|
41
40
|
def compute_column_widths(result)
|
|
42
41
|
[].tap do |widths|
|
|
43
42
|
result.columns.each_with_index do |column, i|
|
|
@@ -57,7 +56,7 @@ module ActiveRecord
|
|
|
57
56
|
items.each_with_index do |item, i|
|
|
58
57
|
item = "NULL" if item.nil?
|
|
59
58
|
justifier = item.is_a?(Numeric) ? "rjust" : "ljust"
|
|
60
|
-
cells << item.to_s.
|
|
59
|
+
cells << item.to_s.public_send(justifier, widths[i])
|
|
61
60
|
end
|
|
62
61
|
"| " + cells.join(" | ") + " |"
|
|
63
62
|
end
|
|
@@ -1,15 +1,72 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support/time_with_zone"
|
|
4
|
+
|
|
3
5
|
module ActiveRecord
|
|
4
6
|
module ConnectionAdapters
|
|
5
7
|
module MySQL
|
|
6
8
|
module Quoting # :nodoc:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
|
12
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
|
13
|
+
|
|
14
|
+
module ClassMethods # :nodoc:
|
|
15
|
+
def column_name_matcher
|
|
16
|
+
/
|
|
17
|
+
\A
|
|
18
|
+
(
|
|
19
|
+
(?:
|
|
20
|
+
# `table_name`.`column_name` | function(one or no argument)
|
|
21
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`) | \w+\((?:|\g<2>)\))
|
|
22
|
+
)
|
|
23
|
+
(?:(?:\s+AS)?\s+(?:\w+|`\w+`))?
|
|
24
|
+
)
|
|
25
|
+
(?:\s*,\s*\g<1>)*
|
|
26
|
+
\z
|
|
27
|
+
/ix
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def column_name_with_order_matcher
|
|
31
|
+
/
|
|
32
|
+
\A
|
|
33
|
+
(
|
|
34
|
+
(?:
|
|
35
|
+
# `table_name`.`column_name` | function(one or no argument)
|
|
36
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`) | \w+\((?:|\g<2>)\))
|
|
37
|
+
)
|
|
38
|
+
(?:\s+COLLATE\s+(?:\w+|"\w+"))?
|
|
39
|
+
(?:\s+ASC|\s+DESC)?
|
|
40
|
+
)
|
|
41
|
+
(?:\s*,\s*\g<1>)*
|
|
42
|
+
\z
|
|
43
|
+
/ix
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def quote_column_name(name)
|
|
47
|
+
QUOTED_COLUMN_NAMES[name] ||= "`#{name.to_s.gsub('`', '``')}`".freeze
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def quote_table_name(name)
|
|
51
|
+
QUOTED_TABLE_NAMES[name] ||= "`#{name.to_s.gsub('`', '``').gsub(".", "`.`")}`".freeze
|
|
52
|
+
end
|
|
9
53
|
end
|
|
10
54
|
|
|
11
|
-
def
|
|
12
|
-
|
|
55
|
+
def cast_bound_value(value)
|
|
56
|
+
case value
|
|
57
|
+
when Rational
|
|
58
|
+
value.to_f.to_s
|
|
59
|
+
when Numeric
|
|
60
|
+
value.to_s
|
|
61
|
+
when BigDecimal
|
|
62
|
+
value.to_s("F")
|
|
63
|
+
when true
|
|
64
|
+
"1"
|
|
65
|
+
when false
|
|
66
|
+
"0"
|
|
67
|
+
else
|
|
68
|
+
value
|
|
69
|
+
end
|
|
13
70
|
end
|
|
14
71
|
|
|
15
72
|
def unquoted_true
|
|
@@ -32,49 +89,39 @@ module ActiveRecord
|
|
|
32
89
|
"x'#{value.hex}'"
|
|
33
90
|
end
|
|
34
91
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
92
|
+
def unquote_identifier(identifier)
|
|
93
|
+
if identifier && identifier.start_with?("`")
|
|
94
|
+
identifier[1..-2]
|
|
95
|
+
else
|
|
96
|
+
identifier
|
|
97
|
+
end
|
|
41
98
|
end
|
|
42
99
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
|
62
|
-
)
|
|
63
|
-
(?:\s+ASC|\s+DESC)?
|
|
64
|
-
)
|
|
65
|
-
(?:\s*,\s*\g<1>)*
|
|
66
|
-
\z
|
|
67
|
-
/ix
|
|
68
|
-
|
|
69
|
-
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
|
70
|
-
|
|
71
|
-
private
|
|
72
|
-
def _type_cast(value)
|
|
73
|
-
case value
|
|
74
|
-
when Date, Time then value
|
|
75
|
-
else super
|
|
100
|
+
# Override +type_cast+ we pass to mysql2 Date and Time objects instead
|
|
101
|
+
# of Strings since MySQL adapters are able to handle those classes more efficiently.
|
|
102
|
+
def type_cast(value) # :nodoc:
|
|
103
|
+
case value
|
|
104
|
+
when ActiveSupport::TimeWithZone
|
|
105
|
+
# We need to check explicitly for ActiveSupport::TimeWithZone because
|
|
106
|
+
# we need to transform it to Time objects but we don't want to
|
|
107
|
+
# transform Time objects to themselves.
|
|
108
|
+
if default_timezone == :utc
|
|
109
|
+
value.getutc
|
|
110
|
+
else
|
|
111
|
+
value.getlocal
|
|
112
|
+
end
|
|
113
|
+
when Time
|
|
114
|
+
if default_timezone == :utc
|
|
115
|
+
value.utc? ? value : value.getutc
|
|
116
|
+
else
|
|
117
|
+
value.utc? ? value.getlocal : value
|
|
76
118
|
end
|
|
119
|
+
when Date
|
|
120
|
+
value
|
|
121
|
+
else
|
|
122
|
+
super
|
|
77
123
|
end
|
|
124
|
+
end
|
|
78
125
|
end
|
|
79
126
|
end
|
|
80
127
|
end
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module MySQL
|
|
6
|
-
class SchemaCreation <
|
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
|
7
7
|
delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true
|
|
8
8
|
|
|
9
9
|
private
|
|
10
|
-
|
|
11
10
|
def visit_DropForeignKey(name)
|
|
12
11
|
"DROP FOREIGN KEY #{name}"
|
|
13
12
|
end
|
|
14
13
|
|
|
14
|
+
def visit_DropCheckConstraint(name)
|
|
15
|
+
"DROP #{mariadb? ? 'CONSTRAINT' : 'CHECK'} #{name}"
|
|
16
|
+
end
|
|
17
|
+
|
|
15
18
|
def visit_AddColumnDefinition(o)
|
|
16
19
|
add_column_position!(super, column_options(o.column))
|
|
17
20
|
end
|
|
@@ -21,15 +24,46 @@ module ActiveRecord
|
|
|
21
24
|
add_column_position!(change_column_sql, column_options(o.column))
|
|
22
25
|
end
|
|
23
26
|
|
|
24
|
-
def
|
|
25
|
-
|
|
27
|
+
def visit_ChangeColumnDefaultDefinition(o)
|
|
28
|
+
sql = +"ALTER COLUMN #{quote_column_name(o.column.name)} "
|
|
29
|
+
if o.default.nil? && !o.column.null
|
|
30
|
+
sql << "DROP DEFAULT"
|
|
31
|
+
else
|
|
32
|
+
sql << "SET DEFAULT #{quote_default_expression(o.default, o.column)}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def visit_CreateIndexDefinition(o)
|
|
37
|
+
sql = visit_IndexDefinition(o.index, true)
|
|
38
|
+
sql << " #{o.algorithm}" if o.algorithm
|
|
39
|
+
sql
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def visit_IndexDefinition(o, create = false)
|
|
43
|
+
index_type = o.type&.to_s&.upcase || o.unique && "UNIQUE"
|
|
44
|
+
|
|
45
|
+
sql = create ? ["CREATE"] : []
|
|
46
|
+
sql << index_type if index_type
|
|
47
|
+
sql << "INDEX"
|
|
48
|
+
sql << quote_column_name(o.name)
|
|
49
|
+
sql << "USING #{o.using}" if o.using
|
|
50
|
+
sql << "ON #{quote_table_name(o.table)}" if create
|
|
51
|
+
sql << "(#{quoted_columns(o)})"
|
|
52
|
+
|
|
53
|
+
add_sql_comment!(sql.join(" "), o.comment)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def add_table_options!(create_sql, o)
|
|
57
|
+
create_sql << " DEFAULT CHARSET=#{o.charset}" if o.charset
|
|
58
|
+
create_sql << " COLLATE=#{o.collation}" if o.collation
|
|
59
|
+
add_sql_comment!(super, o.comment)
|
|
26
60
|
end
|
|
27
61
|
|
|
28
62
|
def add_column_options!(sql, options)
|
|
29
63
|
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
|
30
64
|
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
|
31
65
|
# column to contain NULL, explicitly declare it with the NULL attribute.
|
|
32
|
-
# See https://dev.mysql.com/doc/refman/
|
|
66
|
+
# See https://dev.mysql.com/doc/refman/en/timestamp-initialization.html
|
|
33
67
|
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
|
34
68
|
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
|
35
69
|
end
|
|
@@ -63,8 +97,8 @@ module ActiveRecord
|
|
|
63
97
|
end
|
|
64
98
|
|
|
65
99
|
def index_in_create(table_name, column_name, options)
|
|
66
|
-
|
|
67
|
-
|
|
100
|
+
index, _ = @conn.add_index_options(table_name, column_name, **options)
|
|
101
|
+
accept(index)
|
|
68
102
|
end
|
|
69
103
|
end
|
|
70
104
|
end
|
|
@@ -57,9 +57,18 @@ module ActiveRecord
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# = Active Record MySQL Adapter \Table Definition
|
|
60
61
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
|
61
62
|
include ColumnMethods
|
|
62
63
|
|
|
64
|
+
attr_reader :charset, :collation
|
|
65
|
+
|
|
66
|
+
def initialize(conn, name, charset: nil, collation: nil, **)
|
|
67
|
+
super
|
|
68
|
+
@charset = charset
|
|
69
|
+
@collation = collation
|
|
70
|
+
end
|
|
71
|
+
|
|
63
72
|
def new_column_definition(name, type, **options) # :nodoc:
|
|
64
73
|
case type
|
|
65
74
|
when :virtual
|
|
@@ -77,16 +86,24 @@ module ActiveRecord
|
|
|
77
86
|
end
|
|
78
87
|
|
|
79
88
|
private
|
|
89
|
+
def valid_column_definition_options
|
|
90
|
+
super + [:auto_increment, :charset, :as, :size, :unsigned, :first, :after, :type, :stored]
|
|
91
|
+
end
|
|
92
|
+
|
|
80
93
|
def aliased_types(name, fallback)
|
|
81
94
|
fallback
|
|
82
95
|
end
|
|
83
96
|
|
|
84
97
|
def integer_like_primary_key_type(type, options)
|
|
85
|
-
options[:auto_increment]
|
|
98
|
+
unless options[:auto_increment] == false
|
|
99
|
+
options[:auto_increment] = true
|
|
100
|
+
end
|
|
101
|
+
|
|
86
102
|
type
|
|
87
103
|
end
|
|
88
104
|
end
|
|
89
105
|
|
|
106
|
+
# = Active Record MySQL Adapter \Table
|
|
90
107
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
|
91
108
|
include ColumnMethods
|
|
92
109
|
end
|
|
@@ -49,18 +49,24 @@ module ActiveRecord
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def schema_limit(column)
|
|
52
|
-
super unless /\A(?:
|
|
52
|
+
super unless /\A(?:tiny|medium|long)?(?:text|blob)\b/.match?(column.sql_type)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def schema_precision(column)
|
|
56
|
-
|
|
56
|
+
if /\Atime(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
|
|
57
|
+
nil
|
|
58
|
+
elsif column.type == :datetime
|
|
59
|
+
column.precision == 0 ? "nil" : super
|
|
60
|
+
else
|
|
61
|
+
super
|
|
62
|
+
end
|
|
57
63
|
end
|
|
58
64
|
|
|
59
65
|
def schema_collation(column)
|
|
60
66
|
if column.collation
|
|
61
67
|
@table_collation_cache ||= {}
|
|
62
68
|
@table_collation_cache[table_name] ||=
|
|
63
|
-
@connection.
|
|
69
|
+
@connection.internal_exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
|
|
64
70
|
column.collation.inspect if column.collation != @table_collation_cache[table_name]
|
|
65
71
|
end
|
|
66
72
|
end
|
|
@@ -79,7 +85,10 @@ module ActiveRecord
|
|
|
79
85
|
" WHERE table_schema = #{scope[:schema]}" \
|
|
80
86
|
" AND table_name = #{scope[:name]}" \
|
|
81
87
|
" AND column_name = #{column_name}"
|
|
82
|
-
|
|
88
|
+
# Calling .inspect leads into issues with the query result
|
|
89
|
+
# which already returns escaped quotes.
|
|
90
|
+
# We remove the escape sequence from the result in order to deal with double escaping issues.
|
|
91
|
+
@connection.query_value(sql, "SCHEMA").gsub("\\'", "'").inspect
|
|
83
92
|
end
|
|
84
93
|
end
|
|
85
94
|
end
|