#37097: Nested double-unioned query for model with ordering fails on
Postgres/MySql
-------------------------------------+-------------------------------------
Reporter: Shai Berger | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: dev | Severity: Release
| blocker
Keywords: Regression | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Yep. Sorry about the title, that's the most succinct I can make it.
Add the following test in
{{{django/tests/queries/test_qs_combinators.py}}}, say after
{{{test_union_in_with_ordering_and_slice}}}
{{{#!python
def test_double_union_in_with_ordering(self):
qs1 = Author.objects.filter(num__gt=7)
qs2 = Author.objects.filter(num__lt=2)
qs3 = Author.objects.filter(num=5)
self.assertQuerySetEqual(
# Query formatted to allow easy commenting-out of parts
Author.objects.exclude(id__in=qs1
.union(qs2, all=True)
.union(qs3, all=True)
.values("id")),
[]
)
}}}
On Postgres, this passes on 6.0, but fails on the main branch (towards 6.1
as I write this). The error is
{{{
django.db.utils.ProgrammingError: each UNION query must have the same
number of columns
LINE 1: ...) ORDER BY "__orderbycol2" ASC) UNION ALL (SELECT "U0"."id" ...
}}}
because the query (formatted for some readability) is
{{{#!sql
SELECT "queries_author"."id", "queries_author"."name",
"queries_author"."num", "queries_author"."extra_id"
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 -- I think this is the
culprit
) 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
}}}
Notes:
- Double union is required, a single union works
- This happens when the ordering is defined in the model Meta, but not if
you just add ordering on the queries. I suspect this is because having the
ordering in the Meta makes the query equivalent to
{{{#!python
Author.objects.exclude(id__in=qs1
.union(qs2, all=True)
.order_by("name") # This is implied
.union(qs3, all=True)
.values("id"))
}}}
- On Oracle and Sqlite, the inner order is removed by the fix of #36938. I
haven't actually tested it on MySql, but I believe it has the same
relevant feature flags and so should behave the same.
- The test as written fails on Sqlite on 6.0, with
{{{django.db.utils.DatabaseError: ORDER BY not allowed in subqueries of
compound statements}}} -- similar tests are skipped there; but it passes
on Postgres, and passes on Sqlite on main.
--
Ticket URL: <https://code.djangoproject.com/ticket/37097>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019e1d0093ba-a16b6240-db57-48a0-a61d-bac9d961ac16-000000%40eu-central-1.amazonses.com.