freenode
Databases & Infrastructure

PostgreSQL 19 eager aggregation wrong on bpchar trailing spaces

Misclaimed equal-image support for bpchar and oidvector also broke B-tree deduplication; fixes drop that support and may require REINDEX.

PostgreSQL 19 can return incorrect aggregate counts for joins and groupings on blank-padded character (bpchar) columns, because a new eager-aggregation path trusted a false claim that equal bpchar values are bitwise identical. Equality on bpchar ignores trailing spaces, so values that compare equal can still differ in storage. Shihao Zhong reported the failure with a simple join-and-group query that doubled a count on master and 19 while PostgreSQL 18 got it right.

The same incorrect equal-image marking on bpchar_ops and bpchar_pattern_ops also lets nbtree deduplication collapse distinct on-disk values. That path is older, so the corruption risk reaches back through earlier releases, not only the 19 feature. Index-only scans can surface the mismatch as wrong multiplicities; amcheck can assert on affected indexes.

Tom Lane audited every type that advertises equal-image support and found a second offender: oidvector. Its comparator ignores the array lower-bound field, so values that compare equal need not be bitwise equal. He and Peter Geoghegan agreed to drop equal-image support for bpchar opclasses broadly, and for oidvector on 19 and master only. Rescinding oidvector on released branches would make amcheck flag routine system-catalog indexes even when their contents are fine, a disruption judged worse than the narrow risk of nonstandard oidvector values in catalogs.

Geoghegan committed the fixes. Existing bpchar indexes built under the old marking need REINDEX before amcheck will accept them; catalog contents on released branches were left unchanged so ordinary upgrades are not forced through initdb-level rewrites. Cross-version upgrade tests that run amcheck against pre-fix data still need follow-up so ancient clusters are not rejected solely for this historical marking.