1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00
Commit Graph

65366 Commits

Author SHA1 Message Date
Richard Guo
3ad05dea13 Set hasSubLinks when expanding a whole-row join alias reference
If a subquery has been flattened into its parent, the joinaliasvars
entries of a join above it can be arbitrary expressions rather than
plain Vars, so expanding a reference to such a join alias may insert a
SubLink into a lower-level subquery.  flatten_join_alias_vars_mutator
detects that and sets the subquery's hasSubLinks flag, but only in the
single-column code path; the whole-row path just asserted in a comment
that its recursive call would handle this, which is true only when the
alias entry is itself a Var referencing another join.

Hence a whole-row reference to such a join appearing in a sub-select
left that sub-select's hasSubLinks false, so preprocess_expression
skipped SS_process_sublinks for it, and the unprocessed SubLink
reached code that is not prepared for one: this produced "cannot
handle unplanned sub-select" from cost_qual_eval, an assertion failure
in preprocess_aggrefs, or "unrecognized node type" at execution,
depending on where in the sub-select the SubLink ended up.

To fix, make the same check in the whole-row expansion path.

Back-patch to all supported branches.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/CAMbWs49PgeNFhQTZ2gSzwatF0_LXyegMPGt++jSfxUN7NZuQ5Q@mail.gmail.com
Backpatch-through: 14
2026-10-04 12:07:30 +09:00
Tom Lane
e1cda300ff Fix lcov duplicate directory specification in non-VPATH builds.
In an in-tree build, "make coverage-html" invoked lcov with two
"-d ." options, because $(srcdir) is just ".".  With lcov 2.0
(and perhaps earlier versions?) that results in scanning every
foo.gcda file twice and producing counts twice what they should
be.  With later lcov versions (at least 2.3), it results in
"duplicate file" errors.

In VPATH builds we do need two -d options to cover both regular
and generated .c files.  But in in-tree builds it suffices to
specify "-d .", so suppress the second switch.

Author: Narek Galstyan <narek.galstyan@enterprisedb.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAHsn6_xCDQWe8_vVFhtFk27_xTdyVV+Dr0yWzaooBZ6+-VH-5w@mail.gmail.com
Backpatch-through: 14
2026-10-03 14:44:39 -04:00
Álvaro Herrera
10c67bcb2d Clear out values from dropped columns during REPACK (CONCURRENTLY)
When repacking a table concurrently, some border conditions can cause
a concurrent update to propagate the original old tuple to the transient
table (such as a trigger that returns OLD).  That's essentially just
wasted space, which REPACK is there to remove.  Prevent that by setting
the isnull flag to true for any column cataloged as dropped in tuples
being "replayed" as concurrent updates.

Reported-by: Radim Marek <radim@boringsql.com>
Reviewed-by: Antonin Houska <ah@cybertec.at>
Backpatch: 19
Discussion: https://postgr.es/m/CAJgoLkK2UBzB1J9buCsSUbjf7bOqz-o_0=CeiTruU789BhBw-Q@mail.gmail.com
2026-10-03 13:04:41 +02:00
Amit Kapila
a72542b793 Use the relation map's index when searching deleted tuples sequentially.
When the index cannot be used to find a recently deleted row,
RelationFindDeletedTupleInfoSeq() scans the table. It looked up the
relation's replica identity or primary key again to determine which
columns to compare, which could differ from the index selected when the
relation was opened. A concurrent DROP INDEX CONCURRENTLY could remove the
replica identity in between, so the search compared the whole row and
reported the conflict as update_deleted instead of update_missing.

Use the index recorded in the relation map instead. The relation map
already records the replica identity index, or the primary key if there is
no replica identity. It also avoids using a deferrable primary key, which
cannot serve as a replica identity; using its columns could incorrectly
report a deleted row with different values as update_deleted instead of
update_missing.

Author: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Author: Nisha Moond <nisha.moond412@gmail.com>
Reviewed-by: Vignesh C <vignesh21@gmail.com>
Reviewed-by: Zhijie Hou <houzhijie22@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CABdArM5ydwdRrpaZyK1q2p3-vY_+pnBtTmkvg_pcM=gHwmH7Kg@mail.gmail.com
Discussion: https://postgr.es/m/OS7PR01MB1831779ED93F5470CA1D57605F58C2@OS7PR01MB18317.jpnprd01.prod.outlook.com
Backpatch-through: 19
2026-10-02 06:05:41 -04:00
Michael Paquier
fa96254c63 pg_dump: Include column statistics for index-backed constraints
dumpIndex() emits ALTER INDEX .. SET STATISTICS for per-column
statistics targets, but dumpConstraint() never did.  Targets set on the
expression columns of an exclusion constraint's index were silently
lost on dump/restore and pg_upgrade.

The same code can be used in the index and constraint dump code to
generate these ALTER INDEX commands.  The logic has been refactored so
that both share a new subroutine in charge of generating all these
custom SET STATISTICS, if any.

Oversight in e4fca461ab.

