Skip to content

Commit 7c68c52

Browse files
authored
Merge pull request rails#51353 from Shopify/get-rid-lease-connection
Eliminate remaining uses of `lease_connection` inside Active Record
2 parents 27942bc + f8d8183 commit 7c68c52

File tree

9 files changed

+70
-65
lines changed

9 files changed

+70
-65
lines changed

activerecord/lib/active_record/associations/join_dependency/join_association.rb

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,39 +37,41 @@ def join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
3737
chain << [reflection, table]
3838
end
3939

40-
# The chain starts with the target table, but we want to end with it here (makes
41-
# more sense in this context), so we reverse
42-
chain.reverse_each do |reflection, table|
43-
klass = reflection.klass
40+
base_klass.with_connection do |connection|
41+
# The chain starts with the target table, but we want to end with it here (makes
42+
# more sense in this context), so we reverse
43+
chain.reverse_each do |reflection, table|
44+
klass = reflection.klass
4445

45-
scope = reflection.join_scope(table, foreign_table, foreign_klass)
46+
scope = reflection.join_scope(table, foreign_table, foreign_klass)
4647

47-
unless scope.references_values.empty?
48-
associations = scope.eager_load_values | scope.includes_values
48+
unless scope.references_values.empty?
49+
associations = scope.eager_load_values | scope.includes_values
4950

50-
unless associations.empty?
51-
scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
51+
unless associations.empty?
52+
scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
53+
end
5254
end
53-
end
5455

55-
arel = scope.arel(alias_tracker.aliases)
56-
nodes = arel.constraints.first
56+
arel = scope.arel(alias_tracker.aliases)
57+
nodes = arel.constraints.first
5758

58-
if nodes.is_a?(Arel::Nodes::And)
59-
others = nodes.children.extract! do |node|
60-
!Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
59+
if nodes.is_a?(Arel::Nodes::And)
60+
others = nodes.children.extract! do |node|
61+
!Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
62+
end
6163
end
62-
end
6364

64-
joins << join_type.new(table, Arel::Nodes::On.new(nodes))
65+
joins << join_type.new(table, Arel::Nodes::On.new(nodes))
6566

66-
if others && !others.empty?
67-
joins.concat arel.join_sources
68-
append_constraints(joins.last, others)
69-
end
67+
if others && !others.empty?
68+
joins.concat arel.join_sources
69+
append_constraints(connection, joins.last, others)
70+
end
7071

71-
# The current table in this iteration becomes the foreign table in the next
72-
foreign_table, foreign_klass = table, klass
72+
# The current table in this iteration becomes the foreign table in the next
73+
foreign_table, foreign_klass = table, klass
74+
end
7375
end
7476

7577
joins
@@ -88,10 +90,10 @@ def strict_loading?
8890
end
8991

9092
private
91-
def append_constraints(join, constraints)
93+
def append_constraints(connection, join, constraints)
9294
if join.is_a?(Arel::Nodes::StringJoin)
9395
join_string = Arel::Nodes::And.new(constraints.unshift join.left)
94-
join.left = Arel.sql(base_klass.lease_connection.visitor.compile(join_string))
96+
join.left = Arel.sql(connection.visitor.compile(join_string))
9597
else
9698
right = join.right
9799
right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)

activerecord/lib/active_record/integration.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :no
178178
def can_use_fast_cache_version?(timestamp)
179179
timestamp.is_a?(String) &&
180180
cache_timestamp_format == :usec &&
181-
self.class.lease_connection.default_timezone == :utc &&
181+
# FIXME: checking out a connection for this is wasteful
182+
# we should store/cache this information in the schema cache
183+
# or similar.
184+
self.class.with_connection(&:default_timezone) == :utc &&
182185
!updated_at_came_from_user?
183186
end
184187

activerecord/lib/active_record/table_metadata.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def associated_table(table_name)
4444
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
4545
TableMetadata.new(association_klass, arel_table, reflection)
4646
else
47-
type_caster = TypeCaster::Connection.new(klass, table_name)
47+
type_caster = TypeCaster::Connection.new(klass)
4848
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
4949
TableMetadata.new(nil, arel_table, reflection)
5050
end

activerecord/lib/active_record/transactions.rb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,19 @@ def rolledback!(force_restore_state: false, should_run_callbacks: true) # :nodoc
393393
# This method is available within the context of an ActiveRecord::Base
394394
# instance.
395395
def with_transaction_returning_status
396-
status = nil
397-
connection = self.class.lease_connection
398-
ensure_finalize = !connection.transaction_open?
396+
self.class.with_connection do |connection|
397+
status = nil
398+
ensure_finalize = !connection.transaction_open?
399399

