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,33 +5,112 @@ require "active_support/multibyte/chars"
|
|
|
5
5
|
|
|
6
6
|
module ActiveRecord
|
|
7
7
|
module ConnectionAdapters # :nodoc:
|
|
8
|
+
# = Active Record Connection Adapters \Quoting
|
|
8
9
|
module Quoting
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
|
|
12
|
+
module ClassMethods # :nodoc:
|
|
13
|
+
# Regexp for column names (with or without a table name prefix).
|
|
14
|
+
# Matches the following:
|
|
15
|
+
#
|
|
16
|
+
# "#{table_name}.#{column_name}"
|
|
17
|
+
# "#{column_name}"
|
|
18
|
+
def column_name_matcher
|
|
19
|
+
/
|
|
20
|
+
\A
|
|
21
|
+
(
|
|
22
|
+
(?:
|
|
23
|
+
# table_name.column_name | function(one or no argument)
|
|
24
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
|
25
|
+
)
|
|
26
|
+
(?:(?:\s+AS)?\s+\w+)?
|
|
27
|
+
)
|
|
28
|
+
(?:\s*,\s*\g<1>)*
|
|
29
|
+
\z
|
|
30
|
+
/ix
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Regexp for column names with order (with or without a table name prefix,
|
|
34
|
+
# with or without various order modifiers). Matches the following:
|
|
35
|
+
#
|
|
36
|
+
# "#{table_name}.#{column_name}"
|
|
37
|
+
# "#{table_name}.#{column_name} #{direction}"
|
|
38
|
+
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
|
39
|
+
# "#{table_name}.#{column_name} NULLS LAST"
|
|
40
|
+
# "#{column_name}"
|
|
41
|
+
# "#{column_name} #{direction}"
|
|
42
|
+
# "#{column_name} #{direction} NULLS FIRST"
|
|
43
|
+
# "#{column_name} NULLS LAST"
|
|
44
|
+
def column_name_with_order_matcher
|
|
45
|
+
/
|
|
46
|
+
\A
|
|
47
|
+
(
|
|
48
|
+
(?:
|
|
49
|
+
# table_name.column_name | function(one or no argument)
|
|
50
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
|
51
|
+
)
|
|
52
|
+
(?:\s+ASC|\s+DESC)?
|
|
53
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
|
54
|
+
)
|
|
55
|
+
(?:\s*,\s*\g<1>)*
|
|
56
|
+
\z
|
|
57
|
+
/ix
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Quotes the column name. Must be implemented by subclasses
|
|
61
|
+
def quote_column_name(column_name)
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Quotes the table name. Defaults to column name quoting.
|
|
66
|
+
def quote_table_name(table_name)
|
|
67
|
+
quote_column_name(table_name)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
9
71
|
# Quotes the column value to help prevent
|
|
10
72
|
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
|
11
73
|
def quote(value)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
74
|
+
case value
|
|
75
|
+
when String, Symbol, ActiveSupport::Multibyte::Chars
|
|
76
|
+
"'#{quote_string(value.to_s)}'"
|
|
77
|
+
when true then quoted_true
|
|
78
|
+
when false then quoted_false
|
|
79
|
+
when nil then "NULL"
|
|
80
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
81
|
+
when BigDecimal then value.to_s("F")
|
|
82
|
+
when Numeric then value.to_s
|
|
83
|
+
when Type::Binary::Data then quoted_binary(value)
|
|
84
|
+
when Type::Time::Value then "'#{quoted_time(value)}'"
|
|
85
|
+
when Date, Time then "'#{quoted_date(value)}'"
|
|
86
|
+
when Class then "'#{value}'"
|
|
87
|
+
else raise TypeError, "can't quote #{value.class.name}"
|
|
16
88
|
end
|
|
17
|
-
|
|
18
|
-
_quote(value)
|
|
19
89
|
end
|
|
20
90
|
|
|
21
91
|
# Cast a +value+ to a type that the database understands. For example,
|
|
22
92
|
# SQLite does not understand dates, so this method will convert a Date
|
|
23
93
|
# to a String.
|
|
24
|
-
def type_cast(value
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
94
|
+
def type_cast(value)
|
|
95
|
+
case value
|
|
96
|
+
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
|
97
|
+
value.to_s
|
|
98
|
+
when true then unquoted_true
|
|
99
|
+
when false then unquoted_false
|
|
100
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
101
|
+
when BigDecimal then value.to_s("F")
|
|
102
|
+
when nil, Numeric, String then value
|
|
103
|
+
when Type::Time::Value then quoted_time(value)
|
|
104
|
+
when Date, Time then quoted_date(value)
|
|
105
|
+
else raise TypeError, "can't cast #{value.class.name}"
|
|
29
106
|
end
|
|
107
|
+
end
|
|
30
108
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
109
|
+
# Cast a value to be used as a bound parameter of unknown type. For example,
|
|
110
|
+
# MySQL might perform dangerous castings when comparing a string to a number,
|
|
111
|
+
# so this method will cast numbers to string.
|
|
112
|
+
def cast_bound_value(value) # :nodoc:
|
|
113
|
+
value
|
|
35
114
|
end
|
|
36
115
|
|
|
37
116
|
# If you are having to call this function, you are likely doing something
|
|
@@ -43,16 +122,6 @@ module ActiveRecord
|
|
|
43
122
|
# represent the type doesn't sufficiently reflect the differences
|
|
44
123
|
# (varchar vs binary) for example. The type used to get this primitive
|
|
45
124
|
# should have been provided before reaching the connection adapter.
|
|
46
|
-
def type_cast_from_column(column, value) # :nodoc:
|
|
47
|
-
if column
|
|
48
|
-
type = lookup_cast_type_from_column(column)
|
|
49
|
-
type.serialize(value)
|
|
50
|
-
else
|
|
51
|
-
value
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# See docs for #type_cast_from_column
|
|
56
125
|
def lookup_cast_type_from_column(column) # :nodoc:
|
|
57
126
|
lookup_cast_type(column.sql_type)
|
|
58
127
|
end
|
|
@@ -60,23 +129,23 @@ module ActiveRecord
|
|
|
60
129
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
|
61
130
|
# characters.
|
|
62
131
|
def quote_string(s)
|
|
63
|
-
s.gsub(
|
|
132
|
+
s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
|
64
133
|
end
|
|
65
134
|
|
|
66
|
-
# Quotes the column name.
|
|
135
|
+
# Quotes the column name.
|
|
67
136
|
def quote_column_name(column_name)
|
|
68
|
-
column_name
|
|
137
|
+
self.class.quote_column_name(column_name)
|
|
69
138
|
end
|
|
70
139
|
|
|
71
|
-
# Quotes the table name.
|
|
140
|
+
# Quotes the table name.
|
|
72
141
|
def quote_table_name(table_name)
|
|
73
|
-
|
|
142
|
+
self.class.quote_table_name(table_name)
|
|
74
143
|
end
|
|
75
144
|
|
|
76
145
|
# Override to return the quoted table name for assignment. Defaults to
|
|
77
146
|
# table quoting.
|
|
78
147
|
#
|
|
79
|
-
# This works for
|
|
148
|
+
# This works for MySQL where table.column can be used to
|
|
80
149
|
# resolve ambiguity.
|
|
81
150
|
#
|
|
82
151
|
# We override this in the sqlite3 and postgresql adapters to use only
|
|
@@ -114,16 +183,16 @@ module ActiveRecord
|
|
|
114
183
|
# if the value is a Time responding to usec.
|
|
115
184
|
def quoted_date(value)
|
|
116
185
|
if value.acts_like?(:time)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
value = value.
|
|
186
|
+
if default_timezone == :utc
|
|
187
|
+
value = value.getutc if !value.utc?
|
|
188
|
+
else
|
|
189
|
+
value = value.getlocal
|
|
121
190
|
end
|
|
122
191
|
end
|
|
123
192
|
|
|
124
|
-
result = value.
|
|
193
|
+
result = value.to_fs(:db)
|
|
125
194
|
if value.respond_to?(:usec) && value.usec > 0
|
|
126
|
-
"
|
|
195
|
+
result << "." << sprintf("%06d", value.usec)
|
|
127
196
|
else
|
|
128
197
|
result
|
|
129
198
|
end
|
|
@@ -139,113 +208,32 @@ module ActiveRecord
|
|
|
139
208
|
end
|
|
140
209
|
|
|
141
210
|
def sanitize_as_sql_comment(value) # :nodoc:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
211
|
+
# Sanitize a string to appear within a SQL comment
|
|
212
|
+
# For compatibility, this also surrounding "/*+", "/*", and "*/"
|
|
213
|
+
# charcacters, possibly with single surrounding space.
|
|
214
|
+
# Then follows that by replacing any internal "*/" or "/ *" with
|
|
215
|
+
# "* /" or "/ *"
|
|
216
|
+
comment = value.to_s.dup
|
|
217
|
+
comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
|
|
218
|
+
comment.gsub!("*/", "* /")
|
|
219
|
+
comment.gsub!("/*", "/ *")
|
|
220
|
+
comment
|
|
151
221
|
end
|
|
152
222
|
|
|
153
|
-
# Regexp for column names (with or without a table name prefix).
|
|
154
|
-
# Matches the following:
|
|
155
|
-
#
|
|
156
|
-
# "#{table_name}.#{column_name}"
|
|
157
|
-
# "#{column_name}"
|
|
158
|
-
COLUMN_NAME = /
|
|
159
|
-
\A
|
|
160
|
-
(
|
|
161
|
-
(?:
|
|
162
|
-
# table_name.column_name | function(one or no argument)
|
|
163
|
-
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
|
164
|
-
)
|
|
165
|
-
(?:\s+AS\s+\w+)?
|
|
166
|
-
)
|
|
167
|
-
(?:\s*,\s*\g<1>)*
|
|
168
|
-
\z
|
|
169
|
-
/ix
|
|
170
|
-
|
|
171
|
-
# Regexp for column names with order (with or without a table name prefix,
|
|
172
|
-
# with or without various order modifiers). Matches the following:
|
|
173
|
-
#
|
|
174
|
-
# "#{table_name}.#{column_name}"
|
|
175
|
-
# "#{table_name}.#{column_name} #{direction}"
|
|
176
|
-
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
|
177
|
-
# "#{table_name}.#{column_name} NULLS LAST"
|
|
178
|
-
# "#{column_name}"
|
|
179
|
-
# "#{column_name} #{direction}"
|
|
180
|
-
# "#{column_name} #{direction} NULLS FIRST"
|
|
181
|
-
# "#{column_name} NULLS LAST"
|
|
182
|
-
COLUMN_NAME_WITH_ORDER = /
|
|
183
|
-
\A
|
|
184
|
-
(
|
|
185
|
-
(?:
|
|
186
|
-
# table_name.column_name | function(one or no argument)
|
|
187
|
-
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
|
188
|
-
)
|
|
189
|
-
(?:\s+ASC|\s+DESC)?
|
|
190
|
-
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
|
191
|
-
)
|
|
192
|
-
(?:\s*,\s*\g<1>)*
|
|
193
|
-
\z
|
|
194
|
-
/ix
|
|
195
|
-
|
|
196
|
-
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
|
197
|
-
|
|
198
223
|
private
|
|
199
224
|
def type_casted_binds(binds)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
225
|
+
binds.map do |value|
|
|
226
|
+
if ActiveModel::Attribute === value
|
|
227
|
+
type_cast(value.value_for_database)
|
|
228
|
+
else
|
|
229
|
+
type_cast(value)
|
|
230
|
+
end
|
|
204
231
|
end
|
|
205
232
|
end
|
|
206
233
|
|
|
207
234
|
def lookup_cast_type(sql_type)
|
|
208
235
|
type_map.lookup(sql_type)
|
|
209
236
|
end
|
|
210
|
-
|
|
211
|
-
def id_value_for_database(value)
|
|
212
|
-
if primary_key = value.class.primary_key
|
|
213
|
-
value.instance_variable_get(:@attributes)[primary_key].value_for_database
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def _quote(value)
|
|
218
|
-
case value
|
|
219
|
-
when String, Symbol, ActiveSupport::Multibyte::Chars
|
|
220
|
-
"'#{quote_string(value.to_s)}'"
|
|
221
|
-
when true then quoted_true
|
|
222
|
-
when false then quoted_false
|
|
223
|
-
when nil then "NULL"
|
|
224
|
-
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
225
|
-
when BigDecimal then value.to_s("F")
|
|
226
|
-
when Numeric, ActiveSupport::Duration then value.to_s
|
|
227
|
-
when Type::Binary::Data then quoted_binary(value)
|
|
228
|
-
when Type::Time::Value then "'#{quoted_time(value)}'"
|
|
229
|
-
when Date, Time then "'#{quoted_date(value)}'"
|
|
230
|
-
when Class then "'#{value}'"
|
|
231
|
-
else raise TypeError, "can't quote #{value.class.name}"
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def _type_cast(value)
|
|
236
|
-
case value
|
|
237
|
-
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
|
238
|
-
value.to_s
|
|
239
|
-
when true then unquoted_true
|
|
240
|
-
when false then unquoted_false
|
|
241
|
-
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
242
|
-
when BigDecimal then value.to_s("F")
|
|
243
|
-
when nil, Numeric, String then value
|
|
244
|
-
when Type::Time::Value then quoted_time(value)
|
|
245
|
-
when Date, Time then quoted_date(value)
|
|
246
|
-
else raise TypeError
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
237
|
end
|
|
250
238
|
end
|
|
251
239
|
end
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
|
5
|
+
# = Active Record Connection Adapters \Savepoints
|
|
5
6
|
module Savepoints
|
|
6
7
|
def current_savepoint_name
|
|
7
8
|
current_transaction.savepoint_name
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def create_savepoint(name = current_savepoint_name)
|
|
11
|
-
|
|
12
|
+
internal_execute("SAVEPOINT #{name}", "TRANSACTION")
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
|
15
|
-
|
|
16
|
+
internal_execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def release_savepoint(name = current_savepoint_name)
|
|
19
|
-
|
|
20
|
+
internal_execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -2,152 +2,189 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
|
5
|
-
class
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
class SchemaCreation # :nodoc:
|
|
6
|
+
def initialize(conn)
|
|
7
|
+
@conn = conn
|
|
8
|
+
@cache = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def accept(o)
|
|
12
|
+
m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
|
|
13
|
+
send m, o
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
|
17
|
+
:options_include_default?, :supports_indexes_in_create?, :use_foreign_keys?,
|
|
18
|
+
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
|
|
19
|
+
:supports_index_include?, :supports_exclusion_constraints?, :supports_unique_constraints?,
|
|
20
|
+
:supports_nulls_not_distinct?,
|
|
21
|
+
to: :@conn, private: true
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def visit_AlterTable(o)
|
|
25
|
+
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
|
26
|
+
sql << o.adds.map { |col| accept col }.join(" ")
|
|
27
|
+
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
|
28
|
+
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
|
29
|
+
sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
|
|
30
|
+
sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def visit_ColumnDefinition(o)
|
|
34
|
+
o.sql_type = type_to_sql(o.type, **o.options)
|
|
35
|
+
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
|
36
|
+
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
|
37
|
+
column_sql
|
|
10
38
|
end
|
|
11
39
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
send m, o
|
|
40
|
+
def visit_AddColumnDefinition(o)
|
|
41
|
+
+"ADD #{accept(o.column)}"
|
|
15
42
|
end
|
|
16
43
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
44
|
+
def visit_TableDefinition(o)
|
|
45
|
+
create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
|
|
46
|
+
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
|
47
|
+
create_sql << "#{quote_table_name(o.name)} "
|
|
20
48
|
|
|
21
|
-
|
|
49
|
+
statements = o.columns.map { |c| accept c }
|
|
50
|
+
statements << accept(o.primary_keys) if o.primary_keys
|
|
22
51
|
|
|
23
|
-
|
|
24
|
-
|
|
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(" ")
|
|
52
|
+
if supports_indexes_in_create?
|
|
53
|
+
statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
|
|
28
54
|
end
|
|
29
55
|
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
column_sql
|
|
56
|
+
if use_foreign_keys?
|
|
57
|
+
statements.concat(o.foreign_keys.map { |fk| accept fk })
|
|
35
58
|
end
|
|
36
59
|
|
|
37
|
-
|
|
38
|
-
|
|
60
|
+
if supports_check_constraints?
|
|
61
|
+
statements.concat(o.check_constraints.map { |chk| accept chk })
|
|
39
62
|
end
|
|
40
63
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
create_sql << "#{quote_table_name(o.name)} "
|
|
64
|
+
if supports_exclusion_constraints?
|
|
65
|
+
statements.concat(o.exclusion_constraints.map { |exc| accept exc })
|
|
66
|
+
end
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
statements
|
|
68
|
+
if supports_unique_constraints?
|
|
69
|
+
statements.concat(o.unique_constraints.map { |exc| accept exc })
|
|
70
|
+
end
|
|
48
71
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
72
|
+
create_sql << "(#{statements.join(', ')})" if statements.present?
|
|
73
|
+
add_table_options!(create_sql, o)
|
|
74
|
+
create_sql << " AS #{to_sql(o.as)}" if o.as
|
|
75
|
+
create_sql
|
|
76
|
+
end
|
|
52
77
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
def visit_PrimaryKeyDefinition(o)
|
|
79
|
+
"PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
|
|
80
|
+
end
|
|
56
81
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
def visit_ForeignKeyDefinition(o)
|
|
83
|
+
quoted_columns = Array(o.column).map { |c| quote_column_name(c) }
|
|
84
|
+
quoted_primary_keys = Array(o.primary_key).map { |c| quote_column_name(c) }
|
|
85
|
+
sql = +<<~SQL
|
|
86
|
+
CONSTRAINT #{quote_column_name(o.name)}
|
|
87
|
+
FOREIGN KEY (#{quoted_columns.join(", ")})
|
|
88
|
+
REFERENCES #{quote_table_name(o.to_table)} (#{quoted_primary_keys.join(", ")})
|
|
89
|
+
SQL
|
|
90
|
+
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
|
91
|
+
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
|
92
|
+
sql
|
|
93
|
+
end
|
|
62
94
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
def visit_AddForeignKey(o)
|
|
96
|
+
"ADD #{accept(o)}"
|
|
97
|
+
end
|
|
66
98
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
FOREIGN KEY (#{quote_column_name(o.column)})
|
|
71
|
-
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
|
72
|
-
SQL
|
|
73
|
-
sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
|
|
74
|
-
sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
|
|
75
|
-
sql
|
|
76
|
-
end
|
|
99
|
+
def visit_DropForeignKey(name)
|
|
100
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
|
101
|
+
end
|
|
77
102
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
103
|
+
def visit_CreateIndexDefinition(o)
|
|
104
|
+
index = o.index
|
|
105
|
+
|
|
106
|
+
sql = ["CREATE"]
|
|
107
|
+
sql << "UNIQUE" if index.unique
|
|
108
|
+
sql << "INDEX"
|
|
109
|
+
sql << o.algorithm if o.algorithm
|
|
110
|
+
sql << "IF NOT EXISTS" if o.if_not_exists
|
|
111
|
+
sql << index.type if index.type
|
|
112
|
+
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
|
113
|
+
sql << "USING #{index.using}" if supports_index_using? && index.using
|
|
114
|
+
sql << "(#{quoted_columns(index)})"
|
|
115
|
+
sql << "INCLUDE (#{quoted_include_columns(index.include)})" if supports_index_include? && index.include
|
|
116
|
+
sql << "NULLS NOT DISTINCT" if supports_nulls_not_distinct? && index.nulls_not_distinct
|
|
117
|
+
sql << "WHERE #{index.where}" if supports_partial_index? && index.where
|
|
118
|
+
|
|
119
|
+
sql.join(" ")
|
|
120
|
+
end
|
|
81
121
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
122
|
+
def visit_CheckConstraintDefinition(o)
|
|
123
|
+
"CONSTRAINT #{o.name} CHECK (#{o.expression})"
|
|
124
|
+
end
|
|
85
125
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
table_options[:options] = o.options
|
|
90
|
-
table_options
|
|
91
|
-
end
|
|
126
|
+
def visit_AddCheckConstraint(o)
|
|
127
|
+
"ADD #{accept(o)}"
|
|
128
|
+
end
|
|
92
129
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
create_sql
|
|
98
|
-
end
|
|
130
|
+
def visit_DropCheckConstraint(name)
|
|
131
|
+
"DROP CONSTRAINT #{quote_column_name(name)}"
|
|
132
|
+
end
|
|
99
133
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
134
|
+
def quoted_columns(o)
|
|
135
|
+
String === o.columns ? o.columns : quoted_columns_for_index(o.columns, o.column_options)
|
|
136
|
+
end
|
|
103
137
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if options[:null] == false
|
|
108
|
-
sql << " NOT NULL"
|
|
109
|
-
end
|
|
110
|
-
if options[:auto_increment] == true
|
|
111
|
-
sql << " AUTO_INCREMENT"
|
|
112
|
-
end
|
|
113
|
-
if options[:primary_key] == true
|
|
114
|
-
sql << " PRIMARY KEY"
|
|
115
|
-
end
|
|
116
|
-
sql
|
|
117
|
-
end
|
|
138
|
+
def supports_index_using?
|
|
139
|
+
true
|
|
140
|
+
end
|
|
118
141
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
142
|
+
def add_table_options!(create_sql, o)
|
|
143
|
+
create_sql << " #{o.options}" if o.options
|
|
144
|
+
create_sql
|
|
145
|
+
end
|
|
123
146
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
end
|
|
147
|
+
def column_options(o)
|
|
148
|
+
o.options.merge(column: o)
|
|
149
|
+
end
|
|
128
150
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
151
|
+
def add_column_options!(sql, options)
|
|
152
|
+
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
|
153
|
+
# must explicitly check for :null to allow change_column to work on migrations
|
|
154
|
+
if options[:null] == false
|
|
155
|
+
sql << " NOT NULL"
|
|
156
|
+
end
|
|
157
|
+
if options[:auto_increment] == true
|
|
158
|
+
sql << " AUTO_INCREMENT"
|
|
159
|
+
end
|
|
160
|
+
if options[:primary_key] == true
|
|
161
|
+
sql << " PRIMARY KEY"
|
|
135
162
|
end
|
|
163
|
+
sql
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def to_sql(sql)
|
|
167
|
+
sql = sql.to_sql if sql.respond_to?(:to_sql)
|
|
168
|
+
sql
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
|
172
|
+
def table_modifier_in_create(o)
|
|
173
|
+
" TEMPORARY" if o.temporary
|
|
174
|
+
end
|
|
136
175
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
end
|
|
176
|
+
def action_sql(action, dependency)
|
|
177
|
+
case dependency
|
|
178
|
+
when :nullify then "ON #{action} SET NULL"
|
|
179
|
+
when :cascade then "ON #{action} CASCADE"
|
|
180
|
+
when :restrict then "ON #{action} RESTRICT"
|
|
181
|
+
else
|
|
182
|
+
raise ArgumentError, <<~MSG
|
|
183
|
+
'#{dependency}' is not supported for :on_update or :on_delete.
|
|
184
|
+
Supported values are: :nullify, :cascade, :restrict
|
|
185
|
+
MSG
|
|
148
186
|
end
|
|
149
|
-
|
|
187
|
+
end
|
|
150
188
|
end
|
|
151
|
-
SchemaCreation = AbstractAdapter::SchemaCreation # :nodoc:
|
|
152
189
|
end
|
|
153
190
|
end
|