Don't overwrite scan key in systable_beginscan()

From: Peter Eisentraut <peter(at)eisentraut(dot)org>
To: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Don't overwrite scan key in systable_beginscan()
Date: 2024-08-08 06:46:35
Message-ID: f8c739d9-f48d-4187-b214-df3391ba41ab@eisentraut.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

When systable_beginscan() and systable_beginscan_ordered() choose an
index scan, they remap the attribute numbers in the passed-in scan keys
to the attribute numbers of the index, and then write those remapped
attribute numbers back into the scan key passed by the caller. This
second part is surprising and gratuitous. It means that a scan key
cannot safely be used more than once (but it might sometimes work,
depending on circumstances). Also, there is no value in providing these
remapped attribute numbers back to the caller, since they can't do
anything with that.

I propose to fix that by making a copy of the scan keys passed by the
caller and make the modifications there.

In order to prove to myself that there are no other cases where
caller-provided scan keys are modified, I went through and
const-qualified all the APIs. This works out correctly. Several levels
down in the stack, the access methods make their own copy of the scan
keys that they store in their scan descriptors, and they use those in
non-const-clean ways, but that's ok, that's their business. As far as
the top-level callers are concerned, they can rely on their scan keys to
be const after this.

I'm not proposing this second patch for committing at this time, since
that would modify the public access method APIs in an incompatible way.
I've made a proposal of a similar nature in [0]. At some point, it
might be worth batching these and other changes together and make the
change. I might come back to that later.

[0]:
https://www.postgresql.org/message-id/flat/14c31f4a-0347-0805-dce8-93a9072c05a5%40eisentraut.org

While researching how the scan keys get copied around, I noticed that
the index access methods all use memmove() to make the above-mentioned
copy into their own scan descriptor. This is fine, but memmove() is
usually only used when something special is going on that would prevent
memcpy() from working, which is not the case there. So to avoid the
confusion for future readers, I changed those to memcpy(). I suspect
that this code has been copied between the different index AM over time.
(The nbtree version of this code is literally unchanged since July 1996.)

Attachment Content-Type Size
0001-Don-t-overwrite-scan-key-in-systable_beginscan.patch text/plain 3.8 KB
0002-Augment-ScanKey-arguments-with-const-qualifiers.patch text/plain 21.6 KB
0003-Replace-gratuitous-memmove-with-memcpy.patch text/plain 5.4 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bertrand Drouvot 2024-08-08 06:49:27 Re: Restart pg_usleep when interrupted
Previous Message Amit Kapila 2024-08-08 06:33:30 Re: [bug fix] prepared transaction might be lost when max_prepared_transactions is zero on the subscriber