400-
connection.transaction do
401-
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
402-
remember_transaction_record_state
400+
connection.transaction do
401+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
402+
remember_transaction_record_state
403403

404-
status = yield
405-
raise ActiveRecord::Rollback unless status
404+
status = yield
405+
raise ActiveRecord::Rollback unless status
406+
end
407+
status
406408
end
407-
status
408409
end
409410

410411
def trigger_transactional_callbacks? # :nodoc:
@@ -496,7 +497,9 @@ def transaction_include_any_action?(actions)
496497
# Add the record to the current transaction so that the #after_rollback and #after_commit
497498
# callbacks can be called.
498499
def add_to_transaction(ensure_finalize = true)
499-
self.class.lease_connection.add_transaction_record(self, ensure_finalize)
500+
self.class.with_connection do |connection|
501+
connection.add_transaction_record(self, ensure_finalize)
502+
end
500503
end
501504

502505
def has_transactional_callbacks?

activerecord/lib/active_record/type_caster/connection.rb

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
module ActiveRecord
44
module TypeCaster
55
class Connection # :nodoc:
6-
def initialize(klass, table_name)
6+
def initialize(klass)
77
@klass = klass
8-
@table_name = table_name
98
end
109

1110
def type_cast_for_database(attr_name, value)
@@ -14,20 +13,8 @@ def type_cast_for_database(attr_name, value)
1413
end
1514

1615
def type_for_attribute(attr_name)
17-
schema_cache = @klass.schema_cache
18-
19-
if schema_cache.data_source_exists?(table_name)
20-
column = schema_cache.columns_hash(table_name)[attr_name.to_s]
21-
if column
22-
type = @klass.lease_connection.lookup_cast_type_from_column(column)
23-
end
24-
end
25-
26-
type || Type.default_value
16+
@klass.type_for_attribute(attr_name) || Type.default_value
2717
end
28-
29-
private
30-
attr_reader :table_name
3118
end
3219
end
3320
end

activerecord/lib/active_record/validations/uniqueness.rb

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,20 @@ def resolve_attributes(record, attributes)
110110

111111
def build_relation(klass, attribute, value)
112112
relation = klass.unscoped
113-
comparison = relation.bind_attribute(attribute, value) do |attr, bind|
114-
return relation.none! if bind.unboundable?
113+
# TODO: Add case-sensitive / case-insensitive operators to Arel
114+
# to no longer need to checkout a connection here.
115+
comparison = klass.with_connection do |connection|
116+
relation.bind_attribute(attribute, value) do |attr, bind|
117+
return relation.none! if bind.unboundable?
115118

116-
if !options.key?(:case_sensitive) || bind.nil?
117-
klass.lease_connection.default_uniqueness_comparison(attr, bind)
118-
elsif options[:case_sensitive]
119-
klass.lease_connection.case_sensitive_comparison(attr, bind)
120-
else
121-
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
122-
klass.lease_connection.case_insensitive_comparison(attr, bind)
119+
if !options.key?(:case_sensitive) || bind.nil?
120+
connection.default_uniqueness_comparison(attr, bind)
121+
elsif options[:case_sensitive]
122+
connection.case_sensitive_comparison(attr, bind)
123+
else
124+
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
125+
connection.case_insensitive_comparison(attr, bind)
126+
end
123127
end
124128
end
125129

activerecord/lib/arel/nodes/node.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ def invert
147147
# Maybe we should just use `Table.engine`? :'(
148148
def to_sql(engine = Table.engine)
149149
collector = Arel::Collectors::SQLString.new
150-
collector = engine.lease_connection.visitor.accept self, collector
151-
collector.value
150+
engine.with_connection do |connection|
151+
connection.visitor.accept(self, collector).value
152+
end
152153
end
153154

154155
def fetch_attribute

activerecord/lib/arel/tree_manager.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ def to_dot
5252

5353
def to_sql(engine = Table.engine)
5454
collector = Arel::Collectors::SQLString.new
55-
collector = engine.lease_connection.visitor.accept @ast, collector
56-
collector.value
55+
engine.with_connection do |connection|
56+
engine.lease_connection.visitor.accept(@ast, collector).value
57+
end
5758
end
5859

5960
def initialize_copy(other)

activerecord/test/cases/arel/support/fake_record.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ def initialize
129129
@connection_pool = ConnectionPool.new
130130
end
131131

132+
def with_connection(...)
133+
connection_pool.with_connection(...)
134+
end
135+
132136
def lease_connection
133137
connection_pool.lease_connection
134138
end

0 commit comments

Comments
 (0)