]> git.ipfire.org Git - thirdparty/postgresql.git/log
thirdparty/postgresql.git
55 min agopostgres_fdw: reject use_scram_passthrough for subscriptions. REL_19_STABLE github/REL_19_STABLE
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

73 min agoImprove DROP SERVER handling of dependent subscriptions.
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

2 hours agoFix lock release for role membership grants in DROP OWNED BY.
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

2 hours agoDon't skip invalid databases when enabling data checksums
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

3 hours agoDo not log subscription conninfo.
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

5 hours agoUndo inadvertent loosening of archive filename checking.
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

9 hours agoRemove unused arg and dead code in set_attnotnull()
Á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

13 hours agoFix missing space before WHERE in GRAPH_TABLE deparse
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

14 hours agoFix nullability check for a sub-select's upper-level Vars
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

24 hours agoTighten up TS dictionary cache entry creation.
Tom Lane [Sun, 2 Aug 2026 20:49:18 +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

28 hours agoFix memory-safety bugs in the ispell/hunspell dictionary loader.
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

30 hours agoUpdate time zone data files to tzdata release 2026c.
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

2 days agoAdd a comment to distinguish backend types
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

2 days agodoc: Fix glossary entry for data checksums workers
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

2 days agoAllow IO time to be counted without a matching IO operation in pg_stat_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

3 days agoAdd list of major features to the v19 release notes.
Nathan Bossart [Fri, 31 Jul 2026 19:00:37 +0000 (14:00 -0500)] 
Add list of major features to the v19 release notes.

Reviewed-by: Michael Banck <mbanck@gmx.net>
Discussion: https://postgr.es/m/akWIxtcathhoUuCQ%40nathan
Backpatch-through: 19 only

3 days agolibpq-oauth: Avoid overflow for very large intervals
Jacob Champion [Fri, 31 Jul 2026 18:13:41 +0000 (11:13 -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

3 days agoPrevent walsummarizer from getting stuck at a timeline switch.
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

3 days agoFix autovacuum's database sorting.
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

3 days agoFix Hash Join performance issue when hashing NULL values
David Rowley [Fri, 31 Jul 2026 11:24:23 +0000 (23:24 +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

3 days agoImprove wording of sequence origin warning in logical replication.
Amit Kapila [Fri, 31 Jul 2026 04:21:08 +0000 (09:51 +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

3 days agoFix issue with RANGE's DEFAULT partition pruning
David Rowley [Fri, 31 Jul 2026 03:37:12 +0000 (15:37 +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

3 days agoFix incorrect Result node flattening logic
David Rowley [Fri, 31 Jul 2026 01:16:29 +0000 (13:16 +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

3 days agoFix background psql session cleanup in 051_effective_wal_level.pl.
Masahiko Sawada [Thu, 30 Jul 2026 23:17:13 +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

4 days agoFix races between deactivation of logical decoding and slot creation.
Masahiko Sawada [Thu, 30 Jul 2026 19:47:08 +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

4 days agoReject non-finite reltuples when restoring stats
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

4 days agoInitialize bs_reltuples in parallel GIN builds
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

4 days agoMake sure to detach injection points for re-attaching
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

4 days agoAdd previous commit to .git-blame-ignore-revs
Daniel Gustafsson [Thu, 30 Jul 2026 07:30:53 +0000 (09:30 +0200)] 
Add previous commit to .git-blame-ignore-revs

4 days agopgindent fix for 4ee0ccfd
Daniel Gustafsson [Thu, 30 Jul 2026 07:26:07 +0000 (09:26 +0200)] 
pgindent fix for 4ee0ccfd

4 days agoSkip SUBSCRIPTION TABLE TOC entries with --no-subscriptions.
Amit Kapila [Thu, 30 Jul 2026 06:19:33 +0000 (11:49 +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

5 days agodoc: Add a note that refint will be removed in v20
Daniel Gustafsson [Wed, 29 Jul 2026 19:51:46 +0000 (21:51 +0200)] 
doc: Add a note that refint will be removed in v20

refint has been removed from the spi contrib module in v20.  Add a note
to the documentation of the still-supported back branches so that users
are aware the module is going away.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reported-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAJTYsWUHq8Ohc6-N-xamOPYz-q3qUYMtwQX-1=Zi=5N1Q_GSEQ@mail.gmail.com
Backpatch-through: 14

5 days agodoc: remove added space within synopsis replaceable tags
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

5 days agoFix stale comment in parallel_vacuum_main().
Masahiko Sawada [Wed, 29 Jul 2026 16:52:10 +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

5 days agoFix cascading standby reconnect failure after archive fallback
Á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

5 days agoProtect PGPROC lookup when terminating background workers
Michael Paquier [Wed, 29 Jul 2026 08:39:40 +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

5 days agoAvoid accumulating relation locks during sequence synchronization.
Amit Kapila [Wed, 29 Jul 2026 04:09:59 +0000 (09:39 +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

6 days agoFix planner's nullability/strictness logic for ScalarArrayOpExpr.
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

6 days agoHandle invalid and dropped databases during checksum enable
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

6 days agoRecheck checksum state before file_copy during CREATE DATABASE
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

6 days agoFix logical decoding of empty prepared transactions.
Masahiko Sawada [Tue, 28 Jul 2026 19:33:31 +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

6 days agoFix pg_get_publication_tables() failure with concurrent DROP TABLE.
Masahiko Sawada [Tue, 28 Jul 2026 17:39:40 +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

6 days agoRestore vacuum_delay_point() in GIN posting-tree leaf vacuum
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

6 days agoAvoid RETURNING side effects for FOR PORTION OF leftovers.
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

6 days agoFix portability issue in authentication test 003_peer
Michael Paquier [Tue, 28 Jul 2026 01:50:23 +0000 (10:50 +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

6 days agoFix propagation of indimmediate flag in index_create_copy()
Michael Paquier [Mon, 27 Jul 2026 23:35:09 +0000 (08:35 +0900)] 
Fix propagation of indimmediate flag in index_create_copy()

index_create_copy is used to create copy definitions of existing indexes.
Currently, it passes 0 as constr_flags to index_create(), which results
in the copied index to always be created as immediate (indimmediate set
to true).  For deferrable unique constraints, it means that the
transient index used during the phase 2 of REINDEX CONCURRENTLY forces
immediate constraint checks on concurrent inserts, which can cause
unexpected constraint violations based on the definition of the parent
table, inconsistently set in the copied index.

To fix this without violating the contract of constr_flags (which should
only be used when creating constraints) and without relaxing the strict
assertion in index_create(), this introduces a new index creation flag:
INDEX_CREATE_DEFERRABLE.  If set, a copied index's indimmediate is set
to false, meaning that unique constraints are not enforced immediately
on insertion, but at transaction commit time.

An isolation test for REINDEX CONCURRENTLY is added, based on an
injection point waiting after phase 1 of the operation, where an index
copy has been built and is able to accept DMLs for its validation in
phase 2.  The test is tentatively backpatched down to v17.
INJECTION_POINT() is outside a transaction context, which should be fine
on HEAD since 8daeaa9b642c but I suspect may cause issues in v19 and
older branches due to the wait facility depending on condition variables
and a DSM setup, but let's see what the buildfarm tells.

Author: Nitin Motiani <nitinmotiani@google.com>
Discussion: https://postgr.es/m/CAH5HC97JmjPpgiQOqW9xm8qXhNiu7zZ1Qh+FfhEESJuDv69kuQ@mail.gmail.com
Backpatch-through: 14

7 days agoFix race condition when enabling logical decoding concurrently.
Masahiko Sawada [Mon, 27 Jul 2026 16:10:48 +0000 (09:10 -0700)] 
Fix race condition when enabling logical decoding concurrently.

With wal_level = 'replica', logical decoding is enabled on demand
when the first logical replication slot is created:

When enabling logical decoding, EnableLogicalDecoding() flips the
shared logical_decoding_enabled flag and writes an
XLOG_LOGICAL_DECODING_STATUS_CHANGE record so that standbys follow the
status change. The initial "already enabled?" check and the WAL record
write happen under two separate acquisitions of
LogicalDecodingControlLock, since the lock must be released while
waiting for the ProcSignalBarrier: processes absorbing the barrier
acquire the same lock in shared mode.

Consequently, if two backends concurrently created the first logical
slots, both could pass the initial check and both write a
status-change record. The redundant record lands after the decoding
start point already reserved by the other backend's slot, so decoding
that slot processes the record and fails with "unexpected logical
decoding status change", as xlog_decode() assumes that no such record
can appear within the WAL range any slot decodes.

Fix by re-checking the status after re-acquiring the lock, so that
only the backend that actually performs the disabled->enabled
transition writes the WAL record.

Reported-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Author: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CAFC+b6oYzmAgp7F0ivrhfZT46-CjvCTrU9pWuMNcem-52YjOTw@mail.gmail.com
Backpatch-through: 19

7 days agoDeparse FOR PORTION OF using the range column's current name.
Tom Lane [Mon, 27 Jul 2026 13:37:04 +0000 (09:37 -0400)] 
Deparse FOR PORTION OF using the range column's current name.

Commit 8e72d914c recorded the range column's name in ForPortionOfExpr
and used that for deparsing FOR PORTION OF.  This gives the wrong
answer if the ForPortionOfExpr is saved in a rule or SQL function and
then the column gets renamed.  Drop the ForPortionOfExpr.range_name
field; instead fetch the current column name from the catalogs when
needed.

Also drop ForPortionOfState.fp_rangeName, which wasn't being used
anywhere.

Full disclosure: an earlier draft of this patch was made with
Claude Opus 4.8.

Reported-by: John Naylor <johncnaylorls@gmail.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CANWCAZYFEpJ5Oi45gi4q9Y6LYa4_oiAXxuNNWe-1ym-i0fF8Pw@mail.gmail.com
Backpatch-through: 19

7 days agopg_resetwal: do not allow zero next multixact offset
Heikki Linnakangas [Mon, 27 Jul 2026 12:29:51 +0000 (15:29 +0300)] 
pg_resetwal: do not allow zero next multixact offset

Offset 0 is the "invalid" marker in pg_multixact/offsets since offsets
went 64-bit and the allocator stopped skipping it. pg_resetwal could
still produce it via -O 0 or guessed control values, breaking the first
multixact created after the reset ("MultiXact n has invalid offset",
and vacuum of the affected table fails from then on). Reject -O 0 like
-m and -o already do, and guess 1 like initdb does.

Author: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://www.postgresql.org/message-id/CAN4CZFNoO6MUkg526TmA=mC_RjY2gp4VKCnvK6y12v3ppOkhJA@mail.gmail.com
Backpatch-through: 19

7 days agoFix issues in logical replication sequence synchronization.
Amit Kapila [Mon, 27 Jul 2026 03:34:31 +0000 (09:04 +0530)] 
Fix issues in logical replication sequence synchronization.

1. Stop a running sequence synchronization worker when
ALTER SUBSCRIPTION ... DISABLE is executed.  The worker did not reread its
subscription after starting a transaction, so it kept running with a stale
copy and missed the disable. It now calls maybe_reread_subscription()
after StartTransactionCommand(), matching the apply worker.

2. Restore the invariant that publisher-side synchronization slots are
dropped last during ALTER SUBSCRIPTION ... REFRESH PUBLICATION.  The
slot-drop loop now runs after the sequence-removal loop, so the
non-transactional slot drops happen only after all catalog changes that
could still be rolled back on error.

3. Restore psql tab completion for
ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (.

4. Make pg_stat_subscription report NULL for the fields that do not apply
to a sequence synchronization worker, which does not stream from a
walsender, and update the documentation accordingly.

5. Update the pg_subscription_rel.srsublsn catalog documentation to
describe its semantics for sequence rows.

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

7 days agoFix deparsing of JSON_ARRAY(subquery) with a FORMAT clause
Richard Guo [Mon, 27 Jul 2026 01:21:18 +0000 (10:21 +0900)] 
Fix deparsing of JSON_ARRAY(subquery) with a FORMAT clause

Commit 8d829f5a0 introduced the JSCTOR_JSON_ARRAY_QUERY constructor
type so that ruleutils.c could deparse JSON_ARRAY(subquery) using its
original syntax, storing the transformed subquery in a new orig_query
field.  However, the input FORMAT clause of JSON_ARRAY(subquery FORMAT
...) was not preserved for deparsing.  The format was recorded only in
the executable expression kept in the func field, which ruleutils.c
does not inspect, so it is silently dropped.

This is more than cosmetic, because FORMAT JSON changes the result:
without it a text value is treated as a string to be quoted, while
with it the value is treated as already-formatted JSON.

To fix, record the input FORMAT in a new deparse-only field of
JsonConstructorExpr, alongside orig_query, and emit it in ruleutils.c.

Bump catalog version.

Author: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/4C89B193-7D54-4705-9CF9-F0D484B9E099@gmail.com
Backpatch-through: 19

8 days agoAdd _bt_set_startikey row compare test coverage.
Peter Geoghegan [Sun, 26 Jul 2026 16:49:54 +0000 (12:49 -0400)] 
Add _bt_set_startikey row compare test coverage.

Add pg_regress tests that exercise the row compare logic that commit
7d9cd2df added to _bt_set_startikey.  Also add tests that exercise the
_bt_set_startikey SAOP array path.

Author: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAH2-Wz=KjQsD2W2a=b51uH905=0mF6Le4evhWkN2FL1+uRPhUg@mail.gmail.com
Backpatch-through: 19

9 days agoAdd missing PGDLLIMPORT marker
Álvaro Herrera [Sat, 25 Jul 2026 17:16:42 +0000 (19:16 +0200)] 
Add missing PGDLLIMPORT marker

Oversight in commit fb23cc7e81db.

Reported-by: Anton Voloshin <a.voloshin@postgrespro.ru>
Discussion: https://postgr.es/m/ad5d772e-09d9-4248-97a4-0011afab9e71@postgrespro.ru

9 days agoFix another empty nbtree index SSI race.
Peter Geoghegan [Sat, 25 Jul 2026 16:01:34 +0000 (12:01 -0400)] 
Fix another empty nbtree index SSI race.

Commit f9b7fc65 fixed a race when predicate-locking completely empty
btrees: without a buffer lock held, a matching key could be inserted
between _bt_search and the PredicateLockRelation call, so the scan would
miss concurrently inserted tuples while the writer wouldn't see the
reader's predicate lock.  That commit only fixed _bt_first's _bt_search
path, though.  Scans without useful insertion scan keys return early
from _bt_first via _bt_endpoint, which still didn't recheck if the
relation was empty.

To fix, add handling to _bt_endpoint that is analogous to the handling
added to _bt_search by commit f9b7fc65.

Author: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAH2-WzkNoTn3yXY0iGkSuavJ+sL8EROf+kitW+_2v2tJVWuKmA@mail.gmail.com
Backpatch-through: 14

9 days agopsql: Allow pg_read_all_stats to see database size in \l+
Fujii Masao [Sat, 25 Jul 2026 10:09:19 +0000 (19:09 +0900)] 
psql: Allow pg_read_all_stats to see database size in \l+

pg_database_size() allows access to users who have either CONNECT
privilege on the target database or privileges of the pg_read_all_stats
role. However, previously, psql's \l+ checked only for CONNECT,
so users with privileges of pg_read_all_stats still saw "No Access" for
databases they could not connect to.

Fix this by making \l+ also check
pg_has_role('pg_read_all_stats', 'USAGE'), matching
pg_database_size()'s permission rules.

For back branches, emit the pg_read_all_stats check only when
connected to PostgreSQL 10 or later, since earlier releases do not have
that predefined role.

Backpatch to all supported versions.

Author: Christoph Berg <myon@debian.org>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/amCo6qRmnfPVk4-V@msg.df7cb.de
Backpatch-through: 14

9 days agoAvoid reporting permission-denied publisher sequences as missing
Fujii Masao [Sat, 25 Jul 2026 01:30:30 +0000 (10:30 +0900)] 
Avoid reporting permission-denied publisher sequences as missing

Previously, if a sequence synchronization batch contained both a sequence
that had been dropped on the publisher and another for which the
replication role lacked SELECT privilege, the latter was reported
twice: once as a permission failure and again as missing on the
publisher.

This happened because the permission-denied sequence was not marked as
found on the publisher. As a result, when another sequence in the batch
was genuinely missing, the later missing-sequence check incorrectly
classified the permission-denied sequence as missing as well.

Fix this by marking the permission-denied sequence as found before
reporting the permission failure, so it is not later reported as
missing.

Reported-by: Noah Misch <noah@leadboat.com>
Author: Vignesh C <vignesh21@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CALDaNm3LsUjW7PahuCsbYAxajSF+S328tw5E9rF0erdh7dKOXw@mail.gmail.com
Backpatch-through: 19

10 days agoFix EXCEPT publication test to check subscriber
Fujii Masao [Fri, 24 Jul 2026 06:44:56 +0000 (15:44 +0900)] 
Fix EXCEPT publication test to check subscriber

Commit fd366065e06 added tests intended to verify that rows inserted
on the publisher are replicated to the subscriber when using multiple
publications, with one excluding the target table via EXCEPT and
another including it.

However, the tests queried the publisher instead of the subscriber.
Since the rows were inserted directly into the publisher, the checks
would always succeed, providing no coverage of replication.

Fix this by querying the subscriber so the tests verify the replicated
state.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwGfXUO7f4t6KNGurYwg6QsnLtpP0K3EACbAwYWtxGfKfQ@mail.gmail.com
Backpatch-through: 19

11 days agoValidate subscription conninfo on owner change
Fujii Masao [Thu, 23 Jul 2026 10:24:55 +0000 (19:24 +0900)] 
Validate subscription conninfo on owner change

For subscriptions using SERVER, changing the owner can change the
effective connection string. However, ALTER SUBSCRIPTION ... OWNER TO
did not validate the generated conninfo for the new owner.

As a result, ownership could be transferred to a non-superuser whose
generated connection string did not satisfy password_required=true.
The ownership change succeeded, but the subscription would fail later
when the worker or another command tried to connect.

Fix this by making ALTER SUBSCRIPTION ... OWNER TO validate the new
owner's generated conninfo with walrcv_check_conninfo().

Backpatch to v19, where SERVER subscriptions were introduced.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Yuanchao Zhang <145zhangyc@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/CAHGQGwFGa6+wWVgUmZPFwN=fBY59mYPkMK3=TxT=Pv5C1mNNRQ@mail.gmail.com
Backpatch-through: 19

11 days agodoc: Improve pg_stat_recovery documentation
Fujii Masao [Thu, 23 Jul 2026 10:22:36 +0000 (19:22 +0900)] 
doc: Improve pg_stat_recovery documentation

Improve the documentation for pg_stat_recovery in several ways:

- Mention the view in high-availability.sgml as a way to monitor
  recovery state and replay progress, alongside the existing recovery
  information functions.
- Clarify that the view returns at most one row, not exactly one row,
  and no rows to users who lack the pg_read_all_stats privilege.
- Correct the description of last_replayed_end_lsn to clarify that it
  is the end LSN of the last replayed record plus one.
- Document that replay_end_tli equals last_replayed_tli when no WAL
  record is currently being replayed.
- Clarify that current_chunk_start_time is NULL until streaming WAL
  has been received.

Backpatch to v19, where pg_stat_recovery was introduced.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAHGQGwGRavm18HqnQn_f68QB96qk6arhjET1V93OJH09Mgojkg@mail.gmail.com
Backpatch-through: 19

11 days agoinjection_points: Clear waiter slot on error and exit
Michael Paquier [Thu, 23 Jul 2026 05:37:42 +0000 (14:37 +0900)] 
injection_points: Clear waiter slot on error and exit

injection_wait() only clears its slot in the waiter array after the
wait loop finishes.  When the waiting query is canceled or the backend
is terminated (wait look has a CHECK_FOR_INTERRUPS), the slot leaks.
Later wakeups of the same point then bump the counter of the leaked slot
instead of the real waiter, that sleeps forever.  Repeated leaks can
exhaust all the slots.

The code is changed so as the waiting loop is wrapped with
PG_ENSURE_ERROR_CLEANUP, so as the injection point slots, that are
shared resources, can be cleaned up on ERROR as much as a FATAL.

An isolation test is added: cancel one waiter, terminate another waiter,
then check that a later waiter still receives a wakeup.  Without the
fixed code, the test would fail on timeout.

Author: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/CAN4CZFO+KF=cc0-iEg28RhqRBp_fTs6D4b8b7D7DB-pGYP3Ccg@mail.gmail.com
Backpatch-through: 17

11 days agoReject sequence synchronization against pre-PostgreSQL 19 publishers.
Amit Kapila [Thu, 23 Jul 2026 05:09:03 +0000 (10:39 +0530)] 
Reject sequence synchronization against pre-PostgreSQL 19 publishers.

Sequence synchronization requires the page_lsn field returned by
pg_get_sequence_data(), which was added in PostgreSQL 19. Previously,
requesting sequence synchronization against an older publisher (via
ALTER SUBSCRIPTION ... REFRESH SEQUENCES or by running
ALTER SUBSCRIPTION ... CONNECTION on a disabled subscription with
sequences in the INIT state and subsequently enabling the subscription)
would cause the sequence synchronization worker to repeatedly fail with a
confusing "invalid query response" error.

Check the publisher's server version up front in both
AlterSubscription_refresh_seq() and copy_sequences(), and error out
immediately when it predates PostgreSQL 19.

Also document the PostgreSQL 19 publisher requirement for sequence
replication in the logical replication documentation and in
ALTER SUBSCRIPTION ... REFRESH SEQUENCES.

Reported-by: Noah Misch <noah@leadboat.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Shveta Malik <shveta.malik@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com

12 days agowalsummarizer: Guard against WAL files whose tail ends are not valid.
Robert Haas [Wed, 22 Jul 2026 12:47:44 +0000 (08:47 -0400)] 
walsummarizer: Guard against WAL files whose tail ends are not valid.

SummarizeWAL documents that maximum_lsn should be passed as "the switch
point when reading a historic timeline, or the most-recently-measured end of
WAL when reading the current timeline." But the caller always passed the
most recently measured end-of-WAL even when reading from a historic
timeline, due to an oversight on my part. Fix that.

As far as I can determine, for this to become an issue in practice, it's
necessary to have a corrupted WAL file in the archive.  SummarizeWAL checks
that every record it processes both starts and ends before switch_lsn; so if
all the WAL files in the archive are valid, SummarizeWAL will still discover
where it should stop summarizing and do the right thing.  However, if
there's a corrupted file in the WAL archive, and if it is also the case that
the end of the current timeline has advanced past the switch point, then the
incorrect maximum_lsn value can result in trying to read an invalid record
and erroring out, which leads repeatedly retrying and failing with an error
every time.

One way this could occur is if a new primary is promoted and creates a
.partial file, and the user manually renames that file to remove the suffix,
and it is then archived. In that situation, the tail end of the file need
not be valid WAL, and that could lead to a stuck WAL summarizer.

Reported-by: Fabrice Chapuis <fabrice636861@gmail.com>
Analyzed-by: Thom Brown <thom@linux.com> (using claude)
Discussion: http://postgr.es/m/CAA5-nLDdvGMkN6Z-GaHGHG5T7QWEgv4YoHO7XvOJbeD00cghNg@mail.gmail.com
Backpatch-through: 17

13 days agodoc: clarify how TIMESTAMP WITH TIME ZONE behaves
Bruce Momjian [Tue, 21 Jul 2026 16:06:10 +0000 (12:06 -0400)] 
doc:  clarify how TIMESTAMP WITH TIME ZONE behaves

Mention "time zone conversion" as a way to clarify the time zone is not
stored in the database.

Reported-by: Richard Neill
Discussion: https://postgr.es/m/ddf41f033a8add84e1f28a095defafae@richardneill.org

Backpatch-through: 19

13 days agodoc: clarify to_char("OF") HH/MM doesn't represent actual chars
Bruce Momjian [Tue, 21 Jul 2026 15:59:37 +0000 (11:59 -0400)] 
doc:  clarify to_char("OF") HH/MM doesn't represent actual chars

Change formatting and chars to be less of a match against actual
formatting characters.

Reported-by: Phil
Discussion: https://postgr.es/m/177801333530.795.16999885814007014333@wrigleys.postgresql.org

Backpatch-through: 19

13 days agoFix typo
Peter Eisentraut [Tue, 21 Jul 2026 15:18:41 +0000 (17:18 +0200)] 
Fix typo

from commit c1fe2d1a383

13 days agoRemove assertion added by commit 7dcea51c2a4d
Álvaro Herrera [Tue, 21 Jul 2026 15:18:06 +0000 (17:18 +0200)] 
Remove assertion added by commit 7dcea51c2a4d

We've got no reports of problems.  Get rid of it.

Author: Álvaro Herrera <alvherre@kurilemu.de>
Backpatch-through: 19
Discussion: https://postgr.es/m/alewd1f2G0kKeM1i@alvherre.pgsql

13 days agopg_upgrade: Message wording fix
Peter Eisentraut [Tue, 21 Jul 2026 14:56:37 +0000 (16:56 +0200)] 
pg_upgrade: Message wording fix

For internally consistent terminology

13 days agoMessage style fixes
Peter Eisentraut [Tue, 21 Jul 2026 13:27:02 +0000 (15:27 +0200)] 
Message style fixes

Change DETAIL messages to conform to the style guide by capitalizing
the first word of sentences and ending sentences with a period.

Author: Peter Smith <peter.b.smith@fujitsu.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: vignesh C <vignesh21.gmail.com>
Reviewed-by: Xiaopeng Wang <wxp_728.163.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://www.postgresql.org/message-id/flat/CAHut%2BPszSntkUgN%2BQa9matGY6MLEoFGSuVbuKDgnnTdZ7YPRwg%40mail.gmail.com

13 days agoTest what BEFORE UPDATE triggers do to FOR PORTION OF
Peter Eisentraut [Tue, 21 Jul 2026 06:33:25 +0000 (08:33 +0200)] 
Test what BEFORE UPDATE triggers do to FOR PORTION OF

If a BEFORE trigger changes NEW.valid_at, what is the interaction with
FOR PORTION OF?  This commit gives a test to capture our current
behavior: The trigger's change replaces the value we computed
automatically, but it does not change the bounds of the temporal
leftovers.

This matches the behavior of MariaDB.  On the other hand, DB2 rejects
changing the start/end columns of a PERIOD.  Since we don't have
PERIODs, we can't reject the change at trigger definition time as DB2
does, but we could reject it at run time by comparing the values
before and after running triggers.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
Discussion: https://www.postgresql.org/message-id/CA%2BrenyV3Cr9BvWsPeb1t8b%3DPk24apuzyGbubAEs_YsgLUTfXpg%40mail.gmail.com

13 days agoAllow logical replication workers to ignore default_transaction_read_only.
Amit Kapila [Tue, 21 Jul 2026 03:42:52 +0000 (09:12 +0530)] 
Allow logical replication workers to ignore default_transaction_read_only.

Sequence synchronization updates sequence state via setval(), which
explicitly calls PreventCommandIfReadOnly(). If
default_transaction_read_only is enabled on the subscriber, this causes
sequencesync workers to fail with "cannot execute setval() in a read-only
transaction". Apply and tablesync workers are not affected, since they
write via direct heap access rather than through these read-only-checked
functions.

Rather than special-casing sequencesync, override
default_transaction_read_only to "off" for all logical replication workers
in InitializeLogRepWorker(), the same way session_replication_role and
search_path are already forced there. This keeps the initialization
uniform.

For PG-19, we kept the fix narrow by overriding
default_transaction_read_only to "off" only for sequencesync workers.

Reported-by: Noah Misch <noah@leadboat.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com

13 days agoAdd logical decoding status to pg_control_checkpoint().
Masahiko Sawada [Tue, 21 Jul 2026 00:11:21 +0000 (17:11 -0700)] 
Add logical decoding status to pg_control_checkpoint().

Commit 8108765f04b added the logical decoding status to the
pg_controldata output, but overlooked the pg_control_checkpoint() SQL
function, which reports the same checkpoint information. This commit
adds a logical_decoding column to pg_control_checkpoint(), placed
after full_page_writes to match the pg_controldata output order.

Oversight in 8108765f04b.

Bump catalog version.

Reported-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEkp1-1n5iC38+yHSNh955+KshwtCL6DzA0vk_vuUF_Eg@mail.gmail.com
Backpatch-through: 19

2 weeks agodoc: Granting TRIGGER or REFERENCES on table is dangerous.
Robert Haas [Mon, 20 Jul 2026 17:36:39 +0000 (13:36 -0400)] 
doc: Granting TRIGGER or REFERENCES on table is dangerous.

It's always been the case that granting these privileges to users that
you don't fully trust was a bad idea, but it hasn't always been
obvious to people reading the documentation that this is the case.
To prevent confusion, and also repeated reports to pgsql-security,
mention it explicitly.

Discussion: http://postgr.es/m/CA+TgmobrjCHBuWHrvX3=2vndUCO2thUOdevrCcMDFW86cqCYvw@mail.gmail.com
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Backpatch-through: 14

2 weeks agoFix restore of partitions with exclusion constraints
Álvaro Herrera [Mon, 20 Jul 2026 15:21:20 +0000 (17:21 +0200)] 
Fix restore of partitions with exclusion constraints

Commit 8c852ba9a4 allowed exclusion constraints to be added to
partitioned tables, but wasn't careful to verify that pg_restore worked
correctly for them.  Fix that by making CompareIndexInfo() more
selective about what needs to be rejected.

Author: Japin Li <japinli@hotmail.com>
Reported-by: Keith Paskett <keith.paskett@logansw.com>
Discussion: https://postgr.es/m/2A40921D-83AB-411E-ADA6-7E509A46F1E4@logansw.com

2 weeks agoFix LSN format in REPACK worker debug message
Álvaro Herrera [Mon, 20 Jul 2026 11:50:45 +0000 (13:50 +0200)] 
Fix LSN format in REPACK worker debug message

Commit 6f6f284c7ee4 introduced use of LSN_FORMAT_ARGS across the whole
tree to remove use of manual bit-shifting, and commit 2633dae2e487
changed the printf format to be %X/%08X; however commit 28d534e2ae0a
violated both conventions by reintroducing the old manual-shift style
with the deprecated %X/%X format in one debug message.  Make that new
message conform to our style.

Author:  kenny <kennychen851228@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/CAPXstDuWD8jg0=C8PXTXGSTTsZcjqJ+u+xKCrMpN99CXsxQzCg@mail.gmail.com

2 weeks agoMove code to get_tables_to_repack_partitioned
Álvaro Herrera [Mon, 20 Jul 2026 10:12:13 +0000 (12:12 +0200)] 
Move code to get_tables_to_repack_partitioned

Some of its code was pointlessly in its caller.  This makes it better
contained and clearer.

Backpatch to 19, to avoid having two different copies in case we have to
modify it again later.

Author: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: ChangAo Chen <cca5507@qq.com>
Discussion: https://postgr.es/m/alD9l-XlCuu3eUEe@alvherre.pgsql

2 weeks agoFix RLS checks for FOR PORTION OF leftover rows
Peter Eisentraut [Mon, 20 Jul 2026 06:38:08 +0000 (08:38 +0200)] 
Fix RLS checks for FOR PORTION OF leftover rows

UPDATE/DELETE FOR PORTION OF may insert leftover rows to preserve the
parts of the old row that are outside the target range.  Those inserts
go through ExecInsert(), which checks RLS policies using
WCO_RLS_INSERT_CHECK.

However, the rewriter only added RLS WITH CHECK options for the
original statement command.  For UPDATE, that meant only
WCO_RLS_UPDATE_CHECK options were available, so ExecInsert() skipped
them.  For DELETE, no RLS WITH CHECK options were added at all.  As a
result, leftover rows could be inserted even when they violated INSERT
RLS policies.

Fix this by adding INSERT RLS WITH CHECK options for UPDATE/DELETE FOR
PORTION OF target relations.  Also add regression coverage for both
UPDATE and DELETE, including cases where allowed leftovers still
succeed and disallowed leftovers are rejected.

Author: Chao Li <lic@highgo.com>
Co-authored-by: Paul A Jungwirth <pj@illuminatedcomputing.com>
Reviewed-by: Paul A Jungwirth <pj@illuminatedcomputing.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/6C34A987-AC50-4477-BD71-2D4AFEE1A589%40gmail.com
Discussion: https://www.postgresql.org/message-id/flat/CAJTYsWWdeBkoH5g8D-k9LDw9ciqsMxb21EJSiFXAzP4J%3DXyxOQ%40mail.gmail.com

2 weeks agoHandle concurrent sequence refreshes.
Amit Kapila [Mon, 20 Jul 2026 05:36:45 +0000 (11:06 +0530)] 
Handle concurrent sequence refreshes.

'ALTER SUBSCRIPTION ... REFRESH SEQUENCES' can race with a running
sequence synchronization worker. If the worker has fetched a sequence's
value from the publisher but not yet marked it READY, a concurrent refresh
that resets the sequence to INIT can be overwritten by the worker's stale
value, silently losing the refresh request.

Handle this by stopping any running sequence sync worker before resetting
the sequences to INIT. This is race-free because AlterSubscription()
already holds AccessExclusiveLock on the subscription object. That lock
blocks a running worker's UpdateSubscriptionRelState(), which takes
AccessShareLock on the object, and also any worker the apply worker
re-launches, because a new worker takes AccessShareLock on the object in
InitializeLogRepWorker() before it reads pg_subscription_rel. Such a
worker cannot act on the sequence states until the refresh commits, by
which time they are reset to INIT and it will synchronize the latest
publisher values.

Reported-by: Noah Misch <noah@leadboat.com>
Author: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: vignesh C <vignesh21@gmail.com>
Reviewed-by: Shveta Malik <shveta.malik@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com

2 weeks agoSkip unnecessary get_relids_in_jointree() when there are no PHVs
Richard Guo [Mon, 20 Jul 2026 03:13:11 +0000 (12:13 +0900)] 
Skip unnecessary get_relids_in_jointree() when there are no PHVs

Commit 1df9e8d96 made remove_useless_result_rtes() compute the set of
baserels in the jointree, to pass down to the find_dependent_phvs()
checks.  But those checks are no-ops when the query contains no PHVs,
since find_dependent_phvs() and find_dependent_phvs_in_jointree() both
return early in that case.  So we can avoid the
get_relids_in_jointree() scan altogether when root->glob->lastPHId is
zero, leaving baserels as NULL.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAMbWs49H275KzgZr3Cd1Hy+6Lmwp35bZ+5PrVc62k3HDLj6hNQ@mail.gmail.com
Backpatch-through: 16

2 weeks agoRun nbtree test module tests under autoconf builds
Peter Geoghegan [Mon, 20 Jul 2026 02:15:36 +0000 (22:15 -0400)] 
Run nbtree test module tests under autoconf builds

Commit 1e4e5783e added the src/test/modules/nbtree test module, but only
registered it in the meson build, not in the module list in
src/test/modules/Makefile.  As a result, autoconf builds never ran the
module's tests.

To fix, add the module to the Makefile's lists of
injection-point-dependent modules.

Oversight in commit 1e4e5783e.

Author: Peter Geoghegan <pg@bowt.ie>
Reviewed-by: Michael Paquiër <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAH2-Wz=JchiD5ksiT35p8Ar02gaNv8_y6w2wBAST+Zzen-eNjw@mail.gmail.com
Backpatch-through: 19

2 weeks agoFix parsing of underscores in pg_plan_advice occurrence numbers
Daniel Gustafsson [Sun, 19 Jul 2026 21:27:52 +0000 (23:27 +0200)] 
Fix parsing of underscores in pg_plan_advice occurrence numbers

The pg_plan_advice scanner recognizes underscores as digit separators
just like the core parser, but used strtoint() to convert occurrence
numbers which does not support underscores.  Consequently, advice such
as SEQ_SCAN(x#1_0) failed to parse.  Fix by using pg_strtoint32_safe()
like the core scanner, and also add regression test coverage.

This bug was independently found and reported by Lukas Fittl and Chao
Li.  Backpatch down to v19 where pg_plan_advice was introduced.

Author: Chao Li <lic@highgo.com>
Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
Reported-by: Lukas Fittl <lukas@fittl.com>
Reported-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Lukas Fittl <lukas@fittl.com>
Discussion: https://postgr.es/m/22E2ECE0-B768-43D5-8575-61C3EBC2E4E8@gmail.com
Discussion: https://postgr.es/m/CAP53PkzKeD=t90OfeMsniYrcRe2THQbUx3g6wV17Y=ZtiwmWTQ@mail.gmail.com
Backpatch-through: 19

2 weeks agoRemove redundant null-treatment check in window function dedup.
Tatsuo Ishii [Sun, 19 Jul 2026 01:47:29 +0000 (10:47 +0900)] 
Remove redundant null-treatment check in window function dedup.

Commit 25a30bbd423 (IGNORE NULLS / RESPECT NULLS for window functions)
made ExecInitWindowAgg() treat two otherwise-equal window functions as
duplicates only when their ignore_nulls settings also matched:

    if (i <= wfuncno && wfunc->ignore_nulls == perfunc[i].ignore_nulls)

That extra term reads WindowStatePerFuncData.ignore_nulls, but the field
was never populated when a per-function entry was filled in, so it stayed
zero from palloc0_array().  Consequently a duplicate call carrying
IGNORE NULLS or an explicit RESPECT NULLS never matched an identical
earlier entry and was needlessly given its own per-function slot and
evaluated twice.  (Results stayed correct; this was a missed sharing, not
a wrong answer.)

The extra term is in fact redundant.  WindowFunc.ignore_nulls is a plain
scalar field with no pg_node_attr, so _equalWindowFunc() already compares
it; the preceding equal() call therefore never matches two WindowFuncs
that differ only in null treatment.  If equal() matches, ignore_nulls
necessarily matched too, so the term can never change the outcome, and
WindowStatePerFuncData.ignore_nulls existed only to feed it.

Rather than populate the shadow field, drop the redundant term and the
field (and adjust the now-stale comment) and let equal() do the work.
That fixes the same bug while removing the hand-maintained duplicate
state that caused it, so it cannot silently drift again.

Author: Chao Li <li.evan.chao@gmail.com>
Co-authored-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tatsuo Ishii <ishii@postgresql.org>
Discussion: https://postgr.es/m/5D2C9081-5DFE-4E27-AB14-7358238EA1BC%40gmail.com
Backpatch-through: 19

2 weeks agodoc PG 19 relnotes: \crosstab to \crosstabview
Bruce Momjian [Sun, 19 Jul 2026 00:43:24 +0000 (20:43 -0400)] 
doc PG 19 relnotes:  \crosstab to \crosstabview

Backpatch-through: 19 only

2 weeks agodoc PG 19 relnotes: update to current
Bruce Momjian [Sun, 19 Jul 2026 00:41:00 +0000 (20:41 -0400)] 
doc PG 19 relnotes:  update to current

Backpatch-through: 19 only

2 weeks agoFurther cleanup for commit 54cd6fc83.
Etsuro Fujita [Sat, 18 Jul 2026 18:50:01 +0000 (03:50 +0900)] 
Further cleanup for commit 54cd6fc83.

Commit 54cd6fc83 set the version argument for the stats-import functions
introduced by that commit, which is of type int, using UInt32GetDatum,
not Int32GetDatum.  This would be completely harmless as it's positive
and currently ignored in the functions, but let's fix that code to use
Int32GetDatum for consistency.

Author: Etsuro Fujita <etsuro.fujita@gmail.com>
Discussion: https://postgr.es/m/CAPmGK14aremJGrPezVwFqWt7dnrMhD3KF1DgzsRygAUPETBU7w%40mail.gmail.com
Backpatch-through: 19

2 weeks agoFix edge case in remove_useless_result_rtes() with outer joins.
Tom Lane [Sat, 18 Jul 2026 18:09:10 +0000 (14:09 -0400)] 
Fix edge case in remove_useless_result_rtes() with outer joins.

find_dependent_phvs() and find_dependent_phvs_in_jointree() decide
whether a PlaceHolderVar depends on the RTE_RESULT rel we're
considering removing by comparing the PHV's phrels to a singleton set
containing that rel's RT index, reasoning that if phrels contains any
other relid bits then those define an appropriate place where we can
evaluate the PHV.  But since this code was originally written, we've
redefined phrels to include outer-join relids, and that breaks this
logic, potentially allowing us to remove an RTE_RESULT that leaves no
valid place to evaluate the PHV.  The planner doesn't throw an error
when that happens, but it does produce an incorrect plan that will not
replace the PHV's value with NULL when needed.

In the known test case for this bug, the "extra" OJ relid is one that
we've actually decided to remove but haven't yet cleaned out of the
query's PHVs.  It's not entirely clear though that that would always
be the case.  Let's restore this code to the way it was designed to
work, by considering only base relids within the PHV's phrels.

Bug: #19553
Reported-by: Viktor Leis <leis@in.tum.de>
Author: Matheus Alcantara <matheusssilv97@gmail.com>
Co-authored-by: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19553-4561747f93f368a7@postgresql.org
Backpatch-through: 16

2 weeks agoRestore the ability to use | and -> as prefix operators.
Tom Lane [Sat, 18 Jul 2026 16:57:42 +0000 (12:57 -0400)] 
Restore the ability to use | and -> as prefix operators.

Commit 2f094e7ac changed the parser to treat these as built-in
operator names, where before they were just generic Op.  While
it correctly gave them the same precedence as Op and added new
productions to allow them to still be used as infix operators,
it missed allowing them to still be used as prefix operators.
At least one extension expects to be able to do that, so add
the necessary productions.

Bug: #19558
Reported-by: Pierre Senellart <pierre@senellart.com>
Author: Pierre Forstmann <pierre.forstmann@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19558-ad1fca59a3a471a0@postgresql.org
Backpatch-through: 19

2 weeks agoFix REASSIGN OWNED for subscriptions in other databases.
Jeff Davis [Sat, 18 Jul 2026 16:22:40 +0000 (09:22 -0700)] 
Fix REASSIGN OWNED for subscriptions in other databases.

Subscription objects are conceptually database-local objects, but
pg_subscription is a shared catalog so that the launcher process can
scan it.

Check readers of pg_subscription to ensure that, unless it's the
launcher process, it filters by MyDatabaseId. Most readers were
already doing so, but this commit fixes REASSIGN OWNED and adds guards
to catch other problems in the future. Also, clarify documentation.

Author: Dilip Kumar <dilipbalaut@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: shveta malik <shveta.malik@gmail.com>
Discussion: https://postgr.es/m/20260710192533.4f.noahmisch@microsoft.com
Backpatch-through: 19

2 weeks agoRevert "Reject concurrent sequence refreshes".
Amit Kapila [Sat, 18 Jul 2026 02:23:13 +0000 (07:53 +0530)] 
Revert "Reject concurrent sequence refreshes".

This reverts commit f38afa4abb04e85530c94b88daf11c089375daca.

That commit fixed a race that could leave stale sequence values on the
subscriber after 'ALTER SUBSCRIPTION ... REFRESH SEQUENCES'. It did so by
raising an ERROR during 'ALTER SUBSCRIPTION ... REFRESH SEQUENCES'
whenever a sequence synchronization worker was already running for the
subscription.

That approach caused intermittent buildfarm failures, because the existing
tests did not ensure the sequencesync worker had stopped before executing
'ALTER SUBSCRIPTION ... REFRESH SEQUENCES'. While discussing how to fix
the tests, we concluded that blocking the command while a sequencesync
worker is running is inconvenient for users. So we will fix the original
race differently in a follow-up commit.

Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Author: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/3614163.1784163070@sss.pgh.pa.us
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com

2 weeks agoFix yet another portability problem in new NLS test.
Tom Lane [Fri, 17 Jul 2026 22:08:23 +0000 (18:08 -0400)] 
Fix yet another portability problem in new NLS test.

Álvaro reported offlist that his machine was passing the new-in-v19
nls.sql test in "make check" but not in "make installcheck".  On
investigation, the cause turned out to be that he has LANGUAGE set in
his environment, and with (at least recent versions of) glibc that
overrides LC_MESSAGES and friends, as per previous research by Bryan
Green.  "make check" works because pg_regress unsets LANGUAGE before
starting the postmaster, but in installcheck mode we're exposed to
the prevailing value and we lose.

We're already hacking the value of LANGUAGE in this test for Solaris,
so let's just extend that to unsetting LANGUAGE on every other platform.

Reported-by: Álvaro Herrera <alvherre@kurilemu.de>
Diagnosed-by: Andrew Dunstan <andrew@dunslane.net>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/a337896e-5bff-490b-afc9-c545f06c014c@gmail.com
Backpatch-through: 19

2 weeks agoTurn visibilitymap_clear() Assert back into an error
Melanie Plageman [Fri, 17 Jul 2026 20:47:33 +0000 (16:47 -0400)] 
Turn visibilitymap_clear() Assert back into an error

Commit ed62d26caca fixed a bug in clearing the visibility map and, while
doing so, made some incidental changes to visibilitymap_clear(). One of
them replaced the error thrown when the wrong buffer is passed to
visibilitymap_clear() with an Assert().

While anyone adding a new visibilitymap_clear() caller should be running
assert-enabled builds, visibilitymap_set() still reports the same
wrong-buffer condition with an elog(ERROR), so visibilitymap_clear()
should also do so for consistency. This change was also unrelated to
the bug fix and is better made as a separate commit. Restore the error.

Reported-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwF_PzOv5y7ucFh7Fqqqa8ar83zYwvWugqarRD6%2B7GCtEQ%40mail.gmail.com
Backpatch-through: 19

2 weeks agoRevert "Add GROUP BY ALL".
Tom Lane [Fri, 17 Jul 2026 20:13:57 +0000 (16:13 -0400)] 
Revert "Add GROUP BY ALL".

This reverts commit ef38a4d9756db9ae1d20f40aa39f3cf76059b81a which
implemented the GROUP BY ALL syntax, as well as 2ce745836 which
made some comment improvements therein.

A postcommit review discovered that GROUP BY ALL missed our special
handling of entries that also appear in an ORDER BY in the query.
This caused the query to return wrong results when ORDER BY
specifies non-default equality semantics.  While this should be
fixable with some refactoring, doing it cleanly seems like too
much code churn for late beta.  We'll revert and try again in v20.

The reverted commit also included some additional comment wordsmithing
and docs cleanup, which are retained as they weren't connected to the
reverted feature.

catversion bump needed due to change in struct Query.

Reported-by: Chao Li <li.evan.chao@gmail.com>
Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/5243308F-8E5C-45AA-828C-FAD96C4F34DA@gmail.com
Backpatch-through: 19

2 weeks agodoc PG 19 relnote: move Oauth items
Bruce Momjian [Fri, 17 Jul 2026 19:56:54 +0000 (15:56 -0400)] 
doc PG 19 relnote:  move Oauth items

Reported-by: Jacob Champion
Author: Jacob Champion

Discussion: https://postgr.es/m/CAOYmi+k5h_w5p6HsVJF5k+bNGmChMAhpGU_1gjJMxHg080XibA@mail.gmail.com

Backpatch-through: 19

2 weeks agoFix GiST index-only scan column alignment issue.
Peter Geoghegan [Fri, 17 Jul 2026 19:53:07 +0000 (15:53 -0400)] 
Fix GiST index-only scan column alignment issue.

An index-only scan filled its result slot from the HeapTuple an index AM
returns in scan->xs_hitup by deforming it with the virtual slot's own
tuple descriptor (during GiST and SP-GiST index-only scans).  But index
AMs form that heap tuple using their own descriptor, scan->xs_hitupdesc.
The AM's descriptor may disagree with the IoS virtual slot's descriptor
about each column's precise alignment, leading to "can't happen" errors
in certain rare edge cases.  Hard crashes were possible but much less
likely.

To fix, deform the tuple with the descriptor it was formed with.  This
is simpler, and makes xs_hitup handling (used by GiST and SP-GiST)
uniform with the nearby existing xs_itup handling (used by nbtree).

In practice this issue was very unlikely to be hit (it was found during
testing of a patch that will change the table AM API used during index
scans).  The only currently affected core opclass is GiST's range_ops.
It was only possible for the datum to be accessed at an incorrectly
aligned offset when reading the second or subsequent column from a
multicolumn GiST index.  This couldn't happen in the common case where
the datum used an unaligned short varlena header.  Moreover, an earlier
column had to leave the range datum at an offset where the two
alignments actually disagree (e.g., an odd-length varlena datum).

Author: Peter Geoghegan <pg@bowt.ie>
Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/CAH2-WzkGXa2SKnebdW29RT1hCcQBo_p03v3iqif2u9bjzLB-aQ@mail.gmail.com
Backpatch-through: 14

2 weeks agoci: Generate crashlogs on Windows
Andres Freund [Fri, 17 Jul 2026 15:43:52 +0000 (11:43 -0400)] 
ci: Generate crashlogs on Windows

This configures cdb.exe to log all crashes to
"<workspace>\crashlogs\crashlog-<pid-in-hex>.txt" (as it was previously set up
for cirrus-ci based CI). The upload logs step already collects these logs.

The logic is copied from the generation of Postgres CI Windows images for
cirrus-ci [1].  Since this would be too long to include inline in pg-ci.yml,
it is implemented as 'src/tools/ci/gha_setup_windows_debugger.ps1' script.

[1] https://github.com/anarazel/pg-vm-images/blob/main/scripts/windows_install_dbg.ps1

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CAN55FZ1BgsXSTzOpehnMa4NzWL8Aivsxx-di7-VT6bZ3j2Omow%40mail.gmail.com
Discussion: https://postgr.es/m/iggjozfshwbqpv33x5jqwtju5k5zrkyu3257dlifxkhtpg7eoq@k2ccyrdi5dtu
Backpatch-through: 19, where GHA CI was added

2 weeks agoci: Use optimized build for mingw
Andres Freund [Fri, 17 Jul 2026 15:43:52 +0000 (11:43 -0400)] 
ci: Use optimized build for mingw

The test runtime dominates over the compile time on GHA.  Note that we just
need to remove options, as postgres's default is debugoptimized.

Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/a2ejn7lfqolutzz7kozalbhy3bixdrujb4buc3pgbtlk4am2ba@wbv6v7riia33
Backpatch-through: 19, where GHA CI was added

2 weeks agomeson: Fix ccache issues when using precompiled headers with gcc
Andres Freund [Fri, 17 Jul 2026 15:23:18 +0000 (11:23 -0400)] 
meson: Fix ccache issues when using precompiled headers with gcc

Unfortunately the combination of gcc, precompiled headers, ccache and meson
currently is not safe without further options. The dependencies emitted by gcc
are insufficient to trigger rebuilds when headers "below" the precompiled
headers are changed. Whether that's a ccache, gcc or meson bug is
debatable. Luckily gcc's -fpch-deps option fixes the issue.

This problem occasionally leads to build failures, e.g. if only c.h,
postgres.h or pg_config_manual.h change. That's e.g. the case when creating a
new major version branch.

Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://postgr.es/m/CAN55FZ0tqR6Xz%3DiVFLc1BBoLOEHU775ARhcGYwggHA3XLA%3DoQg%40mail.gmail.com
Discussion: https://postgr.es/m/CA+hUKG+s7Yvt0PUnSQUEjCjysV-7-51n9B1h468Le3VJi0x4ZQ@mail.gmail.com
Discussion: https://postgr.es/m/phsrssp75npoyalqsolcd7fmnmlbzbmquc2p7w7mqjlw7432jk@bzskz3luyjvb
Discussion: https://github.com/ccache/ccache/issues/1686
Backpatch-through: 16, where meson support was added

2 weeks agodoc: Fix SQL quoting in example
Peter Eisentraut [Fri, 17 Jul 2026 13:45:30 +0000 (15:45 +0200)] 
doc: Fix SQL quoting in example

The identifier "order" needs to be quoted, just like in the example a
little bit earlier.

Author: Thom Brown <thom@linux.com>
Discussion: https://www.postgresql.org/message-id/CAA-aLv4xyAaxm8vq5LEhznh-SGphs4wUAGC6Vpas%2B1hHZzzD7A%40mail.gmail.com

2 weeks agoFix truncation rules for base64 encoding
Daniel Gustafsson [Fri, 17 Jul 2026 13:40:16 +0000 (15:40 +0200)] 
Fix truncation rules for base64 encoding

Commit e1d917182 added support for base64url encoding, a base64 variant
intended to be safe for usage in URLs and filenames.  The padding rules
for base64url and base64 differ in that base64url require no extra '='
padding, but the commit unintentionally relaxed this requirement for
base64 as well.  Fix by making sure that the truncation logic check
for the encoding and add a test to make sure.

Backpatch down to v19 where support for base64url was introduced.

Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: David E. Wheeler <david@justatheory.com>
Discussion: https://postgr.es/m/3258FC72-F5E1-40B9-B5D7-64478CAF7728@yesql.se
Backpatch-through: 19

2 weeks agoRestrict pg_stat_io entries for data checksum processes
Fujii Masao [Fri, 17 Jul 2026 11:16:34 +0000 (20:16 +0900)] 
Restrict pg_stat_io entries for data checksum processes

The data checksums launcher and workers were exposed in pg_stat_io
with the same broad set of object/context combinations as general
background workers. However, several of those entries can never
accumulate I/O statistics for these processes, such as bulkwrite,
relation init, temporary relation, and launcher vacuum entries.

Teach pgstat_tracks_io_object() and pgstat_tracks_io_op() about the
actual I/O performed by the data checksum processes. Keep the entries
needed for catalog scans, including bulkread catalog scans, worker
relation processing with a vacuum access strategy, and WAL writes and
initialization, while excluding WAL reads and other object/context
combinations that can never be used.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAHGQGwHz_-nt+YkHDMRZNBZrnoHro8cMOgSwuXEmSYT6vxgQ=w@mail.gmail.com
Backpatch-through: 19

2 weeks agoDoc: Clarify DROP SUBSCRIPTION behavior after SET (slot_name = NONE).
Amit Kapila [Fri, 17 Jul 2026 04:11:07 +0000 (09:41 +0530)] 
Doc: Clarify DROP SUBSCRIPTION behavior after SET (slot_name = NONE).

The previous text claimed that once the slot is disassociated with
ALTER SUBSCRIPTION ... SET (slot_name = NONE), DROP SUBSCRIPTION "will no
longer attempt any actions on a remote host".  That is inaccurate:
DROP SUBSCRIPTION may still connect to the publisher to drop
internally-created table synchronization slots when some table
synchronization is left unfinished.  Reword to describe this, and note
that if the publisher is unreachable those slots (and the main slot, if
it still exists) must be dropped manually to avoid indefinitely reserving
WAL.

Reported-by: Jeff Davis <pgsql@j-davis.com>
Author: Amit Kapila <amit.kapila16@gmail.com>
Backpatch-through: 14
Discussion: https://postgr.es/m/CAA4eK1+tyYSpPxMBy1974kjivuGeR7YY=yopwRGrK3+vCTysdg@mail.gmail.com
Discussion: https://postgr.es/m/D908370F-2695-4231-851D-17179A6A6F2A@gmail.com