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
|
@@ -14,29 +14,39 @@ module ActiveRecord
|
|
|
14
14
|
sql
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
|
|
17
|
+
def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil, allow_retry = false) # :nodoc:
|
|
18
|
+
# Arel::TreeManager -> Arel::Node
|
|
18
19
|
if arel_or_sql_string.respond_to?(:ast)
|
|
20
|
+
arel_or_sql_string = arel_or_sql_string.ast
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if Arel.arel_node?(arel_or_sql_string) && !(String === arel_or_sql_string)
|
|
19
24
|
unless binds.empty?
|
|
20
25
|
raise "Passing bind parameters with an arel AST is forbidden. " \
|
|
21
26
|
"The values must be stored on the AST directly"
|
|
22
27
|
end
|
|
23
28
|
|
|
29
|
+
collector = collector()
|
|
30
|
+
collector.retryable = true
|
|
31
|
+
|
|
24
32
|
if prepared_statements
|
|
25
|
-
|
|
33
|
+
collector.preparable = true
|
|
34
|
+
sql, binds = visitor.compile(arel_or_sql_string, collector)
|
|
26
35
|
|
|
27
36
|
if binds.length > bind_params_length
|
|
28
37
|
unprepared_statement do
|
|
29
|
-
|
|
30
|
-
visitor.preparable = false
|
|
38
|
+
return to_sql_and_binds(arel_or_sql_string)
|
|
31
39
|
end
|
|
32
40
|
end
|
|
41
|
+
preparable = collector.preparable
|
|
33
42
|
else
|
|
34
|
-
sql = visitor.compile(arel_or_sql_string
|
|
43
|
+
sql = visitor.compile(arel_or_sql_string, collector)
|
|
35
44
|
end
|
|
36
|
-
|
|
45
|
+
allow_retry = collector.retryable
|
|
46
|
+
[sql.freeze, binds, preparable, allow_retry]
|
|
37
47
|
else
|
|
38
|
-
|
|
39
|
-
[arel_or_sql_string
|
|
48
|
+
arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
|
|
49
|
+
[arel_or_sql_string, binds, preparable, allow_retry]
|
|
40
50
|
end
|
|
41
51
|
end
|
|
42
52
|
private :to_sql_and_binds
|
|
@@ -56,30 +66,28 @@ module ActiveRecord
|
|
|
56
66
|
end
|
|
57
67
|
|
|
58
68
|
# Returns an ActiveRecord::Result instance.
|
|
59
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
|
69
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false)
|
|
60
70
|
arel = arel_from_relation(arel)
|
|
61
|
-
sql, binds = to_sql_and_binds(arel, binds)
|
|
62
|
-
|
|
63
|
-
if preparable.nil?
|
|
64
|
-
preparable = prepared_statements ? visitor.preparable : false
|
|
65
|
-
end
|
|
71
|
+
sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable, allow_retry)
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
select(sql, name, binds,
|
|
74
|
+
prepare: prepared_statements && preparable,
|
|
75
|
+
async: async && FutureResult::SelectAll,
|
|
76
|
+
allow_retry: allow_retry
|
|
77
|
+
)
|
|
78
|
+
rescue ::RangeError
|
|
79
|
+
ActiveRecord::Result.empty(async: async)
|
|
72
80
|
end
|
|
73
81
|
|
|
74
82
|
# Returns a record hash with the column names as keys and column values
|
|
75
83
|
# as values.
|
|
76
|
-
def select_one(arel, name = nil, binds = [])
|
|
77
|
-
select_all(arel, name, binds).first
|
|
84
|
+
def select_one(arel, name = nil, binds = [], async: false)
|
|
85
|
+
select_all(arel, name, binds, async: async).then(&:first)
|
|
78
86
|
end
|
|
79
87
|
|
|
80
88
|
# Returns a single value from a record
|
|
81
|
-
def select_value(arel, name = nil, binds = [])
|
|
82
|
-
|
|
89
|
+
def select_value(arel, name = nil, binds = [], async: false)
|
|
90
|
+
select_rows(arel, name, binds, async: async).then { |rows| single_value_from_rows(rows) }
|
|
83
91
|
end
|
|
84
92
|
|
|
85
93
|
# Returns an array of the values of the first column in a select:
|
|
@@ -90,8 +98,8 @@ module ActiveRecord
|
|
|
90
98
|
|
|
91
99
|
# Returns an array of arrays containing the field values.
|
|
92
100
|
# Order is the same as that returned by +columns+.
|
|
93
|
-
def select_rows(arel, name = nil, binds = [])
|
|
94
|
-
select_all(arel, name, binds).rows
|
|
101
|
+
def select_rows(arel, name = nil, binds = [], async: false)
|
|
102
|
+
select_all(arel, name, binds, async: async).then(&:rows)
|
|
95
103
|
end
|
|
96
104
|
|
|
97
105
|
def query_value(sql, name = nil) # :nodoc:
|
|
@@ -103,7 +111,7 @@ module ActiveRecord
|
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
def query(sql, name = nil) # :nodoc:
|
|
106
|
-
|
|
114
|
+
internal_exec_query(sql, name).rows
|
|
107
115
|
end
|
|
108
116
|
|
|
109
117
|
# Determines whether the SQL statement is a write query.
|
|
@@ -113,40 +121,64 @@ module ActiveRecord
|
|
|
113
121
|
|
|
114
122
|
# Executes the SQL statement in the context of this connection and returns
|
|
115
123
|
# the raw result from the connection adapter.
|
|
124
|
+
#
|
|
125
|
+
# Setting +allow_retry+ to true causes the db to reconnect and retry
|
|
126
|
+
# executing the SQL statement in case of a connection-related exception.
|
|
127
|
+
# This option should only be enabled for known idempotent queries.
|
|
128
|
+
#
|
|
129
|
+
# Note: the query is assumed to have side effects and the query cache
|
|
130
|
+
# will be cleared. If the query is read-only, consider using #select_all
|
|
131
|
+
# instead.
|
|
132
|
+
#
|
|
116
133
|
# Note: depending on your database connector, the result returned by this
|
|
117
|
-
# method may be manually memory managed. Consider using
|
|
134
|
+
# method may be manually memory managed. Consider using #exec_query
|
|
118
135
|
# wrapper instead.
|
|
119
|
-
def execute(sql, name = nil)
|
|
120
|
-
|
|
136
|
+
def execute(sql, name = nil, allow_retry: false)
|
|
137
|
+
internal_execute(sql, name, allow_retry: allow_retry)
|
|
121
138
|
end
|
|
122
139
|
|
|
123
140
|
# Executes +sql+ statement in the context of this connection using
|
|
124
141
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
125
142
|
# the executed +sql+ statement.
|
|
143
|
+
#
|
|
144
|
+
# Note: the query is assumed to have side effects and the query cache
|
|
145
|
+
# will be cleared. If the query is read-only, consider using #select_all
|
|
146
|
+
# instead.
|
|
126
147
|
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
|
127
|
-
|
|
148
|
+
internal_exec_query(sql, name, binds, prepare: prepare)
|
|
128
149
|
end
|
|
129
150
|
|
|
130
151
|
# Executes insert +sql+ statement in the context of this connection using
|
|
131
152
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
132
153
|
# the executed +sql+ statement.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
# Some adapters support the `returning` keyword argument which allows to control the result of the query:
|
|
155
|
+
# `nil` is the default value and maintains default behavior. If an array of column names is passed -
|
|
156
|
+
# the result will contain values of the specified columns from the inserted row.
|
|
157
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
|
|
158
|
+
sql, binds = sql_for_insert(sql, pk, binds, returning)
|
|
159
|
+
internal_exec_query(sql, name, binds)
|
|
136
160
|
end
|
|
137
161
|
|
|
138
162
|
# Executes delete +sql+ statement in the context of this connection using
|
|
139
163
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
140
164
|
# the executed +sql+ statement.
|
|
141
165
|
def exec_delete(sql, name = nil, binds = [])
|
|
142
|
-
|
|
166
|
+
internal_exec_query(sql, name, binds)
|
|
143
167
|
end
|
|
144
168
|
|
|
145
169
|
# Executes update +sql+ statement in the context of this connection using
|
|
146
170
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
147
171
|
# the executed +sql+ statement.
|
|
148
172
|
def exec_update(sql, name = nil, binds = [])
|
|
149
|
-
|
|
173
|
+
internal_exec_query(sql, name, binds)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def exec_insert_all(sql, name) # :nodoc:
|
|
177
|
+
internal_exec_query(sql, name)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def explain(arel, binds = [], options = []) # :nodoc:
|
|
181
|
+
raise NotImplementedError
|
|
150
182
|
end
|
|
151
183
|
|
|
152
184
|
# Executes an INSERT query and returns the new record's ID
|
|
@@ -157,9 +189,15 @@ module ActiveRecord
|
|
|
157
189
|
#
|
|
158
190
|
# If the next id was calculated in advance (as in Oracle), it should be
|
|
159
191
|
# passed in as +id_value+.
|
|
160
|
-
|
|
192
|
+
# Some adapters support the `returning` keyword argument which allows defining the return value of the method:
|
|
193
|
+
# `nil` is the default value and maintains default behavior. If an array of column names is passed -
|
|
194
|
+
# an array of is returned from the method representing values of the specified columns from the inserted row.
|
|
195
|
+
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
|
|
161
196
|
sql, binds = to_sql_and_binds(arel, binds)
|
|
162
|
-
value = exec_insert(sql, name, binds, pk, sequence_name)
|
|
197
|
+
value = exec_insert(sql, name, binds, pk, sequence_name, returning: returning)
|
|
198
|
+
|
|
199
|
+
return returning_column_values(value) unless returning.nil?
|
|
200
|
+
|
|
163
201
|
id_value || last_inserted_id(value)
|
|
164
202
|
end
|
|
165
203
|
alias create insert
|
|
@@ -178,17 +216,18 @@ module ActiveRecord
|
|
|
178
216
|
|
|
179
217
|
# Executes the truncate statement.
|
|
180
218
|
def truncate(table_name, name = nil)
|
|
181
|
-
execute(
|
|
219
|
+
execute(build_truncate_statement(table_name), name)
|
|
182
220
|
end
|
|
183
221
|
|
|
184
222
|
def truncate_tables(*table_names) # :nodoc:
|
|
223
|
+
table_names -= [pool.schema_migration.table_name, pool.internal_metadata.table_name]
|
|
224
|
+
|
|
185
225
|
return if table_names.empty?
|
|
186
226
|
|
|
187
227
|
with_multi_statements do
|
|
188
228
|
disable_referential_integrity do
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
end
|
|
229
|
+
statements = build_truncate_statements(table_names)
|
|
230
|
+
execute_batch(statements, "Truncate Tables")
|
|
192
231
|
end
|
|
193
232
|
end
|
|
194
233
|
end
|
|
@@ -196,17 +235,43 @@ module ActiveRecord
|
|
|
196
235
|
# Runs the given block in a database transaction, and returns the result
|
|
197
236
|
# of the block.
|
|
198
237
|
#
|
|
238
|
+
# == Transaction callbacks
|
|
239
|
+
#
|
|
240
|
+
# #transaction yields an ActiveRecord::Transaction object on which it is
|
|
241
|
+
# possible to register callback:
|
|
242
|
+
#
|
|
243
|
+
# ActiveRecord::Base.transaction do |transaction|
|
|
244
|
+
# transaction.before_commit { puts "before commit!" }
|
|
245
|
+
# transaction.after_commit { puts "after commit!" }
|
|
246
|
+
# transaction.after_rollback { puts "after rollback!" }
|
|
247
|
+
# end
|
|
248
|
+
#
|
|
199
249
|
# == Nested transactions support
|
|
200
250
|
#
|
|
251
|
+
# #transaction calls can be nested. By default, this makes all database
|
|
252
|
+
# statements in the nested transaction block become part of the parent
|
|
253
|
+
# transaction. For example, the following behavior may be surprising:
|
|
254
|
+
#
|
|
255
|
+
# ActiveRecord::Base.transaction do
|
|
256
|
+
# Post.create(title: 'first')
|
|
257
|
+
# ActiveRecord::Base.transaction do
|
|
258
|
+
# Post.create(title: 'second')
|
|
259
|
+
# raise ActiveRecord::Rollback
|
|
260
|
+
# end
|
|
261
|
+
# end
|
|
262
|
+
#
|
|
263
|
+
# This creates both "first" and "second" posts. Reason is the
|
|
264
|
+
# ActiveRecord::Rollback exception in the nested block does not issue a
|
|
265
|
+
# ROLLBACK. Since these exceptions are captured in transaction blocks,
|
|
266
|
+
# the parent block does not see it and the real transaction is committed.
|
|
267
|
+
#
|
|
201
268
|
# Most databases don't support true nested transactions. At the time of
|
|
202
269
|
# writing, the only database that supports true nested transactions that
|
|
203
270
|
# we're aware of, is MS-SQL.
|
|
204
271
|
#
|
|
205
272
|
# In order to get around this problem, #transaction will emulate the effect
|
|
206
273
|
# of nested transactions, by using savepoints:
|
|
207
|
-
# https://dev.mysql.com/doc/refman/
|
|
208
|
-
# Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
|
|
209
|
-
# supports savepoints.
|
|
274
|
+
# https://dev.mysql.com/doc/refman/en/savepoint.html.
|
|
210
275
|
#
|
|
211
276
|
# It is safe to call this method if a database transaction is already open,
|
|
212
277
|
# i.e. if #transaction is called within another #transaction block. In case
|
|
@@ -218,6 +283,24 @@ module ActiveRecord
|
|
|
218
283
|
# - However, if +:requires_new+ is set, the block will be wrapped in a
|
|
219
284
|
# database savepoint acting as a sub-transaction.
|
|
220
285
|
#
|
|
286
|
+
# In order to get a ROLLBACK for the nested transaction you may ask for a
|
|
287
|
+
# real sub-transaction by passing <tt>requires_new: true</tt>.
|
|
288
|
+
# If anything goes wrong, the database rolls back to the beginning of
|
|
289
|
+
# the sub-transaction without rolling back the parent transaction.
|
|
290
|
+
# If we add it to the previous example:
|
|
291
|
+
#
|
|
292
|
+
# ActiveRecord::Base.transaction do
|
|
293
|
+
# Post.create(title: 'first')
|
|
294
|
+
# ActiveRecord::Base.transaction(requires_new: true) do
|
|
295
|
+
# Post.create(title: 'second')
|
|
296
|
+
# raise ActiveRecord::Rollback
|
|
297
|
+
# end
|
|
298
|
+
# end
|
|
299
|
+
#
|
|
300
|
+
# only post with title "first" is created.
|
|
301
|
+
#
|
|
302
|
+
# See ActiveRecord::Transactions to learn more.
|
|
303
|
+
#
|
|
221
304
|
# === Caveats
|
|
222
305
|
#
|
|
223
306
|
# MySQL doesn't support DDL transactions. If you perform a DDL operation,
|
|
@@ -230,9 +313,9 @@ module ActiveRecord
|
|
|
230
313
|
# #transaction will raise exceptions when it tries to release the
|
|
231
314
|
# already-automatically-released savepoints:
|
|
232
315
|
#
|
|
233
|
-
# Model.
|
|
234
|
-
# Model.
|
|
235
|
-
# Model.
|
|
316
|
+
# Model.lease_connection.transaction do # BEGIN
|
|
317
|
+
# Model.lease_connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
|
|
318
|
+
# Model.lease_connection.create_table(...)
|
|
236
319
|
# # active_record_1 now automatically released
|
|
237
320
|
# end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
|
|
238
321
|
# end
|
|
@@ -257,7 +340,7 @@ module ActiveRecord
|
|
|
257
340
|
# semantics of these different levels:
|
|
258
341
|
#
|
|
259
342
|
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
|
260
|
-
# * https://dev.mysql.com/doc/refman/
|
|
343
|
+
# * https://dev.mysql.com/doc/refman/en/set-transaction.html
|
|
261
344
|
#
|
|
262
345
|
# An ActiveRecord::TransactionIsolationError will be raised if:
|
|
263
346
|
#
|
|
@@ -265,43 +348,64 @@ module ActiveRecord
|
|
|
265
348
|
# * You are joining an existing open transaction
|
|
266
349
|
# * You are creating a nested (savepoint) transaction
|
|
267
350
|
#
|
|
268
|
-
# The mysql2 and postgresql adapters support setting the transaction
|
|
351
|
+
# The mysql2, trilogy, and postgresql adapters support setting the transaction
|
|
269
352
|
# isolation level.
|
|
270
|
-
|
|
353
|
+
# :args: (requires_new: nil, isolation: nil, &block)
|
|
354
|
+
def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
|
|
271
355
|
if !requires_new && current_transaction.joinable?
|
|
272
356
|
if isolation
|
|
273
357
|
raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
|
|
274
358
|
end
|
|
275
|
-
yield
|
|
359
|
+
yield current_transaction.user_transaction
|
|
276
360
|
else
|
|
277
|
-
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable)
|
|
361
|
+
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
|
|
278
362
|
end
|
|
279
363
|
rescue ActiveRecord::Rollback
|
|
280
364
|
# rollbacks are silently swallowed
|
|
281
365
|
end
|
|
282
366
|
|
|
283
|
-
attr_reader :transaction_manager
|
|
367
|
+
attr_reader :transaction_manager # :nodoc:
|
|
284
368
|
|
|
285
369
|
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
|
286
370
|
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
|
287
|
-
:disable_lazy_transactions!, :enable_lazy_transactions!,
|
|
371
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, :dirty_current_transaction,
|
|
372
|
+
to: :transaction_manager
|
|
373
|
+
|
|
374
|
+
def mark_transaction_written_if_write(sql) # :nodoc:
|
|
375
|
+
transaction = current_transaction
|
|
376
|
+
if transaction.open?
|
|
377
|
+
transaction.written ||= write_query?(sql)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
288
380
|
|
|
289
381
|
def transaction_open?
|
|
290
382
|
current_transaction.open?
|
|
291
383
|
end
|
|
292
384
|
|
|
293
|
-
def reset_transaction
|
|
385
|
+
def reset_transaction(restore: false) # :nodoc:
|
|
386
|
+
# Store the existing transaction state to the side
|
|
387
|
+
old_state = @transaction_manager if restore && @transaction_manager&.restorable?
|
|
388
|
+
|
|
294
389
|
@transaction_manager = ConnectionAdapters::TransactionManager.new(self)
|
|
390
|
+
|
|
391
|
+
if block_given?
|
|
392
|
+
# Reconfigure the connection without any transaction state in the way
|
|
393
|
+
result = yield
|
|
394
|
+
|
|
395
|
+
# Now the connection's fully established, we can swap back
|
|
396
|
+
if old_state
|
|
397
|
+
@transaction_manager = old_state
|
|
398
|
+
@transaction_manager.restore_transactions
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
result
|
|
402
|
+
end
|
|
295
403
|
end
|
|
296
404
|
|
|
297
405
|
# Register a record with the current transaction so that its after_commit and after_rollback callbacks
|
|
298
406
|
# can be called.
|
|
299
|
-
def add_transaction_record(record)
|
|
300
|
-
current_transaction.add_record(record)
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def transaction_state
|
|
304
|
-
current_transaction.state
|
|
407
|
+
def add_transaction_record(record, ensure_finalize = true)
|
|
408
|
+
current_transaction.add_record(record, ensure_finalize)
|
|
305
409
|
end
|
|
306
410
|
|
|
307
411
|
# Begins the transaction (and turns off auto-committing).
|
|
@@ -330,9 +434,17 @@ module ActiveRecord
|
|
|
330
434
|
# done if the transaction block raises an exception or returns false.
|
|
331
435
|
def rollback_db_transaction
|
|
332
436
|
exec_rollback_db_transaction
|
|
437
|
+
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::ConnectionFailed
|
|
438
|
+
# Connection's gone; that counts as a rollback
|
|
333
439
|
end
|
|
334
440
|
|
|
335
|
-
def exec_rollback_db_transaction() end
|
|
441
|
+
def exec_rollback_db_transaction() end # :nodoc:
|
|
442
|
+
|
|
443
|
+
def restart_db_transaction
|
|
444
|
+
exec_restart_db_transaction
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def exec_restart_db_transaction() end # :nodoc:
|
|
336
448
|
|
|
337
449
|
def rollback_to_savepoint(name = nil)
|
|
338
450
|
exec_rollback_to_savepoint(name)
|
|
@@ -348,10 +460,10 @@ module ActiveRecord
|
|
|
348
460
|
end
|
|
349
461
|
|
|
350
462
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
|
351
|
-
# something beyond a simple insert (
|
|
352
|
-
# Most of adapters should implement
|
|
463
|
+
# something beyond a simple insert (e.g. Oracle).
|
|
464
|
+
# Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
|
|
353
465
|
# We keep this method to provide fallback
|
|
354
|
-
# for databases like
|
|
466
|
+
# for databases like SQLite that do not support bulk inserts.
|
|
355
467
|
def insert_fixture(fixture, table_name)
|
|
356
468
|
execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
|
|
357
469
|
end
|
|
@@ -359,14 +471,12 @@ module ActiveRecord
|
|
|
359
471
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
|
360
472
|
fixture_inserts = build_fixture_statements(fixture_set)
|
|
361
473
|
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
|
362
|
-
|
|
474
|
+
statements = table_deletes + fixture_inserts
|
|
363
475
|
|
|
364
476
|
with_multi_statements do
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
execute_batch(sql, "Fixtures Load")
|
|
369
|
-
end
|
|
477
|
+
transaction(requires_new: true) do
|
|
478
|
+
disable_referential_integrity do
|
|
479
|
+
execute_batch(statements, "Fixtures Load")
|
|
370
480
|
end
|
|
371
481
|
end
|
|
372
482
|
end
|
|
@@ -401,9 +511,41 @@ module ActiveRecord
|
|
|
401
511
|
end
|
|
402
512
|
end
|
|
403
513
|
|
|
514
|
+
# This is a safe default, even if not high precision on all databases
|
|
515
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP", retryable: true).freeze # :nodoc:
|
|
516
|
+
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
517
|
+
|
|
518
|
+
# Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with
|
|
519
|
+
# arbitrary precision date/time columns.
|
|
520
|
+
#
|
|
521
|
+
# Adapters supporting datetime with precision should override this to
|
|
522
|
+
# provide as much precision as is available.
|
|
523
|
+
def high_precision_current_timestamp
|
|
524
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false) # :nodoc:
|
|
528
|
+
raise NotImplementedError
|
|
529
|
+
end
|
|
530
|
+
|
|
404
531
|
private
|
|
405
|
-
def
|
|
406
|
-
|
|
532
|
+
def internal_execute(sql, name = "SCHEMA", allow_retry: false, materialize_transactions: true)
|
|
533
|
+
sql = transform_query(sql)
|
|
534
|
+
check_if_write_query(sql)
|
|
535
|
+
|
|
536
|
+
mark_transaction_written_if_write(sql)
|
|
537
|
+
|
|
538
|
+
raw_execute(sql, name, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def execute_batch(statements, name = nil)
|
|
542
|
+
statements.each do |statement|
|
|
543
|
+
internal_execute(statement, name)
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
|
|
548
|
+
raise NotImplementedError
|
|
407
549
|
end
|
|
408
550
|
|
|
409
551
|
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
|
@@ -414,7 +556,7 @@ module ActiveRecord
|
|
|
414
556
|
end
|
|
415
557
|
|
|
416
558
|
def build_fixture_sql(fixtures, table_name)
|
|
417
|
-
columns = schema_cache.columns_hash(table_name)
|
|
559
|
+
columns = schema_cache.columns_hash(table_name).reject { |_, column| supports_virtual_columns? && column.virtual? }
|
|
418
560
|
|
|
419
561
|
values_list = fixtures.map do |fixture|
|
|
420
562
|
fixture = fixture.stringify_keys
|
|
@@ -435,8 +577,7 @@ module ActiveRecord
|
|
|
435
577
|
end
|
|
436
578
|
|
|
437
579
|
table = Arel::Table.new(table_name)
|
|
438
|
-
manager = Arel::InsertManager.new
|
|
439
|
-
manager.into(table)
|
|
580
|
+
manager = Arel::InsertManager.new(table)
|
|
440
581
|
|
|
441
582
|
if values_list.size == 1
|
|
442
583
|
values = values_list.shift
|
|
@@ -453,21 +594,24 @@ module ActiveRecord
|
|
|
453
594
|
end
|
|
454
595
|
|
|
455
596
|
manager.values = manager.create_values_list(values_list)
|
|
456
|
-
manager.
|
|
597
|
+
visitor.compile(manager.ast)
|
|
457
598
|
end
|
|
458
599
|
|
|
459
600
|
def build_fixture_statements(fixture_set)
|
|
460
|
-
fixture_set.
|
|
601
|
+
fixture_set.filter_map do |table_name, fixtures|
|
|
461
602
|
next if fixtures.empty?
|
|
462
603
|
build_fixture_sql(fixtures, table_name)
|
|
463
|
-
end
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
def build_truncate_statement(table_name)
|
|
608
|
+
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
|
464
609
|
end
|
|
465
610
|
|
|
466
|
-
def build_truncate_statements(
|
|
467
|
-
|
|
468
|
-
|
|
611
|
+
def build_truncate_statements(table_names)
|
|
612
|
+
table_names.map do |table_name|
|
|
613
|
+
build_truncate_statement(table_name)
|
|
469
614
|
end
|
|
470
|
-
combine_multi_statements(truncate_tables)
|
|
471
615
|
end
|
|
472
616
|
|
|
473
617
|
def with_multi_statements
|
|
@@ -479,15 +623,49 @@ module ActiveRecord
|
|
|
479
623
|
end
|
|
480
624
|
|
|
481
625
|
# Returns an ActiveRecord::Result instance.
|
|
482
|
-
def select(sql, name = nil, binds = [])
|
|
483
|
-
|
|
484
|
-
|
|
626
|
+
def select(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false)
|
|
627
|
+
if async && async_enabled?
|
|
628
|
+
if current_transaction.joinable?
|
|
629
|
+
raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
|
|
630
|
+
end
|
|
485
631
|
|
|
486
|
-
|
|
487
|
-
|
|
632
|
+
future_result = async.new(
|
|
633
|
+
pool,
|
|
634
|
+
sql,
|
|
635
|
+
name,
|
|
636
|
+
binds,
|
|
637
|
+
prepare: prepare,
|
|
638
|
+
)
|
|
639
|
+
if supports_concurrent_connections? && current_transaction.closed?
|
|
640
|
+
future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
|
|
641
|
+
else
|
|
642
|
+
future_result.execute!(self)
|
|
643
|
+
end
|
|
644
|
+
return future_result
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
result = internal_exec_query(sql, name, binds, prepare: prepare, allow_retry: allow_retry)
|
|
648
|
+
if async
|
|
649
|
+
FutureResult.wrap(result)
|
|
650
|
+
else
|
|
651
|
+
result
|
|
652
|
+
end
|
|
488
653
|
end
|
|
489
654
|
|
|
490
|
-
def sql_for_insert(sql, pk, binds)
|
|
655
|
+
def sql_for_insert(sql, pk, binds, returning) # :nodoc:
|
|
656
|
+
if supports_insert_returning?
|
|
657
|
+
if pk.nil?
|
|
658
|
+
# Extract the table from the insert sql. Yuck.
|
|
659
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
|
660
|
+
pk = primary_key(table_ref) if table_ref
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
returning_columns = returning || Array(pk)
|
|
664
|
+
|
|
665
|
+
returning_columns_statement = returning_columns.map { |c| quote_column_name(c) }.join(", ")
|
|
666
|
+
sql = "#{sql} RETURNING #{returning_columns_statement}" if returning_columns.any?
|
|
667
|
+
end
|
|
668
|
+
|
|
491
669
|
[sql, binds]
|
|
492
670
|
end
|
|
493
671
|
|
|
@@ -495,6 +673,10 @@ module ActiveRecord
|
|
|
495
673
|
single_value_from_rows(result.rows)
|
|
496
674
|
end
|
|
497
675
|
|
|
676
|
+
def returning_column_values(result)
|
|
677
|
+
[last_inserted_id(result)]
|
|
678
|
+
end
|
|
679
|
+
|
|
498
680
|
def single_value_from_rows(rows)
|
|
499
681
|
row = rows.first
|
|
500
682
|
row && row.first
|
|
@@ -507,6 +689,12 @@ module ActiveRecord
|
|
|
507
689
|
relation
|
|
508
690
|
end
|
|
509
691
|
end
|
|
692
|
+
|
|
693
|
+
def extract_table_ref_from_insert_sql(sql)
|
|
694
|
+
if sql =~ /into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
|
|
695
|
+
$1.delete('"').strip
|
|
696
|
+
end
|
|
697
|
+
end
|
|
510
698
|
end
|
|
511
699
|
end
|
|
512
700
|
end
|