Skip to content

Commit 2c7eb1f

Browse files
committed
repair legacy_last_joined_entity for no onclause
Fixed regression where the :meth:`_orm.Query.filter_by` method would fail to locate the correct source entity if the :meth:`_orm.Query.join` method had been used targeting an entity without any kind of ON clause. Fixes: sqlalchemy#6092 Change-Id: I38d9099844f842f314c6673bd922467242409cdb
1 parent 3fec502 commit 2c7eb1f

3 files changed

Lines changed: 75 additions & 9 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.. change::
2+
:tags: bug, orm, regression
3+
:tickets: 6092
4+
5+
Fixed regression where the :meth:`_orm.Query.filter_by` method would fail
6+
to locate the correct source entity if the :meth:`_orm.Query.join` method
7+
had been used targeting an entity without any kind of ON clause.
8+

lib/sqlalchemy/orm/context.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2136,7 +2136,7 @@ def _legacy_determine_last_joined_entity(setup_joins, entity_zero):
21362136
if right is not None and "parententity" in right._annotations:
21372137
right = right._annotations["parententity"].entity
21382138

2139-
if onclause is not None and right is not None:
2139+
if right is not None:
21402140
last_entity = right
21412141
insp = inspect(last_entity)
21422142
if insp.is_clause_element or insp.is_aliased_class or insp.is_mapper:

test/orm/test_joins.py

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import itertools
2+
13
import sqlalchemy as sa
24
from sqlalchemy import and_
35
from sqlalchemy import desc
@@ -232,23 +234,79 @@ def test_join_on_synonym(self):
232234
class JoinTest(QueryTest, AssertsCompiledSQL):
233235
__dialect__ = "default"
234236

235-
def test_filter_by_from_full_join(self):
237+
@testing.combinations_list(
238+
set(
239+
itertools.product(
240+
[
241+
"relationship",
242+
"relationship_only",
243+
"string_relationship",
244+
"string_relationship_only",
245+
"none",
246+
"explicit",
247+
"table_none",
248+
"table_explicit",
249+
],
250+
[True, False],
251+
)
252+
).difference(
253+
[
254+
("string_relationship", False),
255+
("string_relationship_only", False),
256+
]
257+
),
258+
argnames="onclause_type, use_legacy",
259+
)
260+
def test_filter_by_from_join(self, onclause_type, use_legacy):
236261
User, Address = self.classes("User", "Address")
262+
(address_table,) = self.tables("addresses")
263+
(user_table,) = self.tables("users")
264+
265+
if use_legacy:
266+
sess = fixture_session()
267+
q = sess.query(User)
268+
else:
269+
q = select(User).set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
270+
271+
if onclause_type == "relationship":
272+
q = q.join(Address, User.addresses)
273+
elif onclause_type == "string_relationship":
274+
q = q.join(Address, "addresses")
275+
elif onclause_type == "relationship_only":
276+
q = q.join(User.addresses)
277+
elif onclause_type == "string_relationship_only":
278+
q = q.join("addresses")
279+
elif onclause_type == "none":
280+
q = q.join(Address)
281+
elif onclause_type == "explicit":
282+
q = q.join(Address, User.id == Address.user_id)
283+
elif onclause_type == "table_none":
284+
q = q.join(address_table)
285+
elif onclause_type == "table_explicit":
286+
q = q.join(
287+
address_table, user_table.c.id == address_table.c.user_id
288+
)
289+
else:
290+
assert False
237291

238-
sess = fixture_session()
292+
q2 = q.filter_by(email_address="foo")
239293

240-
q = (
241-
sess.query(User)
242-
.join(Address, User.addresses)
243-
.filter_by(email_address="foo")
244-
)
245294
self.assert_compile(
246-
q,
295+
q2,
247296
"SELECT users.id AS users_id, users.name AS users_name "
248297
"FROM users JOIN addresses ON users.id = addresses.user_id "
249298
"WHERE addresses.email_address = :email_address_1",
250299
)
251300

301+
if use_legacy:
302+
q2 = q.reset_joinpoint().filter_by(name="user")
303+
self.assert_compile(
304+
q2,
305+
"SELECT users.id AS users_id, users.name AS users_name "
306+
"FROM users JOIN addresses ON users.id = addresses.user_id "
307+
"WHERE users.name = :name_1",
308+
)
309+
252310
def test_invalid_kwarg_join(self):
253311
User = self.classes.User
254312
sess = fixture_session()

0 commit comments

Comments
 (0)