activerecord 5.2.8.1 → 6.1.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- 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 +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -5,10 +5,11 @@ module ActiveRecord
|
|
5
5
|
class TransactionState
|
6
6
|
def initialize(state = nil)
|
7
7
|
@state = state
|
8
|
-
@children =
|
8
|
+
@children = nil
|
9
9
|
end
|
10
10
|
|
11
11
|
def add_child(state)
|
12
|
+
@children ||= []
|
12
13
|
@children << state
|
13
14
|
end
|
14
15
|
|
@@ -32,6 +33,10 @@ module ActiveRecord
|
|
32
33
|
@state == :fully_rolledback
|
33
34
|
end
|
34
35
|
|
36
|
+
def invalidated?
|
37
|
+
@state == :invalidated
|
38
|
+
end
|
39
|
+
|
35
40
|
def fully_completed?
|
36
41
|
completed?
|
37
42
|
end
|
@@ -40,34 +45,21 @@ module ActiveRecord
|
|
40
45
|
committed? || rolledback?
|
41
46
|
end
|
42
47
|
|
43
|
-
def set_state(state)
|
44
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
45
|
-
The set_state method is deprecated and will be removed in
|
46
|
-
Rails 6.0. Please use rollback! or commit! to set transaction
|
47
|
-
state directly.
|
48
|
-
MSG
|
49
|
-
case state
|
50
|
-
when :rolledback
|
51
|
-
rollback!
|
52
|
-
when :committed
|
53
|
-
commit!
|
54
|
-
when nil
|
55
|
-
nullify!
|
56
|
-
else
|
57
|
-
raise ArgumentError, "Invalid transaction state: #{state}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
48
|
def rollback!
|
62
|
-
@children
|
49
|
+
@children&.each { |c| c.rollback! }
|
63
50
|
@state = :rolledback
|
64
51
|
end
|
65
52
|
|
66
53
|
def full_rollback!
|
67
|
-
@children
|
54
|
+
@children&.each { |c| c.rollback! }
|
68
55
|
@state = :fully_rolledback
|
69
56
|
end
|
70
57
|
|
58
|
+
def invalidate!
|
59
|
+
@children&.each { |c| c.invalidate! }
|
60
|
+
@state = :invalidated
|
61
|
+
end
|
62
|
+
|
71
63
|
def commit!
|
72
64
|
@state = :committed
|
73
65
|
end
|
@@ -87,52 +79,87 @@ module ActiveRecord
|
|
87
79
|
def closed?; true; end
|
88
80
|
def open?; false; end
|
89
81
|
def joinable?; false; end
|
90
|
-
def add_record(record); end
|
82
|
+
def add_record(record, _ = true); end
|
91
83
|
end
|
92
84
|
|
93
85
|
class Transaction #:nodoc:
|
94
|
-
attr_reader :connection, :state, :
|
95
|
-
|
86
|
+
attr_reader :connection, :state, :savepoint_name, :isolation_level
|
87
|
+
attr_accessor :written
|
96
88
|
|
97
|
-
def initialize(connection,
|
89
|
+
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
|
98
90
|
@connection = connection
|
99
91
|
@state = TransactionState.new
|
100
|
-
@records =
|
101
|
-
@
|
92
|
+
@records = nil
|
93
|
+
@isolation_level = isolation
|
94
|
+
@materialized = false
|
95
|
+
@joinable = joinable
|
102
96
|
@run_commit_callbacks = run_commit_callbacks
|
97
|
+
@lazy_enrollment_records = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_record(record, ensure_finalize = true)
|
101
|
+
@records ||= []
|
102
|
+
if ensure_finalize
|
103
|
+
@records << record
|
104
|
+
else
|
105
|
+
@lazy_enrollment_records ||= ObjectSpace::WeakMap.new
|
106
|
+
@lazy_enrollment_records[record] = record
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
|
-
def
|
106
|
-
|
110
|
+
def records
|
111
|
+
if @lazy_enrollment_records
|
112
|
+
@records.concat @lazy_enrollment_records.values
|
113
|
+
@lazy_enrollment_records = nil
|
114
|
+
end
|
115
|
+
@records
|
116
|
+
end
|
117
|
+
|
118
|
+
def materialize!
|
119
|
+
@materialized = true
|
120
|
+
end
|
121
|
+
|
122
|
+
def materialized?
|
123
|
+
@materialized
|
107
124
|
end
|
108
125
|
|
109
126
|
def rollback_records
|
110
|
-
|
127
|
+
return unless records
|
128
|
+
ite = records.uniq(&:__id__)
|
129
|
+
already_run_callbacks = {}
|
111
130
|
while record = ite.shift
|
112
|
-
record.
|
131
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
132
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
133
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
134
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
113
135
|
end
|
114
136
|
ensure
|
115
|
-
ite
|
137
|
+
ite&.each do |i|
|
116
138
|
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
117
139
|
end
|
118
140
|
end
|
119
141
|
|
120
142
|
def before_commit_records
|
121
|
-
records.uniq.each(&:before_committed!) if @run_commit_callbacks
|
143
|
+
records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
|
122
144
|
end
|
123
145
|
|
124
146
|
def commit_records
|
125
|
-
|
147
|
+
return unless records
|
148
|
+
ite = records.uniq(&:__id__)
|
149
|
+
already_run_callbacks = {}
|
126
150
|
while record = ite.shift
|
127
151
|
if @run_commit_callbacks
|
128
|
-
record.
|
152
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
153
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
154
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
155
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
129
156
|
else
|
130
157
|
# if not running callbacks, only adds the record to the parent transaction
|
131
|
-
record
|
158
|
+
connection.add_transaction_record(record)
|
132
159
|
end
|
133
160
|
end
|
134
161
|
ensure
|
135
|
-
ite
|
162
|
+
ite&.each { |i| i.committed!(should_run_callbacks: false) }
|
136
163
|
end
|
137
164
|
|
138
165
|
def full_rollback?; true; end
|
@@ -142,24 +169,30 @@ module ActiveRecord
|
|
142
169
|
end
|
143
170
|
|
144
171
|
class SavepointTransaction < Transaction
|
145
|
-
def initialize(connection, savepoint_name, parent_transaction, options
|
146
|
-
super(connection, options
|
172
|
+
def initialize(connection, savepoint_name, parent_transaction, **options)
|
173
|
+
super(connection, **options)
|
147
174
|
|
148
175
|
parent_transaction.state.add_child(@state)
|
149
176
|
|
150
|
-
if
|
177
|
+
if isolation_level
|
151
178
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
152
179
|
end
|
153
|
-
|
180
|
+
|
181
|
+
@savepoint_name = savepoint_name
|
182
|
+
end
|
183
|
+
|
184
|
+
def materialize!
|
185
|
+
connection.create_savepoint(savepoint_name)
|
186
|
+
super
|
154
187
|
end
|
155
188
|
|
156
189
|
def rollback
|
157
|
-
connection.rollback_to_savepoint(savepoint_name)
|
190
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
158
191
|
@state.rollback!
|
159
192
|
end
|
160
193
|
|
161
194
|
def commit
|
162
|
-
connection.release_savepoint(savepoint_name)
|
195
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
163
196
|
@state.commit!
|
164
197
|
end
|
165
198
|
|
@@ -167,22 +200,23 @@ module ActiveRecord
|
|
167
200
|
end
|
168
201
|
|
169
202
|
class RealTransaction < Transaction
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
203
|
+
def materialize!
|
204
|
+
if isolation_level
|
205
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
174
206
|
else
|
175
207
|
connection.begin_db_transaction
|
176
208
|
end
|
209
|
+
|
210
|
+
super
|
177
211
|
end
|
178
212
|
|
179
213
|
def rollback
|
180
|
-
connection.rollback_db_transaction
|
214
|
+
connection.rollback_db_transaction if materialized?
|
181
215
|
@state.full_rollback!
|
182
216
|
end
|
183
217
|
|
184
218
|
def commit
|
185
|
-
connection.commit_db_transaction
|
219
|
+
connection.commit_db_transaction if materialized?
|
186
220
|
@state.full_commit!
|
187
221
|
end
|
188
222
|
end
|
@@ -191,24 +225,71 @@ module ActiveRecord
|
|
191
225
|
def initialize(connection)
|
192
226
|
@stack = []
|
193
227
|
@connection = connection
|
228
|
+
@has_unmaterialized_transactions = false
|
229
|
+
@materializing_transactions = false
|
230
|
+
@lazy_transactions_enabled = true
|
194
231
|
end
|
195
232
|
|
196
|
-
def begin_transaction(
|
233
|
+
def begin_transaction(isolation: nil, joinable: true, _lazy: true)
|
197
234
|
@connection.lock.synchronize do
|
198
235
|
run_commit_callbacks = !current_transaction.joinable?
|
199
236
|
transaction =
|
200
237
|
if @stack.empty?
|
201
|
-
RealTransaction.new(
|
238
|
+
RealTransaction.new(
|
239
|
+
@connection,
|
240
|
+
isolation: isolation,
|
241
|
+
joinable: joinable,
|
242
|
+
run_commit_callbacks: run_commit_callbacks
|
243
|
+
)
|
202
244
|
else
|
203
|
-
SavepointTransaction.new(
|
204
|
-
|
245
|
+
SavepointTransaction.new(
|
246
|
+
@connection,
|
247
|
+
"active_record_#{@stack.size}",
|
248
|
+
@stack.last,
|
249
|
+
isolation: isolation,
|
250
|
+
joinable: joinable,
|
251
|
+
run_commit_callbacks: run_commit_callbacks
|
252
|
+
)
|
205
253
|
end
|
206
254
|
|
255
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
|
256
|
+
@has_unmaterialized_transactions = true
|
257
|
+
else
|
258
|
+
transaction.materialize!
|
259
|
+
end
|
207
260
|
@stack.push(transaction)
|
208
261
|
transaction
|
209
262
|
end
|
210
263
|
end
|
211
264
|
|
265
|
+
def disable_lazy_transactions!
|
266
|
+
materialize_transactions
|
267
|
+
@lazy_transactions_enabled = false
|
268
|
+
end
|
269
|
+
|
270
|
+
def enable_lazy_transactions!
|
271
|
+
@lazy_transactions_enabled = true
|
272
|
+
end
|
273
|
+
|
274
|
+
def lazy_transactions_enabled?
|
275
|
+
@lazy_transactions_enabled
|
276
|
+
end
|
277
|
+
|
278
|
+
def materialize_transactions
|
279
|
+
return if @materializing_transactions
|
280
|
+
return unless @has_unmaterialized_transactions
|
281
|
+
|
282
|
+
@connection.lock.synchronize do
|
283
|
+
begin
|
284
|
+
@materializing_transactions = true
|
285
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
286
|
+
ensure
|
287
|
+
@materializing_transactions = false
|
288
|
+
end
|
289
|
+
@has_unmaterialized_transactions = false
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
212
293
|
def commit_transaction
|
213
294
|
@connection.lock.synchronize do
|
214
295
|
transaction = @stack.last
|
@@ -227,29 +308,47 @@ module ActiveRecord
|
|
227
308
|
def rollback_transaction(transaction = nil)
|
228
309
|
@connection.lock.synchronize do
|
229
310
|
transaction ||= @stack.pop
|
230
|
-
transaction.rollback
|
311
|
+
transaction.rollback unless transaction.state.invalidated?
|
231
312
|
transaction.rollback_records
|
232
313
|
end
|
233
314
|
end
|
234
315
|
|
235
|
-
def within_new_transaction(
|
316
|
+
def within_new_transaction(isolation: nil, joinable: true)
|
236
317
|
@connection.lock.synchronize do
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
318
|
+
transaction = begin_transaction(isolation: isolation, joinable: joinable)
|
319
|
+
ret = yield
|
320
|
+
completed = true
|
321
|
+
ret
|
322
|
+
rescue Exception => error
|
323
|
+
if transaction
|
324
|
+
transaction.state.invalidate! if error.is_a? ActiveRecord::TransactionRollbackError
|
325
|
+
rollback_transaction
|
326
|
+
after_failure_actions(transaction, error)
|
327
|
+
end
|
328
|
+
|
329
|
+
raise
|
330
|
+
ensure
|
331
|
+
if transaction
|
332
|
+
if error
|
333
|
+
# @connection still holds an open or invalid transaction, so we must not
|
334
|
+
# put it back in the pool for reuse.
|
335
|
+
@connection.throw_away! unless transaction.state.rolledback?
|
336
|
+
else
|
248
337
|
if Thread.current.status == "aborting"
|
249
|
-
rollback_transaction
|
338
|
+
rollback_transaction
|
250
339
|
else
|
340
|
+
if !completed && transaction.written
|
341
|
+
ActiveSupport::Deprecation.warn(<<~EOW)
|
342
|
+
Using `return`, `break` or `throw` to exit a transaction block is
|
343
|
+
deprecated without replacement. If the `throw` came from
|
344
|
+
`Timeout.timeout(duration)`, pass an exception class as a second
|
345
|
+
argument so it doesn't use `throw` to abort its block. This results
|
346
|
+
in the transaction being committed, but in the next release of Rails
|
347
|
+
it will rollback.
|
348
|
+
EOW
|
349
|
+
end
|
251
350
|
begin
|
252
|
-
commit_transaction
|
351
|
+
commit_transaction
|
253
352
|
rescue Exception
|
254
353
|
rollback_transaction(transaction) unless transaction.state.completed?
|
255
354
|
raise
|
@@ -269,7 +368,6 @@ module ActiveRecord
|
|
269
368
|
end
|
270
369
|
|
271
370
|
private
|
272
|
-
|
273
371
|
NULL_TRANSACTION = NullTransaction.new
|
274
372
|
|
275
373
|
# Deallocate invalidated prepared statements outside of the transaction
|