| From: | Nidal FAKIH <nidal(dot)fakih(at)soptimal(dot)com> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Wrong result: count(DISTINCT x COLLATE "C") with GROUP BY x on a nondeterministic collation |
| Date: | 2026-11-01 09:27:43 |
| Message-ID: | c6790a7b-7c10-4baf-9c8f-b404420c63f9@soptimal.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hello,
I would like to report what looks like a wrong-result bug with presorted
aggregation when the GROUP BY column uses a nondeterministic collation
and the DISTINCT aggregate uses a different (deterministic) collation.
Version (SELECT version()):
PostgreSQL 18.3 on x86_64-windows, compiled by msvc-19.44.35223, 64-bit
System: Windows 11 x64. ICU collation provider. The script sets
max_parallel_workers_per_gather = 0 only to keep the plan simple; the
result is
the same without it.
_
Self-contained reproduction script:_
CREATE COLLATION ci_ai (provider = icu, locale = 'und-u-ks-level1',
deterministic = false);
CREATE TABLE t (x varchar(10) COLLATE ci_ai);
-- 60 rows: 'a' x20, 'A' x20, 'b' x20
INSERT INTO t SELECT (ARRAY['a','A','b'])[1 + i % 3] FROM
generate_series(0, 59) i;
SET max_parallel_workers_per_gather = 0;
SELECT x COLLATE "C" AS grp, count(DISTINCT x COLLATE "C") AS variants
FROM t GROUP BY x ORDER BY 1;
EXPLAIN (COSTS OFF)
SELECT count(DISTINCT x COLLATE "C") FROM t GROUP BY x;
SET enable_presorted_aggregate = off;
SELECT x COLLATE "C" AS grp, count(DISTINCT x COLLATE "C") AS variants
FROM t GROUP BY x ORDER BY 1;
RESET enable_presorted_aggregate;
DROP TABLE t;
DROP COLLATION ci_ai;
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).
The plan looks right: the input is sorted by (x COLLATE ci_ai, x COLLATE
"C").
So I suspect the presorted DISTINCT aggregate compares adjacent values
with the GROUP BY collation, or does not compare them at all, instead of
using theaggregate argument's collation "C". 40 is the number of rows in
the group ('a' and 'A'), so in effect every row is counted as a new
distinct value. With a different distribution of the same three values,
I got 41 in an earlier test, so the wrong count depends on the data.
Workaround: SET enable_presorted_aggregate = off, or compute the
distinct values in a subquery first, for example:
SELECT g, count(*) FROM (SELECT DISTINCT x AS g, x COLLATE "C" AS v
FROM t) s GROUP BY g;
Thank you for your work on PostgreSQL.
B.Regards
N.Fakih
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-11-01 14:40:41 | BUG #19825: JSON_VALUE(... RETURNING <domain over json/jsonb>) loses the re-quoting of scalar strings and silent |
| Previous Message | PG Bug reporting form | 2026-11-01 08:07:24 | BUG #19824: OMIT QUOTES breaks non-string results: array / composite / array-domain coercions in JSON_QUERY / JS |