Skip to content

Commit be42d45

Browse files
Enable #exists? queries to be retryable
Previously, `#exists?` queries could never be retryable because `"1 AS one"` was passed as a String (which would be wrapped as a non-retryable `SqlLiteral`). This commit addresses that issue by wrapping `"1 AS one"` in a `SqlLiteral` with `retryable: true`. While not guaranteeing that all `#exists?` queries can be retryable, this no longer prevents otherwise retryable `#exists?` queries from being retryable. Additionally, a small change was needed to ensure the retryable `SqlLiteral` wasn't wrapped in a non-retryable `SqlLiteral`. A [previous commit][1] added a `to_s` in `arel_column` which caused all `SqlLiteral`s to be non-retryable (the `Arel.arel_node?` predicate would always be false since `field` was always a `String`). The `to_s` was moved to the specific case it was needed, which was inside `sum` calculations. [1]: aaad493 Co-authored-by: classidied <[email protected]>
1 parent 6c7a848 commit be42d45

File tree

5 files changed

+17
-3
lines changed

5 files changed

+17
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Enable automatically retrying idempotent `#exists?` queries on connection
2+
errors.
3+
4+
*Hartley McGuire*, *classidied*
5+
16
* Deprecate usage of unsupported methods in conjunction with `update_all`:
27

38
`update_all` will now print a deprecation message if a query includes either `WITH`,

activerecord/lib/active_record/relation/calculations.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def aggregate_column(column_name)
418418
when :all
419419
Arel.star
420420
else
421-
arel_column(column_name)
421+
arel_column(column_name.to_s)
422422
end
423423
end
424424

activerecord/lib/active_record/relation/finder_methods.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def construct_relation_for_exists(conditions)
441441
if distinct_value && offset_value
442442
relation = except(:order).limit!(1)
443443
else
444-
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
444+
relation = except(:select, :distinct, :order)._select!(Arel.sql(ONE_AS_ONE, retryable: true)).limit!(1)
445445
end
446446

447447
case conditions

activerecord/lib/active_record/relation/query_methods.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ def arel_column_with_table(table_name, column_name)
19851985
def arel_column(field)
19861986
field = field.name if is_symbol = field.is_a?(Symbol)
19871987

1988-
field = model.attribute_aliases[field] || field.to_s
1988+
field = model.attribute_aliases[field] || field
19891989
from = from_clause.name || from_clause.value
19901990

19911991
if model.columns_hash.key?(field) && (!from || table_name_matches?(from))

activerecord/test/cases/adapter_test.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,15 @@ def teardown
710710
assert_predicate @connection, :active?
711711
end
712712

713+
test "#exists? queries are retried and result in a reconnect" do
714+
Post.first
715+
716+
remote_disconnect @connection
717+
718+
assert_predicate Post, :exists?
719+
assert_predicate @connection, :active?
720+
end
721+
713722
test "queries containing SQL fragments are not retried" do
714723
Post.first
715724

0 commit comments

Comments
 (0)