aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb3
-rw-r--r--activerecord/lib/active_record/connection_handling.rb2
-rw-r--r--activerecord/lib/active_record/core.rb45
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb2
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb1
-rw-r--r--activerecord/lib/active_record/transactions.rb41
7 files changed, 50 insertions, 51 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8d76b4145b..b5dd19988d 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Dont enroll records in the transaction if they dont have commit callbacks.
+ That was causing a memory grow problem when creating a lot of records inside a transaction.
+
+ Fixes #15549.
+
+ *Will Bryant*, *Aaron Patterson*
+
* Correctly create through records when created on a has many through
association when using `where`.
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index 3a1e4a4a88..ebb4a1523f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -1,13 +1,10 @@
module ActiveRecord
module ConnectionAdapters
class TransactionState
- attr_reader :parent
-
VALID_STATES = Set.new([:committed, :rolledback, nil])
def initialize(state = nil)
@state = state
- @parent = nil
end
def finalized?
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index 984af79642..24f5849e45 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -5,7 +5,7 @@ module ActiveRecord
# Establishes the connection to the database. Accepts a hash as input where
# the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
- # example for regular databases (MySQL, Postgresql, etc):
+ # example for regular databases (MySQL, PostgreSQL, etc):
#
# ActiveRecord::Base.establish_connection(
# adapter: "mysql",
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index d41872d767..97ce4642aa 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -483,51 +483,6 @@ module ActiveRecord
private
- def set_transaction_state(state) # :nodoc:
- @transaction_state = state
- end
-
- def has_transactional_callbacks? # :nodoc:
- !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
- end
-
- # Updates the attributes on this particular ActiveRecord object so that
- # if it is associated with a transaction, then the state of the AR object
- # will be updated to reflect the current state of the transaction
- #
- # The @transaction_state variable stores the states of the associated
- # transaction. This relies on the fact that a transaction can only be in
- # one rollback or commit (otherwise a list of states would be required)
- # Each AR object inside of a transaction carries that transaction's
- # TransactionState.
- #
- # This method checks to see if the ActiveRecord object's state reflects
- # the TransactionState, and rolls back or commits the ActiveRecord object
- # as appropriate.
- #
- # Since ActiveRecord objects can be inside multiple transactions, this
- # method recursively goes through the parent of the TransactionState and
- # checks if the ActiveRecord object reflects the state of the object.
- def sync_with_transaction_state
- update_attributes_from_transaction_state(@transaction_state, 0)
- end
-
- def update_attributes_from_transaction_state(transaction_state, depth)
- @reflects_state = [false] if depth == 0
-
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
- unless @reflects_state[depth]
- restore_transaction_record_state if transaction_state.rolledback?
- clear_transaction_record_state
- @reflects_state[depth] = true
- end
-
- if transaction_state.parent && !@reflects_state[depth+1]
- update_attributes_from_transaction_state(transaction_state.parent, depth+1)
- end
- end
- end
-
# Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
# of the array, and then rescues from the possible NoMethodError. If those elements are
# ActiveRecord::Base's, then this triggers the various method_missing's that we have,
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 4a4de86d48..7f27e7b463 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -222,7 +222,7 @@ module ActiveRecord
end
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
- # Postgresql doesn't like ORDER BY when there are no GROUP BY
+ # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
relation = unscope(:order)
column_alias = column_name
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index fb47d915ff..7bd091b66c 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -1,4 +1,3 @@
-require 'active_support/deprecation'
require 'active_support/core_ext/string/filters'
module ActiveRecord
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 598defce50..b620233c3a 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -442,5 +442,46 @@ module ActiveRecord
end
end
end
+
+ def set_transaction_state(state) # :nodoc:
+ @transaction_state = state
+ end
+
+ def has_transactional_callbacks? # :nodoc:
+ !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
+ end
+
+ # Updates the attributes on this particular ActiveRecord object so that
+ # if it is associated with a transaction, then the state of the AR object
+ # will be updated to reflect the current state of the transaction
+ #
+ # The @transaction_state variable stores the states of the associated
+ # transaction. This relies on the fact that a transaction can only be in
+ # one rollback or commit (otherwise a list of states would be required)
+ # Each AR object inside of a transaction carries that transaction's
+ # TransactionState.
+ #
+ # This method checks to see if the ActiveRecord object's state reflects
+ # the TransactionState, and rolls back or commits the ActiveRecord object
+ # as appropriate.
+ #
+ # Since ActiveRecord objects can be inside multiple transactions, this
+ # method recursively goes through the parent of the TransactionState and
+ # checks if the ActiveRecord object reflects the state of the object.
+ def sync_with_transaction_state
+ update_attributes_from_transaction_state(@transaction_state, 0)
+ end
+
+ def update_attributes_from_transaction_state(transaction_state, depth)
+ @reflects_state = [false] if depth == 0
+
+ if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
+ unless @reflects_state[depth]
+ restore_transaction_record_state if transaction_state.rolledback?
+ clear_transaction_record_state
+ @reflects_state[depth] = true
+ end
+ end
+ end
end
end