[PG19] eager aggregation gives wrong results because of bpchar_ops
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
This thread has been committed, so CI has stopped here. Anything below is the last result it produced.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254077psql -h localhost -U postgresBuilt from patchset v11 (message #11), October 07, 2026 at 12:57 AM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t254077_11 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t254077_11 && git checkout t254077_11Patchset v11 (message #11) is on t254077_11
Hi hackers,
I used Opus to go over the new features in PG19, and it found wrong
results from eager aggregation on a bpchar column with no length.
create table e1 (k int, pat text);
insert into e1 values (1, 'a'), (2, 'a ');
create table e2 (c bpchar, v int);
insert into e2 select case when g % 2 = 0 then 'a' else 'a ' end, 1
from generate_series(1, 20000) g;
analyze e1, e2;
select e1.k, count(*) from e1 join e2 on e2.c like e1.pat
group by e1.k order by 1;
18 returns
k | count
---+-------
1 | 10000
2 | 10000
19 and master return
k | count
---+-------
2 | 20000
bpchar equality ignores trailing spaces, but bpchar_ops and
bpchar_pattern_ops have an equalimage function, and eager aggregation
trusts it. nbtree deduplication does too, also on 18. In the attached
bpchar-nbtree-ios.sql the heap has octet_length 1 x 98 and 3 x 1, and
the index-only scan returns 1 x 99. BUG #19749 [1]/messages/by-id/19749-d46adf7c7d910b07@postgresql.org has the assert.
The patches follow the interval_ops fix [2]/messages/by-id/20231011013317.22.nmisch@google.com. 0001 drops support
function 4 from both opclasses, catversion bump needed. 0002 is a
test. The .txt file is for back branches, where the equalimage
functions also return false for bpchar. Opus drafted them.
This also ends deduplication for char(n), where it was safe. Peter,
do you want to keep it there? Old indexes need REINDEX, and amcheck
flags them until then, so I am not sure about the back branches. The
eager aggregation part is new in 19, so I suggest an open item.
[1]: /messages/by-id/19749-d46adf7c7d910b07@postgresql.org
[2]: /messages/by-id/20231011013317.22.nmisch@google.com
Thanks,
Shihao
Attachments:
v1-REL_18-0001-Remove-equalimage-support-from-bpchar_ops-and-bpc.patch.txttext/plain; charset=US-ASCII; name=v1-REL_18-0001-Remove-equalimage-support-from-bpchar_ops-and-bpc.patch.txtDownload+53-38
v1-0001-Remove-equalimage-support-from-bpchar_ops-and-bpc.patchapplication/octet-stream; name=v1-0001-Remove-equalimage-support-from-bpchar_ops-and-bpc.patchDownload+39-29
v1-0002-Add-test-for-eager-aggregation-with-a-bpchar-colu.patchapplication/octet-stream; name=v1-0002-Add-test-for-eager-aggregation-with-a-bpchar-colu.patchDownload+57-1
I'm inclined to use the newer patch in v19, rather than trusting
the runtime return-false method.
Sounds good to me. 0001 and 0002 apply to REL_19_STABLE as they are.
Thanks,
Shihao
Import Notes
Reply to msg id not found: 1356708.1791253792@sss.pgh.pa.us
shihao zhong <zhong950419@gmail.com> writes:
I used Opus to go over the new features in PG19, and it found wrong
results from eager aggregation on a bpchar column with no length.
I went through all the data types that allege equalimage support
carefully, and found another problem: oidvector is claimed to
behave this way, but it does not. In particular, btoidvectorcmp
intentionally pays no attention to the array lower bound field.
While oidvectors would normally have a lower bound of 0, it's
not hard at all to make one that doesn't:
regression=# select array_lower(array[12,34]::oidvector, 1);
array_lower
-------------
1
(1 row)
So we find that these things are equal per btoidvectorcmp:
regression=# select array[12,34]::oidvector = '12 34'::oidvector;
?column?
----------
t
(1 row)
but they are not actually bitwise equal:
regression=# select array[12,34]::oidvector::oid[] = '12 34'::oidvector::oid[];
?column?
----------
f
(1 row)
So my first instinct is that we'd better rescind equalimage support
for oidvector too. But then pg_proc_proname_args_nsp_index and
perhaps some other system catalog indexes will start failing amcheck
in existing installations. That'd likely cause enough trouble to
outweigh the safety argument, especially since I really doubt that
it's possible to get a nonstandard oidvector value into a catalog
without doing superuser-y things.
So I'm not quite sure what to do about this. Maybe rescind in
HEAD/v19, and do nothing in the back branches?
By the by, I'm not especially happy about the errhint that Noah
added in 5f27b5f84:
+ has_interval_ops
+ ? errhint("This is known of \"interval\" indexes last built on a version predating 2023-11.")
+ : 0));
This seems to me to have passed its sell-by date somewhere around
2024. I see that Shihao's patch tries to emulate that, but doing so
for three or so different types seems to me like it will be a complete
mess, and I see no real value in it. The outcome is the same
regardless of cause: you'd better REINDEX.
regards, tom lane
On Tue, Oct 6, 2026 at 12:51 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
I went through all the data types that allege equalimage support
carefully, and found another problem: oidvector is claimed to
behave this way, but it does not. In particular, btoidvectorcmp
intentionally pays no attention to the array lower bound field.
Thanks for going to the trouble. I'll prepare a fix for these issues.
While oidvectors would normally have a lower bound of 0, it's
not hard at all to make one that doesn't:
So my first instinct is that we'd better rescind equalimage support
for oidvector too. But then pg_proc_proname_args_nsp_index and
perhaps some other system catalog indexes will start failing amcheck
in existing installations. That'd likely cause enough trouble to
outweigh the safety argument, especially since I really doubt that
it's possible to get a nonstandard oidvector value into a catalog
without doing superuser-y things.So I'm not quite sure what to do about this. Maybe rescind in
HEAD/v19, and do nothing in the back branches?
+1. Once we rescind oidvector support for deduplication, amcheck will
reliably flag every affected index's metapage as corrupt -- regardless
of the actual contents of the index. That doesn't seem worth it, all
things considered.
By the by, I'm not especially happy about the errhint that Noah
added in 5f27b5f84:+ has_interval_ops + ? errhint("This is known of \"interval\" indexes last built on a version predating 2023-11.") + : 0));This seems to me to have passed its sell-by date somewhere around
2024.
I'll remove that on master in passing. Also, I'll remove the relevant
pg_amproc.dat entries on 19 and master, but leave them alone on the
backbranches (backbranches will have to teach btequalimage and
btvarstrequalimage to disallow deduplication with these unsafe
opclasses).
--
Peter Geoghegan
On Tue, Oct 6, 2026 at 1:05 PM Peter Geoghegan <pg@bowt.ie> wrote:
Thanks for going to the trouble. I'll prepare a fix for these issues.
Attached are lightly edited versions of Shihao Zhong's bug fix
patches, incorporating the revisions I agreed to earlier today.
Note again that the patch that's intended for the released back
branches deliberately ignores the oidvector issue. Also, there are no
changes to system catalog contents on released branches (just 19 and
master), which isn't how Noah's similar 2023 interval_ops commit did
things. Shihao followed that precedent, but I don't think it's
appropriate to change the contents of the catalogs that initdb
creates, unless it's truly unavoidable.
If there are no objections, I'll commit these in the next couple of days.
--
Peter Geoghegan
Attachments:
v2_REL_18_STABLE-0001-Rescind-unsafe-deduplication-suppor.patchapplication/octet-stream; name=v2_REL_18_STABLE-0001-Rescind-unsafe-deduplication-suppor.patchDownload+25-29
v2_master-0001-Rescind-unsafe-deduplication-support.patchapplication/octet-stream; name=v2_master-0001-Rescind-unsafe-deduplication-support.patchDownload+32-45
Peter Geoghegan <pg@bowt.ie> writes:
Attached are lightly edited versions of Shihao Zhong's bug fix
patches, incorporating the revisions I agreed to earlier today.
Note again that the patch that's intended for the released back
branches deliberately ignores the oidvector issue. Also, there are no
changes to system catalog contents on released branches (just 19 and
master), which isn't how Noah's similar 2023 interval_ops commit did
things. Shihao followed that precedent, but I don't think it's
appropriate to change the contents of the catalogs that initdb
creates, unless it's truly unavoidable.
Patches LGTM. I could go along with removing those entries from the
.dat files in the older branches, but not doing so is fine too.
regards, tom lane
On Tue, Oct 6, 2026 at 3:15 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Patches LGTM. I could go along with removing those entries from the
.dat files in the older branches, but not doing so is fine too.
I pushed this, but see a XversionUpgrade-REL_18_STABLE-REL_19_STABLE
buildfarm failure on crake. It looks like crake's amcheck run
correctly complains when a bpchar index is upgraded. This must be due
to it using a stale version of REL_18_STABLE with the latest
REL_19_STABLE.
I imagine that the failure will stop soon, once crake starts using a
REL_18_STABLE with the fix. Does that sound right?
--
Peter Geoghegan
Peter Geoghegan <pg@bowt.ie> writes:
I pushed this, but see a XversionUpgrade-REL_18_STABLE-REL_19_STABLE
buildfarm failure on crake. It looks like crake's amcheck run
correctly complains when a bpchar index is upgraded. This must be due
to it using a stale version of REL_18_STABLE with the latest
REL_19_STABLE.
Yeah, it's visibly run 19 and HEAD before the older branches, which
seems odd. Usually the BF client does the branches back-to-front.
regards, tom lane
On Tue, Oct 6, 2026 at 7:49 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Actually, we do have a precedent for fixing this: it's to drop
tables or indexes that the newer version gets indigestion on.
See adjust_database_contents in AdjustUpgrade.pm.
I just found that myself; commit b352d3d8 had to do this.
I'm about to go to dinner, but I can work on fixing this afterwards
if you don't want to.
I'll see where I get with following this precedent now.
--
Peter Geoghegan
Import Notes
Reply to msg id not found: 1769161.1791330556@sss.pgh.pa.us
Peter Geoghegan <pg@bowt.ie> writes:
On Tue, Oct 6, 2026 at 7:49 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
I'm about to go to dinner, but I can work on fixing this afterwards
if you don't want to.
I'll see where I get with following this precedent now.
If you like, but my experience is that getting this right is pretty
painful if you don't have a cross-version-upgrade-testing BF animal
to experiment on. I do ...
regards, tom lane
On Tue, Oct 6, 2026 at 8:41 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
If you like, but my experience is that getting this right is pretty
painful if you don't have a cross-version-upgrade-testing BF animal
to experiment on. I do ...
Something like the attached seems like it'd do the job.
But, yeah, realistically, the hard part is proper testing and
validation, which I lack the ability to do myself.
--
Peter Geoghegan
Attachments:
t254077_110001-Fix-XversionUpgrade-allequalimage-failures.patchapplication/x-patch; name=0001-Fix-XversionUpgrade-allequalimage-failures.patchDownload+14-1
Hi Peter, Tom,
Thanks for pushing this and for taking care of the upgrade test failure.
I was not around when the crake failure came up, so I want to explain.
I work a day job in EST, and I do PostgreSQL work
mostly outside those hours. I usually read the list in the evening, and
a reply from me can take until then. It is not that I am ignoring the
thread.
I saw Peter's 0001-Fix-XversionUpgrade-allequalimage-failures.patch, and
the AdjustUpgrade.pm approach looks right to me. Peter said validating
it is the hard part. Let me try to play with this patch.
Thanks,
Shihao
Import Notes
Reply to msg id not found: 1916336.1791334229@sss.pgh.pa.us
Hi Peter,
Something like the attached seems like it'd do the job.
I tried it. I took a pg_dumpall from a 13 cluster after the
regression tests, ran 002_pg_upgrade.pl on master with it, and then
ran amcheck on the upgraded cluster. Without the patch amcheck
complains with the following. With the patch it is clean.
`ERROR: index "ctl_bpchar" metapage incorrectly indicates that
deduplication is safe`
Thanks,
Shihao
Import Notes
Reply to msg id not found: 1942286.1791335879@sss.pgh.pa.us