Michael Paquier [Tue, 21 Jul 2026 07:50:18 +0000 (16:50 +0900)]
Improve generate_partition_qual()'s cache handling on out-of-memory errors
An in-flight failure when trying to set rd_partcheckcxt or
rd_partcheck, while for example doing an allocation in copyObject(),
would leave a backend cache in a corrupted state. The operations are
now ordered so as we avoid a leak in the cache memory context and a
semi-filled cache state when an allocation failure happens.
This is unlikely going to be hit in practice. Like the other
improvements of this kind, no backpatch is done.
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Discussion: https://postgr.es/m/95c64dc2-3abe-4f4e-b285-4c681f565d9f@gmail.com
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
Amit Kapila [Tue, 21 Jul 2026 03:53:11 +0000 (09:23 +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
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.
Fix recovery target test waiting on unavailable WAL
Buildfarm member skink reported a failure in
recovery/003_recovery_targets after commit d5751c33cc3. The newly
added recovery_target_xid set-then-cleared test could time out while
waiting for pg_last_wal_replay_lsn() to reach the expected LSN.
The test recorded lsn6 after calling pg_switch_wal(). As a result,
lsn6 pointed into the next WAL segment, but pg_switch_wal() only
archived the previous one. Since the standby in this test restores WAL
from the archive only, it could not obtain the segment containing
lsn6 and waited indefinitely.
Fix this by recording lsn6 before calling pg_switch_wal(), so the
archived WAL contains the LSN that the standby is waiting for.
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.
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
Recovery target parameters are postmaster-startup GUCs, but their
assign hooks previously did more than assign individual parameter
values. They also updated the global recoveryTarget state and raised
ERROR if more than one recovery target appeared to be set.
This was not a good fit for GUC assign hooks. Assign hooks should not
throw ERROR, and deriving cross-parameter state while individual GUCs
are still being assigned makes the result depend on assignment order
rather than the final configuration.
For example, setting one recovery target and then setting another
recovery_target_* parameter to an empty string could clear
recoveryTarget, causing recovery to proceed with no target even
though a valid target remained configured.
Fix this by having the assign hooks only store their own parameter
values. The effective recoveryTarget is now derived once from the
final recovery_target* settings in
validateRecoveryParameters(), which also rejects configurations that
specify more than one recovery target with FATAL. This preserves the
expected behavior for repeated assignments of the same GUC, treats empty
values as "not set", and removes cross-GUC validation from the assign
hooks.
Allow PostgreSQL::Test::Cluster::start() to pass postmaster options
Previously, tests that needed extra postmaster command-line options had
to invoke pg_ctl start directly, because
PostgreSQL::Test::Cluster::start() provided no way to pass them. That
bypassed the test framework's postmaster PID tracking, so a postmaster
could be left running if the test failed after startup.
Add an options parameter to
PostgreSQL::Test::Cluster::start(), which is passed to pg_ctl's
--options argument. This allows tests to use start() while
preserving the framework's normal cleanup behavior.
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.
Michael Paquier [Mon, 20 Jul 2026 06:52:18 +0000 (15:52 +0900)]
Improve pgstat_get_entry_ref_cached() behavior on out-of-memory errors
A failure in allocating a new cache entry in the backend-level hash
table holding references to shared stats entries would leave the table
in an inconsistent state, crash or FATAL at session exit, depending on
if there are pending stats.
Rather than leaving things in an inconsistent state on OOM, the code is
switched to use MemoryContextAllocExtended(MCXT_ALLOC_NO_OOM), so as an
allocation failure leads to a cleanup of the hash table before issuing
the allocation error.
The problem is unlikely going to show up in practice, so no backpatch is
done. Note that shared memory is not impacted, only a backend-level
hash table.
Reported-by: Alex Masterov <amasterov@gmail.com>
Discussion: https://postgr.es/m/CA+8z=zumV9sscgK=j1Es+-564maVoO9CMDdB9CsW9=FCziCj3w@mail.gmail.com
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
Amit Kapila [Mon, 20 Jul 2026 05:41:45 +0000 (11:11 +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
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
Peter Geoghegan [Mon, 20 Jul 2026 02:15:37 +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.
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
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
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.
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
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
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.
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
Jeff Davis [Fri, 17 Jul 2026 23:41:14 +0000 (16:41 -0700)]
Generate unicode_limits.h.
To ensure we do not overflow a size_t while case mapping on a 32-bit
platform, we need to know the maximum amount a UTF8 string can expand.
Calculate that maximum while generating unicode tables as a part of
the update-unicode target, and output into a new header
unicode_limits.h. Minor refactoring along the way.
Add a StaticAssertDecl to check that a MaxAllocSize text value
expanded by that amount would still have a length that fits in
size_t. (We couldn't actually create a new text value out of that, but
we still need to avoid overflow.)
Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/3213927.1783950167@sss.pgh.pa.us
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
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.
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
Peter Geoghegan [Fri, 17 Jul 2026 19:53:10 +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
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.
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
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
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
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
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.
Amit Kapila [Fri, 17 Jul 2026 04:17:33 +0000 (09:47 +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
Peter Geoghegan [Thu, 16 Jul 2026 22:55:36 +0000 (18:55 -0400)]
Fix wrong variable offset sanity check.
Commit c7aeb775 rewrote the HOT-chain offset sanity checks in three
places, but in heap_get_root_tuples it accidentally tested offnum -- the
outer loop variable, which is already bounded by the loop condition --
instead of nextoffnum, the offset actually passed to PageGetItemId. The
pre-c7aeb775 check tested nextoffnum.
With the check ineffective, a stale t_ctid could make PageGetItemId read
past the end of the line pointer array (which is data corruption that we
expect to be able to catch here).
Author: Peter Geoghegan <pg@bowt.ie> Reported-by: Konstantin Knizhnik <knizhnik@garret.ru>
Discussion: https://postgr.es/m/87c7d8a4-3a82-4334-bee6-e8c2ad3f3293@garret.ru
Backpatch-through: 15
Michael Paquier [Thu, 16 Jul 2026 22:40:10 +0000 (07:40 +0900)]
Remove SQL function getpgusername()
Since 457ac0331cd3, current_user() is the recommended way to get access
to this information, and getpgusername() was marked as deprecated since,
without being documented.
Bump catalog version.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv44sPoKhHZqBvhqRdrFUEKwatGEmXBtqC360UuD5Lt7Nw@mail.gmail.com
The logical decoding status is stored in checkpoint records and used
to restore the status at server startup, but pg_controldata did not
show it. This information is useful for diagnosing issues around the
dynamic activation and deactivation of logical decoding.
Correct logical decoding status at end of recovery with minimal WAL level.
Crash recovery running with wal_level='minimal' can replay an
XLOG_LOGICAL_DECODING_STATUS_CHANGE record that activates logical
decoding, if the server previously ran with a higher wal_level and
crashed after the last logical slot was dropped but before the
checkpointer deactivated logical decoding. Replaying such a record is
correct since it reflects the status at the time it was
written. However, UpdateLogicalDecodingStatusEndOfRecovery() asserted
that logical decoding is never active with wal_level='minimal',
causing an assertion failure at the end of recovery. In production
builds, logical decoding would remain active while running with
wal_level='minimal'.
Instead of special-casing wal_level='minimal', recompute the status at
the end of recovery as usual: no logical slot can exist with
wal_level='minimal' as RestoreSlotFromDisk() would have rejected it,
so the recomputation always deactivates logical decoding in this case,
also writing the corresponding status change record.
Reject infinite and out-of-range interval shifts in uuidv7().
uuidv7(interval) shifts the current time by the given interval before
encoding it into the 48-bit Unix-millisecond timestamp field of the
generated UUID. Two cases were mishandled:
An infinite interval ('infinity' or '-infinity') produced an infinite
timestamp, which overflowed during the conversion to Unix-epoch
microseconds and yielded a garbage UUID. Reject infinite intervals up
front, before any timestamp arithmetic.
A shift that moved the timestamp outside the range representable by
the 48-bit field was silently accepted. Timestamps before the Unix
epoch wrapped when cast to unsigned, and timestamps beyond
approximately year 10889 overflowed the field; both produced UUIDs
with bogus timestamps that break sort ordering. Reject any shifted
timestamp outside the supported range.
Also document that infinite intervals and out-of-range shifts are
rejected.
Although raising a new error changes behavior in a stable branch, this
is back-patched to 18 (where uuidv7(interval) was introduced) because
the previous behavior can silently corrupt data. Failing loudly is far
safer than silently accepting the wraparound; otherwise users may not
discover that their UUIDv7 values are no longer sortable until years
later, when recovery is painful. It also matches how PostgreSQL
already handles timestamp + interval overflow, which raises an
error. The change only affects applications passing an interval large
enough to push the result outside the representable range.
Backpatch to 18, where uuidv7(interval) was introduced.
Tom Lane [Thu, 16 Jul 2026 15:56:01 +0000 (11:56 -0400)]
In transformIndexStmt, transform index expressions in INCLUDING.
Process these just like the adjacent loop for expressions in regular
index columns. This logic was originally omitted because there was
no intention of supporting index expressions in INCLUDING.
There's still no near-term intention of that, but without this change
the ChooseIndexExpressionName code added by 181b6185c spits up on
expressions in INCLUDING: that expects to handle parse-transformed
expressions, and it runs before we reach the place that is currently
supposed to throw the "not supported" error. We could fix this
problem in other ways, but this way avoids contorting the logic,
and it results in less code to be revised not more if we ever get
around to supporting INCLUDING expressions.
Reported-by: Maaz Syed Adeeb <maaz.adeeb@gmail.com>
Author: Tom Lane <tgl@sss.pgh.pa.us> Test-authored-by: Maaz Syed Adeeb <maaz.adeeb@gmail.com>
Discussion: https://postgr.es/m/CAG+FJqOxYj=sVyHcys64h9DbvzP6EUPGHJ7oKj-PW=Qp5Ebk_g@mail.gmail.com
Handle concurrent sequence drops during synchronization
Commit d4a657b0a4d added a call to has_sequence_privilege() while
fetching sequence information from the publisher, so that
publisher-side permission failures could be distinguished from missing
sequences. It also assumed that has_sequence_privilege() could never
return NULL, and asserted accordingly.
However, that assumption was incorrect. If a sequence is dropped after
the synchronization worker collects its metadata but while fetching the
sequence information, has_sequence_privilege() can return NULL.
This can trigger the assertion failure. This was also reported in
a buildfarm failure on member culicidae.
Fix this by treating a NULL result from has_sequence_privilege() as
indicating that the sequence was dropped concurrently, and report it as
a missing sequence instead of asserting that the result is never NULL.
postgres_fdw: stabilize terminated-connection regression tests
The regression test for postgres_fdw_get_connections(true) assumed that
a terminated remote connection would still remain visible in the FDW
connection cache long enough to be reported as closed with a nonzero
remote_backend_pid.
That assumption is not always valid. postgres_fdw_get_connections()
reports only entries that are still present in ConnectionHash, while
pgfdw_inval_callback() may immediately discard an idle cached connection
(xact_depth == 0) when a relevant invalidation arrives. In CI, that can
happen between terminating the remote backend and querying
postgres_fdw_get_connections(true), causing the function to return no
rows.
Adjust the idle-connection test to accept either outcome: if the cache
entry is still present, verify that it reports the expected server name,
closed status, and nonzero remote backend PID; otherwise treat zero rows
as a legitimate result.
To preserve coverage of the terminated-backend reporting path, add a
separate check inside an explicit transaction. In that case, concurrent
invalidation may mark the connection invalid but cannot discard it
before transaction end, so postgres_fdw_get_connections(true) should
still report the terminated connection as in-use, closed, and associated
with a nonzero remote backend PID.
Backpatch to v18, where the affected postgres_fdw_get_connections(true)
test was introduced.
Reported-by: Robert Haas <robertmhaas@gmail.com>
Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CA+Tgmoax3cHXHsm9OidN4F-xiu16y8q2W8T5dTNFic1Zoo2cOw@mail.gmail.com
Backpatch-through: 18
Commit 67846550dc6d removed the xreflabels for initdb options, which
turned the sentence "The second field contains the page checksum if
data checksums are enabled" into "The second field contains the page
checksum if -k are enabled", as well "Only has effect if data checksums
are enabled" into "Only has effect if -k are enabled".
Fix by setting an explicit link text, and while there also change the
link to point to the data checksum page which has more information
than just the initdb option.
The original report was for one instance, further inspection turned
up quite a few more cases. Also redirect the link in the amcheck
docs which albeit was reading right, but will be more helpful if
linking to the main page on data checksums. Backpatch to v18 where
the xreflabels were removed.
Peter Eisentraut [Thu, 16 Jul 2026 09:47:41 +0000 (11:47 +0200)]
Require ICU 55 or later
Support for older versions is removed. Since we no longer support
RHEL 7, we don't need to support these old versions anymore. This
allows a fair amount of code cleanup, including some code blocks that
specifically catered to old versions that probably received very
little actual testing and use.
Peter Eisentraut [Thu, 16 Jul 2026 09:47:41 +0000 (11:47 +0200)]
Make PL/Tcl require Tcl 8.6 or later
Support for Tcl 8.5 and 8.4 is removed. Since we no longer support
RHEL 7, we don't need to support these old versions anymore. This
allows some small amount of code cleanup.
Peter Eisentraut [Thu, 16 Jul 2026 09:47:41 +0000 (11:47 +0200)]
Drop support for _MSC_VER less than 1933
Commit aa7c8685234 added a workaround for _MSC_VER less than 1933,
which is Visual Studio 2022 version 17.3. Since we dropped support
for Visual Studio before 2022, and the versions up to 17.3 are long
EOL, we can drop this extra code.
Peter Eisentraut [Thu, 16 Jul 2026 09:47:41 +0000 (11:47 +0200)]
Raise requirement to Visual Studio 2022
The use of _Generic from commit "Replace __builtin_types_compatible_p
with _Generic" causes compiler errors from VS 2019. Apparently, that
compiler is just broken for that (even though it appears to support
_Generic in general, for example in commit 59c2f03d1ec).
Per discussion, just drop support for VS 2019 and require at least VS
2022. This just updates the documentation about that. In passing,
some information about VS 2026 is added.
Check CREATE_REPLICATION_SLOT response shape in libpqwalreceiver
Previously, libpqrcv_create_slot() checked only that
CREATE_REPLICATION_SLOT returned PGRES_TUPLES_OK before reading
values from the first row. If the server unexpectedly returned an
invalid result, such as zero rows, PQgetvalue() could return NULL,
leading to a crash while parsing the LSN.
Other replication commands, such as IDENTIFY_SYSTEM, already validate
the response shape before accessing result values, but
CREATE_REPLICATION_SLOT did not.
Fix this by verifying that CREATE_REPLICATION_SLOT response contains
exactly one row with four fields, and report a protocol violation otherwise.
doc: Mention REPACK in MAINTAIN privilege descriptions
REPACK requires the MAINTAIN privilege, but it was omitted from the
lists of commands covered by that privilege in ddl.sgml and the
description of the predefined pg_maintain role in user-manag.sgml.
This was an oversight in commit ac58465e061, which introduced
REPACK.
Add REPACK to both documentation lists, and update the corresponding
comment in aclchk.c.
doc: Fix log_parameter_max_length docs to reference log_min_duration_statement
The documentation for log_parameter_max_length said it affects messages
generated by log_duration. However, log_duration alone does not log bind
parameter values, so this is misleading.
This commit updates the documentation to reference log_min_duration_statement,
which can log bind parameters, to better reflect actual behavior.
The WAL summarizer only tracks registered buffers, so unregistered VM
clears are ommitted from incremental backups, corrupting the restored
visibility map. Test those cases are now fixed.
Heap WAL records that clear bits on the visibility map (like inserts and
deletes) did not register the visibility map blocks they modified.
Because the WAL summarizer only records registered blocks, an
incremental backup taken over such operations would omit the changed VM
pages. On restore, the VM would retain stale all-visible/all-frozen
bits, which can cause wrong results from index-only scans and incorrect
relfrozenxid advancement due to vacuum page skipping.
Not registering the VM buffer also meant we never emitted FPIs of VM
pages when clearing bits. A torn VM page won't raise an error because
the VM is read with ZERO_ON_ERROR; with checksums on, it would be
detected and zeroed, but with checksums off, it is accepted as-is and
can lead to data corruption.
Fix this by registering the VM buffer in the WAL record when clearing VM
bits. The VM buffer must now be locked throughout the critical section
that modifies the VM and heap pages and emits the WAL record. This can
slow down operations that clear the VM, since the VM lock is held longer
and VM FPIs may be emitted, but it is required for correctness.
Note that this fix does not repair existing incremental backups.
Bumps XLOG_PAGE_MAGIC.
Author: Melanie Plageman <melanieplageman@gmail.com>
Author: Andres Freund <andres@anarazel.de> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://postgr.es/m/flat/CAAKRu_bn%2Be7F4yPFBgFbnP%2BsyJRKyNK092bjD2LKvZW7O4Svag>
Backpatch-through: 17
Make VM clear take a RelFileLocator and not fake relcache
This brings it in line with visibilitymap_set(). An upcoming commit will
start reading visibility map buffers with XLogReadBuffer*() functions,
so we no longer require a relation object to pin the visibility map,
allowing us to remove this fake relcache business altogether.
While we're at it, remove a spurious const qualifier from the
RelFileLocator parameter to visibilitymap_set().
Introduce macros for WAL block reference IDs of some heap record types
When registering a buffer with the WAL machinery, the caller assigns it a
block reference ID, and replay must read each block back by that same ID.
Today these IDs are bare integers assigned by convention (0, 1, 2, ...),
which is easy to follow when a record registers a single block, or when the
blocks are handled during replay in their registration order.
An upcoming bug fix registers up to two visibility map blocks in addition
to the heap block(s) when clearing the VM, and these are not handled during
replay in a straightforward 1:1, in-registration-order fashion. Relying on
bare integers for the block IDs in that case is error-prone.
Introduce macros naming the block reference IDs for the heap record types
that the upcoming commit extends to register visibility map blocks, so the
registration and replay sites refer to the same block by a meaningful name.
Include last block in FSM vacuum of bulk extended relation
When bulk-extending a relation, we add the newly-added blocks that we
won't immediately use to the free space map and then call
FreeSpaceMapVacuumRange() to propagate that free space up the FSM tree,
so other backends can find and reuse it.
However, the end block argument to FreeSpaceMapVacuumRange() is
exclusive, and we passed the number of the last added block (since 00d1e02be24). If that block was the first one covered by a new FSM page,
its free space wasn't propagated up the tree and was therefore invisible
to FSM searches until the next FSM vacuum.
Fix by passing the block number one past the last added block, so the
full range is vacuumed.
Jeff Davis [Wed, 15 Jul 2026 19:34:20 +0000 (12:34 -0700)]
Fix like_fixed_prefix_ci() selectivity.
A wrong calculation introduced by 9c8de15969 could cause trailing
characters from the prefix to be passed to like_selectivity() rather
than just the "rest".
Robert Haas [Wed, 15 Jul 2026 17:04:32 +0000 (13:04 -0400)]
Add additional sanity checks when reading a blkreftable.
Code elsewhere in the system assumes that fork numbers and chunk sizes
are within bounds, so the code that reads those quantities from disk
should validate that they are. Without these additional checks, a
corrupted file can cause us to index off the end of fork number or chunk
entry arrays, potentially resulting in a crash.
Reported-by: oxsignal <awo@kakao.com> (chunk sizes) Reported-by: Robert Haas <rhaas@postgresql.org> (fork numbers) Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: http://postgr.es/m/CA+TgmoYP8RKoBGosS7C6Fdr-GNCfyz_W1zmK=Tx1Fe0ZvzGh0g@mail.gmail.com
Backpatch-through: 17
Fix argument names in pg_clear_attribute_stats() errors
pg_clear_attribute_stats() checks its required arguments manually
because the function is not strict. Previously, when schemaname or
relname was passed as NULL, the error incorrectly reported the
argument name as "relation" in both cases:
ERROR: argument "relation" must not be null
This was misleading, especially for schemaname, and inconsistent with
the function's SQL-visible argument names.
The cause is that cleararginfo[] in attribute_stats.c used
"relation" for both the schema-name and relation-name arguments.
This commit fixes the issue by using "schemaname" and "relname" instead,
matching the function's declared argument names so that the error reports
the correct argument name.
Backpatch to v18, where pg_clear_attribute_stats() was introduced.
Amit Kapila [Wed, 15 Jul 2026 10:10:36 +0000 (15:40 +0530)]
Reject concurrent sequence refreshes.
'ALTER SUBSCRIPTION ... REFRESH SEQUENCES' can race with an already
running sequence synchronization worker. If a second refresh request
resets the synchronization state while the worker has already fetched
sequence values from the publisher but has not yet applied them to the
subscriber, the worker can overwrite the subscriber with stale values
and mark the synchronization as complete.
Avoid this race by rejecting 'ALTER SUBSCRIPTION ... REFRESH SEQUENCES'
when a sequence synchronization worker is already running for the
subscription. The command reports an error asking the user to rerun it
after the current synchronization completes.
Also add a wait for the re-added 'regress_s4' sequence to finish
synchronizing in 036_sequences.pl, so the subsequent test does not race
against its sequencesync worker.
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, where it was introduced
Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com
Peter Eisentraut [Wed, 15 Jul 2026 08:58:13 +0000 (10:58 +0200)]
Add assertion about ssize_t narrowing in AIO code
The result from pg_preadv() or pg_pwritev(), which is of type ssize_t,
is assigned to PgAioHandle.result, which is of type int. This should
be ok because the maximum result is limited by PG_IOV_MAX times
BLCKSZ. Add an assertion and a code comment to explain and check
this.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Peter Eisentraut [Wed, 15 Jul 2026 08:58:13 +0000 (10:58 +0200)]
Clean up write() return type
and analogously for pg_pwrite() and FileWrite()
Be sure to store the return value in a variable of type ssize_t, not
int.
Some callers of FileWrite() did not have a separate error message for
a short write. This is okay in practice because FileWriteV() sets
ENOSPC for all non-error returns, so you'll get a reasonable error
message either way. But callers handled this inconsistently, and this
behavior isn't really prominently documented and commit 871fe4917e1
seems to frown upon it, so it seems better to make all callers handle
this consistently by adding the separate error message.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Peter Eisentraut [Wed, 15 Jul 2026 07:43:03 +0000 (09:43 +0200)]
Clean up read() return type
and analogously for pg_pread() and FileRead()
Be sure to store the return value in a variable of type ssize_t, not
int.
Also make the error messages for short reads consistent. They should
always be like "read %zd of %zu". Appearance of other placeholders
indicates the types are probably wrong (although in some cases some
casts are added to make macros have the right type and keep the
strings consistent, and it some cases it's left as "%zu of %zu", which
is close enough).
In several cases, the input length is derived from struct stat
st_size, which has type off_t, which is neither size_t nor ssize_t.
To keep the type handling clearer, this introduces intermediate
variables in these cases.
In SendTimeLineHistory() in walsender.c, we need to adjust the logic a
bit to over underflow wrap if we end up reading more from the file
than expected. This is believed to be a theoretical problem only.
Alternatively, we could treat this as an error. Note that the
previous code would have processed the extra data but only up to a
full block, which seems wrong in any case.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Peter Eisentraut [Wed, 15 Jul 2026 05:59:42 +0000 (07:59 +0200)]
Clean up secure_read()/secure_write() return type
The return type is ssize_t, not int, but some callers didn't handle
this properly.
The BIO callbacks are constrained by the OpenSSL API, so they take int
for the length and return int. This is safe, since the return value
can't be greater than the input length. To make it more clear that
this is intentional, cast the result of the
secure_read()/secure_write() call to int explicitly.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Michael Paquier [Wed, 15 Jul 2026 01:34:19 +0000 (10:34 +0900)]
Rework pgstat_write_statsfile() in combination with to_serialized_data
Contrary to the from_serialized_data callback used by the pgstats reads
at startup, the to_serialized_data callback used for the pgstats writes
matched with pgstat_write_statsfile(), by not returning a boolean
status, expecting a ferror() failure to deal with the discard of the
stats file should an error happen while writing the stats. This was
slightly confusing designed this way.
Things are changed in this commit with:
- to_serialized_data now returns a boolean status on a write failure.
pgstat_write_statsfile() detects that and switches to failure mode
instead of continuing to process the entries to write, speeding up the
shutdown.
- pgstat_write_statsfile() now uses STATS_DISCARD if a failure happens,
to let the registered callbacks directly know that something is wrong,
and that things need to be cleaned up. This gives a better error path
detection for custom stats kinds. For example, they do not have to rely
solely on the expectation of an ferror() for an auxiliary file.
This new set of behaviors matches with what is already done in
pgstat_read_statsfile() for the finish() callback (DISCARD on failure,
READ on success) and the from_serialized_data with a status returned.
Author: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/CAA5RZ0sMgOvuhpb2P=KSJOjgjC6AfUu+GYcu9mHar-y_Xtd=Pg@mail.gmail.com
Backpatch-through: 19
Michael Paquier [Wed, 15 Jul 2026 01:03:35 +0000 (10:03 +0900)]
Include check on polpermissive relcache for policies
equalPolicy() is used in the relation cache to check if two policy
definitions are equivalent, but missed to check for polpermissive.
ALTER POLICY cannot switch a policy to be PERMISSIVE or RESTRICTIVE, so
this would need a dropped and then re-created policy, which would
trigger a relcache invalidation. Anyway, there is no harm in being
consistent in the check, and if one decides to add an ALTER POLICY to
switch PERMISSIVE or RESTRICTIVE, we would be silently in trouble.
Richard Guo [Wed, 15 Jul 2026 00:20:35 +0000 (09:20 +0900)]
Strip removed-relation references from PHVs in join clauses
Commit 9a60f295b stripped the stale PlaceHolderVars left behind by
left-join removal from the surviving rels' baserestrictinfo and from
EquivalenceClass member expressions, but it overlooked join clauses.
A PlaceHolderVar embedded in a join clause can likewise retain the
removed rel and join in its phrels, since remove_rel_from_query()
fixes up the RestrictInfo's own relid sets but not the PHVs inside its
expression.
As before, this is normally harmless, because later processing
consults those relid sets rather than the embedded PHVs. However, a
restriction clause derived from such an OR join clause inherits the
stale PlaceHolderVar, and when the derived clause is translated for an
appendrel child, pull_varnos() recomputes its relids and folds the
removed relation back in. The rebuilt clause then references a
no-longer-existent relation, tripping an assertion during path
generation.
Fix by also stripping the removed relation from the PlaceHolderVars in
the surviving rels' join clauses, including the sub-clauses of any OR
clause.
Like 9a60f295b, this is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars.
Author: Arne Roland <arne.roland@malkut.net> Reviewed-by: Tender Wang <tndrwang@gmail.com> Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/27a44087-3d65-473e-8d88-7c12228e0d7e@malkut.net
Backpatch-through: 18
Michael Paquier [Tue, 14 Jul 2026 23:05:03 +0000 (08:05 +0900)]
Revert "Rename routines for write/read of pgstats file"
This reverts commit ed823da1289, that has made pgstat_write_chunk() and
pgstat_read_chunk() available for public use. These routines do not
have a symmetric API definition across reads and writes, with the write
part returning a void status, deferring an error detection once all the
stats entries have been processed with an ferror(), and the read part
returning a boolean status.
These routines are just tiny wrappers around fread() and fwrite(), and
extensions can just define they own routines instead of relying on the
same facilities as the core pgstat.c. This commit removes their
declaration from the public headers, to reduce the confusion.
test_custom_stats is updated to use its own read/write routines.
Perhaps something better could be designed in the future; trying to do
so for v19 is not feasable during beta.
Reported-by: Peter Eisentraut <peter@eisentraut.org>
Author: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/a4a8e9af-3eaf-4bbf-9b21-21620f3fc434@eisentraut.org
Backpatch-through: 19
postgres_fdw: don't push down non-relabeling ArrayCoerceExpr
Commit 62c3b4cd9ddc taught postgres_fdw to push down ArrayCoerceExpr, but
foreign_expr_walker() only recursed into the input array expression and
never examined elemexpr, the per-element conversion that gives the
coercion its semantics. deparseArrayCoerceExpr() then shipped a bare
"arg::resulttype" cast, or nothing at all for an implicit-format
coercion, leaving the remote server to re-resolve the element conversion
against its own catalogs and session state.
This produced wrong results or remote errors whenever the element
conversion was not a plain relabeling, and it was inconsistent with how
postgres_fdw treats the equivalent scalar coercions. An ArrayCoerceExpr
was shipped even when its elemexpr was a cast function (whose
shippability was never checked), a CoerceViaIO (e.g. float8out or
byteaout, which depend on extra_float_digits / bytea_output that
postgres_fdw sets differently on the remote session), or a
CoerceToDomain (which pushes domain enforcement to the remote catalog).
By contrast, a scalar CoerceViaIO is never shipped, and a scalar cast
function is shipped only when it is shippable.
Restrict pushdown to element coercions that are a plain relabeling, that
is, elemexpr is a RelabelType or a bare CaseTestExpr. Any other element
coercion is now evaluated locally. This keeps the common
binary-coercible case pushed down, including "col = ANY($1)" with a
varchar[]-to-text[] relabeling, which is the case 62c3b4cd9ddc set out to
optimize.
Pushing down shippable element cast functions, to reach parity with the
scalar case, is left out here for simplicity.
Remove unreachable error check in JSON_TABLE plan transform
transformJsonTableNestedColumns() looked up the nested column named by a
JSON_TABLE PLAN node and raised "invalid JSON_TABLE plan clause / PATH
name was %s not found in nested columns list" if none was found. That
lookup cannot fail: validateJsonTableChildPlan() runs first, at every
plan level, and already matches the plan's sibling path names one-to-one
against the nested columns (reporting any uncovered nested path or any
extra or duplicate sibling node). The check has been unreachable since
the PLAN clause code was first written.
Replace it with an Assert documenting the invariant, which also removes
a user-facing message that could never be emitted.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv5_9%3DzgA_Y7aoFp-%2BQSeh0kx4dfbAas9Wx%3DyrweQSqa6Q%40mail.gmail.com
Avoid redundant re-evaluation of JSON_TABLE nested paths
86ab7f4c721d makes JSON_TABLE with a NESTED PATH re-ran the nested path's
jsonpath expression several times for each parent row. That makes such
queries significantly slower as the nested arrays grew, even without a PLAN
clause.
Two leftovers from the plan/join executor rework were responsible.
JsonTablePlanScanNextRow() still reset and advanced the nested plan
itself, although JsonTablePlanNextRow() now does that; and
JsonTableResetNestedPlan() eagerly called JsonTableResetRowPattern()
(which evaluates the path) in addition to setting the reset flag that
makes JsonTablePlanNextRow() evaluate it again. Together these caused
the nested path to be evaluated multiple times per parent row.
Reduce JsonTablePlanScanNextRow() to advancing its own row pattern
iterator, and have JsonTableResetNestedPlan() only reset the transient
scan state (so a not-yet-advanced sibling still reads as NULL) while
deferring the actual path evaluation to the reset flag. The nested path
is now evaluated exactly once per parent row, as before the PLAN clause
feature; results are unchanged and are covered by the existing tests.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv5U94KD4C%2BLhAPYcCeGvs1xBMngcS5oEkZHN9YWwXUHsA%40mail.gmail.com
Correct the JSON_TABLE synopsis to place the ON ERROR clause after the
PLAN clause, matching the grammar (the previous order could not be
typed). Replace a dangling reference to json_path_specification with
path_expression, the term the synopsis actually defines. Mark up the
PLAN DEFAULT keywords with <literal> and fix a couple of wording issues.
Also list OUTER before INNER consistently, including in the parent/child
join description, where OUTER is the default.
Author: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv5PGAFmAEpbhKQz8wppoOOTHfo-=LJb2sAB3974-9QtOw@mail.gmail.com
Make JSON_TABLE generated path names avoid collisions
generateJsonTablePathName() produced names of the form
"json_table_path_N" in the same namespace as user-supplied path and
column names, without checking whether the name was already in use.
When an unnamed NESTED path's generated name happened to match a
user-supplied path name that a PLAN clause referenced, two sibling paths
matched the same plan entry and one of them, together with its columns,
was silently dropped from the output.
Bump the counter until the generated name is unused, so a generated name
can no longer coincide with a user-supplied one. The still-uncovered
path is then correctly reported as not found in the plan.
The row pattern (root) path is named before the user-supplied column and
path names are collected, so when it is left unnamed its generated name
could not avoid them either, and a user column or path named like a
generated name, e.g.
SELECT * FROM JSON_TABLE(jsonb '1', '$'
COLUMNS (json_table_path_0 int PATH '$')) jt;
was rejected with a bogus "duplicate JSON_TABLE column or path name"
error. Collect the user-supplied names first and generate the row
pattern path's name afterwards, so that it avoids all of them. An
explicit root path name is still seeded into the namespace, so a column
duplicating it is still correctly rejected.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv7aZGSExnbjJRw8eKkoXbu34TdoKLLA2gPye3aHjO5OSA@mail.gmail.com
Discussion: https://postgr.es/m/CAA-aLv5U94KD4C%2BLhAPYcCeGvs1xBMngcS5oEkZHN9YWwXUHsA%40mail.gmail.com
Fix JSON_TABLE PLAN deparse to keep parentheses around nested joins
get_json_table_plan() parenthesized the child of a parent/child
(OUTER/INNER) plan only when that child was a sibling (UNION/CROSS)
join, not when it was itself a parent/child join. A plan such as
PLAN (p0 OUTER (p1 INNER p11)) was therefore deparsed as
PLAN (p0 OUTER p1 INNER p11), which does not parse back to the same
plan tree -- a dump/restore hazard. Parenthesize the child whenever it
is not a bare path name, matching the logic already used for the
operands of sibling joins.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv7aZGSExnbjJRw8eKkoXbu34TdoKLLA2gPye3aHjO5OSA@mail.gmail.com
86ab7f4c721d commit made the table-level ON ERROR clause serve as the default
ON ERROR for columns lacking their own, so that a top-level ERROR ON ERROR
turned per-column evaluation errors into hard errors.
The SQL standard does mandate this cascade, but introducing it should be
a deliberate, separately-documented change, so restore the previous
behavior for now. This also reverts the paired ruleutils.c logic that
deparsed a column's behavior against an ERROR default: that dropped an
explicit ERROR ON EMPTY from a dumped view, and otherwise emitted a
redundant NULL ON EMPTY.
Reported-by: Thom Brown <thom@linux.com>
Discussion: https://postgr.es/m/CAA-aLv7aZGSExnbjJRw8eKkoXbu34TdoKLLA2gPye3aHjO5OSA@mail.gmail.com
Peter Eisentraut [Tue, 14 Jul 2026 08:28:04 +0000 (10:28 +0200)]
Replace __builtin_types_compatible_p with _Generic
_Generic is the C11 standard equivalent (and superset) of
__builtin_types_compatible_p, so by replacing the latter with the
former, we can now rely on this working on all compilers, instead of
previously just with GCC-compatible ones. And we can drop a configure
test.
This affects StaticAssertVariableIsOfType() and
StaticAssertVariableIsOfTypeMacro() and indirectly unconstify() and
unvolatize().
Neither _Generic nor __builtin_types_compatible_p works in C++, so
this does not change that, but this adds an explicit code comment
about that.
There are some subtle behavior changes, but these do not affect cases
that are in use or likely to be useful. _Generic does lvalue
conversion on the controlling expression, which means it drops
top-level qualifiers and converts arrays to pointers.
__builtin_types_compatible_p on the other hand, supports arrays and
just ignores qualifiers. So before, StaticAssertVariableIsOfType(x,
const int) might have worked, but now it does not. (But note that it
would previously have succeeded even if x was a non-const int, so this
usage would always have been dubious.) Also,
StaticAssertVariableIsOfType(y, char[]) would have worked, but now you
need to write char *. (But this is not backward compatible, because
char * would previously not have succeeded.) Similarly, unconstify of
non-pointers, like unconstify(const int, x) would previously have
worked, but this was just by accident and never useful (you can just
assign directly, without a cast), and the C++ implementation rejects
non-pointers anyway. Some comments are added to explain this a bit.
There are no current uses affected by this.
Note that even though we have required C11 since f5e0186f865, we have
not made use of _Generic until now (except in an MSVC-specific case in
commit 59c2f03d1ec). This now raises the effective compiler
requirement on the trailing edge slightly from GCC 4.8 to GCC 4.9.
This in turn means that we effectively drop support for RHEL 7.
Author: Peter Eisentraut <peter@eisentraut.org> Co-authored-by: Thomas Munro <thomas.munro@gmail.com> Co-authored-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/flat/CA+hUKGL7trhWiJ4qxpksBztMMTWDyPnP1QN+Lq341V7QL775DA@mail.gmail.com
Michael Paquier [Mon, 13 Jul 2026 23:00:46 +0000 (08:00 +0900)]
Add recovery test for missing redo segment with backup_label
This commit adds a test case for early startup where a backup_label file
uses a checkpoint LSN and a redo LSN located in two different segments,
where the segment of the redo LSN is missing. This code has never been
covered, and is complex enough that a test case is going to be useful in
the long-term.
Nitin has proposed a more complex approach than what is added by this
commit, by forcing a reuse of the injection points to produce a split
between redo and checkpoint. This commit relies on the checkpoint and
redo LSNs generated by the first steps of the test, combined with a
generated backup_label, making the whole cheaper.
Author: Nitin Jadhav <nitinjadhavpostgres@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAMm1aWZ9Tv=Wrx52_2Ppw+6ULf_twRZuQm=ZWLA_a-kXWykHkQ@mail.gmail.com
Peter Eisentraut [Mon, 13 Jul 2026 09:01:36 +0000 (11:01 +0200)]
Make blkreftable API use size_t/ssize_t consistently
It was using int for the input and output length, where size_t or
ssize_t would be more appropriate. It might not matter in practice,
but it makes the APIs consistent at all levels.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Peter Eisentraut [Mon, 13 Jul 2026 09:01:36 +0000 (11:01 +0200)]
Clean up readlink() return type
The return type of readlink() per POSIX is ssize_t, but most existing
callers use int, so fix that. Also fix the return type of the Windows
implementation to match.
In _pglstat64(), we neglected to handle the case where the output
buffer is not large enough and the result would be truncated. This
case actually can't happen, because the Windows pgreadlink()
implementation doesn't ever return that case, but adding this seems
good for consistency with _pgstat64(), which already had this check,
and in case pgreadlink() ever changes in this regard.
Some callers of readlink(), in particular _pglstat64(), assume that
errno == EINVAL means that the file was not a symlink. But Windows
pgreadlink() also sets EINVAL in other cases, in particular if the
buffer was too small. This could result in incorrect behavior, so
pick a different errno. (There might be other cases where EINVAL is
set inappropriately, but they are outside the theme of this patch.)
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Peter Eisentraut [Mon, 13 Jul 2026 09:01:36 +0000 (11:01 +0200)]
Some const qualifications added in passing
These are some cases in the vicinity of the patches to improve the
size_t/ssize_t use with POSIX file system APIs. For example, the
input buffers for write operations or the file names passed for error
reporting can be const.
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://www.postgresql.org/message-id/flat/f9aab072-0078-49e4-ab93-3b08086a4406@eisentraut.org
Amit Kapila [Mon, 13 Jul 2026 03:57:47 +0000 (09:27 +0530)]
Don't show tables redundantly when their schema is published.
A table published both explicitly and through its schema (FOR TABLES IN
SCHEMA) was listed twice by \dRp+ and \d. Since publishing a schema
publishes its tables in full, the explicit entry's row filter has no
effect; suppress it when the same publication also publishes the table's
schema.
Author: Peter Smith <smithpb2250@gmail.com>
Co-author: Jim Jones <jim.jones@uni-muenster.de> Reviewed-by: Nisha Moond <nisha.moond412@gmail.com> Reviewed-by: vignesh C <vignesh21@gmail.com> Reviewed-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Discussion: https://postgr.es/m/CAHut%2BPvSOmRrQX%2BVrFYHtFipV9hM%3Dp99FeOwYCzkuU2BOaLu7Q%40mail.gmail.com
Michael Paquier [Mon, 13 Jul 2026 00:19:20 +0000 (09:19 +0900)]
Add recovery/startup test with backup_label and missing checkpoint segment
This test is able to trigger the following failure at the beginning of
recovery, that was not covered yet:
FATAL: could not locate required checkpoint record at %X/%X
Note that the backup used for the node created has its pg_wal/ removed,
which is why the segment expected is missing.
Tomas Vondra [Sat, 11 Jul 2026 13:14:50 +0000 (15:14 +0200)]
Shorten pg_attribute_always_inline to pg_always_inline
The pg_attribute_always_inline macro name is so long it forces pgindent
to format the code in strange ways. Which may incentivize patch authors
to either structure the code in strange ways (e.g. reorder prototypes),
use shorter names, etc. Neither is very desirable for code readability.
This shortens the name by removing the _attribute_ part. It also makes
it more consistent with pg_noinline, which does not have the _attribute_
part either.
Backpatched to all supported branches, to prevent conflicts when
backpatching other fixes. The backbranches however keep both the old and
new macro name, so that existing code keeps working.
Author: Andres Freund <andres@anarazel.de> Reviewed-by: Peter Geoghegan <pg@bowt.ie> Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/bqqdehahpoa36igpictuqyn2s2mexk3t3ehidh2ffd2slb35e5@rzgksuiszgbg
Backpatch-through: 14
Peter Eisentraut [Sat, 11 Jul 2026 12:38:33 +0000 (14:38 +0200)]
Fix for loop variables used with lengthof
lengthof returns type size_t, but most for loops used int as a loop
variable. Fix that. This avoids possible warnings about
signed/unsigned mismatches under higher warning levels. (The compiler
will likely optimize these loops beyond recognition, so this shouldn't
affect the generated code much.)
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/d639aede-209f-412b-927a-d38d4848b370%40eisentraut.org
Peter Eisentraut [Sat, 11 Jul 2026 12:38:33 +0000 (14:38 +0200)]
Fix for loop variables
A number of for loops used loop variables that did not match the type
of the end condition. This could lead to wraparound or
signed/unsigned mismatches. Probably none of these are a problem in
practice, but it's fragile code.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/d639aede-209f-412b-927a-d38d4848b370%40eisentraut.org
b46e1e54d078de allowed setting the VM while on-access pruning, but it
neglected to update the freespace map. Once the page was all-visible,
vacuum could skip it, leading to stale freespace map values and,
effectively, bloat. Fix it by updating the FSM if we updated the VM.
Andres Freund [Fri, 10 Jul 2026 17:25:08 +0000 (13:25 -0400)]
bufmgr: Fix order of operations in UnlockBufHdrExt
In c75ebc657ffc I (Andres) introduced UnlockBufHdrExt() which can set and
clear bits in the buffer state using CAS. Unfortunately I added bits before
subtracting them, which means that a bit that was both removed and set would
remain unset. Fix the order of operations.
The only known case where that is a problem is that BM_IO_ERROR would not
actually remain set.
It's unfortunately not trivial to add a decent, race-free, test to verify that
BM_IO_ERROR remains set. That's therefore left for the 20 cycle.
Reported-by: Yura Sokolov <y.sokolov@postgrespro.ru>
Discussion: https://postgr.es/m/ab0dcc9e-aba0-44e3-ac23-8d74c48888e6@postgrespro.ru
Backpatch-through: 19, where c75ebc657ffc went in
When doing a whole database repack, we build a list of tables to process
taking a lock on each. But because it's a regular transaction-scoped
lock, it's automatically released immediately after building the list
anyway, which makes it not very useful. (Also, we have three ways to
obtain a list of tables to repack, and only one of them acquired this
lock.) Remove that lock acquisition, as it's useless and inconsistent.
We acquire a lock properly afterwards (and recheck that the table can
still be repacked as indicated), so we don't need to do anything other
than drop that initial lock acquisition and harden the code in
repack_is_permitted_for_relation() against possible concurrent drops.
This is similar to how vacuum does it in get_all_vacuum_rels().
In order for this to work reliably, also change
repack_is_permitted_for_relation() to cope with the possibility of the
table going away partway through. Similarly, in ExecRepack(), be
prepared for what we believed to be a table or matview to now be
something else, and skip it without erroring out, by changing
try_table_open() to try_relation_open() and testing the relkind
separately.
While at it, replace one relation_close() call in get_tables_to_repack()
with table_close() to match the table_open() that opened the catalog.
Fix data checksum processing for temp relations and dropped databases
When building the list of temporary relations to wait for, the code
previously included temporary relations without storage, such as
temporary views, even though they are irrelevant to checksum
processing. As a result, enabling data checksums could wait for a
long-lived session that owned only a temporary view.
This commit fixes the issue by filtering temporary relations with storage
only, matching the existing behavior for non-temporary relations.
Also, when enabling data checksums online, the launcher assigns the
first worker to process shared catalogs and prevents later workers from
doing so. Previously, if that worker's database was dropped after it
had been selected for processing but before checksum processing began,
the worker failed without processing the shared catalogs, yet they were
still marked as processed. As a result, later workers skipped them, and
checksum enabling could complete successfully even though the shared
catalogs had never been processed.
This commit fixes the issue by marking shared catalogs as processed
only after a worker completes successfully.
pg_stat_progress_data_checksums uses -1 as a sentinel value that is
displayed as NULL for progress counters. However, after
pgstat_progress_start_command() initialized all progress counters to
zero, data checksum progress did not reset those counters to -1.
As a result, some counters could incorrectly appear as zero instead
of NULL. For example, workers could report zero database counters,
and the disabling launcher could report zero relation and block counters.
Also, blocks_done was not reset when a worker started processing
a new relation fork. As a result, it could temporarily exceed blocks_total
or report a stale value for an empty relation fork.
Fix this by initializing the data checksum progress counters to -1
when progress reporting starts for both launcher and worker processes.
Also reset blocks_done together with blocks_total when starting each
relation fork.
postgres_fdw: Mark statistics import helpers as static
The set_*_arg helper functions in postgres_fdw.c are declared
static, but their definitions omitted the static keyword. Add it to
make their file-local scope explicit and keep the declarations and
definitions consistent.
Peter Eisentraut [Fri, 10 Jul 2026 08:08:21 +0000 (10:08 +0200)]
Forbid FOR PORTION OF on views with INSTEAD OF triggers
Previously, an attempt to use these features together caused a crash.
Oversight of commit 8e72d914c528.
Tests are added also to show that the check for this should be in the
rewriter, not the parser, as an earlier patch version suggested.
Author: Aleksander Alekseev <aleksander@tigerdata.com>
Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
Discussion: https://www.postgresql.org/message-id/flat/CAJ7c6TME%2Bix6VRf-2TPnVTsj8qn_hy6sYAOmMhZEivwsu2wS6g%40mail.gmail.com
postgres_fdw: Remove SPI from postgresImportForeignStatistics.
Previously, this function imported remote statistics by executing SQL
functions like pg_restore_relation_stats and pg_restore_attribute_stats
via SPI (in read-write mode). As the SQL functions take a schema name
and a relation name as two separate arguments, rather than a single OID
argument, if the containing schema was concurrently renamed, the
callback function would throw an error like this:
ERROR: schema "foo" does not exist
To fix, 1) provide new interface functions to import remote statistics
that are directly callable from FDWs and take a single OID, and 2)
modify the callback function to use the interface functions instead when
importing remote statistics.
For #1, this commit does a bit of refactoring to
relation_statistics_update and attribute_statistics_update, which are
the workhorse functions for pg_restore_relation_stats and
pg_restore_attribute_stats respectively: since they also take a schema
name and a relation name, separate the guts of them into new functions
so that they take a single OID and are callable not only from the
workhorse functions but from the interface functions introduced by #1.
truncate_query_log() returns NULL when statement truncation is
disabled or the supplied query does not need to be truncated. Therefore,
callers do not need to check log_statement_max_length before calling
it.
Remove the redundant checks and let truncate_query_log() make the
decision in one place. This simplifies the statement and duration
logging code without changing its behavior.
Author: Jim Jones <jim.jones@uni-muenster.de> Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwFOV+7nOdfoO=kfVH=-fRA9aQE1YcHHLYty3nfQ9rQ4RA@mail.gmail.com
log_statement_max_length limits the statement text logged by
log_statement and duration logging. However, the prepared statement
shown in the DETAIL message for EXECUTE was still logged in full,
allowing very large prepared queries to bypass the limit.
Apply the same truncation to the prepared statement text in
errdetail_execute(), making the setting behave consistently across the
main log message and its associated DETAIL output.
Also append an ellipsis to truncated statement text so users can easily
tell when truncation has occurred. With this change, a limit of zero
logs only the ellipsis, indicating that the entire statement text was
truncated.
Finally, avoid scanning the entire query string just to determine
whether truncation is needed. Use strnlen() with sufficient lookahead
for multibyte character handling, then use pg_mbcliplen() to ensure
truncation never splits a multibyte character.
Author: Jim Jones <jim.jones@uni-muenster.de> Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwFOV+7nOdfoO=kfVH=-fRA9aQE1YcHHLYty3nfQ9rQ4RA@mail.gmail.com