Daniel Gustafsson [Thu, 6 Aug 2026 12:07:57 +0000 (14:07 +0200)]
doc: Define MXID as an acronym
XID is defined as an acronym in the documentation but MXID (Multixact
ID) was missing from the acronym list. This adds MXID as an acronym
and links it to the "Multixacts and Wraparound" section.
Author: Koshino Taiki <koshino@sraoss.co.jp>
Discussion: https://postgr.es/m/OS9PR01MB17364A940ACFCADBB7593498A94D32@OS9PR01MB17364.jpnprd01.prod.outlook.com
Peter Eisentraut [Thu, 6 Aug 2026 08:23:44 +0000 (10:23 +0200)]
Report duplicate property and label names with a proper error
Adding a property with the same name multiple times to a label on an
element, either within a single PROPERTIES clause or across statements
via ALTER PROPERTY GRAPH ... ADD PROPERTIES, previously failed with a
unique-index violation on pg_propgraph_label_property. The same class
of bug existed for labels: listing the same label multiple times on
one element in CREATE PROPERTY GRAPH, or adding a label to an element
that already has it via ALTER PROPERTY GRAPH ... ADD LABEL, failed
with a unique-index violation on pg_propgraph_element_label. Detect
the duplicates up front and raise a friendlier error in both cases.
For properties, the cross-statement duplicate is caught by a syscache
probe before insertion. The in-clause duplicate could have been
caught by the same probe if we issued a CommandCounterIncrement()
between property inserts, but that forces a catalog invalidation per
property purely to detect a condition we can check for free on the
in-memory target list. The list-based check is only needed when the
properties are listed explicitly; when they are derived from the
table's attributes, names are already unique.
For labels, a single syscache probe on pg_propgraph_element_label
suffices for both the in-clause and cross-statement cases because
insert_element_record() already issues CommandCounterIncrement()
between successive label inserts.
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://www.postgresql.org/message-id/flat/
20260630173053.51.noahmisch%40microsoft.com
Michael Paquier [Thu, 6 Aug 2026 07:46:03 +0000 (16:46 +0900)]
Tighten proto_version parsing in pgoutput
This is similar to
58ff4a0a0867, but this time for the parameter
"proto_version", when given as a parameter to pgoutput for logical
replication. strtoul() lacked a check for an empty string, leading to
an inconsistent behavior depending on the platform.
The author has originally proposed a TAP test to check this empty value
pattern. I have added a cheaper SQL query, instead, test_decoding
including a test area where this is possible.
Author: Tristan Partin <tristan@partin.io>
Discussion: https://postgr.es/m/DKBS2Z9CGARC.2T07O6TJYSE8B@partin.io
Michael Paquier [Thu, 6 Aug 2026 06:39:56 +0000 (15:39 +0900)]
Tighten tid input parsing with strtoul() to reject empty fields
strtoul() informs that in the case of no conversion, "endptr" is set
equal to the location of the input pointer, which is something that
tidin() has never checked.
This allowed inputs like "(,)", "(1,)" or "(,1)" to be accepted on some
platforms, like Linux where "(1,)" implied "(1,0)", but rejected on
others like macos where "(1,)" is rejected, due to the fact that errno
may not be set.
This change may cause some issues as some tid values will now be
rejected, but at least we get the consistent strtoul() experience.
If it proves to be a pain for some, it could always be reverted.
Another point of this change is that we get one step closer to a
possible common strtoul() where the error handling could be unified in
core, with all the errors handled the same way for errno and no input
parsed, at least.
Reported-by: Michael Malis <malis@pgrust.com>
Author: Tristan Partin <tristan@partin.io>
Discussion: https://postgr.es/m/19584-
e60c446ba6f57c9c@postgresql.org
Discussion: https://postgr.es/m/DKBS2Z9CGARC.2T07O6TJYSE8B@partin.io
Amit Kapila [Thu, 6 Aug 2026 06:11:18 +0000 (11:41 +0530)]
Fix race condition in subscription TAP test 023_twophase_stream.
Buildfarm member olingo intermittently failed this test, timing out while
waiting for the subscriber log to report an ERROR because
max_prepared_transactions is zero there. The test captured the log offset
only after issuing the publisher's
BEGIN/INSERT/PREPARE TRANSACTION/COMMIT PREPARED sequence.
Since streaming is enabled, the subscriber can receive and apply the
transaction, and log the expected ERROR, before that publisher SQL command
even returns, i.e. before the test captures the offset. The subsequent
wait_for_log() calls then searched only from a point after the message had
already been written, and timed out waiting for it.
Fix by moving the offset capture to before the publisher's transaction is
issued, ensuring it always precedes the point where the ERROR can appear
in the subscriber log.
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 16, where test was introduced
Discussion: https://postgr.es/m/
c43753d8-5265-4f77-83ff-
9b1167276ec5@gmail.com
David Rowley [Thu, 6 Aug 2026 05:42:44 +0000 (17:42 +1200)]
Fix unlikely incremental tuple deform bug with missing attrs
The code added in
c456e3911 added populate_isnull_array() to bulk
populate the slot's tts_isnull array 8 elements at a time. When tuples
don't have an exact multiple-of-eight number of attributes, this will
lead to populating the tts_isnull elements for attributes that don't
exist in the tuple. This is ok as the array is large enough. However,
if we perform tuple deforming in two passes, and on the first pass
deform *some* of the attributes with slot_getmissingattrs() then later
when we deform the remaining missing attributes, the subsequent call to
populate_isnull_array() would overwrite the tts_isnull values previously
set by slot_getmissingattrs(), and since that function only continues
where it left off, it wouldn't reapply the previously set values and those
would be left as NULLs, as populate_isnull_array() would have set them.
Here, we fix by passing the tuple's natts to slot_getmissingattrs()
rather than the attnum we're deforming from. This means we apply all
the missing attribute values each deform pass, so slightly more work,
but deforming several missing values in different deform passes is
likely exceedingly rare. Doing that seems much better than adding
overhead in the happy path to check for this and skip the subsequent call
to populate_isnull_array().
Author: David Rowley <dgrowleyml@gmail.com>
Reported-by: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAH2-WznHo4b+6AmAj0GZ0jXqDSK69MfHe8fAQwuY_01y7cVNdw@mail.gmail.com
Backpatch-through: 19
Michael Paquier [Wed, 5 Aug 2026 23:19:13 +0000 (08:19 +0900)]
Remove redundant unlink() in KeepFileRestoredFromArchive() for non-WIN32
KeepFileRestoredFromArchive() called unlink() on an existing WAL segment
before durable_rename() replaced it. rename(2) atomically replaces a
target on POSIX systems, and the extra unlink() created a small window
where it would be possible for a concurrent WAL sender to see a segment
as missing.
Note that the window still exists on WIN32, as we lack a safe concurrent
alternative. Perhaps something like ReplaceFile() could be looked at
for this purpose.
This problem is hard to reach in practice, so no backpatch is done. I
also tend to be conservative regarding recovery changes, even small, in
stable branches.
Author: Stepan Neretin <slpmcf@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: Neil Chen <carpenter.nail.cz@gmail.com>
Discussion: https://postgr.es/m/CA+Yyo5S0C25jS_pRWQiGgoiy+X=GyJS7ZJkEq=_SW1WWpkL3Sg@mail.gmail.com
Jeff Davis [Wed, 5 Aug 2026 20:19:21 +0000 (13:19 -0700)]
When changing owner of a subscription, do not throw an error.
Errors will be caught when the connection is actually used.
Restore uses multiple DDL commands to restore a subscription, so
checks of the intermediate state risk restore errors. In the future we
could address this with a more careful restoration order, but the
DDL-time errors are merely for convenience.
Addresses finding 2 in the report from the linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Discussion: https://postgr.es/m/
e103ae8daf74485e0c0ebde297fae735d38f54d1.camel@j-davis.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 20:19:10 +0000 (13:19 -0700)]
Revert "Validate subscription conninfo on owner change"
This reverts commit
1c9c35890421e96a91129b51f2c6446a6d95af95.
Raising errors during OWNER TO can cause problems during restore. An
upcoming commit will avoid other errors that can happen in this path.
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
e103ae8daf74485e0c0ebde297fae735d38f54d1.camel@j-davis.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 20:19:02 +0000 (13:19 -0700)]
CREATE SUBSCRIPTION: do not construct conninfo unnecessarily.
Still check that the creating user has USAGE privileges on the server,
and that the FDW supports subscription connections.
Addresses finding 1 in the report from the linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Discussion: https://postgr.es/m/
e103ae8daf74485e0c0ebde297fae735d38f54d1.camel@j-davis.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 20:18:44 +0000 (13:18 -0700)]
For subscription DDL, demote user mapping checks to WARNING.
The checks are useful to report to the user, but there's no reason to
raise an error. If needed while constructing conninfo, fdwconnection
will raise an error then.
Partially addresses finding 1, and addresses finding 13 in report from
the linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Discussion: https://postgr.es/m/
e103ae8daf74485e0c0ebde297fae735d38f54d1.camel@j-davis.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 20:18:34 +0000 (13:18 -0700)]
Always check foreign-server USAGE when resolving subscription conninfo.
Previously, this was skipped in some cases to avoid raising errors
when conninfo wasn't even needed. That was wrong in cases where
conninfo was needed.
Now that we only build conninfo when needed, always perform the USAGE
check.
Addresses finding 7 in report from linked discussion.
Co-authored-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reviewed-by: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 20:11:04 +0000 (13:11 -0700)]
Be precise about when ALTER SUBSCRIPTION needs conninfo.
Decide early whether the original conninfo is needed so that errors
happen consistently.
Addresses finding 12 in report from linked discussion.
Co-authored-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 18:57:36 +0000 (11:57 -0700)]
Build subscription conninfo after checking that it's enabled.
If a subscription is disabled, don't try to build conninfo because
that may generate a confusing error and try to disable an
already-disabled subscription.
Partially addresses finding 5 in report from linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Backpatch-through: 19
Jeff Davis [Wed, 5 Aug 2026 18:36:37 +0000 (11:36 -0700)]
Remove Subscription conninfo field; generate in caller.
After server-based subscriptions, conninfo became more than just a
catalog field. It has its own error paths, and it's important that
callers that don't need conninfo don't encounter errors related to it.
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch%40microsoft.com
Backpatch-through: 19
Peter Eisentraut [Wed, 5 Aug 2026 17:26:30 +0000 (19:26 +0200)]
Fix MSVC warnings from new timezone code
The new timezone code from commit
aeb07c55fab introduced a few new
compiler warnings from MSVC:
../src/timezone/zic.c(353): warning C5287: operands are different enum types '<unnamed-enum-RF_NAME>' and '<unnamed-enum-LF_TARGET>'; use an explicit cast to silence this warning
../src/timezone/zic.c(353): warning C5287: operands are different enum types '<unnamed-enum-RF_NAME>' and '<unnamed-enum-LP_YEAR>'; use an explicit cast to silence this warning
../src/timezone/zic.c(1654): warning C4146: unary minus operator applied to unsigned type, result still unsigned
Silence these warnings with pragmas.
In order not to make future code merges more complicated, the pragmas
apply to the entire file, not only to the specific code sections where
they are needed. This also prevents further warnings of the same
kinds creeping in.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/
2294297.
1780270682%40sss.pgh.pa.us
Álvaro Herrera [Wed, 5 Aug 2026 09:40:39 +0000 (11:40 +0200)]
Fix calculating length of match to localized month/weekday names
seq_search_localized() returns the length of the matching prefix in
*len, but because it internally case-folds the inputs, it gets
confused on the length. The caller expects to get the length of the
prefix in the original string, but what it actually returns is the
length of the prefix after case-folding, which can be different if the
case-folded characters have different byte-length than the original,
or with ICU, if the case-folding changes the number of characters
(e.g. "ß", the German double s).
To fix, once we have determined that we have a match, work harder to
find the match's length in the original string. This adds some
overhead, but the strings are expected to be short.
The function does "case-folding" by converting a string to upper-case,
then to lower-case, which is a little ugly given that we have
dedicated functions for case-folding nowadays. But switching to that
doesn't seem appropriate to backpatch in a security fix, and that's
not available in older stable versions, anyway.
Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Reported-by: Xint Code
Reviewed-by: Jeff Davis <pgsql@j-davis.com>
Peter Eisentraut [Wed, 5 Aug 2026 08:44:10 +0000 (10:44 +0200)]
Disallow aggregates, window functions, and SRFs in GRAPH_TABLE COLUMNS
The COLUMNS list of a GRAPH_TABLE query is parsed as an ordinary select
target list, which permits aggregate functions, window functions, and
set-returning functions. GRAPH_TABLE has no machinery to evaluate them,
though: the rewriter copies the COLUMNS target list verbatim into a
freshly built subquery whose hasAggs/hasWindowFuncs/hasTargetSRFs flags
are never set, so the planner builds no Agg/WindowAgg node (and no SRF
expansion) and the Aggref/WindowFunc/SRF reaches the executor. This
triggers an assertion failure ("ecxt_aggvalues != NULL"), or "Aggref
found in non-Agg plan node" on a non-assert build, for otherwise
parser-accepted SQL such as
SELECT max(c) FROM GRAPH_TABLE
(g MATCH (x IS v) COLUMNS (count(*) AS c));
Reject these constructs in transformRangeGraphTable() the same way
subqueries are already handled: save and clear pstate->p_hasAggs,
p_hasWindowFuncs, and p_hasTargetSRFs around the transformation of the
COLUMNS list, and raise a "not supported" error if any of them got set.
This is deliberately a blanket prohibition for now. Once quantified
element patterns such as (a)->{1,5} are supported, aggregates over
property references of higher degree (e.g. count(a) or sum(a.val)) can
be allowed; at that point the check will need to inspect the aggregate
arguments rather than reject all aggregates outright.
Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAON2xHOYAmYLkB2jGi6g77d6Fqv8YgOrfV-riQVf0K_7AdxD3w@mail.gmail.com
Michael Paquier [Wed, 5 Aug 2026 07:55:23 +0000 (16:55 +0900)]
Initialize read stream before fetching metapage in hash bulk-deletion
hashbulkdelete() fetched the relcache's cached hash metapage before
calling read_stream_begin_relation(). During the read stream
initialization, relation lookups may process pending relcache
invalidation messages, which could cause the cached metapage to be
invalidated before the read stream uses it, leading to the failure of a
VACUUM bulk-deletion for a hash index.
This commit reworks the order of hashbulkdelete() so as its read stream
is initialized before fetching the cached metapage, so as pending
invalidation messages do not interfere with the relation scan.
Issue introduced by
bfa3c4f106b1.
Author: Mikhail Nikalayeu <mihailnikalayeu@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Discussion: https://postgr.es/m/CADzfLwVEJ2_7ioX3ZSB1P7qXW40ghUy_ZCzeFvhDLoa_3Muztg@mail.gmail.com
Backpatch-through: 19
Peter Eisentraut [Wed, 5 Aug 2026 06:35:10 +0000 (08:35 +0200)]
More tab-completion for DROP PROPERTY GRAPH
This adds completion for CASCADE and RESTRICT, similar to what
completion of other DROP commands provides.
Author: Peter Smith <peter.b.smith@fujitsu.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAHut+PuHsLupVWZ9SUeKm=jKR34wYP6qAZPoOHFhU3uDbx34wQ@mail.gmail.com
Fujii Masao [Wed, 5 Aug 2026 02:36:43 +0000 (11:36 +0900)]
doc: Update XID wraparound error example
Commit
edee0c621de, and the equivalent v17 commit
f2353dd71724,
changed the runtime XID wraparound messages to use "transaction IDs"
terminology, but one corresponding error example in maintenance.sgml
still used the older XID wording.
Update that documentation example in line with the current runtime
message.
Backpatch to v17, where the runtime messages were changed.
Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Yugo Nagata <nagata@sraoss.co.jp>
Discussion: https://postgr.es/m/CAHGQGwHTN-Xc5iDtbzNSjfxuab5Y9qAArw8cB4PrrDJpZ+1fgA@mail.gmail.com
Backpatch-through: 17
Fujii Masao [Wed, 5 Aug 2026 02:34:29 +0000 (11:34 +0900)]
Clarify wraparound warning percentage messages
Commit
e646450e609 added DETAIL messages for XID and MultiXactId
wraparound warnings that described the reported percentage as the
percentage of IDs available for use. However, the percentage is actually
calculated from the remaining distance to the wraparound limit, not the
stop limit where new IDs are refused. As a result, the wording could be
misinterpreted as meaning that the reported percentage of IDs can still
be allocated.
Update the wording to clarify that the reported percentage represents the
remaining transaction ID space or MultiXactId space before wraparound.
Also update the related XID warning hints to use "transaction ID"
terminology consistently.
Backpatch to v19, where the DETAIL messages were added.
Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Yugo Nagata <nagata@sraoss.co.jp>
Discussion: https://postgr.es/m/CAHGQGwHWZTsR6bjdfpa+pOkBPjoXXm2LuJ+5nh+CvdyqEASHcQ@mail.gmail.com
Backpatch-through: 19
Fujii Masao [Wed, 5 Aug 2026 02:29:15 +0000 (11:29 +0900)]
doc: Clarify wal_sender_shutdown_timeout values
Clarify how special wal_sender_shutdown_timeout values affect shutdown
waiting. A value of -1 disables the shutdown timeout and lets the
WAL sender wait for the receiver to catch up, while 0 causes immediate
termination without waiting for catch-up. Positive values bound how long
shutdown waits, so document that they should be high enough for WAL data
to be replicated under normal circumstances.
Update the main documentation, the GUC long description, and
postgresql.conf.sample consistently. While here, fix nearby paragraph
indentation and spacing.
Backpatch to v19, where wal_sender_shutdown_timeout was introduced.
Author: Chao Li <lic@highgo.com>
Reviewed-by: Ian Barwick <barwick@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/
AF4FE756-A220-4DA7-87B7-
A126F3F307FD@gmail.com
Backpatch-through: 19
Melanie Plageman [Tue, 4 Aug 2026 22:04:28 +0000 (18:04 -0400)]
Silence Coverity warning about unused visibilitymap_clear() result
Commit
c0d9864f5ce made all but one caller of visibilitymap_clear() check
its return value, causing Coverity to flag the remaining unchecked call
in heap_page_fix_vm_corruption().
This VM clear is not WAL-logged, so the caller doesn't need the return
value of visibilitymap_clear(). Add an explicit void cast and comment to
document that the return value is intentionally ignored.
Backpatch to 19 when the number of callers discarding the return value
dropped low enough to trigger Coverity's warning.
Discussion: https://postgr.es/m/
1065814.
1784514869%40sss.pgh.pa.us
Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Backpatch-through: 19
Michael Paquier [Tue, 4 Aug 2026 21:53:10 +0000 (06:53 +0900)]
Improving handling of oversized records in xlogreader.c
XLogRecordAssemble() refuses records larger than XLogRecordMaxSize when
generating records, but the reader-side only checked a minimal number
for xl_tot_len.
A crafted multi-page record with xl_tot_len near UINT32_MAX could bypass
the contrecord length checks, overflow allocate_recordbuf()'s size math,
and corrupt memory during reassembly (or hit related asserts under
cassert).
xlogreader.c is updated to check that the received record is never
larger than XLogRecordMaxSize, when first receiving the first bytes of
xl_tot_len, then again when validating the record header.
WAL is a source of data trusted by the server, with CRC32 checksums
providing a level of protection before replaying the records if data is
corrupted. These limits could be internally reached only with crafted
WAL records, which is something that analyzers (named as LLMs) like
complaining about these days.
039_end_of_wal.pl is adjusted according to the new maximum limit, a test
for XLogRecordMaxSize is added.
Author: David Karapetyan <dkarapetyan@gmail.com>
Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Discussion: https://postgr.es/m/CALmTjZBddzeGVU2o1JNZb3mPvV68PqDskWPAUQBVb-35yVkiwA@mail.gmail.com
Masahiko Sawada [Tue, 4 Aug 2026 20:41:02 +0000 (13:41 -0700)]
Add comments to uuid_extract_timestamp().
The timestamp-reassembly expressions in uuid_extract_timestamp() are
chains of shifted octets whose shift counts encode the field layout of
each UUID version, which is not otherwise recoverable from the code.
This commit documents, for UUIDv1, UUIDv6, and UUIDv7 alike, which
octets carry which part of the timestamp and where each part lands in
the reassembled value, citing the RFC section that defines it.
Author: Tristan Partin <tristan@partin.io>
Reviewed-by: Miłosz Bieniek <bieniek.milosz@proton.me>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/DJHJW50YWKIT.XIOT4NOZRQ03@partin.io
Masahiko Sawada [Tue, 4 Aug 2026 17:57:43 +0000 (10:57 -0700)]
Support UUIDv6 in uuid_extract_timestamp().
Previously, uuid_extract_timestamp() returned NULL for UUIDv6 values,
even though it already extracted timestamps from UUIDv1 and
UUIDv7.
This commit adds a UUIDv6 branch that reassembles the timestamp from
that layout and then converts it exactly as the UUIDv1 branch does. We
provide no uuidv6() generator, but such values can be produced by
client applications and stored in the database, just as UUIDv1 values
already are.
Author: Tristan Partin <tristan@partin.io>
Reviewed-by: Miłosz Bieniek <bieniek.milosz@proton.me>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/DJHJW50YWKIT.XIOT4NOZRQ03@partin.io
Daniel Gustafsson [Tue, 4 Aug 2026 13:42:56 +0000 (15:42 +0200)]
Reindent conditional to improve readability
Found via readability-misleading-indentation warning in clangd.
Author: Tristan Partin <tristan@partin.io>
Discussion: https://postgr.es/m/DKFO99FP6SLY.2O6A6BUK6P3OQ@partin.io
Peter Eisentraut [Tue, 4 Aug 2026 13:10:22 +0000 (15:10 +0200)]
psql: Message style fixes
Peter Eisentraut [Tue, 4 Aug 2026 12:36:47 +0000 (14:36 +0200)]
doc: Make synopsis placeholders consistent
Existing text (e.g., create_foreign_table.sgml) uses server_name, not
servername.
Daniel Gustafsson [Tue, 4 Aug 2026 10:16:55 +0000 (12:16 +0200)]
Do not reuse rd_smgr in fork loop when enabling data checksums
ProcessSingleRelationByOid called RelationGetSmgr(rel), discarded the
result, and then read rel->rd_smgr directly when looping over forks.
Only RelationGetSmgr is authorized to read that field since a relcache
invalidation resets rd_smgr to NULL.
Backpatch to v19 where online checksums were introduced.
Author: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
Reviewed-by: ChangAo Chen <cca5507@qq.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CADzfLwXGvb4Y-mqy8T+O0f_tkXR1sTDBGzP5Z=V_qcGnZ46rWg@mail.gmail.com
Backpatch-through: 19
Álvaro Herrera [Tue, 4 Aug 2026 09:44:11 +0000 (11:44 +0200)]
pg_surgery: Fix infinite loop on large TID arrays
heap_force_common() tracked the current position in the caller-supplied
tid[] using OffsetNumber, which is only 16 bits wide, so when the array
held more than 65535 entries, the updated index wrapped around and the
outer loop never reached the exit condition. A SQL call with a
sufficiently large TID array would then run until interrupted.
Fix by tracking the tid[] position using int instead of OffsetNumber.
A regress case based on the report is included.
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reported-by: Yuelin Wang <1217816127@qq.com>
Backpatch-through: 14
Bug: #19607
Discussion: https://postgr.es/m/19607-
2f256a66481c514b@postgresql.org
Peter Eisentraut [Tue, 4 Aug 2026 08:31:55 +0000 (10:31 +0200)]
doc: Add PROPERTY GRAPH to the access privilege tables
The SELECT privilege can be granted on a property graph, and its
privileges can be examined with psql's \dp command, but property
graphs were missing from both summary tables in the "Privileges"
section: the applicable object types for SELECT in the privilege
abbreviations table, and the per-object-type row in the summary of
access privileges table. Add the missing entries so the tables match
the actual behavior described for the SELECT privilege and in GRANT.
While at it, also add a test for \dp on a property graph.
Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAOzEurScgwLDXQmNFnDZANGAMMiva9GnLH_kO8qGtGVHUvVk2A%40mail.gmail.com
Peter Eisentraut [Tue, 4 Aug 2026 07:55:03 +0000 (09:55 +0200)]
Prohibit GRANT ... ON TABLE on a property graph
We allowed GRANT ... ON TABLE on sequences for backward compatibility.
We don't need to consider backward compatibility in case of property
graphs since we will be prohibiting its usage on property graph from
the very release which introduced property graphs.
Change regression tests that used GRANT ... ON [TABLE] on property
graphs to use GRANT ... ON PROPERTY GRAPH instead.
While here, add the missing RELKIND_PROPGRAPH cases in
pg_class_aclmask_ext() and in the object-type switch in
ExecGrant_Relation() so that the default ACL and the objtype passed to
restrict_and_check_grant() are correct.
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/
20260630023308.c7.noahmisch@microsoft.com
Fujii Masao [Tue, 4 Aug 2026 08:06:38 +0000 (17:06 +0900)]
Checkpoint replication slots later in the checkpoint cycle
Previously, CheckPointReplicationSlots() ran at the start of
CheckPointGuts(), while WAL cleanup occurred much later in
CreateCheckPoint() and CreateRestartPoint(), after the buffer write
and ProcessSyncRequests() phases. During a spread checkpoint, this gap
could be several minutes.
During that time, active replication slots could advance their
restart_lsn. However, replicationSlotMinLSN had already been
computed from the older saved values. As a result, KeepLogSeg() could
retain WAL segments that were no longer needed, causing unnecessary
pg_wal growth until the next checkpoint or restartpoint.
Fix this by moving CheckPointReplicationSlots(),
CheckPointSnapBuild(), and CheckPointLogicalRewriteHeap() to just
before CheckPointTwoPhase(), after the buffer write and
ProcessSyncRequests() phases. This makes WAL retention decisions use
the latest replication slot state. The logical snapshot and rewrite heap
cleanup decisions also benefit from the updated saved restart_lsn.
Author: Ants Aasma <ants@cybertec.at>
Author: Hüseyin Demir <huseyin.d3r@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CANwKhkPCBcTQ_pk06MD5W5YYNnuYHp8dLNuOUz8-5pMBMPY1Bw%40mail.gmail.com
Fujii Masao [Tue, 4 Aug 2026 08:03:27 +0000 (17:03 +0900)]
Fix error handling in getCopyDataMessage() and pqFunctionCall3()
Commit
f6f0542266f0 changed getNotify(),
getParameterStatus(), and related libpq message-processing paths to
abandon the connection on out-of-memory errors.
However, getCopyDataMessage() and pqFunctionCall3() did not handle
this new fatal-error state. Both can process asynchronous
NotificationResponse and ParameterStatus messages while waiting for
other responses. If one of those messages triggered a fatal error, these
loops continued processing instead of reporting it immediately.
Fix this by checking for a saved fatal error after processing an
asynchronous message. If the connection has been abandoned, return the
appropriate error immediately instead of continuing to parse input.
Backpatch to v18, where commit
f6f0542266f0 introduced this issue.
Author: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAO6_XqpGfm+XHE1OzS=_+jroeDOxhhGa11P3cbm9q2gT05yorA@mail.gmail.com
Backpatch-through: 18
Álvaro Herrera [Tue, 4 Aug 2026 07:06:46 +0000 (09:06 +0200)]
Fix ALTER COLUMN ... DROP EXPRESSION with subpartitions
Per commit
8bf6ec3ba3a4, a column can be GENERATED only if it is such in
the whole inheritance tree.
For this reason, ATPrepDropExpression refuses to be called with ONLY on
a partitioned table. To detect this, the current implementation checks
whether recurse is set to false and the rel has direct children.
Recursion is implemented with ATSimpleRecursion, which calls ATPrepCmd
with recurse = false for every node in the tree. Inner nodes (for
example a partition which itself has subpartitions) then fail the check,
accidentally preventing the command from working on inheritance trees of
depth > 2.
This commit fixes it by also checking that we're at the top level of the
recursive calls using the recursing parameter, which is always true when
called through ATSimpleRecursion, always false when invoked on the root
rel.
Also, remove a comment claiming that DROP EXPRESSION could be
implemented with some effort. It cannot, as the commit message for
8bf6ec3ba3a4 explains.
Author: Alberto Piai <alberto.piai@gmail.com>
Backpatch-through: 14
Discussion: https://postgr.es/m/DHMT78XOD8BK.341V3H87KZ7NO@gmail.com
David Rowley [Tue, 4 Aug 2026 05:59:13 +0000 (17:59 +1200)]
Fix missing money overflow checks for INT64_MIN / -1
Similar to what
1f7cb5c30 did for the INT types, protect against
overflow when dividing the lowest possible money value by -1. This
cannot be represented on a two's complement machine.
Without this check, the result depends on the machine, and in the worst
case, could result in a crash. With the fix installed, this will now
result in:
ERROR: money out of range
Bug: #19585
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reported-by: Michael Malis <malis@pgrust.com>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Rafia Sabih <rafia.pghackers@gmail.com>
Discussion: https://postgr.es/m/19586-
bb603bf5ad9934dd%40postgresql.org
Discussion: https://postgr.es/m/CAB8bMisnXJVXte6s3kUOpuuAY9%3D9kehG6MMX-%2BTQoFsSGan22Q%40mail.gmail.com
Backpatch-through: 14
David Rowley [Tue, 4 Aug 2026 04:06:38 +0000 (16:06 +1200)]
Fix missing MCXT_ALLOC_NO_OOM handling in MemoryContextAllocAligned
Fix missing NULL check in MemoryContextAllocAligned(). The underlying
call to MemoryContextAllocExtended() could return NULL when
flags contains MCXT_ALLOC_NO_OOM and the underlying malloc fails.
There are no current callers using MemoryContextAllocAligned() that pass
the MCXT_ALLOC_NO_OOM in core, so no live bug fix in core here. However,
an extension might use this pattern, so we'd better fix.
Fix this so we correctly pass the NULL to the caller rather than trying
to write to a NULL memory address.
This also fixes the same bug in AlignedAllocRealloc(), which is also
unused in core.
Backpatch to v16, where these functions first appeared.
Author: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/
07DAC4C3-120D-4F3C-8FEE-
BA236F7E9C1D@gmail.com
Backpatch-through: 16
Amit Kapila [Tue, 4 Aug 2026 03:28:32 +0000 (08:58 +0530)]
Validate publisher for retain_dead_tuples in the apply worker.
Enabling retain_dead_tuples requires the publisher to run PostgreSQL 19 or
later and to not be in recovery. Previously this was checked only at DDL
time. That forced ALTER SUBSCRIPTION ... ENABLE to connect to the
publisher, so pg_upgrade (which re-enables subscriptions during restore)
failed if the publisher was unreachable. It was also not authoritative,
since the publisher's version or recovery status can change afterwards,
for example after a failover.
Perform the check authoritatively in the apply worker when it connects,
and stop doing it when enabling a subscription. ENABLE is the only command
issued during restore that triggered it, so this also fixes the pg_upgrade
failure. The DDL-time check is kept as a convenience for the other paths,
none of which are issued during restore.
Reported-by: Noah Misch <noah@leadboat.com>
Analyzed-by: Jeff Davis <pgsql@j-davis.com>
Author: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Jeff Davis <pgsql@j-davis.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Backpatch-through: 19, where it was introduced
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch@microsoft.com
David Rowley [Tue, 4 Aug 2026 01:29:42 +0000 (13:29 +1200)]
Remove unused field from PartitionDescData struct
3592e0ff9 added caching logic to ExecFindPartition() to allow faster
partition lookups for LIST and RANGE partitions when we hit the same
partition multiple times in a row. The last_found_part_index field was
added, but it was never used, so remove it. Caching works by caching the
last matching index into the PartitionBoundInfo.datums, not by caching the
last found partition index.
Update comments to reflect this, and perform other general improvements to
the comments in this area.
Author: Aleksander Alekseev <aleksander@tigerdata.com>
Author: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/CAJ7c6TMRxO6vo1tNgLZs4nTNizpjCSWdUviB8Mf3nkYiNHNhzg@mail.gmail.com
Nathan Bossart [Mon, 3 Aug 2026 21:02:07 +0000 (16:02 -0500)]
Handle concurrently-dropped relations in database-wide VACUUM.
When VACUUM or ANALYZE is run without a table list, we scan
pg_class to build the list of relations to process, and we
check the privileges on each relation we find. Since we don't
take any locks on the relations at this point, it's possible
for one to be concurrently dropped, in which case the privilege
check fails with an ERROR such as the following:
ERROR: relation with OID 16388 does not exist
This unnecessarily aborts the entire command. To fix, use
pg_class_aclcheck_ext() for the privilege check so that we can
detect concurrently-dropped relations and silently skip them.
There's no need to emit a WARNING for such relations because
they weren't explicitly named, and a drop at this point is no
different than one that happened before our pg_class scan
began. Note that concurrent drops that occur later on are
already handled gracefully by vacuum_open_relation().
The new missing_ok behavior is limited to get_all_vacuum_rels().
All other callers of vacuum_is_permitted_for_relation() should
hold a lock on the relation that prevents it from being
concurrently dropped, so this commit also adds an assertion to
that effect.
Oversight in commit
a556549d7e.
This is a bug fix and could be back-patched, but given the
presumed rarity of the race condition and the lack of field
reports, I'm not going to bother.
Reported-by: ChangAo Chen <cca5507@qq.com>
Author: ChangAo Chen <
cca5507@qq.com>
Co-authored-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Reviewed-by: Surya Poondla <suryapoondla4@gmail.com>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/tencent_F9D483523BB0D082C2EFDA80142F192DBC07%40qq.com
Jeff Davis [Mon, 3 Aug 2026 20:41:17 +0000 (13:41 -0700)]
postgres_fdw: reject use_scram_passthrough for subscriptions.
The subscription is initiated from a logical replication worker, so
SCRAM pass-through won't work.
Partially addresses finding 3 in report from linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch@microsoft.com
Backpatch-through: 19
Jeff Davis [Mon, 3 Aug 2026 20:21:46 +0000 (13:21 -0700)]
Improve DROP SERVER handling of dependent subscriptions.
We do not allow a DROP SERVER ... CASCADE to implicitly drop a
subscription, because it's in a shared catalog and dropping a
subscription has side effects. Instead we throw an error and the user
must drop the subscription explicitly. Document this behavior and add
a HINT to the error message.
Generalize AcquireDeletionLock()/ReleaseDeletionLock() to use shared
object locks for all shared catalogs, which includes AuthMemRelationId
and now SubscriptionRelationId.
Move error message after AcquireDeletionLock() to avoid an unnecessary
error if there's a concurrent DROP SUBSCRIPTION.
Addresses finding 10 & 15 in report from linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch@microsoft.com
Backpatch-through: 19
Jeff Davis [Mon, 3 Aug 2026 19:21:05 +0000 (12:21 -0700)]
Fix lock release for role membership grants in DROP OWNED BY.
Commit
6566133c5f5 added a case for AuthMemRelationId in
AcquireDeletionLock(), but not ReleaseDeletionLock(). The fall-through
case would go to UnlockDatabaseObject(), which would raise a WARNING;
and the lock would be retained until the end of the transaction.
Add the missing branch.
Discussion: https://postgr.es/m/
2487ddcd737d4fc8e408e87aa9ad4365eed3bbb3.camel@j-davis.com
Backpatch-through: 16
Daniel Gustafsson [Mon, 3 Aug 2026 18:44:57 +0000 (20:44 +0200)]
Don't skip invalid databases when enabling data checksums
When enabling checksums cannot process a database, the launcher uses
DatabaseExists to tell a concurrent drop (benign) from a real failure.
Since
1df361e3d82 that check also treats a present, but-invalid, data-
base as non-existent. An interrupted DROP DATABASE flush the invalid
marker before the row and files are removed, so a crash or ERROR can
leave an invalid row whose files remain on disk.
Report a database as existing whenever its catalog row is found to
ensure that checksums cannot be enabled if there are invalid databases.
The AccessShareLock in DatabaseExists already waits out an in-flight
drop, so an invalid-but-present row can only be an interrupted drop
leftover whose files still need checksums; enabling then aborts until
it is dropped.
Backpatch to v19 where online checksums were introduced.
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAN4CZFOGdqxtZ5-6gb4apqmvoH=Z+TNH8RKJ3mVtoR1HirKQWg@mail.gmail.com
Backpatch-through: 19
Jeff Davis [Mon, 3 Aug 2026 18:34:58 +0000 (11:34 -0700)]
Do not log subscription conninfo.
Logging connection information, even at DEBUG1, creates unnecessary
risks. Remove the entire log message because it had no other useful
content.
Addresses finding 14 in report from linked discussion.
Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/
20260710195902.4f.noahmisch@microsoft.com
Backpatch-through: 14
Robert Haas [Mon, 3 Aug 2026 16:25:01 +0000 (12:25 -0400)]
Undo inadvertent loosening of archive filename checking.
Commit
c8a350a439826267186c187dbfbf1f839f7521aa attempted to consolidate
code for identify possibly-compressed tar archives by suffix into a new
function parse_tar_compress_algorithm(). Unfortunately, the refactoring
wasn't perfect, and slightly changed the behavior at both existing call
sites.
In CreateBackupStreamer(), the previous code required the filename to
consist of more than just a suffix, so the aforementioned commit had the
effect of allowing pg_basebackup to accept a file from the server whose
entire name was something like .tar.gz -- which should never happen, but
let's reject it as previous releases did.
In precheck_tar_backup_file(), the previous code required the suffix to
be immediately adjacent to the prefix already checked, so the commit
in question allowed pg_verifybackup to accept not only filenames like
base.tar.gz but also filenames like baseFOOBARBAZ.tar.gz. While such
filenames are perhaps unlikely, rejecting them is correct, so let's go
back to that behavior.
Discussion: http://postgr.es/m/CA+TgmoYJY8FkoeYKGF_YF1S6uOK7fd0Bd3zrw0XY_oZXbmVFpQ@mail.gmail.com
Reported-by: Sarath Kumar <Sarath@iitmpravartak.net>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Backpatch-through: 19
Álvaro Herrera [Mon, 3 Aug 2026 11:52:41 +0000 (13:52 +0200)]
Remove unused arg and dead code in set_attnotnull()
The is_valid parameter was never referenced in the function body, and
the 'thisatt' local variable is set but never used. Remove both.
Oversight in
a379061a22a8.
Author: Sami Imseih <samimseih@gmail.com>
Backpatch-through: 18
Discussion: https://postgr.es/m/CAA5RZ0tHnvSrfUy4jWJchjvkL_aJe0hCnZpMsFRdLrSxCne5qQ@mail.gmail.com
Michael Paquier [Mon, 3 Aug 2026 11:05:23 +0000 (20:05 +0900)]
Add dshash_get_dsa_area(), able to retrieve the DSA area of a dshash table
Code using GetNamedDSHash() to retrieve a dshash table may also want to
limit its size, but there is actually no easy way to do so because the
dsa_area of a hash table is hidden within dshash.c.
This commit adds dshash_get_dsa_area() to close the gap, which returns
the dsa_area for a given dshash_table. The DSA area retrieved can then
be passed to dsa_set_size_limit(), to limit its size. This accessor
routine also opens the door for allocating additional objects in the
same DSA area as a hash table, which may be useful for some.
Author: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/CAA5RZ0tKfCVqFnMZtavM42H63ha2Haf_C4mbJNWqkaW30cPW1w@mail.gmail.com
Fujii Masao [Mon, 3 Aug 2026 10:03:40 +0000 (19:03 +0900)]
doc: Clarify VERBOSE output for ANALYZE and VACUUM
ANALYZE VERBOSE and VACUUM VERBOSE both print per-table information
at INFO level, including the table currently being processed and
various statistics. However, the documentation described ANALYZE
VERBOSE only as displaying generic "progress messages", while VACUUM
VERBOSE used different wording about a vacuum activity report.
Reword the VERBOSE option descriptions and Outputs sections to describe
the actual output more consistently.
Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: Surya Poondla <suryapoondla4@gmail.com>
Reviewed-by: solai v <solai.cdac@gmail.com>
Reviewed-by: Maciek Sakrejda <m.sakrejda@gmail.com>
Reviewed-by: David G. Johnston <david.g.johnston@gmail.com>
Reviewed-by: Yushu Chen <gentcys@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAOzEurTpMTUEW8kHu-zKB0EBtuPfpvyoJ--8pxKe87p24BGrpg@mail.gmail.com
Peter Eisentraut [Mon, 3 Aug 2026 08:14:30 +0000 (10:14 +0200)]
Fix missing space before WHERE in GRAPH_TABLE deparse
get_graph_pattern_def() emitted the pattern-level WHERE keyword as
"WHERE " with no leading space, so reverse-parsing produced output
like "(o IS orders)WHERE (...)". The element-level WHERE deparse in
get_path_pattern_expr_def() already prepends a separating space; the
pattern-level branch was inconsistent with it. Emit " WHERE " to
match.
The output still re-parses to the same tree, so this is cosmetic.
For test coverage, add a whole-pattern WHERE clause to the existing
customers_us view, which is already reverse-parsed with
pg_get_viewdef().
Author: Dhruv Chauhan <chauhandhruv351@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CANWwWcpHb0h7tg6otRnL-FV83jwQpAiyw1bhvv8T78kpwZ-0ow%40mail.gmail.com
Richard Guo [Mon, 3 Aug 2026 06:51:59 +0000 (15:51 +0900)]
Fix nullability check for a sub-select's upper-level Vars
When checking whether a sub-select's output columns can produce NULL,
so as to decide whether a NOT IN can be converted to an anti-join,
query_outputs_are_not_nullable() falls back on find_nonnullable_vars()
for targetlist entries that are plain Vars: if the sub-select's own
quals prove the Var non-null, the output is non-nullable. But that
test compared only varno and varattno, without checking varlevelsup.
An outer reference in the targetlist could thus be matched against a
Var of the sub-select's own range table that happens to share the same
varno and varattno, wrongly proving the output non-nullable and
allowing an invalid conversion to an anti-join, which yields wrong
answers when the outer reference is NULL.
To fix, restrict the fallback to Vars of the current query level.
Author: Rui Zhao <zhaorui126@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/CAHWVJhGuaFFRpmq4j+mcMcm_HC5QOT7LZsC9bf9b7BCBmvbfMA@mail.gmail.com
Backpatch-through: 19
Tom Lane [Sun, 2 Aug 2026 20:49:17 +0000 (16:49 -0400)]
Tighten up TS dictionary cache entry creation.
In the not-too-likely scenario where we successfully created a hash
table entry for a TS dictionary, but then failed to make a small
memory context for it, we left the hash entry in existence but with
a garbage value for dictCtx. This confused the code the next time
through, leading to a crash. Rearrange things so that we leave
the hash entry in a well-defined state with dictCtx == NULL, and
then the next try knows it still needs to make a memory context.
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/
0f3ddeb5-0dbd-479c-9d0e-
ae254758e624@gmail.com
Backpatch-through: 14
Tom Lane [Sun, 2 Aug 2026 17:22:39 +0000 (13:22 -0400)]
Fix memory-safety bugs in the ispell/hunspell dictionary loader.
Allocate CompoundAffix with room for its terminator, initialize the
old-format flag buffer before NIAddAffix(), and reject incomplete or
missing Hunspell AF aliases. None of these errors would be likely to
trigger on real dictionary files, accounting for the lack of previous
reports; but they're certainly bugs.
Bug: #19595
Reported-by: Michael Malis <michaelmalis2@gmail.com>
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19595-
7dc18b4e212c4757@postgresql.org
Backpatch-through: 14
Tom Lane [Sun, 2 Aug 2026 15:26:30 +0000 (11:26 -0400)]
Update time zone data files to tzdata release 2026c.
Alberta (America/Edmonton) moved to permanent UTC-06 on
2026-06-18, which will affect their clocks beginning on 2026-11-01.
For lack of any clarity on the point, assume their TZ abbreviation
will be CST from that time forward.
Morocco (Africa/Casablanca) will move to permanent UTC+00,
without daylight saving time transitions, on 2026-09-20.
Backpatch-through: 14
Daniel Gustafsson [Sat, 1 Aug 2026 19:35:51 +0000 (21:35 +0200)]
Add a comment to distinguish backend types
The data checksums entries were seemingly auxiliary processes from
reading the code, but they are in fact background workers. Add a
comment to clarify. Backpatch down to v19 where online checksums
were introduced.
Author: Daniel Gustafsson <daniel@yesql.se>
Reported-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwFsBjQs2fv7b72hxzGV_fJMh6LAg4E83pNfDOu1jVgWCA@mail.gmail.com
Backpatch-through: 19
Daniel Gustafsson [Sat, 1 Aug 2026 19:35:19 +0000 (21:35 +0200)]
doc: Fix glossary entry for data checksums workers
The glossary entry for data checksums workers incorrectly stated that
they were auxiliary processes, but they are implemented as background
workers. Fix, and while there, simplify the entry by combining the
worker and launcher into a single glossary term. Backpatch down to
v19 where online checksums were introduced.
Author: Daniel Gustafsson <daniel@yesql.se>
Reported-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEv-C9ia+rBYyePzO8F=5FVvS412ZqcOupazuOb5RafNg@mail.gmail.com
Backpatch-through: 19
Michael Paquier [Sat, 1 Aug 2026 10:21:46 +0000 (19:21 +0900)]
pg_verifybackup: Improve some error handling around strtoul() calls
Three code paths checking the size, timeline ID and system identifier
stored in a manifest now check for an empty value. Values are always
expected in these parts of a backup banifest. A couple of tests are
added to validate this behavior
Additionally, precheck_tar_backup_file() checked that "endptr" is NULL.
Based on the C standard, strtoul() never sets an "endptr" to NULL when
given a value (that is the case here), returning a pointer to the
original value if there is nothing to convert. The pre-tar validation
code is adjusted to do so.
Author: Tristan Partin <tristan@partin.io>
Discussion: https://postgr.es/m/DKBS2Z9CGARC.2T07O6TJYSE8B@partin.io
Melanie Plageman [Fri, 31 Jul 2026 21:45:45 +0000 (17:45 -0400)]
Allow IO time to be counted without a matching IO operation in pg_stat_io
Since
999dec9ec6a816680, pg_stat_io can show read time with zero reads
for an IO Context: a foreign IO is counted as a read only in the
initiating backend, while other waiters record only the wait time. That
violates pgstat_bktype_io_stats_valid(). Relax the check to allow time
without a matching operation count, since we want to count read wait
time even in backends that did not initiate the read. This also enables
future accounting of waits on IO resources (e.g., AIO handles) in
backends that didn't start the IO.
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reported-by: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://postgr.es/m/ak5lccE4qiQpOBHn@pryzbyj2023
Backpatch-through: 19
Tom Lane [Fri, 31 Jul 2026 18:39:29 +0000 (14:39 -0400)]
On Windows, make link(2) report ENOTSUP when appropriate.
CreateHardLinkA reports ERROR_INVALID_FUNCTION if the target file
is on a filesystem that doesn't support hard links. _dosmaperr
maps that to EINVAL, which confuses zic.c into failure. zic.c is
expecting ENOTSUP if the filesystem lacks link support, and will
properly fall back to making a physical copy if it gets that.
Hence, add code to map ERROR_INVALID_FUNCTION to ENOTSUP.
(We could instead teach _dosmaperr to do that, but it's far from clear
that this would be appropriate as a global behavior: intuitively
it seems like EINVAL should be appropriate most of the time.)
We didn't need this before commit
aeb07c55f, because the tzcode
version we were using before that didn't have this particular
error-handling logic. Hence, no back-patch for now; but if we
decide to back-patch tzcode 2026b or later, we'll need this too.
Author: Vladlen Popolitov <v.popolitov@postgrespro.ru>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/
e6122f9b2eef9096f1f11ecc058bcd91@postgrespro.ru
Jacob Champion [Fri, 31 Jul 2026 18:08:23 +0000 (11:08 -0700)]
libpq-oauth: Avoid overflow for very large intervals
The slow_down interval parsing code checks explicitly for overflow, but
since it does that after the signed overflow has already occurred, we
end up inviting undefined behavior from the compiler anyway.
Use checked arithmetic instead. set_timer() takes a long int in order to
interface nicely with libcurl, so use an int32 as the interval counter
and clamp to LONG_MAX during conversion to milliseconds.
Backpatch to 18, where libpq-oauth was introduced.
Reported-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/qtclihmrkq67ach3xjxyi4qcksstin5qxwsnkqefkmotxwh4g6%40ae2bj6jvcmry
Backpatch-through: 18
Robert Haas [Fri, 31 Jul 2026 15:55:54 +0000 (11:55 -0400)]
Prevent walsummarizer from getting stuck at a timeline switch.
As previously coded, walsummarizer only wants to read WAL from a file
where the TimeLineID in the filename exactly matches the TimeLineID being
summarized. But in some cases, when a timeline switch occurs, the WAL file
from the old timeline is not archived, because it's never completely
filled, so the only way to obtain the contents of that last partial
segment is to read from the first segment on the new timeline. Teach
WAL summarizer to do that, and add a test case to make sure that it
works.
Reported-by: Nick Ivanov <nick.ivanov@enterprisedb.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Tested-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Thom Brown <thom@linux.com>
Discussion: http://postgr.es/m/CA+Tgmobr27GpKDZx3_ezW2+C5_g18i+jSK3sGF_cR-_ESv5N5A@mail.gmail.com
Backpatch-through: 17
Nathan Bossart [Fri, 31 Jul 2026 15:34:40 +0000 (10:34 -0500)]
Fix autovacuum's database sorting.
When db_comparator() was updated to use pg_cmp_s32(), the arguments
were listed in the wrong order. This caused autovacuum to sort the
databases by their scores in ascending order instead of descending
order. To fix, swap the arguments to pg_cmp_s32().
Oversight in commit
3b42bdb471.
Reported-by: Хамидуллин Рустам <r.khamidullin@postgrespro.ru>
Author: Хамидуллин Рустам <r.khamidullin@postgrespro.ru>
Discussion: https://postgr.es/m/
5c5a7984-b149-b505-7ad9-
2a7766c65b55%40postgrespro.ru
Backpatch-through: 17
Nathan Bossart [Fri, 31 Jul 2026 14:57:24 +0000 (09:57 -0500)]
Remove code for pre-v10 servers from AdjustUpgrade.pm.
We recently removed support for upgrading from pre-v10 servers, so
we no longer need to handle older versions in this helper module.
Oversight in commit
14d8418083.
Discussion: https://postgr.es/m/ak7Ekv2-L-G55-YD%40nathan
David Rowley [Fri, 31 Jul 2026 11:23:21 +0000 (23:23 +1200)]
Fix Hash Join performance issue when hashing NULL values
adf97c156 allowed expression evaluation to perform hashing, and
subsequently
9ca67658d fixed a memory stomping bug in that commit
that caused unrelated-to-hashing expression op steps to stomp on the
intermediate hash value. The intermediate hash value needs to be
maintained when hashing multiple hash keys.
9ca67658d didn't quite get
things right when in "strict" mode when it aborted hashing early after
encountering a NULL hash key. What was meant to happen was that the
expression returns NULL directly to indicate to the caller the value
hashed to NULL. The problem was that any EEOP_HASHDATUM_FIRST_STRICT or
EEOP_HASHDATUM_NEXT32_STRICT op step that didn't belong to the final
key to be hashed would have its op->resnull and op->resvalue pointing to
the location to store the intermediate hash value. That's correct for
non-NULLs since we bit-rotate the intermediate value and continue hashing,
but with the strict case, when we get a NULL key, we immediately jump to
the "jumpdone" step. The problem is the jumpdone step expects the
ExprState resnull and resvalue fields to be set (as they would be if we
didn't abort hashing early due to the NULL), but when we aborted early,
the ExprState fields never got set. This would result in inserting
records into the hash table that would never match to any join partner,
which is a waste of CPU and memory.
Here we fix this by having EEOP_HASHDATUM_FIRST_STRICT and
EEOP_HASHDATUM_NEXT32_STRICT populate the ExprState resnull and resvalue
fields directly when the value to hash is NULL.
Although Hash Agg and Hashed Subplans do use hashing from ExprStates,
those were unaffected by this bug, as neither of those uses the STRICT op
steps.
Thanks to Tomas Vondra for finding the offending commit.
Reported-by: Dan Stefura <dstefura@bluecatnetworks.com>
Author: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/YQBPR0101MB89738FB972FBD02A3640C6D3D6C92@YQBPR0101MB8973.CANPRD01.PROD.OUTLOOK.COM
Backpatch-through: 18
Amit Kapila [Fri, 31 Jul 2026 04:28:46 +0000 (09:58 +0530)]
Improve wording of sequence origin warning in logical replication.
check_publications_origin_sequences() warns when a subscription with
origin = NONE synchronizes sequence values that may have originated from
another subscription. The existing warning is phrased in terms of
copy_data and copying data, which is appropriate for table synchronization
but misleading for sequence synchronization.
Reword the warning, detail, and hint to describe sequence synchronization
and the associated origin = NONE semantics more accurately.
Also fix a typo ("rathen" -> "rather") in a comment in sequencesync.c.
Reported-by: Noah Misch <noah@leadboat.com>
Reported-by: Peter Smith <smithpb2250@gmail.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19, where it was introduced
Discussion: https://postgr.es/m/
20260710045217.f0.noahmisch@microsoft.com
Michael Paquier [Fri, 31 Jul 2026 03:44:51 +0000 (12:44 +0900)]
Fix error handling in port's getopt_long() for missing argument
In the long option error path, the code previously returned BADARG
immediately when optstring[0] == ':' for a missing required argument,
without advancing "optind" or resetting "place". This error handling
was inconsistent with the short option path, where both updates are
performed before returning BADARG (and inconsistent with libc,
additionally..).
This affects platforms where our port version of getopt_long() is used,
a concept that should be limited to WIN32 these days. An argument could
be made in favor of a backpatch, but this could lead to a slight
different error handling, for a report that would only show up when
using incorrect option combinations.
Author: Japin Li <japinli@hotmail.com>
Discussion: https://postgr.es/m/SY7PR01MB10921AF81F18A8BCFA06388BEB6C22@SY7PR01MB10921.ausprd01.prod.outlook.com
David Rowley [Fri, 31 Jul 2026 03:36:31 +0000 (15:36 +1200)]
Fix issue with RANGE's DEFAULT partition pruning
Partition pruning for RANGE-partitioned tables could mistakenly prune
the DEFAULT partition in some cases when it was not valid to do so,
which could lead to rows missing from query results.
The only known cases where this could happen is when combining pruning
steps from an IS NOT NULL clause with other steps that matched to the
DEFAULT partition. This could occur due to RANGE partitioned tables
having two distinct internal representations for marking if the DEFAULT
partition should be scanned. The IS NOT NULL steps would mark the
"scan_default" boolean, but other steps created for different purposes
could mark a bound_offset Bitmapset, which would ultimately translate into
also scanning the default partition. This could all fail after multiple
steps were combined with a combine intersect operator, as that will
intersect the bound_offset bits and only set scan_default if all pruning
steps have that flag set. When both input steps to the intersect operator
had different representations of whether to scan the DEFAULT partition,
the resulting intersect step result would contain neither representation.
Here, we fix this by having the IS NOT NULL pruning result mark the
bound_offsets so that it uses both representations to mark that the
DEFAULT partition must be scanned.
Reported-by: Jacob Brazeal <jacob.brazeal@gmail.com>
Diagnosed-by: Jacob Brazeal <jacob.brazeal@gmail.com>
Author: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/CA+COZaDXrfTaBjLE=Z79MTaH6Xun1V4PeKxLvCNv8mXS8wn0rw@mail.gmail.com
Backpatch-through: 14
Michael Paquier [Fri, 31 Jul 2026 02:48:18 +0000 (11:48 +0900)]
Use [re]palloc_array() in buffile.c and fd.c
The code paths patched in this commit fix some of remnants not addressed
by
1b105f9472bd. We should have more holes in the tree that could
benefit from stronger type safety guarantees. These hypothetical holes
could be addressed later; this finishes the job in storage/file/ for the
backend code.
Author: Tristan Partin <tristan@partin.io>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/DKBAWPZ2QDOS.10Y3JDUNKFMXX@partin.io
David Rowley [Fri, 31 Jul 2026 01:15:52 +0000 (13:15 +1200)]
Fix incorrect Result node flattening logic
This fixes some incorrect flattening of nested Result nodes during
create_plan that was introduced by
f2bae51df. That commit failed to
maintain the logic that checks for subplans and gating quals from the
nested Result node before flattening, and that could result in the nested
gating qual and subplan being lost, which could produce incorrect results.
Bug: #19579
Reported-by: Viktor Leis <leis@in.tum.de>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/19579-
e6296b6c9fc0591c@postgresql.org
Backpatch-through: 19
Masahiko Sawada [Thu, 30 Jul 2026 23:17:10 +0000 (16:17 -0700)]
Fix background psql session cleanup in 051_effective_wal_level.pl.
Commit
6aba42c660c added quit() calls for two background psql sessions
whose slot creation is canceled by pg_cancel_backend(). Both sessions
ran with the default ON_ERROR_STOP=1 and ended their script with \q,
so psql exited as soon as the cancellation error arrived. quit() then
wrote another \q to the already-closed pipe, making the test die with
"ack Broken pipe".
Run both sessions with on_error_stop => 0 and drop the trailing \q, so
that psql stays at the prompt after reporting the error and quit() can
shut it down cleanly.
Discussion: https://postgr.es/m/CAD21AoCZY1fKYgfkvHGWGiXpatUKd23FSLnDCL4m9bWFjdXNZw@mail.gmail.com
Backpatch-through: 19
Masahiko Sawada [Thu, 30 Jul 2026 19:47:06 +0000 (12:47 -0700)]
Fix races between deactivation of logical decoding and slot creation.
On standbys, logical decoding can be deactivated while a logical slot
is being created: either by replaying an
XLOG_LOGICAL_DECODING_STATUS_CHANGE record, or by the end-of-recovery
transition upon promotion, which deactivates logical decoding if no
valid logical slot exists. Both could interleave with a check of the
logical decoding status performed before creating a new slot because
the slot invalidation executed as part of the deactivation cannot find
a slot being created.
For regular slot creation on standbys, EnsureLogicalDecodingEnabled()
assumed that logical decoding must still be enabled during recovery
since the caller had already checked it, tripping an assertion failure
if a concurrent deactivation interleaved.
For slot synchronization, the local slot could be created and
persisted based on the remote slot information fetched before the
deactivation was replayed, leaving a valid slot whose restart_lsn
precedes the deactivation.
Fix both paths by re-checking the logical decoding status after the
new slot has been created: regular slot creation raises an error, and
slot synchronization skips persisting the slot. If the deactivation
happens after the re-check instead, it is guaranteed to invalidate the
newly created slot.
Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CAD21AoDEB99VtNbQdDrNd=1gQupJNGMfW_5kdnxq03Q82EK3ag@mail.gmail.com
Backpatch-through: 19
Tomas Vondra [Thu, 30 Jul 2026 13:30:19 +0000 (15:30 +0200)]
Reject non-finite reltuples when restoring stats
When restoring relation stats, pg_restore_relation_stats() rejected
calls with (reltuples < -1.0). But that is insufficient - Infinity and
NaN values both pass that check, and get stored in pg_class verbatim.
This can have various undesirable consequences.
Fixed by rejecting non-finite reltuple values, in the same non-fatal way
as for the existing checks (emit WARNING and skip the update). Adds a
regression test to stats_import for these non-finite values, and to
check the -1.0 special value is still accepted.
Backpatch to 18, where pg_restore_relation_stats() was introduced.
Patch by Jan Nidzwetzki, minor commit message tweaks by me.
Author: Jan Nidzwetzki <jan@planetscale.com>
Discussion: https://postgr.es/m/
518BA772-8026-412A-AA8F-
A7FE4C6B3717@planetscale.com
Backpatch-through: 18
Tomas Vondra [Thu, 30 Jul 2026 12:06:20 +0000 (14:06 +0200)]
Initialize bs_reltuples in parallel GIN builds
Index builds update pg_class.reltuples for the table. In parallel GIN
builds, workers track the number of processed rows, and report it to
the leader, who then updates the pg_class with a total. However,
gin_parallel_build_main failed to initialize the bs_reltuples field,
leaving it set to whatever happens to be on the stack (which may be
bogus values like Infinity or NaN, or just impossibly high values).
If such values get reported to the leader and stored in pg_class, that
can have serious consequences. The pg_class.reltuples field is used to
decide when a table is due for autovacuum or autoanalyze, and if it
happens to be set to a bogus value, that may never happen. The field is
also used by the optimizer when calculating costs.
Fixed by initializing bs_reltuples together with the rest of the build
state. The bs_numtuples was initialized later, but it seems cleaner to
just initialize all the fields at once.
After a bogus value gets persisted in pg_class, affected systems are
unlikely to self-heal. That would require an ANALYZE, but preventing
that is one of the consequences. We have considered forcing autoanalyze
in these cases, but there's not a good way to reliably identify bogus
values (except for a small minority like Infitiny/NaN).
A manual ANALYZE on (possibly) affected tables is the only solution.
Backpatch to 18, where parallel GIN builds were introduced.
Reported-by: Jan Nidzwetzki <jan@planetscale.com>
Discussion: https://postgr.es/m/
518BA772-8026-412A-AA8F-
A7FE4C6B3717@planetscale.com
Backpatch-through: 18
Daniel Gustafsson [Thu, 30 Jul 2026 10:41:40 +0000 (12:41 +0200)]
Make sure to detach injection points for re-attaching
The new test for enabling data checksums with concurrent CREATE
DATABASE calls use the same injection points as a previous test
but accidentally missed detaching the injection point first.
Fix by detaching the injection point in the PG_TEST_EXTRA SKIP
block to make it can be reused. Pointed out by buildfarm member
porpoise which failed with:
die: error running SQL: 'psql:<stdin>:1:
ERROR: injection point "datachecksumsworker-fake-temptable-wait"
already defined'
Backpatch to v19 where online checksums were introduced.
Author: Daniel Gustafsson <daniel@yesql.se>
Reported-by: Buildfarm member porpoise
Reviewed-by: Jonathan Gonzalez V. <jonathan.abdiel@gmail.com>
Discussion: https://postgr.es/m/
28CF6FD9-E1C4-4C04-8270-
E3305AC46171@yesql.se
Backpatch-through: 19
Daniel Gustafsson [Thu, 30 Jul 2026 07:21:31 +0000 (09:21 +0200)]
Add a couple of commits to .git-blame-ignore-revs
Amit Kapila [Thu, 30 Jul 2026 06:23:06 +0000 (11:53 +0530)]
Skip SUBSCRIPTION TABLE TOC entries with --no-subscriptions.
pg_dump in --binary-upgrade mode emits "SUBSCRIPTION TABLE" TOC entries to
preserve pg_subscription_rel state across pg_upgrade. When such a dump
was restored with --no-subscriptions, _tocEntryRequired() skipped the
"SUBSCRIPTION" entry but not the associated "SUBSCRIPTION TABLE" entries,
so the restore would try to apply subscription-relation state for a
subscription that was never created.
Skip "SUBSCRIPTION TABLE" entries as well when no_subscriptions is set.
This can happen when pg_subscription_rel has entries, the dump is taken
with --binary-upgrade, and it is restored with --no-subscriptions.
Reported-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Author: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 17, where it was introduced
Discussion: https://postgr.es/m/OS9PR01MB121493DA4C1A7748B11A646D8F5C02@OS9PR01MB12149.jpnprd01.prod.outlook.com
Tom Lane [Thu, 30 Jul 2026 00:25:54 +0000 (20:25 -0400)]
Fix SystemTap dtrace warning about smgr probe argument types.
Commits
ca326e903 and
1f8c504e3 widened the byte-count arguments of
smgr__md__read__done and smgr__md__write__done to "long long int".
SystemTap's dtrace(1) fails on that specific spelling and falls back
with a warning (misreported near the previous probe). Use ssize_t
and size_t instead, matching the md.c call sites.
Revise probes.d's note about which types are usable as probe
arguments: recommend using system-supplied type names (macOS dtrace
rejects names like PostgreSQL's uint64), and call out "long long int"
as a known SystemTap failure case rather than a wider failure mode.
Also, update the monitoring.sgml entries for these probes,
which were missed by the prior commits.
Reported-by: Laurenz Albe <laurenz.albe@cybertec.at>
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/
697d3c88568442cd637d8453d129f1bb14bbd2a8.camel@cybertec.at
Daniel Gustafsson [Wed, 29 Jul 2026 20:02:57 +0000 (22:02 +0200)]
pgindent fix for
a84eca6627f
Daniel Gustafsson [Wed, 29 Jul 2026 19:14:31 +0000 (21:14 +0200)]
ssl: Use the correct feature macros for TLS protocol support
Our test for if the underlying TLS library supported a specific
version tested against the TLSX_Y_VERSION set of macros. These
are however always defined, regardless of if the library was
built without support for the specific protocol version. Fix
by using the feature test macros OPENSSL_NO_TLSX_Y which are
intended for this usecase.
The previous coding held no risk of protocol downgrade against
the underlying library, a library not supporting the protocol
version selected would simply error out as the feature isn't
available. This can be easily verified using a modern version
of LibreSSL, which in version 3.8 disabled TLS1 and 1.1 by
default. Once we bump our minimum supported version of LibreSSL
to 3.8+ we can add a test for this.
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Reviewed-by: Yilin Zhang <jiezhilove@126.com>
Discussion: https://postgr.es/m/
68B9881D-DAA8-467D-A251-
C96E98E57BA0@yesql.se
Daniel Gustafsson [Wed, 29 Jul 2026 19:14:18 +0000 (21:14 +0200)]
ssl: Replace deprecated API to get commonName
X509_NAME_get_text_by_NID was deprecated in OpenSSL 4.0.0, and could
be removed in a future version of OpenSSL. The replacement APIs are
available in all versions of OpenSSL and LibreSSL that we support so
we can easily change to make the code future proof.
The reason for the deprecation is that X509_NAME_get_text_by_NID can
only grab the first entry in a list, and doesn't handle multibyte
strings well. The fix is to get the index of the name entry with
X509_NAME_get_index_by_NID and use X509_NAME_get_entry to extract
the data.
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Reviewed-by: Yilin Zhang <jiezhilove@126.com>
Discussion: https://postgr.es/m/
68B9881D-DAA8-467D-A251-
C96E98E57BA0@yesql.se
Daniel Gustafsson [Wed, 29 Jul 2026 19:14:08 +0000 (21:14 +0200)]
ssl: Use TLS_method instead of deprecated SSLv23_method
The SSLv23_method() function has been an alias for TLS_method since
2015 (OpenSSL commit
32ec41539b5b) so we should use the appropriate
name to avoid confusion.
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Reviewed-by: Yilin Zhang <jiezhilove@126.com>
Discussion: https://postgr.es/m/
68B9881D-DAA8-467D-A251-
C96E98E57BA0@yesql.se
Daniel Gustafsson [Wed, 29 Jul 2026 19:13:25 +0000 (21:13 +0200)]
ssl: Remove static var tracking tls_init_hook warnings
If the TLS init hook is defined in conjunction with ssl_sni we
issue a warning to help the user re-configure the cluster. To
avoid drowning the log in warnings, we log only once instead of
once per host. This removes the static variable tracking the
warning to aid future multithreading efforts.
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Reviewed-by: Yilin Zhang <jiezhilove@126.com>
Discussion: https://postgr.es/m/
68B9881D-DAA8-467D-A251-
C96E98E57BA0@yesql.se
Bruce Momjian [Wed, 29 Jul 2026 18:20:35 +0000 (14:20 -0400)]
doc: remove added space within synopsis replaceable tags
Restructuring the tags makes the output consistent and doesn't require
added spaces.
Reported-by: Peter Smith
Author: Peter Smith
Discussion: https://postgr.es/m/CAHut+Pu8JahGm76CMdpzH350pHJedA4R2b8JmOim3+m3yxft3Q@mail.gmail.com
Backpatch-through: 19
Masahiko Sawada [Wed, 29 Jul 2026 16:52:07 +0000 (09:52 -0700)]
Fix stale comment in parallel_vacuum_main().
The comment claimed that a parallel vacuum worker has only the
PROC_IN_VACUUM flag because parallel vacuum is not supported for
autovacuum, but commit
1ff3180ca01 allowed autovacuum to use parallel
vacuum workers.
The assertion itself still holds: the leader, whether a backend
running VACUUM or an autovacuum worker, sets PROC_IN_VACUUM before
taking its snapshot, and a parallel worker inherits the flag when
importing the leader's snapshot. The leader's other flags don't reach
the worker, since the snapshot import copies only the PROC_XMIN_FLAGS
bits and PROC_IS_AUTOVACUUM is never set on parallel workers, which
run as regular background workers. Reword the comment to explain that.
Oversight in commit
1ff3180ca01.
Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CALj2ACVwQ4WABqq8Lnf+VZEJ45jcTFhyFLFr_ctfS4=QLL-r5w@mail.gmail.com
Backpatch-through: 19
Peter Geoghegan [Wed, 29 Jul 2026 15:17:32 +0000 (11:17 -0400)]
Fix autovacuum-induced flakiness in backwards scan test.
Two of the permutations in backwards-scan-concurrent-splits rely on
their VACUUM step deleting the leaf pages that the waiting backwards
scan will have to recover from. VACUUM can only do that when it's able
to remove the index tuples whose heap tuples the concurrent session just
deleted. An autovacuum worker holding a snapshot holds back the
removable cutoff, which leaves the pages non-empty, and so undeleted,
causing the test to fail spuriously.
To fix, wait for the removable cutoff to advance past the deletions
before the scan acquires its snapshot. This is much like commit
1c64d2fc, which dealt with the same hazard in nbtree_half_dead_pages by
adding the wait_prunable() helper that we reuse here.
Oversight in commit
e395fbd3.
Author: Peter Geoghegan <pg@bowt.ie>
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Discussion: https://postgr.es/m/
b61d9944-d7a3-45f3-b69a-
f18c8bfbbbd0@gmail.com
Álvaro Herrera [Wed, 29 Jul 2026 15:15:45 +0000 (17:15 +0200)]
Fix cascading standby reconnect failure after archive fallback
A cascading standby could fail to reconnect to its upstream standby with
"requested starting point ... is ahead of the WAL flush position" after
falling back to archive recovery. This happened because archive
recovery processes whole segment files, so after replaying a segment the
cascade's next read position lands at the start of the following
segment, which is ahead of the upstream's flush position reported by
GetStandbyFlushRecPtr() (still inside the just-replayed segment).
Fix by having the walreceiver check the upstream's current WAL flush
position via IDENTIFY_SYSTEM before issuing START_REPLICATION.
IDENTIFY_SYSTEM already returns this position (as xlogpos), but
walrcv_identify_system() previously discarded it; now we have a use for
it. If the requested start point exceeds the upstream's flush position
on the same timeline, the walreceiver waits for
wal_retrieve_retry_interval and retries.
The wait is limited to gaps of at most one WAL segment, which is the
expected case from the segment-granularity of archive recovery. Larger
gaps indicate the upstream is genuinely behind, so START_REPLICATION is
allowed to proceed (and fail) normally, letting the startup process fall
back to other WAL sources. The first wait is logged at LOG level;
subsequent waits are demoted to DEBUG1 to avoid log noise. The
walreceiver honors wal_receiver_timeout during the wait, so it will exit
if the upstream doesn't catch up in time.
To preserve ABI compatibility on back branches, the flush position from
IDENTIFY_SYSTEM is communicated via a new global variable
(WalRcvIdentifySystemLsn) rather than changing the signature of
walrcv_identify_system().
The bug was introduced in Postgres 9.3 by commit
abfd192b1b5b, which
added a flush-position check in StartReplication() that rejects requests
ahead of the upstream server's WAL flush position.
Author: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Backpatch-through: 14
Discussion: https://postgr.es/m/CA+nrD2cTuTkkX5WXVZengTYYZbAO6zV8K+Tri-R0fbLFuoyMBA@mail.gmail.com
Daniel Gustafsson [Wed, 29 Jul 2026 10:37:02 +0000 (12:37 +0200)]
doc: Add getdatabaseencoding to function docs
The getdatabaseencoding function was added in
bf00bbb0c494 in 1998 but
was never documented. While mostly used in tests, there is no reason
not to document it as this function isn't going anywhere and is already
used in extensions.
Author: Ian Barwick <barwick@gmail.com>
Reviewed-by: Thom Brown <thom@linux.com>
Reviewed-by: surya poondla <suryapoondla4@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAB8KJ=ij+pznQGub=DkyJuKL=tC=Q=07qSahTyw7TLb0DdNJsg@mail.gmail.com
Michael Paquier [Wed, 29 Jul 2026 08:39:37 +0000 (17:39 +0900)]
Protect PGPROC lookup when terminating background workers
TerminateBackgroundWorkersForDatabase() uses BackendPidGetProc() and,
until now, accessed fields of the returned PGPROC after releasing
ProcArrayLock, including its database OID. If the PGPROC slot is
recycled during this window, the database OID being checked may belong
to a different backend, causing an unrelated background worker to be
terminated.
Triggering this bug requires a very narrow race: the background worker
identified by BackendPidGetProc() must exit, its PGPROC slot must be
released and reused, and only then must
TerminateBackgroundWorkersForDatabase() examine the database OID.
TerminateBackgroundWorkersForDatabase() holds BackgroundWorkerLock,
preventing parallel workers and dynamically registered workers (such as
those created by worker_spi) from reusing the slot. As far as I know,
the only plausible scenario is a static background worker that exits and
is restarted quickly enough to reuse the same PGPROC slot within the
race window. In practice, this race is extremely unlikely, still
reachable in theory.
Oversight in
f1e251be80a0.
Author: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Aya Iwata <iwata.aya@fujitsu.com>
Reviewed-by: Haibo Yan <tristan.yim@gmail.com>
Discussion: https://postgr.es/m/
78E81763-EA1D-4788-9741-
4092BCB997A5@gmail.com
Backpatch-through: 19
Amit Kapila [Wed, 29 Jul 2026 04:16:53 +0000 (09:46 +0530)]
Avoid accumulating relation locks during sequence synchronization.
While collecting the sequences to synchronize, the sequence sync worker
opened each INIT sequence with RowExclusiveLock and held it until the
transaction committed. With many such sequences, this could exhaust the
shared lock table and fail with "out of shared memory".
The worker only reads each sequence's identity (namespace and name) here
and needs it to stay stable while read, for which AccessShareLock is
enough, as it conflicts with the AccessExclusiveLock taken by DROP,
RENAME, and SET SCHEMA. Take that lock instead and release it as soon as
the identity is read. The later synchronization re-opens each sequence, so
it does not rely on the lock being retained.
Reported-by: Noah Misch <noah@leadboat.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19, where it was introduced
Discussion: https://postgr.es/m/
20260710045217.f0.noahmisch@microsoft.com
Michael Paquier [Tue, 28 Jul 2026 23:54:11 +0000 (08:54 +0900)]
Use more strlcpy() in two-phase transaction code
This commit replaces two calls of strcpy() and one call of strncpy() to
use strlcpy(), which are patterns that static analyzers (mostly LLMs, it
seems) have been complaining regarding buffer overflow risks.
The existing calls are safe, here are more details for each one of them:
- MarkAsPreparingGuts()'s strcpy() was guarded by MarkAsPreparing().
- PrepareRedoAdd()'s strcpy() is safe because the record-level CRC check
prevents corrupted data from reaching it unless intentionally
crafted. The replay code also assumes that the GID is within the allowed
bounds, as WAL records are trusted.
- Similarly, ParsePrepareRecord() stores its GID in a buffer bounded by
GIDSIZE while trusting the length provided by the record.
As a result, these changes are purely cosmetic. They adopt a more
defensive coding style and should also silence some of the static
analysis reports received recently.
Author: Matt Suiche <matt@tolmo.com>
Discussion: https://postgr.es/m/CAGf6Lfx2kbQfcEnCi99V2i65JSWD6ij_E29F+UkY=TyMUyeG6A@mail.gmail.com
Tom Lane [Tue, 28 Jul 2026 20:08:46 +0000 (16:08 -0400)]
Fix planner's nullability/strictness logic for ScalarArrayOpExpr.
find_nonnullable_rels and find_nonnullable_vars mistakenly treated a
ScalarArrayOpExpr that could return FALSE as strict, but that's okay
only at top level of a qual expression; further down, we've got to
insist on a guaranteed-NULL result. The result was that we could draw
mistaken conclusions about whether outer joins can be simplified, if
the decision hinged on a non-top-level ScalarArrayOpExpr with a
potentially-empty array argument.
I believe this error dates to commit
72a070a36, which taught
find_nonnullable_rels to descend into non-top-level parts of qual
expressions. is_strict_saop (added earlier by
72153c058) already had
enough intelligence to do the case correctly, but it wasn't passed the
proper flag, ie "top_level" needs to be passed for "falseOK".
e006a24ad copied that mistake into find_nonnullable_vars.
Later, over-eager refactoring in commit
2f153ddfd broke
contain_nonstrict_functions' handling of ScalarArrayOpExpr by treating
it as though it were no different from an OpExpr. It is, because
we must also prove the array is non-empty before concluding that the
expression is strict. This could result in misclassifying an
expression as strict when it is not, leading to assorted planning
mistakes such as inlining a SQL function that shouldn't be inlined.
We can almost fix this by just re-adding the previous handling of
ScalarArrayOpExpr in that function, but doing only that would lead to
also calling check_functions_in_node() and thus redundantly checking
the operator's strictness. Avoid that by turning the if-series into
an else-if chain, as it arguably should have been all along.
The reason these errors have escaped detection for decades is that
they are exposed only in arcane corner cases. ScalarArrayOpExpr with
an empty array isn't typical usage, and even when that's possible
several other conditions apply before the planner can reach a mistaken
conclusion. While it's possible to build test cases demonstrating
these mistakes, I (tgl) judged them too indirect and special-purpose
to justify consuming regression test cycles forevermore.
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAJTYsWV3vqRJmST-gv1NsXEef-zOnjVJpYS910aBaiuMij4nFg@mail.gmail.com
Discussion: https://postgr.es/m/CAJTYsWWcLGmz0f8_QPP_Liq-fc7-geiFSCdqoq3XGeRHPPsWeA@mail.gmail.com
Backpatch-through: 14
Daniel Gustafsson [Tue, 28 Jul 2026 19:52:27 +0000 (21:52 +0200)]
Handle invalid and dropped databases during checksum enable
Enable errors out early with a hint when an invalid database exists,
since the worker cannot connect to it and its files stay on disk.
A worker that started but failed gets the same dropped-database
heuristic as one that failed to start, so a concurrent drop during
processing no longer aborts the whole run. The existence check locks
the database first, otherwise a DROP DATABASE ... WITH (FORCE) which
killed the worker is still only halfway done and the database looks
like it is there to stay.
Backpatch to v19 where online checksums were introduced.
Author: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAN4CZFOGdqxtZ5-6gb4apqmvoH=Z+TNH8RKJ3mVtoR1HirKQWg@mail.gmail.com
Backpatch-through: 19
Daniel Gustafsson [Tue, 28 Jul 2026 19:52:24 +0000 (21:52 +0200)]
Recheck checksum state before file_copy during CREATE DATABASE
The file_copy strategy check in createdb() runs during option
validation, before the transaction has an XID and before the
pg_database row exists, so the datachecksumsworker launcher
can start in that window and see neither the new database nor
the transaction creating it. It then raw-copies a template
that was not processed yet, and those files stay unchecksummed,
failing verification from then on.
Recheck the state in CreateDatabaseUsingFileCopy(): the XID is
assigned by then, so a launcher starting after this point waits
for the transaction and finds the new database, and the copy
errors out instead. Add an injection point before the catalog
insert to test the window.
Backpatch to v19 where online checksums were introduced.
Author: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAN4CZFPEBsz8JeY4ixQ1V4ZL_xOY6pJaZS8ZLGH7R+wF--pEtg@mail.gmail.com
Backpatch-through: 19
Masahiko Sawada [Tue, 28 Jul 2026 19:33:28 +0000 (12:33 -0700)]
Fix logical decoding of empty prepared transactions.
A two-phase transaction that is assigned an XID but produces no change
to be decoded -- for example, one that only acquires row locks via
SELECT ... FOR SHARE -- has no base snapshot in the reorder
buffer. ReorderBufferReplay() already skips such a transaction at
PREPARE time and never invokes the begin_prepare/change/prepare
callbacks for it, but ReorderBufferFinishPrepared() still called the
commit_prepared (or rollback_prepared) callback. As a result a
spurious COMMIT/ROLLBACK PREPARED was sent to the output plugin with
no preceding PREPARE. For the built-in subscriber this breaks
replication (the apply worker fails to find the prepared transaction),
and test_decoding could even crash.
Fix this by detecting an empty transaction (base_snapshot == NULL) in
ReorderBufferFinishPrepared() and cleaning it up without invoking the
commit/rollback prepared callbacks, mirroring the existing empty
transaction handling in ReorderBufferReplay().
On v18 and newer versions, commit
072ee847ad4 changed
ReorderBufferPrepare() to send the prepare whenever it had not already
been sent, which also fires for empty transactions and emits a
spurious PREPARE. On those branches ReorderBufferPrepare() is
therefore additionally guarded with base_snapshot != NULL. This guard
and the Assert(!rbtxn_sent_prepare()) added in
ReorderBufferFinishPrepared(), are not necessary on v17 and older
versions: there ReorderBufferPrepare() only sends a prepare for
concurrently-aborted transactions (which never applies to an empty
transaction) and the RBTXN_SENT_PREPARE flag does not exist.
Back-patch to v14, where decoding of two-phase transactions was
introduced.
Bug: #19556
Reported-by: Alexander Kozhemyakin <a.kozhemyakin@postgrespro.ru>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/19556-
daa6d7ea65054d48@postgresql.org
Backpatch-through: 14
Masahiko Sawada [Tue, 28 Jul 2026 17:39:36 +0000 (10:39 -0700)]
Fix pg_get_publication_tables() failure with concurrent DROP TABLE.
pg_get_publication_tables() collects the OIDs of the published tables
on its first call, without locking them, and then reopens each table
later, once per result row, to compute its column list and fetch its
row filter. The reopen used table_open(), which errors out with "could
not open relation with OID" if the table has been dropped in the
meantime. This could happen for any published table without an
explicit column list, which is every table in FOR ALL TABLES and FOR
TABLES IN SCHEMA publications, but also FOR TABLE entries without a
column list. The failure is common in environments where many tables
are created and dropped while publication tables are being queried,
e.g. by table synchronization on a subscriber.
Fix by opening every table with try_table_open(), which returns NULL
if the relation no longer exists, and skipping the table in that
case. Concurrently dropped tables are thus simply absent from the
result set, which is the expected point-in-time behavior.
As a side effect, tables with an explicit column list, which were
previously returned without being opened, are now also locked with
AccessShareLock, so the function can block behind concurrent DDL on
such tables where it previously did not.
Backpatch to v16, where we added the table_open() call in
pg_get_publication_tables().
Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: shveta malik <shveta.malik@gmail.com>
Reviewed-by: Ajin Cherian <itsajin@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://www.postgresql.org/message-id/CALj2ACVYYooWH-5tJ6cPKkU%2BmutVxwb_z4S%2BqAi-zdrFqxXE2Q%40mail.gmail.com
Backpatch-through: 16
Alexander Korotkov [Tue, 28 Jul 2026 08:50:13 +0000 (10:50 +0200)]
Restore vacuum_delay_point() in GIN posting-tree leaf vacuum
Commit
fd83c83d094 turned the recursive posting-tree cleanup in
ginVacuumPostingTreeLeaves() into an iterative sweep that follows the
tree's leaf pages via their rightlinks. The recursive version called
vacuum_delay_point() while processing the tree, but that call was removed
and never re-added to the new loop. As that commit only set out to fix a
deadlock, the removal appears to have been unintentional.
Consequently the leaf-page sweep of a single posting tree runs with no
vacuum_delay_point(), and therefore no CHECK_FOR_INTERRUPTS(). A posting
tree stores all the TIDs for one indexed key, so for a frequently
occurring key it can span a large number of leaf pages. While such a
tree is being vacuumed the operation ignores vacuum_cost_delay and does
not respond to query cancellation or statement_timeout; an autovacuum
worker likewise cannot be interrupted mid-sweep when another backend
requests a conflicting lock.
Restore the call, placed after the current page has been unlocked and
released so that no buffer content lock is held across a potential delay
(cf.
21c27af65fb). The sibling loops in ginbulkdelete() and
ginvacuumcleanup() already call vacuum_delay_point() once per page.
Author: Paul Kim <mok03127@gmail.com>
Co-authored-by: Alexander Korotkov <aekorotkov@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: solai v <solai.cdac@gmail.com>
Discussion: https://postgr.es/m/
178447127453.110.
12276981925360691905%40mail.gmail.com
Backpatch-through: 14
Dean Rasheed [Tue, 28 Jul 2026 08:44:23 +0000 (09:44 +0100)]
Avoid RETURNING side effects for FOR PORTION OF leftovers.
UPDATE/DELETE ... FOR PORTION OF inserts leftover rows for the
untouched parts of the original row. These hidden inserts should not
affect the command tag or ROW_COUNT, so they call ExecInsert() with
canSetTag set to false.
However, ExecInsert() still processed the RETURNING list whenever the
target ResultRelInfo had ri_projectReturning set. That caused
RETURNING expressions to be evaluated for leftover rows even though
their results were discarded. As a result, expressions with side
effects and information-leaking functions could be executed on the
leftover rows, in addition to the visibly updated or deleted row.
Fix by having ExecInsert() skip RETURNING processing when it is
handling an internal FOR PORTION OF leftover insert. Use both the
presence of a FOR PORTION OF clause and mtstate->operation ==
CMD_INSERT for this check, so that the auxiliary INSERT of a
cross-partition UPDATE with a FOR PORTION OF clause still processes
RETURNING normally.
Back-patch to v19, where support for FOR PORTION OF was added.
Author: Chao Li <lic@highgo.com>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Reviewed-by: Paul A Jungwirth <pj@illuminatedcomputing.com>
Discussion: https://postgr.es/m/
07C125E5-F6ED-460C-A394-
E6503DAE18FB@gmail.com
Backpatch-through: 19
Michael Paquier [Tue, 28 Jul 2026 01:49:26 +0000 (10:49 +0900)]
Fix portability issue in authentication test 003_peer
The mapped user name is built upon the OS user name of the environment
where the test is run. Depending on the characters used in the OS user
name, CREATE ROLE may not get parsed (the author has mentioned hyphens
as one case), causing a failure of the test.
Let's use double-quotes around the mapped user name, which should be a
solution good enough for the environments where this test tends to run.
The buildfarm issued no complaint over the years.
Oversight in
3c4e26a62c31, so backpatch down to v19. Perhaps
3c4e26a62c31 and this commit should be backpatched further down, but
let's leave that for another day, if it proves necessary.
Author: Yugo Nagata <nagata@sraoss.co.jp>
Discussion: https://postgr.es/m/
20260727133857.
fbd23d43d422f10f376a8bee@sraoss.co.jp
Backpatch-through: 19