From: sebastianbreguel Date: Sun, 31 May 2026 20:12:19 +0000 (-0400) Subject: Hoist loop-invariant set intersection in _get_display_froms X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=0ce74f43bd1a6f3839c21bad7748c3f99bcd95c6;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Hoist loop-invariant set intersection in _get_display_froms Fixes #13336. `SelectState._get_display_froms` recomputed a loop-invariant `_cloned_intersection(...)` once per FROM element in each of the three correlation comprehensions, making each branch O(N²) in the number of FROM elements. This hoists the call so it runs once, which is O(N). `_cloned_intersection` / `_cloned_difference` are pure and return a set, and neither argument changes during the comprehension, so the result is identical. A function-level benchmark asserts `old == new` at every N (full numbers in #13336), and `test/sql/` plus the ORM compilation/query tests pass: 7442 passed, 359 skipped. Net -14 lines. Per the issue discussion, no changelog entry is included. ### Checklist This pull request is: - [x] A short code fix - Issue with a runnable demonstration: #13336 - Behavior-preserving (no logic change), so it is covered by the existing `test/sql/` and ORM compilation/query suites rather than adding new tests. Closes: #13337 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13337 Pull-request-sha: beba43e77a773a4d9e9d55cc39c7c85ecda6293e Change-Id: I95b02ffa66ef709c16bf5275924ec03244c19ecb (cherry picked from commit abfe6cc47c12b87164a63739e3718257b452dac6) --- diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 4a2a318dc1..53fc3e29f4 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -4956,42 +4956,28 @@ class SelectState(util.MemoizedSlots, CompileState): if self.statement._correlate: to_correlate = self.statement._correlate if to_correlate: - froms = [ - f - for f in froms - if f - not in _cloned_intersection( - _cloned_intersection( - froms, explicit_correlate_froms or () - ), - to_correlate, - ) - ] - - if self.statement._correlate_except is not None: - froms = [ - f - for f in froms - if f - not in _cloned_difference( + to_remove = _cloned_intersection( _cloned_intersection( froms, explicit_correlate_froms or () ), - self.statement._correlate_except, + to_correlate, ) - ] + froms = [f for f in froms if f not in to_remove] + + if self.statement._correlate_except is not None: + to_remove = _cloned_difference( + _cloned_intersection(froms, explicit_correlate_froms or ()), + self.statement._correlate_except, + ) + froms = [f for f in froms if f not in to_remove] if ( self.statement._auto_correlate and implicit_correlate_froms and len(froms) > 1 ): - froms = [ - f - for f in froms - if f - not in _cloned_intersection(froms, implicit_correlate_froms) - ] + to_remove = _cloned_intersection(froms, implicit_correlate_froms) + froms = [f for f in froms if f not in to_remove] if not len(froms): raise exc.InvalidRequestError(