Author: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Andrew Krylosov <krylosov.andrew@gmail.com>
Discussion: https://postgr.es/m/CAN4CZFMd9riOuV5LkM+uV=uF-HYp49C8Fh22xWyMxptGLBCZ3A@mail.gmail.com
Backpatch-through: 14
2026-10-02 17:02:39 +09:00
Michael Paquier
7166a1d020 Fix crash when describing a FETCH statement whose cursor is gone
FetchStatementTargetList() dereferenced the portal named by a
FetchStmt without checking that it still exists.  With the extended
query protocol, a client can sent a Parse "FETCH n FROM c" while cursor
"c" is open (which caches a result's TupleDesc), issue a CLOSE on cursor
"c", and then Describe the prepared statement or a portal bound to it.

Describe would re-resolve the target list through the named cursor, and
crash.  In a non-assert builds, this causes a NULL pointer dereference.
An assertion was triggered in assert builds slightly before the pointer
dereference.

This commit changes the describe of a FetchStmt to match with the
ExecuteStmt case: if the named cursor's portal is invalid, fail rather
than assume that the portal should always exist.

A test case is added to libpq_pipeline, backpatchable all the way down.

Author: Dirkjan Bussink <d.bussink@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/7DE248EB-7509-4F8A-9F37-4694A40BBAB7@gmail.com
Backpatch-through: 14
2026-10-02 10:43:27 +09:00
Masahiko Sawada
4a80214270 Refresh autovacuum costs while waiting for parallel workers.
Commit 1ff3180ca0 made a parallel autovacuum leader propagate changes
to the cost-based delay parameters to its workers only from
vacuum_delay_point(), which it no longer reaches once it is waiting in
WaitForParallelWorkersToFinish(). While waiting, the leader neither
processed a config reload nor noticed a change in the number of
autovacuum workers sharing the cost limit, so its workers kept running
with stale parameters until they finished.

Fix by refreshing and propagating the parameters on every wakeup of
that wait loop, and by setting the latches of the balanced autovacuum
workers when their count changes so that a waiting leader wakes up.

A regression test will be added in a separate commit.

Backpatch to v19, where parallel autovacuum was introduced.

Reported-by: Nikolay Samokhvalov <nik@postgres.ai>
Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Manu <manuelreyesbravo@gmail.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/CAM527d-GL=Jp2EJXBSnVBGPK-4XEZwWof5Cv8P0hghS_og6oAg@mail.gmail.com
Backpatch-through: 19
2026-10-01 06:19:26 -07:00
Masahiko Sawada
950a2a1927 Stabilize repack_decode isolation test.
Commit 7164dcb665 added the repack_decode isolation test, whose
s1_decode step counts every change decoded from the slot. A concurrent
autovacuum transaction that modifies only system catalogs is decoded
as an empty BEGIN/COMMIT pair, so the count could come out larger
than expected.

Fix by passing skip-empty-xacts to test_decoding. We pass it, along
with include-xids=0, to s1_decode_updates as well so that both steps
use the same options for consistency, though that step shows only
UPDATE lines and wasn't affected.

Per buildfarm animal skink.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Discussion: https://postgr.es/m/d704cde4-b1f2-48dc-8c5e-659d1128d286@gmail.com
Backpatch-through: 19
2026-10-01 05:52:18 -07:00
David Rowley
5229d4b312 Doc: mention platform-dependent behavior of bitshift operators
There have been several recent complaints that << and >> don't behave
the same way on all supported platforms.  There is a risk that <<
overflows the signed integer type, which is undefined behavior, and there
are platform-dependent behaviors from shifting by numbers of bits >= the
bitwidth of the type, and also from shifting by negative values.

Document this to warn unsuspecting users of these facts.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAApHDvr0O6ZF8NO=Rq9Q+Sz=FHT=NZ1kkNTXZDcNph-OWuk7TQ@mail.gmail.com
Backpatch-through: 14
2026-10-01 15:16:42 +13:00
Tom Lane
9e73b2095f Update time zone data files to tzdata release 2026e.
Canada's Northwest Territories will move to permanent UTC-06 on
2026-11-01.  For now, assume their TZ abbreviation will be CST from
that time forward.  This affects only America/Inuvik as the rest of
the territory is covered by America/Edmonton, for which the
equivalent change was released in 2026c.

Manitoba (America/Winnipeg) will move to permanent UTC-05 on
2026-10-31.  For now, assume their TZ abbreviation will be EST
from that time forward.

(Upstream notes that more changes may be needed soon if smaller
jurisdictions choose to break away from what these have done,
but for now the plan is wait-and-see.)

Historical corrections for Colombia, Iran, and Ireland.

The backward-compatibility zone names EST5EDT, CST6CDT, MST7MDT, and
PST8PDT now conform better to POSIX.  For example, EST5EDT now always
uses the abbreviation "EST" for standard time (now always 5 hours
behind UTC) and "EDT" for daylight saving time, whereas it formerly
had different UT offsets before standard time was introduced and
sometimes used abbreviations like "LMT", "EWT" and "EPT", all contrary
to POSIX.  Also, though not specified by POSIX these names now use US
federal rules rather than rules of specific places like New York,
reverting to 2024a behavior.  This change affects only timestamps
before 1966-10-30 at 01:00 standard time.

Backpatch-through: 14
2026-09-30 17:28:14 -04:00
Tom Lane
a78719fb12 Fix incorrect parallel build of jsonapi.o with Makefiles.
Commit 0785d1b8b wrote

jsonapi_shlib.o: override CPPFLAGS += -DJSONAPI_USE_PQEXPBUFFER

forgetting that GNU make treats this change to CPPFLAGS as affecting
not only jsonapi_shlib.o, but anything that gets built in pursuit of
building jsonapi_shlib.o.  Because of an even more ancient hack
(cf 7143b3e82), that will include jsonapi.o if it's not been built
already.  If we do apply this -D switch to jsonapi.o, it gets built
with the wrong expansible-string infrastructure, which manifests
immediately as a link failure in pg_combinebackup and would misbehave
at runtime even if the build somehow completed.

Perhaps remarkably, we'd not seen field reports of build failures
till now, but it's pretty easy to reproduce a mis-build by trying
to build src/common/ with --shuffle and a high -j factor.

To fix, don't modify CPPFLAGS this way; instead make a dedicated
build rule for jsonapi_shlib.o that injects the additional switches.

There might be other places with similar problems, but some desultory
attempts with -j32 --shuffle on a 32-thread CPU didn't find any more
build failures.  Also, it looks like the meson build infrastructure
lacks this problem (but I'm no meson expert).

Bug: #19727
Reported-by: Ross Burton <ross@burtonini.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Ross Burton <ross@burtonini.com>
Discussion: https://postgr.es/m/19727-32d67d9dea410f38@postgresql.org
Backpatch-through: 18
2026-09-30 15:58:33 -04:00
Heikki Linnakangas
6aa2cefe11 Fix autovacuum docs related to widening multixid offsets to 64 bits
The explanation of aggressive scans claimed that if the multixact
members grows to 2 billion entries, we launch autovacuum even if it's
nominally disabled.  That's no longer true; anti-wraparound vacuum is
only triggered if we're in danger of running out of multixids, we no
longer launch it just to shrink the 'members' SLRU.  There's no
wraparound danger with 'members' anymore, so it's no worse than if a
user table becomes very bloated.

We do still adjust the freeze threshold though, so that if autovacuum
runs, whether on schedule or as an emergency autovacuum to avoid
wraparound, it will freeze more aggressively if the members SLRU is
large.

I removed the mention of the 4 billion member threshold, even though
that still exists, because the explanation felt misleading.  The
aggressiveness is scaled proportionally between 2 and 4 billion
members.  At 4 billion it's as aggressive as it gets, but there's no
sudden cliff.

In the passing, fix some comments.  Remove obsolete mention of safe
threshold for member storage triggering autovacuum.  Secondly, the
freezing cutoff is adjusted to avoid the *members* SLRU from growing
too large.

Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://www.postgresql.org/message-id/20260827231757.78.noahmisch@microsoft.com
Backpatch-through: 19
2026-09-30 15:37:23 +03:00
Heikki Linnakangas
67c01b8478 Allow unknown-size shmem attachments in single-user mode
ShmemRequestInternal() rejected SHMEM_ATTACH_UNKNOWN_SIZE whenever
IsUnderPostmaster was false.  That also rejected an after-startup
attachment in a standalone backend, even if the area exists.

To fix, check whether the shared memory has been initialized
(ShmemIndex == NULL) rather than IsUnderPostmaster.

Refactor the tests, and add more test cases for after-startup
attachment, with SHMEM_ATTACH_UNKNOWN_SIZE and a mismatching size, and
for this single-user case.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discusssion: https://www.postgresql.org/message-id/CAJTYsWXREGXCnWdZJsXt8pT2UY_Y2GSx+HOUu2X3s8YDCLj0_A@mail.gmail.com
Backpatch-through: 19
2026-09-30 14:25:27 +03:00
Michael Paquier
453ebae70c Fix clobbering of proc entry's statusFlags during slot invalidation
ReplicationSlotRelease() copied MyProc->statusFlags unconditionally
when resetting PROC_IN_LOGICAL_DECODING, using its pgxactoff to decide
which area to update.

Slot invalidations can be done by the checkpointer or the startup
process, and ReplicationSlotRelease() ignored the fact that pgxactoff is
only meaningful for processes in the proc array, that auxiliary
processes never join.  pgxactoff would remain at 0 for these, meaning
that an incorrect set of status flags would be updated.

The consequences of this issue could be various, depending on the
statsFlags lost in the proc slot incorrectly overwritten.  Losing
PROC_AFFECTS_ALL_HORIZONS has been mentioned as the worse case, causing
VACUUM to remove rows a standby may needs even if standby feedback is
enabled.  Assertions failures are another possibility.

Let's skip the update of statusFlags unless PROC_IN_LOGICAL_DECODING is
set.  Nothing but StartupDecodingContext() sets it, and no auxiliary
processes call it.

Author: Vlad Lesin <vladlesin@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/889a06dd-45fc-423b-9dd2-87d5b5dc60c6@gmail.com
Backpatch-through: 14
2026-09-30 14:37:14 +09:00
Tom Lane
78d07020bd Prevent self-join elimination when RTEs' checkAsUser fields differ.
SJE didn't consider the possibility that two RTEs referencing the
same table have different securityQuals, and might choose to merge
them anyway, thereby possibly losing quals that need to be enforced.
This is a regression introduced by 2ebf25e7d, since before that we
didn't re-generate baserestrictinfo lists from the RTEs' securityQuals
after performing SJE.

To defend against this, only consider SJE between RTEs with the same
checkAsUser values.  That solves the problem because the set of
applicable RLS policies depends only on the role that is considered
to be accessing the table, so that the securityQuals must be equal
if the checkAsUser values are.  It might also keep us from creating
similar bugs if we ever invent other features that depend on the
accessing role.  And it's a lot cheaper than comparing securityQuals
trees themselves would be, not least because we can't sort them so
the preliminary sort step wouldn't help.

(The first proposed solution was to not perform SJE at all on RTEs
with nonempty securityQuals, but that seems rather sad, especially
since such cases worked before 2ebf25e7d.  Making the restriction
depend on checkAsUser seems much less likely to interfere with SJE
unnecessarily, since in most cases that'll be the same for all
potentially-mergeable RTEs.)

The added test cases show that SJE is rejected when necessary, and
also demonstrate two quirks of this implementation.  One is that if
a removed security qual includes an InitPlan, we'll still attach the
now-unused InitPlan to the plan.  That's because SS_process_sublinks
runs before self-join elimination, so the extra InitPlan has already
been made.  The other quirk is that we won't merge RTEs having zero
and nonzero checkAsUser fields, even if the calling user matches the
nonzero checkAsUser value so that there is no difference for this
user.  That's intentional so that SJE doesn't require having to mark
the plan as caller-dependent.

Reported-by: Yonghwa Lee <underdog@theori.io>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/20260926174457.13.noahmisch@microsoft.com
Backpatch-through: 18
2026-09-29 11:11:15 -04:00
Heikki Linnakangas
f1e60e0eb5 pg_resetwal: Fix handling of commit timestamp XIDs
The help text for -c option documents that zero for either transaction
ID means to leave the corresponding value unchanged.  Commit
978cf02bb8 replaced the separate checks for the two values with a
single flag indicating that the option was specified, causing zero to
be written to the control file instead.

Also parse the second transaction ID with strtouint32_strict(), like
the first one.  Using strtoul() there was an oversight in commit
636c1914b4, which intended to reject negative and out-of-range
arguments.

Author: Chao Li <lic@highgo.com>
Discussion: https://www.postgresql.org/message-id/F61E486B-746B-42F3-A532-B8D4F1519583@gmail.com
Backpatch-through: 19
2026-09-29 16:26:04 +03:00
David Rowley
ecd840a087 Doc: add missing new line in DO example block
Reported-by: Oli Sennhauser <oli.sennhauser@fromdual.com>
Discussion: https://postgr.es/m/777637c4-9d31-498d-a8ef-645fb510bf5a@fromdual.com
Backpatch-through: 14
2026-09-30 02:16:44 +13:00
Daniel Gustafsson
15fea50a8e doc: Fix incorrect output in example
Reported-by: y.saburov@gmail.com
Reviewed-by: David G. Johnston <david.g.johnston@gmail.com>
Discussion: https://postgr.es/m/CAKFQuwZ5zQzv1uyoH1UD5ETb7+ArqF2zNXVU4Et+b0_E8bS2sQ@mail.gmail.com
Backpatch-through: 14
2026-09-29 10:49:15 +02:00
David Rowley
ab274a1e96 Fix incorrect calcSumX2 in numeric deserialize functions
calcSumX2 is used to inform the aggregate transition function whether it
should include the square of the transition value in the aggregate
state.  The deserialize functions for various numeric aggregates that do
use calcSumX2 weren't properly setting the property to true.  This does
not matter in core as we never perform any aggregate transitions after a
deserialize operation.

This fix is only required for external code which plumbs aggregate paths
together in such a way that could result in aggregate transitions being
performed after states have been deserialized.

Author: Maxime Schoemans <maxime.schoemans@enterprisedb.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://postgr.es/m/FEBF5C3D-CC53-455F-AA9D-4D377A2E957C@enterprisedb.com
Backpatch-through: 14
2026-09-29 15:48:44 +13:00
Masahiko Sawada
4331d20f4d Fix crash in parallel autovacuum when no DSM segment can be created.
If no DSM segment can be created, a ParallelContext can still be
created with zero workers, but its seg pointer is NULL. Parallel
autovacuum registered a segment detach callback on that NULL pointer,
crashing the autovacuum worker.

Fix by setting up the shared cost parameters and the detach callback
only when the parallel context has workers, as there are no workers to
propagate the parameters to otherwise.

Oversight in commit 1ff3180ca0.

Found by Bharath using AI assisted review with Claude.

Reported-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Discussion: https://postgr.es/m/CALj2ACVjBN03Fq4XWgKH1zOfkapK6-P3ufNLHUHnZcW1zPm+Mg@mail.gmail.com
Backpatch-through: 19
2026-09-28 16:28:33 -07:00
Álvaro Herrera
2b1d52b197 Turn "check" into assertion
In commit 1813f951ca, I mistakenly assumed that one particular
function named CheckSomething() checks Something.  It doesn't, it merely
return the state to check.  Fix by adding the necessary Assert() call.

Good chance to add trailers for commit 1813f951ca:
Reviewed-by: Manuel Reyes Bravo <manuelreyesbravo@gmail.com>
Reviewed-by: Antonin Houska <ah@cybertec.at>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>

Backpatch-through: 19
Discussion: https://postgr.es/m/CAA-aLv5MF6BLL+BWvix2Yw+CBardtH43AofPReQunhDZPNBtuA@mail.gmail.com
2026-09-28 17:41:38 +02:00
Álvaro Herrera
76a268273c Lock the TOAST table early in REPACK (CONCURRENTLY)
The decoding worker records the relfilenumber of the TOAST table when it
starts, and skips changes stored under any other one, but the TOAST
table was not locked until the data copy began.  If VACUUM FULL rewrote
it while the worker was starting, concurrent updates of TOASTed columns
were silently lost.

Fix by locking the TOAST table in cluster_rel() in the concurrent case,
before the worker starts.

Author: Shihao Zhong <zhong950419@gmail.com>
Reported-by: Thom Brown <thom@linux.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/CAA-aLv5MF6BLL+BWvix2Yw+CBardtH43AofPReQunhDZPNBtuA@mail.gmail.com
2026-09-28 17:12:29 +02:00
Amit Kapila
2f7bf51b7b Fix tuple search during apply after concurrent index DDL.
When searching the local relation by index, the apply worker can use the
first match only if the index is the relation's replica identity or
primary key. Otherwise, every match must be compared with the search slot.

Only the index OID was saved in the relation map, so this was determined
again during the search. Concurrent DROP INDEX or REINDEX can change the
index status between these two checks, causing the tuple search to fail
and the change to be silently skipped as an update_missing conflict.

Fix this by recording the answer as idxisreplident in the relation map
entry and avoid getting it second time in FindReplTupleInLocalRel() and
RelationFindReplTupleByIndex().

Oversight in 89e46da5e5.

Author: Mikhail Nikalayeu <mihailnikalayeu@gmail.com>
Author: vignesh C <vignesh21@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Discussion: https://postgr.es/m/CADzfLwUJovFcnknCC9wjZKECX9xecgnGzC2r2TMV8h4QDD_jwQ@mail.gmail.com
Backpatch-through: 16, where it was introduced
2026-09-28 07:11:29 -04:00
Fujii Masao
23da62e98a Prevent remote notices from repeating local query details in logs
Since 112faf1378, NOTICE, WARNING, and similar messages received through
dblink, postgres_fdw, and replication connections have been logged with
ereport(LOG). With the default log_min_error_statement setting, each
such log entry can also include the current local SQL statement. An active
error-context callback can add local CONTEXT information as well. Repeating
these fields for every remote message increases log volume and processing
overhead.

Use errhidestmt() and errhidecontext() when logging these messages to
prevent the local STATEMENT and CONTEXT fields, when present, from being
repeated for each remote message in the server log.

Reported-by: Merlin Moncure <mmoncure@gmail.com>
Author: Vignesh C <vignesh21@gmail.com
Reviewed-by: Merlin Moncure <mmoncure@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHyXU0yDwOYkWpRi=gtpDwjBxVqeaezgkgZLRWm2p1_FgaiPFQ@mail.gmail.com
Backpatch-though: 19
2026-09-28 18:53:52 +09:00
Fujii Masao
bb356f869f Prevent stale pg_locks.waitstart values
Previously, pg_locks.waitstart could report the start time of a previous
lock wait for a new wait. For a regular backend, this could happen briefly
before the new start time was stored. On a standby, the startup process could
show the old time throughout the next wait, making it appear to have started
earlier than it did.

This happened because PGPROC->waitStart could remain set after a previous
wait in two cases. First, RemoveFromWaitQueue() did not clear it when a wait
was canceled due to a lock timeout, cancellation, or deadlock. Second, even
after a successful lock grant, ProcWakeup() could clear it before the waiter
stored its new start time.

Fix this by clearing waitStart in RemoveFromWaitQueue() when a failed wait
is removed, at the end of ProcSleep() to handle writes made after
ProcWakeup() cleared it, and in LockErrorCleanup() when an error bypasses
the ProcSleep() reset. This prevents pg_locks.waitstart from showing the
previous wait's time for a new wait.

Backpatch to all supported versions.

Author: Shihao Zhong <zhong950419@gmail.com>
Reported-by: Alex Shapalov <shapalov@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Andrew Krylosov <krylosov.andrew@gmail.com>
Discussion: https://postgr.es/m/CAPrb+Q+XN=sNusXiUeWmMo2H7Qgq3Y4uPekSSLkHcnCyf7GhXg@mail.gmail.com
Discussion: https://postgr.es/m/CAGRkXqQLxZBr-ouVrtaX2utMggi4+TiVMbgH04b_0JLgKryxbA@mail.gmail.com
Backpatch-through: 14
2026-09-28 14:21:25 +09:00
Michael Paquier
3004ac4220 Remove OID8_FORMAT from c.h
This marker could break translated strings if used, so let's remove it
and encourage instead the use of PRIu64, something that xgettext is able
to digest.

This marker has been introduced in b139bd3b6e, down to v19 that has
not been officially released yet, so a removal is still possible without
breaking the ABI requirements.

Discussion: https://postgr.es/m/aqeO1OU7uZjhioAq@alvherre.pgsql
Backpatch-through: 19
2026-09-28 13:29:48 +09:00
Michael Paquier
b80d5b17ea Enforce pg_class.relchecks limit (32,767 or INT16_MAX)
pg_class.relchecks reports the number of CHECK constraints in a table,
and is stored within a smallint.  It was possible to define a table that
could overflow the counter when specifying more than 32k constraints
(new table or adding a constraint).  This would cause the table to
become undroppable, as this counter should never be negative when
dropping these constraints.

Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Jian He <jian.universality@gmail.com>
Reviewed-by: Sivaprasad <sivaprasad.postgres@gmail.com>
Discussion: https://postgr.es/m/CAEze2WjSW4qaHYnvkTtbknp85eGEirGJTLMZatotdJJKiA+_hA@mail.gmail.com
Backpatch-through: 14
2026-09-28 06:55:05 +09:00
Tom Lane
054eb938e5 Don't emit garbage "\[un]restrict (null)" commands in pg_dump.
_reconnectToDB() failed to consider the possibility that it could
be called without any restrict_key set.  This is reachable while
generating the "restore.sql" file in tar dump mode, which nobody
noticed because that file is mostly unused (and nothing really
bad happens anyway unless you specified --inserts mode).  But
I wonder if there are other code paths that reach the issue.

Bug: #19718
Reported-by: Pavel Kopylov <pkopylov@cloudlinux.com>
Author: Pavel Kopylov <pkopylov@cloudlinux.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19718-7e945d0ff9b5a589@postgresql.org
Backpatch-through: 14
2026-09-26 12:55:50 -04:00
Etsuro Fujita
a630000c59 postgres_fdw: Improve comment in fetch_remote_statistics().
Mention that the relpages value fetched from a remote server is stored
as-is, regardless of any difference between the remote and local block
sizes.

Follow-up to commit 6a8571568.

Reported-by: Fujii Masao <masao.fujii@gmail.com>
Reported-by: Osama Abdul Qader <osamaabdulqader.cs@gmail.com>
Author: Etsuro Fujita <etsuro.fujita@gmail.com>
Discussion: https://postgr.es/m/CAPmGK14OBMkMEkanHdA9%2BJdrZLGzfNRcEVmb6K4DtDe_CTTTqw%40mail.gmail.com
Backpatch-through: 19
2026-09-26 20:40:01 +09:00
Etsuro Fujita
18c04668f7 Fix privilege handling in postgres_fdw statistics import.
When ANALYZE imports statistics from a remote server, it fetched/stored
the statistics while still running as the user executing ANALYZE, not as
the foreign table's owner.  This is inconsistent with the sampling path,
and it causes a security issue: a role that owns a foreign table but has
no access to the underlying remote data (eg, no access privileges on the
remote server) could obtain that data by having a privileged user run
ANALYZE on the table; the imported statistics like most_common_vals then
expose sampled values from the remote data, as shown in the reproducer
on the discussion thread.

To fix, switch to the foreign table owner's userid in analyze_rel()
before calling the ImportForeignStatistics() routine, mirroring the
identity used by the sampling path.   This not only makes the privilege
handling consistent between the sampling/import paths, but also prevents
statistics import from disclosing data the table owner couldn't
otherwise obtain.

Oversight in commit 28972b6fc.

Reported-by: Fujii Masao <masao.fujii@gmail.com>
Reported-by: Osama Abdul Qader <osamaabdulqader.cs@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Author: Noah Misch <noah@leadboat.com>
Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Etsuro Fujita <etsuro.fujita@gmail.com>
Discussion: https://postgr.es/m/CAPmGK16jVk+i2KMkkgR9ajoPdaUAinvcspkk5Bc6urbo2xYTMQ@mail.gmail.com
Backpatch-through: 19
2026-09-26 20:35:01 +09:00
Amit Langote
f8eb70f050 Check EXECUTE privilege on functions invoked by the RI fast path
ri_FastPathCheck() invokes two functions on the FK values: the
equality operator's function, via the ScanKey the index AM evaluates,
and, when the FK column's type differs from the PK column's, the
implicit cast function.  The SPI path gets EXECUTE on both checked by
ExecInitFunc() when it initializes the generated query, as the
referenced table's owner, but the fast path performed neither check.

Add ri_CheckFunctionPermissions() and call it once the fast-path
metadata is populated, under the switch to the referenced table's
owner, so the checks happen at the same point as the existing relation
permission check.  Add a regression test for each function, reaching
the fast path through per-row validation of a new constraint, and
repeat each against a partitioned referenced table, which takes the
SPI path, to show that the two behave identically.

Reported-by: Nikolay Samokhvalov <nik@postgres.ai> (offlist)
Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com>
Discussion: https://postgr.es/m/CA+HiwqGH+b7sXmsH8sT18diujbheSObWs0gWXqLZqRccMKvZAA@mail.gmail.com
Backpatch-through: 19
2026-09-26 11:09:53 +09:00
Michael Paquier
aa60617b69 Fix import of statistics for domains over [multi]range types and tsvector
pg_restore_attribute_stats() rejected range_length_histogram,
range_empty_frac and range_bounds_histogram for a column whose type is a
domain over a range or a multirange type.  The same issue existed for
most_common_elems and elem_count_histogram for a domain over tsvector.
pg_restore_extended_stats() had the same set of problems for expressions
whose type is a domain over a range, a multirange type, or tsvector.

ANALYZE is able to generate such stats, incorporating the knowledge to
handle domains in the in-core typanalyze callbacks.

This problem is resolved by being more aggressive with the fetch of the
base type of a domain in the early phases of restore for attribute and
extended stats (special tip to Jian He for pointing out the unnecessary
typcache lookups), reflecting on the surrounding helper routines shared
by both code paths.  The fix for v18 is local to attribute_stats.c, as
only attribute stats need to be touched.

Tests are included in a fashion consistent with the surroundings.  The
consequence of this issue was the rejection of stats that ANALYZE was
able to build, which was not critical but annoying as it would lead to a
gap in the stats restored.

Reported-by: Qifan Liu <imchifan@163.com>
Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Jian He <jian.universality@gmail.com>
Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
Discussion: https://postgr.es/m/19715-b8be35083016f289@postgresql.org
Backpatch-through: 18
2026-09-26 09:28:15 +09:00
Tom Lane
d26295f12e Doc: clarify there's no log_line_prefix in csvlog or jsonlog output.
The documentation didn't make clear that "log_line_prefix" is
not output when "log_destination" is "csvlog" or "jsonlog".

Reported-by: Michael Schönitzer <michael@schoenitzer.de>
Author: Laurenz Albe <laurenz.albe@cybertec.at>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/179032875673.1026201.6950455317699774504@wrigleys.postgresql.org
Backpatch-through: 14
2026-09-25 18:36:24 -04:00
Tom Lane
407687a0fb Modernize crypt-des.c a bit, avoiding dubious casts.
The header comment for this file says it assumes that "the CPU is not
picky about alignment", which we wouldn't really accept for Postgres.
The two functions that have alignment requirements have been hacked in
ways that are inconsistent and yet both ugly.  des_setkey just casts
its "const char *" argument to "const uint32 *", relying on the caller
to ensure that that pointer is actually word-aligned, which the caller
does by declaring the buffer as uint32[] and then casting to "char *".
Meanwhile des_cipher carefully memcpy's to and from an internal
uint32[] buffer, which is pretty silly given that what it's passed
must be word-aligned for the benefit of des_setkey.  And on top of
that we have a bunch of ugly casting and oddly-written pointer
arithmetic in the caller px_crypt_des.  The odd pointer arithmetic
causes warnings about possible buffer overrun when using recent gcc
at -O3 or higher.

Let's clean this up by converting the buffer variable into a union
of a uint8 array and a uint32 array, so that we can remove all these
casts, and also replace the strange loop logic with a simple subscript
variable to satisfy gcc.

Reported-by: Andres Freund <andres@anarazel.de>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Co-authored-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/2005885.1790359097@sss.pgh.pa.us
Discussion: https://postgr.es/m/3nuudxv365kjnmwjhnygdakhxuktpdjvf26rt26eb44esgqdrj@y2x3vomkrfoo
Backpatch-through: 14
2026-09-25 15:34:38 -04:00
Álvaro Herrera
a4052efe2a Fix REPACK (CONCURRENTLY) for columns added without a table rewrite
When applying the concurrent data changes, REPACK deformed the decoded
tuples with the descriptor of the transient relation.  That descriptor
has no "missing" values, because make_new_heap() gives the transient
relation none of the defaults and constraints of the source relation.  A
tuple written before an ALTER TABLE ... ADD COLUMN that did not rewrite
the table has fewer attributes than the descriptor, so the missing
values came out as NULL, even in a column declared NOT NULL.  If such a
value belongs to the replica identity, the key used to find the target
tuple was NULL too, so the tuple to modify cannot not be found.  The
scan key does not remember that a value is NULL, so a pass-by-reference
key would even crash the comparison function.  Such tuples will be rare,
because new row versions are normally formed with the current
descriptor.  A BEFORE ROW UPDATE trigger returning OLD is one way to
produce one.

Fix by deforming the decoded tuples with the descriptor of the source
relation, which does have the missing values.  Tuples formed with it are
still valid for the transient relation, whose attributes are a copy of
the source relation ones.  Commit 20d3fe9009 took the same approach
for INSERT and UPDATE in the executor.  Expanding the decoded tuple with
heap_expand_tuple() would be the other option, but that is the
workaround of commit ba9f18abd that 20d3fe9009 got rid of, so do not
bring it back.

Add an isolation test.

Author: Sami Imseih <samimseih.pg@gmail.com>
Reported-by: Shihao Zhong <zhong950419@gmail.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/CAN12+Y+NJwr5EqKVrHpPD=5+b_NRAOzU9fhrVDO3H46x2WRxoA@mail.gmail.com
2026-09-25 14:07:59 +02:00
Amit Langote
9ca52f1a76 Fix missed pgindent in varlena.c
koel's pgindent check only covers master, so this went unnoticed in
REL_19_STABLE.  Fixing it avoids an unnecessary diff between v19 and
v20.

Discussion: https://postgr.es/m/CA+HiwqEzbq+_tjDuOjAQ9bjmHL49LvHy+TT2a1XWTzxXZ-OOiA@mail.gmail.com
2026-09-25 09:46:20 +09:00
Tom Lane
2c5cd772b9 Silence another "may be used uninitialized" compiler warning.
gcc 12.5.0 complains about this instance in LookupFuncWithArgs().
This is the same type of problem fixed in commit f04781df5, and
it's just as obscure why this compiler version picks on this case
when others don't.  Still, silence it in the same way as f04781df5.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/1812498.1790279465@sss.pgh.pa.us
Backpatch-through: 14
2026-09-24 17:57:16 -04:00
Masahiko Sawada
e60ee52841 Add a range check on the sequence index from the publisher.
The sequencesync worker asks the publisher about a batch of sequences,
tagging each one with its position in the worker's own list, and the
publisher returns that position alongside the sequence's data. The
received position is used to subscript the list using list_nth(),
which bounds-checks only on assert builds, so it was possible that an
index we never sent made the worker read a pointer from past the end
of the list and then store the remote last_value through it.

Check the position against the list before using it. No sane publisher
can trigger this, but we should not let a remote server steer a memory
access. An in-range position from another batch still gets through and
would attach one sequence's data to another, but that's a wrong value
rather than a corrupt process.

Also, receive the index as int4 rather than int8. Previously, an
out-of-range int8 value was silently truncated to its lower 32 bits by
DatumGetInt32(), which could turn it into a valid index and defeat the
check.

Backpatch to v19, where sequence synchronization was introduced.

Reported-by: Anthropic OSS program
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAD21AoBWDMuMmnevZaZ1xSOi75eUx8X7LbVQzmUZudk6F8Bdgg@mail.gmail.com
Backpatch-through: 19
2026-09-24 11:05:10 -07:00
Masahiko Sawada
5fd77f6bb6 Don't fully empty GIN pending list in parallel autovacuum workers.
Autovacuum doesn't necessarily fully empty the GIN pending list. It
stops at the tail as of the start of cleanup, so that it doesn't keep
chasing pages appended by concurrent inserters. GIN decided this with
AmAutoVacuumWorkerProcess(), which returns false in parallel vacuum
workers launched by an autovacuum worker, so those workers tried to
fully empty the list as a manual VACUUM does.

Fix this by adding an is_autovacuum field to IndexVacuumInfo, set from
the shared parallel vacuum state in parallel workers, and using it in
GIN instead of checking the process type.

Oversight in commit 1ff3180ca0.

Reported-by: Jingtang Zhang <mrdrivingduck@gmail.com>
Author: Jingtang Zhang <mrdrivingduck@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: Yuhang Qiu <iamqyh@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/CAPsk3_DiF2i1o=JRXRk1YPVMv1VzJaCAbfiEqgwCva4=ZewVAw@mail.gmail.com
Backpatch-through: 19
2026-09-24 10:31:53 -07:00
Heikki Linnakangas
9ac2cb07b4 Fix ShmemInitStruct() reattachment in single-user mode
ShmemInitStruct() only looked for an existing allocation when
IsUnderPostmaster was true.  Because of that, you could not reattach
to an existing shmem area in a standalone backend.

Usually, you only call ShmemInitStruct() for the same shmem area once
in a process and hold onto the returned pointer, but there was no rule
that you couldn't call it twice for the same area if you wanted to,
and before commit 283e823f9d, it worked.  To fix, check for an
existing allocation regardless of process type, like the old
implementation did.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discusssion: https://www.postgresql.org/message-id/CAJTYsWXREGXCnWdZJsXt8pT2UY_Y2GSx+HOUu2X3s8YDCLj0_A@mail.gmail.com
Backpatch-through: 19
2026-09-24 18:21:12 +03:00
Heikki Linnakangas
dae3463fa9 Fix assertion in pg_get_shmem_pagesize() in single-user mode
Remove assertion that was too strict, and tripped if you queried the
pg_shmem_allocations_numa or the pg_buffercache_os_pages view in
single-user mode.

The point of the assertion was that the function should only be called
after "the server has started", but it would be OK to call it from the
postmaster, too, as long as it's after startup, specifically after
huge_pages_status has been set.  We already have a direct assertion
for that.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://www.postgresql.org/message-id/CAJTYsWV-=w5_oFgCnfAixWGc=gMa2pkDinLyGLsb4sKcDaf2FA@mail.gmail.com
Backpatch-through: 18
2026-09-24 14:42:31 +03:00
Amit Langote
5aeb36f327 Ensure ExecutorCheckPerms_hook is called from RI fast path
The fast path's ri_CheckPermissions() called ExecCheckOneRelPerms()
directly, so ExecutorCheckPerms_hook never saw the referenced-table
access that the SPI path's query exposed to it via ExecutorStart().
Modules such as sepgsql that rely on this hook therefore lost control
over FK checks against referenced tables that go through the fast
path.

So, build a one-entry range table and permission-info list and call
ExecCheckPermissions().  The hook now sees the same relation and
requiredPerms as before, once per check that goes through the fast
path.  This also drops the shortcut that skipped the column-level
check when table-level privileges sufficed, since the hook must run
regardless.  While at it, drop the explicit frees in the old code,
because both callers run ri_CheckPermissions() in a per-tuple context
that is reset after each check, so they were redundant.

Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/20260705210533.ee.noahmisch%40microsoft.com
Backpatch-through: 19
2026-09-24 19:30:20 +09:00
Álvaro Herrera
4a4bf490dc Wait for transactions of an initial decoding snapshot to commit
SnapBuildInitialSnapshot() converts the snapshot builder's list of
committed transactions into a regular MVCC snapshot, which is then used
with HeapTupleSatisfiesMVCC().  However, a snapshot produced that way
and used as an MVCC snapshot can potentially cause data corruption, if
it captures a transaction after it writes its commit WAL record but
before it has updated its CLOG entry: it will be incorrectly used to set
hint bits as if that transaction had aborted.

Fix by having SnapBuildInitialSnapshot() wait until such transactions
have removed themselves from procarray, which guarantees correct
visibility.

Other uses of SnapBuildBuildSnapshot only use the snapshot as
historical, so they don't need the waits, but add commentary in that
function to alert possible future callers.

While at this, backpatch commit 504fe10d1d, "Fix misplaced comment in
snapbuild.c."  The comment it moved was nearby the place we modify.

This bug was diagnosed by stress-testing of REPACK (CONCURRENTLY) in
branch 19, so add a test case that tickles it using that feature in that
branch and master.  However, the bug exists in all branches, and in
branch 18 we can add a test with regular logical decoding using
injection points that tickles it.  Unfortunately that test cannot be
backpatched to earlier branches for lack of facilities.

Reported-by: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
Author: Antonin Houska <ah@cybertec.at>
Author: Rui Zhao <zhaorui126@gmail.com>
Backpatch-through: 14
Discussion: https://postgr.es/m/85833.1768840165@localhost
Discussion: https://postgr.es/m/CADzfLwU78as45To9a%3D-Qkr5jEg3tMxc5rUtdKy2MTv4r_SDGng%40mail.gmail.com
2026-09-24 12:24:56 +02:00
Heikki Linnakangas
2ae589741d Fix pg_upgrade from version 9.2
Commit 7f25eccf41 added a cross-check between pg_database.datminmxid
and oldestMulti, but because PostgreSQL 9.2 doesn't have datminmxid,
it broke upgrade from version 9.2.  Disable the check when upgrading
from 9.2 to fix.

This is for REL_19_STABLE only.  Earlier versions don't have the check,
and on 'master' we no longer support upgrading from version 9.2.

Reported-by: Andrew Dunstan <andrew@dunslane.net>
Discussion: https://www.postgresql.org/message-id/baef33d6-0416-48db-8e4d-0529a10a101a@dunslane.net
2026-09-24 13:12:04 +03:00
Michael Paquier
8fbbb338be Forbid pg_get_multixact_stats() during recovery
MultiXactState->oldestOffset is not maintained during recovery, so
calling pg_get_multixact_stats() in this context would report misleading
information.  We could try to work this out by adding this field to the
control file, for example, but such a change would be too invasive at
this stage of the v19 development cycle.

The information of pg_get_multixact_stats() is usually useful to control
the need of some VACUUM or some freezing, operations that cannot happen
on a standby, so the argument to make the function work while recovery
is in progress gets thinner with this point in the balance.

The function is updated to return an ERROR when called under
RecoveryInProgress().

Per discussion with Heikki Linnakangas and Naga Appani.

Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/CA+QeY+DcnsZRL4GZD8JyJu5HD-d6p8_9M5kT4jgF3gq3Rh8n4w@mail.gmail.com
Discussion: https://postgr.es/m/20260827231757.78.noahmisch@microsoft.com
Backpatch-through: 19
2026-09-24 09:36:08 +09:00
Masahiko Sawada
8a2beb5f15 doc: Clarify phase descriptions of pg_stat_progress_repack.
The "initializing" phase was described as expected to be very brief,
but for REPACK (CONCURRENTLY), it also covers enabling and
initializing logical decoding, either of which can take a long
time. Also, the "catch-up" phase includes waiting for the ACCESS
EXCLUSIVE lock needed to swap the files, which was not mentioned.

Adding separate progress phases for these steps is left for v20; for
v19 we only clarify the description.

Author: Sami Imseih <samimseih.pg@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Reviewed-by: Manuel Reyes Bravo <manuelreyesbravo@gmail.com>
Discussion: https://postgr.es/m/CAN12%2BYJOeOyPYB5JS28VE_%2Brzg%3DRbzQXfj58TGfMYwv-TX9mJA%40mail.gmail.com
Backpatch-through: 19
2026-09-23 14:57:50 -07:00
Melanie Plageman
13243ae44c Correct on-access VM setting heuristic
The heuristic to avoid setting the VM during on-access pruning when
doing so would emit an extra FPI missed a few cases. First it missed
temp and unlogged tables. Those will never emit an FPI, so they can
always set the VM if the page is all-visible. It also missed that if
hint bits are not WAL-logged, setting only the VM passes REGBUF_NO_IMAGE
for an already WAL-logged heap page, forbidding a heap FPI in the WAL
record. A page that has never been WAL-logged still requires a heap FPI.

The third is more subtle: If the page is all-visible, the new prune xid
will be InvalidTransactionId. On-access pruning only executes when the
current pd_prune_xid is valid and visible. So, when on-access pruning
finds the page all-visible, it will always clear pd_prune_xid, modifying
the page.

Knowing this means we can set the VM without emitting an extra heap FPI
in more cases. When hint bits are WAL-logged, if the heap buffer is
clean, modifying pd_prune_xid will emit an FPI if one is required. There
is no reason to try to avoid an FPI by not setting the VM. So, set the
VM in this case. However, when the heap buffer is already dirty,
modifying pd_prune_xid can avoid an FPI; so if the page hasn't been
logged since the last checkpoint, setting it all-visible will emit an
extra heap page FPI. We will still avoid setting the VM in this case.

This is being backpatched to 19 because since 378a216187 pd_prune_xid
is set on insert, and if we execute a prune cycle and skip setting the
VM because of an incorrect heuristic, we have added new wasted work in
PG 19.

This commit adds some tests covering these cases. It also updates one of
the existing temp table tests to avoid exceeding the pin limit. Setting
the VM and FSM on-access when querying temp tables takes more local pins
and can run into the limit with fewer heap buffers pinned.

Reported-by: Melanie Plageman <melanieplageman@gmail.com>
Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://postgr.es/m/CAAKRu_amj7qLF4c=9ijd=708Fu2G8gg-2EqwBu=aCdAHU2sPHg@mail.gmail.com
Backpatch-through: 19
2026-09-23 16:40:41 -04:00
Nathan Bossart
f94f8b18d3 Adjust list of major features in the v19 release notes.
Author: Jonathan S. Katz <jkatz@postgresql.org>
Discussion: https://postgr.es/m/e2324238-abec-4026-bd44-9b3e6c70bd49%40postgresql.org
Backpatch-through: 19 only
2026-09-23 14:08:48 -05:00
David Rowley
ad230d5888 Fix incorrect block accounting in TID Range Scans
heapgettup_advance_block() (or heapgettup() and heapgettup_pagemode() in
versions before v16) would incorrectly decrement rs_numblocks when
advancing to the next block.  Ordinarily this was fine, but if the TID
Range scan plan was used by a scrollable cursor and the cursor was fetched
backwards enough to result in another block being required, then
rs_numblocks may have reached 0 prematurely resulting in the scan ending
prematurely.

Reported-by: Jeff Davis <pgsql@j-davis.com>
Author: Ewan Young <kdbase.hack@gmail.com>
Author: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/6b50233fcc0f7d6f4845f083777fa9702d9612e4.camel@j-davis.com
Backpatch-through: 14
2026-09-24 01:19:38 +12:00
Daniel Gustafsson
1b940d1024 doc: Fix example output for format()
The example output for format() didn't show the actual output
generated for the example query.  Backpatch to all supported
branches.

Author: shihao zhong <zhong950419@gmail.com>
Reported-by: y.saburov@gmail.com
Reviewed-by: David G. Johnston <david.g.johnston@gmail.com>
Discussion: https://postgr.es/m/178979714249.1241.1230833804069549466@wrigleys.postgresql.org
Backpatch-through: 14
2026-09-23 14:07:25 +02:00