| From: | David Rowley <dgrowleyml(at)gmail(dot)com> |
|---|---|
| To: | Nidal FAKIH <nidal(dot)fakih(at)soptimal(dot)com> |
| Cc: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: Wrong result: count(DISTINCT x COLLATE "C") with GROUP BY x on a nondeterministic collation |
| Date: | 2026-11-04 09:34:23 |
| Message-ID: | CAApHDvrn=6_xSrUPwX-8HbxChfjG3zwKYtEgJfDnp=QKNjha5A@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
On Mon, 2 Nov 2026 at 23:44, Nidal FAKIH <nidal(dot)fakih(at)soptimal(dot)com> wrote:
> Result obtained:
>
> grp | variants
> -----+----------
> a | 40
> b | 1
>
> Expected result: 'a' and 'A' are equal under ci_ai, so they form one group, but they are two distinct values under "C":
>
> grp | variants
> -----+----------
> a | 2
> b | 1
>
> Plan:
>
> GroupAggregate
> Group Key: x
> -> Sort
> Sort Key: x COLLATE ci_ai, x COLLATE "C"
> -> Seq Scan on t
>
> With SET enable_presorted_aggregate = off, the same query returns the expected result (a = 2, b = 1).
Thanks for the report. I had suspected this was an issue with the
presorted aggregate code, but it's not.
I looked at the results of "select x from t order by t.x COLLATE
ci_ai, t.x COLLATE "C";" and the order of those rows wasn't the same
order as what I was seeing on your test query while watching the
"value" variable after hitting the breakpoint I had in
ExecEvalPreOrderedDistinctSingle(). I was seeing the values
alternating between "A" and "a", whereas, confusingly, that's not what
the plain select query outputs.
As it turns out, the bug is in nodeSort.c. The Datum sort code path
thinks it's ok to use a Datum sort when there's only 1 column. You
might assume only 1 sort key actually matters when there's only 1
column since both sort keys must be on that column, but that's not
true when the first sort key is non-deterministic.
The code change required is basically:
- if (outerTupDesc->natts == 1)
+ if (outerTupDesc->natts == 1 && node->numCols == 1)
sortstate->datumSort = true;
else
sortstate->datumSort = false;
Looking at the explain verbose for "select x from t order by t.x
COLLATE ci_ai, t.x COLLATE "C";" shows the Seq Scan has "Output: x, x,
x", which is why that query didn't highlight the sorting issue.
There's 3 output columns, so no Datum sort. I guess the planner added
the duplicate Vars because it thought it needed the two resjunk
columns for the ORDER BY keys due to the Vars not comparing as equal
because of the varying collation.
See attached for a draft patch. I'll look at committing this tomorrow
as it's a bit late here right now.
David
| Attachment | Content-Type | Size |
|---|---|---|
| draft_fix.patch | application/octet-stream | 738 bytes |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Aleksander Alekseev | 2026-11-04 09:36:13 | Re: BUG #19603: Vuln47: distance_taxicab and distance_chebyshev silently return 0 instead of NaN when a cube coordin |
| Previous Message | Aleksander Alekseev | 2026-11-04 09:05:27 | Re: BUG #19603: Vuln47: distance_taxicab and distance_chebyshev silently return 0 instead of NaN when a cube coordin |