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
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support/core_ext/digest"
|
|
4
|
+
|
|
3
5
|
module ActiveRecord
|
|
4
6
|
module ConnectionAdapters
|
|
7
|
+
# = Active Record Connection Adapters Transaction State
|
|
5
8
|
class TransactionState
|
|
6
9
|
def initialize(state = nil)
|
|
7
10
|
@state = state
|
|
8
|
-
@children =
|
|
11
|
+
@children = nil
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
def add_child(state)
|
|
15
|
+
@children ||= []
|
|
12
16
|
@children << state
|
|
13
17
|
end
|
|
14
18
|
|
|
@@ -32,6 +36,10 @@ module ActiveRecord
|
|
|
32
36
|
@state == :fully_rolledback
|
|
33
37
|
end
|
|
34
38
|
|
|
39
|
+
def invalidated?
|
|
40
|
+
@state == :invalidated
|
|
41
|
+
end
|
|
42
|
+
|
|
35
43
|
def fully_completed?
|
|
36
44
|
completed?
|
|
37
45
|
end
|
|
@@ -41,15 +49,20 @@ module ActiveRecord
|
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
def rollback!
|
|
44
|
-
@children
|
|
52
|
+
@children&.each { |c| c.rollback! }
|
|
45
53
|
@state = :rolledback
|
|
46
54
|
end
|
|
47
55
|
|
|
48
56
|
def full_rollback!
|
|
49
|
-
@children
|
|
57
|
+
@children&.each { |c| c.rollback! }
|
|
50
58
|
@state = :fully_rolledback
|
|
51
59
|
end
|
|
52
60
|
|
|
61
|
+
def invalidate!
|
|
62
|
+
@children&.each { |c| c.invalidate! }
|
|
63
|
+
@state = :invalidated
|
|
64
|
+
end
|
|
65
|
+
|
|
53
66
|
def commit!
|
|
54
67
|
@state = :committed
|
|
55
68
|
end
|
|
@@ -63,86 +76,334 @@ module ActiveRecord
|
|
|
63
76
|
end
|
|
64
77
|
end
|
|
65
78
|
|
|
66
|
-
class
|
|
67
|
-
def initialize
|
|
79
|
+
class TransactionInstrumenter
|
|
80
|
+
def initialize(payload = {})
|
|
81
|
+
@handle = nil
|
|
82
|
+
@started = false
|
|
83
|
+
@payload = nil
|
|
84
|
+
@base_payload = payload
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class InstrumentationNotStartedError < ActiveRecordError; end
|
|
88
|
+
class InstrumentationAlreadyStartedError < ActiveRecordError; end
|
|
89
|
+
|
|
90
|
+
def start
|
|
91
|
+
raise InstrumentationAlreadyStartedError.new("Called start on an already started transaction") if @started
|
|
92
|
+
@started = true
|
|
93
|
+
|
|
94
|
+
ActiveSupport::Notifications.instrument("start_transaction.active_record", @base_payload)
|
|
95
|
+
|
|
96
|
+
@payload = @base_payload.dup # We dup because the payload for a given event is mutated later to add the outcome.
|
|
97
|
+
@handle = ActiveSupport::Notifications.instrumenter.build_handle("transaction.active_record", @payload)
|
|
98
|
+
@handle.start
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def finish(outcome)
|
|
102
|
+
raise InstrumentationNotStartedError.new("Called finish on a transaction that hasn't started") unless @started
|
|
103
|
+
@started = false
|
|
104
|
+
|
|
105
|
+
@payload[:outcome] = outcome
|
|
106
|
+
@handle.finish
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
class NullTransaction # :nodoc:
|
|
68
111
|
def state; end
|
|
69
112
|
def closed?; true; end
|
|
70
113
|
def open?; false; end
|
|
71
114
|
def joinable?; false; end
|
|
72
|
-
def add_record(record); end
|
|
115
|
+
def add_record(record, _ = true); end
|
|
116
|
+
def restartable?; false; end
|
|
117
|
+
def dirty?; false; end
|
|
118
|
+
def dirty!; end
|
|
119
|
+
def invalidated?; false; end
|
|
120
|
+
def invalidate!; end
|
|
121
|
+
def materialized?; false; end
|
|
122
|
+
def before_commit; yield; end
|
|
123
|
+
def after_commit; yield; end
|
|
124
|
+
def after_rollback; end
|
|
125
|
+
def user_transaction; ActiveRecord::Transaction::NULL_TRANSACTION; end
|
|
73
126
|
end
|
|
74
127
|
|
|
75
|
-
class Transaction
|
|
76
|
-
|
|
128
|
+
class Transaction # :nodoc:
|
|
129
|
+
class Callback # :nodoc:
|
|
130
|
+
def initialize(event, callback)
|
|
131
|
+
@event = event
|
|
132
|
+
@callback = callback
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def before_commit
|
|
136
|
+
@callback.call if @event == :before_commit
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def after_commit
|
|
140
|
+
@callback.call if @event == :after_commit
|
|
141
|
+
end
|
|
77
142
|
|
|
78
|
-
|
|
143
|
+
def after_rollback
|
|
144
|
+
@callback.call if @event == :after_rollback
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
attr_reader :connection, :state, :savepoint_name, :isolation_level, :user_transaction
|
|
149
|
+
attr_accessor :written
|
|
150
|
+
|
|
151
|
+
delegate :invalidate!, :invalidated?, to: :@state
|
|
152
|
+
|
|
153
|
+
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
|
|
154
|
+
super()
|
|
79
155
|
@connection = connection
|
|
80
156
|
@state = TransactionState.new
|
|
81
|
-
@
|
|
82
|
-
@
|
|
157
|
+
@callbacks = nil
|
|
158
|
+
@records = nil
|
|
159
|
+
@isolation_level = isolation
|
|
83
160
|
@materialized = false
|
|
84
|
-
@joinable =
|
|
161
|
+
@joinable = joinable
|
|
85
162
|
@run_commit_callbacks = run_commit_callbacks
|
|
163
|
+
@lazy_enrollment_records = nil
|
|
164
|
+
@dirty = false
|
|
165
|
+
@user_transaction = joinable ? ActiveRecord::Transaction.new(self) : ActiveRecord::Transaction::NULL_TRANSACTION
|
|
166
|
+
@instrumenter = TransactionInstrumenter.new(connection: connection, transaction: @user_transaction)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def dirty!
|
|
170
|
+
@dirty = true
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def dirty?
|
|
174
|
+
@dirty
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def open?
|
|
178
|
+
true
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def closed?
|
|
182
|
+
false
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def add_record(record, ensure_finalize = true)
|
|
186
|
+
@records ||= []
|
|
187
|
+
if ensure_finalize
|
|
188
|
+
@records << record
|
|
189
|
+
else
|
|
190
|
+
@lazy_enrollment_records ||= ObjectSpace::WeakMap.new
|
|
191
|
+
@lazy_enrollment_records[record] = record
|
|
192
|
+
end
|
|
86
193
|
end
|
|
87
194
|
|
|
88
|
-
def
|
|
89
|
-
|
|
195
|
+
def before_commit(&block)
|
|
196
|
+
if @state.finalized?
|
|
197
|
+
raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
(@callbacks ||= []) << Callback.new(:before_commit, block)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def after_commit(&block)
|
|
204
|
+
if @state.finalized?
|
|
205
|
+
raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
(@callbacks ||= []) << Callback.new(:after_commit, block)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def after_rollback(&block)
|
|
212
|
+
if @state.finalized?
|
|
213
|
+
raise ActiveRecordError, "Cannot register callbacks on a finalized transaction"
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
(@callbacks ||= []) << Callback.new(:after_rollback, block)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def records
|
|
220
|
+
if @lazy_enrollment_records
|
|
221
|
+
@records.concat @lazy_enrollment_records.values
|
|
222
|
+
@lazy_enrollment_records = nil
|
|
223
|
+
end
|
|
224
|
+
@records
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Can this transaction's current state be recreated by
|
|
228
|
+
# rollback+begin ?
|
|
229
|
+
def restartable?
|
|
230
|
+
joinable? && !dirty?
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def incomplete!
|
|
234
|
+
@instrumenter.finish(:incomplete) if materialized?
|
|
90
235
|
end
|
|
91
236
|
|
|
92
237
|
def materialize!
|
|
93
238
|
@materialized = true
|
|
239
|
+
@instrumenter.start
|
|
94
240
|
end
|
|
95
241
|
|
|
96
242
|
def materialized?
|
|
97
243
|
@materialized
|
|
98
244
|
end
|
|
99
245
|
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
|
106
|
-
already_run_callbacks[record] ||= trigger_callbacks
|
|
107
|
-
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
|
246
|
+
def restore!
|
|
247
|
+
if materialized?
|
|
248
|
+
incomplete!
|
|
249
|
+
@materialized = false
|
|
250
|
+
materialize!
|
|
108
251
|
end
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def rollback_records
|
|
255
|
+
if records
|
|
256
|
+
begin
|
|
257
|
+
ite = unique_records
|
|
258
|
+
|
|
259
|
+
instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite)
|
|
260
|
+
|
|
261
|
+
run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
|
|
262
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
|
263
|
+
end
|
|
264
|
+
ensure
|
|
265
|
+
ite&.each do |i|
|
|
266
|
+
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
112
269
|
end
|
|
270
|
+
|
|
271
|
+
@callbacks&.each(&:after_rollback)
|
|
113
272
|
end
|
|
114
273
|
|
|
115
274
|
def before_commit_records
|
|
116
|
-
|
|
275
|
+
if @run_commit_callbacks
|
|
276
|
+
if records
|
|
277
|
+
if ActiveRecord.before_committed_on_all_records
|
|
278
|
+
ite = unique_records
|
|
279
|
+
|
|
280
|
+
instances_to_run_callbacks_on = records.each_with_object({}) do |record, candidates|
|
|
281
|
+
candidates[record] = record
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
|
|
285
|
+
record.before_committed! if should_run_callbacks
|
|
286
|
+
end
|
|
287
|
+
else
|
|
288
|
+
records.uniq.each(&:before_committed!)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
@callbacks&.each(&:before_commit)
|
|
293
|
+
end
|
|
294
|
+
# Note: When @run_commit_callbacks is false #commit_records takes care of appending
|
|
295
|
+
# remaining callbacks to the parent transaction
|
|
117
296
|
end
|
|
118
297
|
|
|
119
298
|
def commit_records
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
299
|
+
if records
|
|
300
|
+
begin
|
|
301
|
+
ite = unique_records
|
|
302
|
+
|
|
303
|
+
if @run_commit_callbacks
|
|
304
|
+
instances_to_run_callbacks_on = prepare_instances_to_run_callbacks_on(ite)
|
|
305
|
+
|
|
306
|
+
run_action_on_records(ite, instances_to_run_callbacks_on) do |record, should_run_callbacks|
|
|
307
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
|
308
|
+
end
|
|
309
|
+
else
|
|
310
|
+
while record = ite.shift
|
|
311
|
+
# if not running callbacks, only adds the record to the parent transaction
|
|
312
|
+
connection.add_transaction_record(record)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
ensure
|
|
316
|
+
ite&.each { |i| i.committed!(should_run_callbacks: false) }
|
|
131
317
|
end
|
|
132
318
|
end
|
|
133
|
-
|
|
134
|
-
|
|
319
|
+
|
|
320
|
+
if @run_commit_callbacks
|
|
321
|
+
@callbacks&.each(&:after_commit)
|
|
322
|
+
elsif @callbacks
|
|
323
|
+
connection.current_transaction.append_callbacks(@callbacks)
|
|
324
|
+
end
|
|
135
325
|
end
|
|
136
326
|
|
|
137
327
|
def full_rollback?; true; end
|
|
138
328
|
def joinable?; @joinable; end
|
|
139
|
-
|
|
140
|
-
|
|
329
|
+
|
|
330
|
+
protected
|
|
331
|
+
def append_callbacks(callbacks) # :nodoc:
|
|
332
|
+
(@callbacks ||= []).concat(callbacks)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
private
|
|
336
|
+
def unique_records
|
|
337
|
+
records.uniq(&:__id__)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def run_action_on_records(records, instances_to_run_callbacks_on)
|
|
341
|
+
while record = records.shift
|
|
342
|
+
should_run_callbacks = record.__id__ == instances_to_run_callbacks_on[record].__id__
|
|
343
|
+
|
|
344
|
+
yield record, should_run_callbacks
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def prepare_instances_to_run_callbacks_on(records)
|
|
349
|
+
records.each_with_object({}) do |record, candidates|
|
|
350
|
+
next unless record.trigger_transactional_callbacks?
|
|
351
|
+
|
|
352
|
+
earlier_saved_candidate = candidates[record]
|
|
353
|
+
|
|
354
|
+
next if earlier_saved_candidate && record.class.run_commit_callbacks_on_first_saved_instances_in_transaction
|
|
355
|
+
|
|
356
|
+
# If the candidate instance destroyed itself in the database, then
|
|
357
|
+
# instances which were added to the transaction afterwards, and which
|
|
358
|
+
# think they updated themselves, are wrong. They should not replace
|
|
359
|
+
# our candidate as an instance to run callbacks on
|
|
360
|
+
next if earlier_saved_candidate&.destroyed? && !record.destroyed?
|
|
361
|
+
|
|
362
|
+
# If the candidate instance was created inside of this transaction,
|
|
363
|
+
# then instances which were subsequently loaded from the database
|
|
364
|
+
# and updated need that state transferred to them so that
|
|
365
|
+
# the after_create_commit callbacks are run
|
|
366
|
+
record._new_record_before_last_commit = true if earlier_saved_candidate&._new_record_before_last_commit
|
|
367
|
+
|
|
368
|
+
# The last instance to save itself is likeliest to have internal
|
|
369
|
+
# state that matches what's committed to the database
|
|
370
|
+
candidates[record] = record
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# = Active Record Restart Parent \Transaction
|
|
376
|
+
class RestartParentTransaction < Transaction
|
|
377
|
+
def initialize(connection, parent_transaction, **options)
|
|
378
|
+
super(connection, **options)
|
|
379
|
+
|
|
380
|
+
@parent = parent_transaction
|
|
381
|
+
|
|
382
|
+
if isolation_level
|
|
383
|
+
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
@parent.state.add_child(@state)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
delegate :materialize!, :materialized?, :restart, to: :@parent
|
|
390
|
+
|
|
391
|
+
def rollback
|
|
392
|
+
@state.rollback!
|
|
393
|
+
@parent.restart
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def commit
|
|
397
|
+
@state.commit!
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def full_rollback?; false; end
|
|
141
401
|
end
|
|
142
402
|
|
|
403
|
+
# = Active Record Savepoint \Transaction
|
|
143
404
|
class SavepointTransaction < Transaction
|
|
144
|
-
def initialize(connection, savepoint_name, parent_transaction,
|
|
145
|
-
super(connection,
|
|
405
|
+
def initialize(connection, savepoint_name, parent_transaction, **options)
|
|
406
|
+
super(connection, **options)
|
|
146
407
|
|
|
147
408
|
parent_transaction.state.add_child(@state)
|
|
148
409
|
|
|
@@ -158,19 +419,33 @@ module ActiveRecord
|
|
|
158
419
|
super
|
|
159
420
|
end
|
|
160
421
|
|
|
422
|
+
def restart
|
|
423
|
+
return unless materialized?
|
|
424
|
+
|
|
425
|
+
@instrumenter.finish(:restart)
|
|
426
|
+
@instrumenter.start
|
|
427
|
+
|
|
428
|
+
connection.rollback_to_savepoint(savepoint_name)
|
|
429
|
+
end
|
|
430
|
+
|
|
161
431
|
def rollback
|
|
162
|
-
|
|
432
|
+
unless @state.invalidated?
|
|
433
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized? && connection.active?
|
|
434
|
+
end
|
|
163
435
|
@state.rollback!
|
|
436
|
+
@instrumenter.finish(:rollback) if materialized?
|
|
164
437
|
end
|
|
165
438
|
|
|
166
439
|
def commit
|
|
167
440
|
connection.release_savepoint(savepoint_name) if materialized?
|
|
168
441
|
@state.commit!
|
|
442
|
+
@instrumenter.finish(:commit) if materialized?
|
|
169
443
|
end
|
|
170
444
|
|
|
171
445
|
def full_rollback?; false; end
|
|
172
446
|
end
|
|
173
447
|
|
|
448
|
+
# = Active Record Real \Transaction
|
|
174
449
|
class RealTransaction < Transaction
|
|
175
450
|
def materialize!
|
|
176
451
|
if isolation_level
|
|
@@ -182,18 +457,34 @@ module ActiveRecord
|
|
|
182
457
|
super
|
|
183
458
|
end
|
|
184
459
|
|
|
460
|
+
def restart
|
|
461
|
+
return unless materialized?
|
|
462
|
+
|
|
463
|
+
@instrumenter.finish(:restart)
|
|
464
|
+
|
|
465
|
+
if connection.supports_restart_db_transaction?
|
|
466
|
+
@instrumenter.start
|
|
467
|
+
connection.restart_db_transaction
|
|
468
|
+
else
|
|
469
|
+
connection.rollback_db_transaction
|
|
470
|
+
materialize!
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
|
|
185
474
|
def rollback
|
|
186
475
|
connection.rollback_db_transaction if materialized?
|
|
187
476
|
@state.full_rollback!
|
|
477
|
+
@instrumenter.finish(:rollback) if materialized?
|
|
188
478
|
end
|
|
189
479
|
|
|
190
480
|
def commit
|
|
191
481
|
connection.commit_db_transaction if materialized?
|
|
192
482
|
@state.full_commit!
|
|
483
|
+
@instrumenter.finish(:commit) if materialized?
|
|
193
484
|
end
|
|
194
485
|
end
|
|
195
486
|
|
|
196
|
-
class TransactionManager
|
|
487
|
+
class TransactionManager # :nodoc:
|
|
197
488
|
def initialize(connection)
|
|
198
489
|
@stack = []
|
|
199
490
|
@connection = connection
|
|
@@ -202,21 +493,42 @@ module ActiveRecord
|
|
|
202
493
|
@lazy_transactions_enabled = true
|
|
203
494
|
end
|
|
204
495
|
|
|
205
|
-
def begin_transaction(
|
|
496
|
+
def begin_transaction(isolation: nil, joinable: true, _lazy: true)
|
|
206
497
|
@connection.lock.synchronize do
|
|
207
498
|
run_commit_callbacks = !current_transaction.joinable?
|
|
208
499
|
transaction =
|
|
209
500
|
if @stack.empty?
|
|
210
|
-
RealTransaction.new(
|
|
501
|
+
RealTransaction.new(
|
|
502
|
+
@connection,
|
|
503
|
+
isolation: isolation,
|
|
504
|
+
joinable: joinable,
|
|
505
|
+
run_commit_callbacks: run_commit_callbacks
|
|
506
|
+
)
|
|
507
|
+
elsif current_transaction.restartable?
|
|
508
|
+
RestartParentTransaction.new(
|
|
509
|
+
@connection,
|
|
510
|
+
current_transaction,
|
|
511
|
+
isolation: isolation,
|
|
512
|
+
joinable: joinable,
|
|
513
|
+
run_commit_callbacks: run_commit_callbacks
|
|
514
|
+
)
|
|
211
515
|
else
|
|
212
|
-
SavepointTransaction.new(
|
|
213
|
-
|
|
516
|
+
SavepointTransaction.new(
|
|
517
|
+
@connection,
|
|
518
|
+
"active_record_#{@stack.size}",
|
|
519
|
+
current_transaction,
|
|
520
|
+
isolation: isolation,
|
|
521
|
+
joinable: joinable,
|
|
522
|
+
run_commit_callbacks: run_commit_callbacks
|
|
523
|
+
)
|
|
214
524
|
end
|
|
215
525
|
|
|
216
|
-
|
|
217
|
-
@
|
|
218
|
-
|
|
219
|
-
|
|
526
|
+
unless transaction.materialized?
|
|
527
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
|
|
528
|
+
@has_unmaterialized_transactions = true
|
|
529
|
+
else
|
|
530
|
+
transaction.materialize!
|
|
531
|
+
end
|
|
220
532
|
end
|
|
221
533
|
@stack.push(transaction)
|
|
222
534
|
transaction
|
|
@@ -236,18 +548,35 @@ module ActiveRecord
|
|
|
236
548
|
@lazy_transactions_enabled
|
|
237
549
|
end
|
|
238
550
|
|
|
551
|
+
def dirty_current_transaction
|
|
552
|
+
current_transaction.dirty!
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def restore_transactions
|
|
556
|
+
return false unless restorable?
|
|
557
|
+
|
|
558
|
+
@stack.each(&:restore!)
|
|
559
|
+
|
|
560
|
+
true
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def restorable?
|
|
564
|
+
@stack.none?(&:dirty?)
|
|
565
|
+
end
|
|
566
|
+
|
|
239
567
|
def materialize_transactions
|
|
240
568
|
return if @materializing_transactions
|
|
241
|
-
return unless @has_unmaterialized_transactions
|
|
242
569
|
|
|
243
|
-
@
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
570
|
+
if @has_unmaterialized_transactions
|
|
571
|
+
@connection.lock.synchronize do
|
|
572
|
+
begin
|
|
573
|
+
@materializing_transactions = true
|
|
574
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
|
575
|
+
ensure
|
|
576
|
+
@materializing_transactions = false
|
|
577
|
+
end
|
|
578
|
+
@has_unmaterialized_transactions = false
|
|
249
579
|
end
|
|
250
|
-
@has_unmaterialized_transactions = false
|
|
251
580
|
end
|
|
252
581
|
end
|
|
253
582
|
|
|
@@ -261,6 +590,8 @@ module ActiveRecord
|
|
|
261
590
|
@stack.pop
|
|
262
591
|
end
|
|
263
592
|
|
|
593
|
+
dirty_current_transaction if transaction.dirty?
|
|
594
|
+
|
|
264
595
|
transaction.commit
|
|
265
596
|
transaction.commit_records
|
|
266
597
|
end
|
|
@@ -268,35 +599,48 @@ module ActiveRecord
|
|
|
268
599
|
|
|
269
600
|
def rollback_transaction(transaction = nil)
|
|
270
601
|
@connection.lock.synchronize do
|
|
271
|
-
transaction ||= @stack.
|
|
272
|
-
|
|
602
|
+
transaction ||= @stack.last
|
|
603
|
+
begin
|
|
604
|
+
transaction.rollback
|
|
605
|
+
ensure
|
|
606
|
+
@stack.pop if @stack.last == transaction
|
|
607
|
+
end
|
|
273
608
|
transaction.rollback_records
|
|
274
609
|
end
|
|
275
610
|
end
|
|
276
611
|
|
|
277
|
-
def within_new_transaction(
|
|
612
|
+
def within_new_transaction(isolation: nil, joinable: true)
|
|
278
613
|
@connection.lock.synchronize do
|
|
279
|
-
transaction = begin_transaction
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
614
|
+
transaction = begin_transaction(isolation: isolation, joinable: joinable)
|
|
615
|
+
begin
|
|
616
|
+
yield transaction.user_transaction
|
|
617
|
+
rescue Exception => error
|
|
283
618
|
rollback_transaction
|
|
284
619
|
after_failure_actions(transaction, error)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
620
|
+
|
|
621
|
+
raise
|
|
622
|
+
ensure
|
|
623
|
+
unless error
|
|
624
|
+
if Thread.current.status == "aborting"
|
|
625
|
+
rollback_transaction
|
|
626
|
+
else
|
|
627
|
+
begin
|
|
628
|
+
commit_transaction
|
|
629
|
+
rescue ActiveRecord::ConnectionFailed
|
|
630
|
+
transaction.invalidate! unless transaction.state.completed?
|
|
631
|
+
raise
|
|
632
|
+
rescue Exception
|
|
633
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
|
634
|
+
raise
|
|
635
|
+
end
|
|
297
636
|
end
|
|
298
637
|
end
|
|
299
638
|
end
|
|
639
|
+
ensure
|
|
640
|
+
unless transaction&.state&.completed?
|
|
641
|
+
@connection.throw_away!
|
|
642
|
+
transaction&.incomplete!
|
|
643
|
+
end
|
|
300
644
|
end
|
|
301
645
|
end
|
|
302
646
|
|
|
@@ -309,8 +653,7 @@ module ActiveRecord
|
|
|
309
653
|
end
|
|
310
654
|
|
|
311
655
|
private
|
|
312
|
-
|
|
313
|
-
NULL_TRANSACTION = NullTransaction.new
|
|
656
|
+
NULL_TRANSACTION = NullTransaction.new.freeze
|
|
314
657
|
|
|
315
658
|
# Deallocate invalidated prepared statements outside of the transaction
|
|
316
659
|
def after_failure_actions(transaction, error)
|