#37097: Nested double-unioned query for model with ordering fails on Postgres/MySql
-------------------------------------+-------------------------------------
Reporter: Shai Berger | Owner: Jacob
| Walls
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):
* cc: Simon Charette (added)
Comment:
Bisected to 087bb9e8f3478d53f12b1737af865992af17c5f2, which seems like an
improvement.
SQL on stable/6.0.x:
{{{#!sql
SELECT ...
FROM "queries_author"
WHERE NOT ("queries_author"."id" IN ((
(SELECT U0."id" AS "id"
FROM "queries_author" U0
WHERE U0."num" > 7
ORDER BY U0."name" ASC)
UNION ALL
(SELECT U0."id" AS "id"
FROM "queries_author" U0
WHERE U0."num" < 2
ORDER BY U0."name" ASC))
UNION ALL
(SELECT U0."id" AS "id"
FROM "queries_author" U0
WHERE U0."num" = 5
ORDER BY U0."name" ASC)))
ORDER BY "queries_author"."name" ASC;
}}}
And on main:
{{{#!sql
SELECT ...
FROM "queries_author"
WHERE NOT ("queries_author"."id" IN ((
(SELECT "U0"."id" AS "id",
"U0"."name" AS
"__orderbycol2"
FROM "queries_author" "U0"
WHERE "U0"."num" > 7
ORDER BY "U0"."name" ASC)
UNION ALL
(SELECT "U0"."id" AS "id",
"U0"."name" AS
"__orderbycol2"
FROM "queries_author" "U0"
WHERE "U0"."num" < 2
ORDER BY "U0"."name" ASC)
ORDER BY "__orderbycol2" ASC)
UNION ALL
(SELECT "U0"."id" AS "id"
FROM "queries_author" "U0"
WHERE "U0"."num" = 5
ORDER BY "U0"."name" ASC)))
ORDER BY "queries_author"."name" ASC;
}}}
----
Two options come to mind:
**Option 1: take a lighter touch when setting default ordering:**
{{{#!diff
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 6cdd7681b2..9d373410e2 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1702,9 +1702,10 @@ class QuerySet(AltersData):
clone = self._chain()
# Clear limits and ordering so they can be reapplied
clone.query.clear_ordering(force=True)
- clone.query.default_ordering = True
clone.query.clear_limits()
clone.query.combined_queries = (self.query, *(qs.query for qs in
other_qs))
+ if not clone.query.combined_queries:
+ clone.query.default_ordering = True
clone.query.combinator = combinator
clone.query.combinator_all = all
return clone
}}}
**Option 2: Extend the fix from yesterday's Oracle/SQLite fixes to also
clear unnecessary orderings on Postgres:
**
{{{#!diff
diff --git a/django/db/models/sql/compiler.py
b/django/db/models/sql/compiler.py
index 764dc46cfc..bf90397ed8 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -636,13 +636,7 @@ class SQLCompiler:
if selected is not None and compiler.query.selected is None:
compiler.query = compiler.query.clone()
compiler.query.set_values(selected)
- if (
- (
- features.requires_compound_order_by_subquery
- and not
features.ignores_unnecessary_order_by_in_subqueries
- )
- or not features.supports_parentheses_in_compound
- ) and compiler.get_order_by():
+ if compiler.get_order_by():
compiler.query = compiler.query.clone()
compiler.query.clear_ordering(force=False)
part_sql, part_args = compiler.as_sql(with_col_aliases=True)
}}}
Simon, do you have an opinion about the best course of action here?
--
Ticket URL: <
https://code.djangoproject.com/ticket/37097#comment:2>