mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-22 00:22:01 -04:00
Merge "Include GROUP BY in _should_nest_selectable criteria"
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
.. change::
|
||||
:tags: bug, orm
|
||||
:tickets: 5065
|
||||
|
||||
Fixed bug where usage of joined eager loading would not properly wrap the
|
||||
query inside of a subquery when :meth:`.Query.group_by` were used against
|
||||
the query. When any kind of result-limiting approach is used, such as
|
||||
DISTINCT, LIMIT, OFFSET, joined eager loading embeds the row-limited query
|
||||
inside of a subquery so that the collection results are not impacted. For
|
||||
some reason, the presence of GROUP BY was never included in this criterion,
|
||||
even though it has a similar effect as using DISTINCT. Additionally, the
|
||||
bug would prevent using GROUP BY at all for a joined eager load query for
|
||||
most database platforms which forbid non-aggregated, non-grouped columns
|
||||
from being in the query, as the additional columns for the joined eager
|
||||
load would not be accepted by the database.
|
||||
|
||||
|
||||
@@ -3479,6 +3479,7 @@ class Query(Generative):
|
||||
kwargs.get("limit") is not None
|
||||
or kwargs.get("offset") is not None
|
||||
or kwargs.get("distinct", False)
|
||||
or kwargs.get("group_by", False)
|
||||
)
|
||||
|
||||
def exists(self):
|
||||
|
||||
@@ -1109,6 +1109,46 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
|
||||
|
||||
self.assert_sql_count(testing.db, go, 1)
|
||||
|
||||
def test_group_by_only(self):
|
||||
# like distinct(), a group_by() has a similar effect so the
|
||||
# joined eager load needs to subquery for this as well
|
||||
users, Address, addresses, User = (
|
||||
self.tables.users,
|
||||
self.classes.Address,
|
||||
self.tables.addresses,
|
||||
self.classes.User,
|
||||
)
|
||||
|
||||
mapper(
|
||||
User,
|
||||
users,
|
||||
properties={
|
||||
"addresses": relationship(
|
||||
mapper(Address, addresses),
|
||||
lazy="joined",
|
||||
order_by=addresses.c.email_address,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
q = create_session().query(User)
|
||||
eq_(
|
||||
[
|
||||
User(id=7, addresses=[Address(id=1)]),
|
||||
User(
|
||||
id=8,
|
||||
addresses=[
|
||||
Address(id=3, email_address="ed@bettyboop.com"),
|
||||
Address(id=4, email_address="ed@lala.com"),
|
||||
Address(id=2, email_address="ed@wood.com"),
|
||||
],
|
||||
),
|
||||
User(id=9, addresses=[Address(id=5)]),
|
||||
User(id=10, addresses=[]),
|
||||
],
|
||||
q.order_by(User.id).group_by(User).all(), # group by all columns
|
||||
)
|
||||
|
||||
def test_limit_2(self):
|
||||
keywords, items, item_keywords, Keyword, Item = (
|
||||
self.tables.keywords,
|
||||
@@ -3478,7 +3518,7 @@ class LoadOnExistingTest(_fixtures.FixtureTest):
|
||||
|
||||
self.assert_sql_count(testing.db, go, 1)
|
||||
|
||||
assert 'addresses' in u1.__dict__
|
||||
assert "addresses" in u1.__dict__
|
||||
|
||||
def test_populate_existing_propagate(self):
|
||||
# both SelectInLoader and SubqueryLoader receive the loaded collection
|
||||
|
||||
@@ -1113,6 +1113,45 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
|
||||
result = q.order_by(sa.desc(User.id)).limit(2).offset(2).all()
|
||||
eq_(list(reversed(self.static.user_all_result[0:2])), result)
|
||||
|
||||
def test_group_by_only(self):
|
||||
# test group_by() not impacting results, similarly to joinedload
|
||||
users, Address, addresses, User = (
|
||||
self.tables.users,
|
||||
self.classes.Address,
|
||||
self.tables.addresses,
|
||||
self.classes.User,
|
||||
)
|
||||
|
||||
mapper(
|
||||
User,
|
||||
users,
|
||||
properties={
|
||||
"addresses": relationship(
|
||||
mapper(Address, addresses),
|
||||
lazy="subquery",
|
||||
order_by=addresses.c.email_address,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
q = create_session().query(User)
|
||||
eq_(
|
||||
[
|
||||
User(id=7, addresses=[Address(id=1)]),
|
||||
User(
|
||||
id=8,
|
||||
addresses=[
|
||||
Address(id=3, email_address="ed@bettyboop.com"),
|
||||
Address(id=4, email_address="ed@lala.com"),
|
||||
Address(id=2, email_address="ed@wood.com"),
|
||||
],
|
||||
),
|
||||
User(id=9, addresses=[Address(id=5)]),
|
||||
User(id=10, addresses=[]),
|
||||
],
|
||||
q.order_by(User.id).group_by(User).all(), # group by all columns
|
||||
)
|
||||
|
||||
def test_one_to_many_scalar(self):
|
||||
Address, addresses, users, User = (
|
||||
self.classes.Address,
|
||||
|
||||
Reference in New Issue
Block a user