Conversation
Some of its code was pointlessly in its caller. This makes it better contained and clearer. Backpatch to 19, to avoid having two different copies in case we have to modify it again later. Author: Álvaro Herrera <alvherre@kurilemu.de> Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> Reviewed-by: ChangAo Chen <cca5507@qq.com> Discussion: https://postgr.es/m/alD9l-XlCuu3eUEe@alvherre.pgsql
Commit 6f6f284 introduced use of LSN_FORMAT_ARGS across the whole tree to remove use of manual bit-shifting, and commit 2633dae changed the printf format to be %X/%08X; however commit 28d534e violated both conventions by reintroducing the old manual-shift style with the deprecated %X/%X format in one debug message. Make that new message conform to our style. Author: kenny <kennychen851228@gmail.com> Backpatch-through: 19 Discussion: https://postgr.es/m/CAPXstDuWD8jg0=C8PXTXGSTTsZcjqJ+u+xKCrMpN99CXsxQzCg@mail.gmail.com
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. Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: JoongHyuk Shin <sjh910805@gmail.com> Discussion: https://postgr.es/m/CAHGQGwEpfE0CDUUODjBt7GO9U4ZF11hqga_Ci3wP8=O49oFKVw@mail.gmail.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. Author: JoongHyuk Shin <sjh910805@gmail.com> Reviewed-by: Greg Lamberson <greg@lamco.io> Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Scott Ray <scott@scottray.io> Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de> Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Reviewed-by: Henson Choi <assam258@gmail.com> Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/CACSdjfPUa4UvKjADgOERXoxNYmCg2mqqiqKkiJk6mX6E4qgVFw@mail.gmail.com
Commit 8c852ba 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
It's always been the case that granting these privileges to users that you don't fully trust was a bad idea, but it hasn't always been obvious to people reading the documentation that this is the case. To prevent confusion, and also repeated reports to pgsql-security, mention it explicitly. Discussion: http://postgr.es/m/CA+TgmobrjCHBuWHrvX3=2vndUCO2thUOdevrCcMDFW86cqCYvw@mail.gmail.com Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Backpatch-through: 14
Buildfarm member skink reported a failure in recovery/003_recovery_targets after commit d5751c3. 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. Per buildfarm member skink. Reported-by: Álvaro Herrera <alvherre@kurilemu.de> Author: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/al5Y2mWffRs1NP34@alvherre.pgsql
Commit 8108765 added the logical decoding status to the pg_controldata output, but overlooked the pg_control_checkpoint() SQL function, which reports the same checkpoint information. This commit adds a logical_decoding column to pg_control_checkpoint(), placed after full_page_writes to match the pg_controldata output order. Oversight in 8108765. Bump catalog version. Reported-by: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/CAHGQGwEkp1-1n5iC38+yHSNh955+KshwtCL6DzA0vk_vuUF_Eg@mail.gmail.com Backpatch-through: 19
…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
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
…rrors 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
Change DETAIL messages to conform to the style guide by capitalizing the first word of sentences and ending sentences with a period. Author: Peter Smith <peter.b.smith@fujitsu.com> Reviewed-by: Chao Li <li.evan.chao@gmail.com> Reviewed-by: vignesh C <vignesh21.gmail.com> Reviewed-by: Xiaopeng Wang <wxp_728.163.com> Reviewed-by: Peter Eisentraut <peter@eisentraut.org> Discussion: https://www.postgresql.org/message-id/flat/CAHut%2BPszSntkUgN%2BQa9matGY6MLEoFGSuVbuKDgnnTdZ7YPRwg%40mail.gmail.com
For internally consistent terminology
We've got no reports of problems. Get rid of it. Author: Álvaro Herrera <alvherre@kurilemu.de> Backpatch-through: 19 Discussion: https://postgr.es/m/alewd1f2G0kKeM1i@alvherre.pgsql
Change formatting and chars to be less of a match against actual formatting characters. Reported-by: Phil Discussion: https://postgr.es/m/177801333530.795.16999885814007014333@wrigleys.postgresql.org Backpatch-through: 19
Mention "time zone conversion" as a way to clarify the time zone is not stored in the database. Reported-by: Richard Neill Discussion: https://postgr.es/m/ddf41f033a8add84e1f28a095defafae@richardneill.org Backpatch-through: 19
This commit adds pgstat_prep_pending_from_entry_ref(), a new pgstats routine that is able to prepare an existing PgStat_EntryRef to receive pending stats. This split gives a way for callers to obtain first a reference via pgstat_get_entry_ref(), then set up pending data as two separate, distinctive, steps. Previously, the only way to get an entry reference with pending data ready was pgstat_prep_pending_entry(), which bundles lookup, creation, and pending setup in a single call. Callers that need finer control over the entry creation had no way to attach pending data to an already-obtained entry reference. One case where this has shown to matter for a stats kind is where one wants to check some capacity (for example where a GUC bounds the maximum numer of entries allowed) before deciding if a new entry should be created. So this split can help in reducing calls to pgstat_get_entry_ref(), meaning less shmem hash table lookups. The only logical ordering change is that pgStatPendingContext is initialized after calling pgstat_get_entry_ref() in pgstat_prep_pending_entry(). This does not matter in practice. pgstat_prep_pending_entry() is refactored to use the new function internally. All the existing callers are unchanged. Existing out-of-core custom stats kinds should see no impact. Author: Sami Imseih <samimseih@gmail.com> Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/CAA5RZ0sV+TsLejUMhAM=PJoOm8u-t8ru7B67KvyLCy=19sM87g@mail.gmail.com
If an error happens during the initialization of the TYPEOID catcache, as part of lookup_type_cache(), the error handling of that lookup would cause an assertion failure via finalize_in_progress_typentries(), called during error recovery, the presence of an in-progress type OID causing a catcache initialization outside of a transaction context. The in-progress list is now delayed to happen after the initial entry lookup. Alexander Lakhin has found a fancy way to reproduce the problem, with the injection of probabilistic memory allocation failures. This problem is unlikely going to show up in practice. Like the other changes 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
SummarizeWAL documents that maximum_lsn should be passed as "the switch point when reading a historic timeline, or the most-recently-measured end of WAL when reading the current timeline." But the caller always passed the most recently measured end-of-WAL even when reading from a historic timeline, due to an oversight on my part. Fix that. As far as I can determine, for this to become an issue in practice, it's necessary to have a corrupted WAL file in the archive. SummarizeWAL checks that every record it processes both starts and ends before switch_lsn; so if all the WAL files in the archive are valid, SummarizeWAL will still discover where it should stop summarizing and do the right thing. However, if there's a corrupted file in the WAL archive, and if it is also the case that the end of the current timeline has advanced past the switch point, then the incorrect maximum_lsn value can result in trying to read an invalid record and erroring out, which leads repeatedly retrying and failing with an error every time. One way this could occur is if a new primary is promoted and creates a .partial file, and the user manually renames that file to remove the suffix, and it is then archived. In that situation, the tail end of the file need not be valid WAL, and that could lead to a stuck WAL summarizer. Reported-by: Fabrice Chapuis <fabrice636861@gmail.com> Analyzed-by: Thom Brown <thom@linux.com> (using claude) Discussion: http://postgr.es/m/CAA5-nLDdvGMkN6Z-GaHGHG5T7QWEgv4YoHO7XvOJbeD00cghNg@mail.gmail.com Backpatch-through: 17
Sequence synchronization requires the page_lsn field returned by pg_get_sequence_data(), which was added in PostgreSQL 19. Previously, requesting sequence synchronization against an older publisher (via ALTER SUBSCRIPTION ... REFRESH SEQUENCES or by running ALTER SUBSCRIPTION ... CONNECTION on a disabled subscription with sequences in the INIT state and subsequently enabling the subscription) would cause the sequence synchronization worker to repeatedly fail with a confusing "invalid query response" error. Check the publisher's server version up front in both AlterSubscription_refresh_seq() and copy_sequences(), and error out immediately when it predates PostgreSQL 19. Also document the PostgreSQL 19 publisher requirement for sequence replication in the logical replication documentation and in ALTER SUBSCRIPTION ... REFRESH SEQUENCES. Reported-by: Noah Misch <noah@leadboat.com> Author: vignesh C <vignesh21@gmail.com> Reviewed-by: Shveta Malik <shveta.malik@gmail.com> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Backpatch-through: 19 Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com
injection_wait() only clears its slot in the waiter array after the wait loop finishes. When the waiting query is canceled or the backend is terminated (wait look has a CHECK_FOR_INTERRUPS), the slot leaks. Later wakeups of the same point then bump the counter of the leaked slot instead of the real waiter, that sleeps forever. Repeated leaks can exhaust all the slots. The code is changed so as the waiting loop is wrapped with PG_ENSURE_ERROR_CLEANUP, so as the injection point slots, that are shared resources, can be cleaned up on ERROR as much as a FATAL. An isolation test is added: cancel one waiter, terminate another waiter, then check that a later waiter still receives a wakeup. Without the fixed code, the test would fail on timeout. Author: Zsolt Parragi <zsolt.parragi@percona.com> Discussion: https://postgr.es/m/CAN4CZFO+KF=cc0-iEg28RhqRBp_fTs6D4b8b7D7DB-pGYP3Ccg@mail.gmail.com Backpatch-through: 17
The documentation of pg_stat_activity used an incomplete list of values for backend_type. While on it, it is improved to use an itemized list, now ordered alphabetically, with a short description about each item. Author: Laurenz Albe <laurenz.albe@cybertec.at> Reviewed-By: Michael Paquier <michael@paquier.xyz> Reviewed-By: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/5e94c0196084f648ae6a00107125494f5804318a.camel@cybertec.at
socket_putmessage_noblock() used pq_putmessage(), which redirects to PqCommMethods->putmessage. In the common cases, this points to socket_putmessage(), but it would become incorrect if PqCommMethods points to a different implementation. This change may look like a bug, but as far as I can see this is mostly cosmetic. The code is able to work currently, as the repalloc() done in the noblock() call ensures that the blocking path of internal_putbytes() is never reached. The issue has gone unnoticed since 2bd9e41. Author: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/CAO6_Xqpf5+Rzw_-XOOz-d-R5x6_2JHtpnzXP0nrYWiHyZokA_Q@mail.gmail.com
Improve the documentation for pg_stat_recovery in several ways: - Mention the view in high-availability.sgml as a way to monitor recovery state and replay progress, alongside the existing recovery information functions. - Clarify that the view returns at most one row, not exactly one row, and no rows to users who lack the pg_read_all_stats privilege. - Correct the description of last_replayed_end_lsn to clarify that it is the end LSN of the last replayed record plus one. - Document that replay_end_tli equals last_replayed_tli when no WAL record is currently being replayed. - Clarify that current_chunk_start_time is NULL until streaming WAL has been received. Backpatch to v19, where pg_stat_recovery was introduced. Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/CAHGQGwGRavm18HqnQn_f68QB96qk6arhjET1V93OJH09Mgojkg@mail.gmail.com Backpatch-through: 19
For subscriptions using SERVER, changing the owner can change the effective connection string. However, ALTER SUBSCRIPTION ... OWNER TO did not validate the generated conninfo for the new owner. As a result, ownership could be transferred to a non-superuser whose generated connection string did not satisfy password_required=true. The ownership change succeeded, but the subscription would fail later when the worker or another command tried to connect. Fix this by making ALTER SUBSCRIPTION ... OWNER TO validate the new owner's generated conninfo with walrcv_check_conninfo(). Backpatch to v19, where SERVER subscriptions were introduced. Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Yuanchao Zhang <145zhangyc@gmail.com> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Discussion: https://postgr.es/m/CAHGQGwFGa6+wWVgUmZPFwN=fBY59mYPkMK3=TxT=Pv5C1mNNRQ@mail.gmail.com Backpatch-through: 19
Commit fd36606 added tests intended to verify that rows inserted on the publisher are replicated to the subscriber when using multiple publications, with one excluding the target table via EXCEPT and another including it. However, the tests queried the publisher instead of the subscriber. Since the rows were inserted directly into the publisher, the checks would always succeed, providing no coverage of replication. Fix this by querying the subscriber so the tests verify the replicated state. Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Discussion: https://postgr.es/m/CAHGQGwGfXUO7f4t6KNGurYwg6QsnLtpP0K3EACbAwYWtxGfKfQ@mail.gmail.com Backpatch-through: 19
Document table_name, column_name, and schema_name in the CREATE PUBLICATION and ALTER PUBLICATION reference pages. Also add anchors for the ALTER PUBLICATION parameter list, matching the style already used by CREATE PUBLICATION. Author: Peter Smith <smithpb2250@gmail.com> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/CAHut+Ptekz+TO4ui8-fiBm4Y+O2v=HQnkK_cW4G=w9ep8654EA@mail.gmail.com
Previously, if a sequence synchronization batch contained both a sequence that had been dropped on the publisher and another for which the replication role lacked SELECT privilege, the latter was reported twice: once as a permission failure and again as missing on the publisher. This happened because the permission-denied sequence was not marked as found on the publisher. As a result, when another sequence in the batch was genuinely missing, the later missing-sequence check incorrectly classified the permission-denied sequence as missing as well. Fix this by marking the permission-denied sequence as found before reporting the permission failure, so it is not later reported as missing. Reported-by: Noah Misch <noah@leadboat.com> Author: Vignesh C <vignesh21@gmail.com> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> Discussion: https://postgr.es/m/CALDaNm3LsUjW7PahuCsbYAxajSF+S328tw5E9rF0erdh7dKOXw@mail.gmail.com Backpatch-through: 19
pg_database_size() allows access to users who have either CONNECT
privilege on the target database or privileges of the pg_read_all_stats
role. However, previously, psql's \l+ checked only for CONNECT,
so users with privileges of pg_read_all_stats still saw "No Access" for
databases they could not connect to.
Fix this by making \l+ also check
pg_has_role('pg_read_all_stats', 'USAGE'), matching
pg_database_size()'s permission rules.
For back branches, emit the pg_read_all_stats check only when
connected to PostgreSQL 10 or later, since earlier releases do not have
that predefined role.
Backpatch to all supported versions.
Author: Christoph Berg <myon@debian.org>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/amCo6qRmnfPVk4-V@msg.df7cb.de
Backpatch-through: 14
Commit f9b7fc6 fixed a race when predicate-locking completely empty btrees: without a buffer lock held, a matching key could be inserted between _bt_search and the PredicateLockRelation call, so the scan would miss concurrently inserted tuples while the writer wouldn't see the reader's predicate lock. That commit only fixed _bt_first's _bt_search path, though. Scans without useful insertion scan keys return early from _bt_first via _bt_endpoint, which still didn't recheck if the relation was empty. To fix, add handling to _bt_endpoint that is analogous to the handling added to _bt_search by commit f9b7fc6. Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-WzkNoTn3yXY0iGkSuavJ+sL8EROf+kitW+_2v2tJVWuKmA@mail.gmail.com Backpatch-through: 14
Oversight in commit fb23cc7. Reported-by: Anton Voloshin <a.voloshin@postgrespro.ru> Discussion: https://postgr.es/m/ad5d772e-09d9-4248-97a4-0011afab9e71@postgrespro.ru
Add coverage for predicate locking of completely empty nbtree indexes, where we must predicate lock the entire relation (instead of some individual leaf page). Both paths that can find the index empty (and must consider whether it's still empty after PredicateLockRelation returns) are covered by a new isolation test that uses injection points. Catalog relation scans skip the injection points. The waiting session runs catalog queries of its own after arming the (session-local) points, and could otherwise suspend itself with nothing lined up to wake it. Follow-up to bugfix commits ce3f19e (the _bt_endpoint fix) and f9b7fc6 (the _bt_first/_bt_search fix). Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-WzkNoTn3yXY0iGkSuavJ+sL8EROf+kitW+_2v2tJVWuKmA@mail.gmail.com
Backwards scans have unique concurrency rules: rather than unreservedly trusting a saved left link, the scan optimistically rechecks its pointed-to leaf page's right link (i.e. whether it still points back to the page that _bt_readpage just read). Usually, the left sibling of the just-read page won't have changed, in which case the scan can proceed with reading the left sibling as planned. But it's possible that the key space that the scan needs to read next is no longer covered by the original left sibling page due to concurrent page splits and/or page deletions. When that happens, the scan must recover by relocating the new/current left sibling of the just-read page. Test coverage for backwards scans was limited to the happy path. Add an isolation test (and associated injection points) that test the recovery path. This covers several distinct recovery scenarios (concurrent page splits, concurrent page deletions, and minor variants thereof). Author: Peter Geoghegan <pg@bowt.ie> Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru> Discussion: https://postgr.es/m/CAH2-WzmD+jUBOpFS2jrnqqrdPSAjoxqyL9FPKaE1BtnY=8Nntg@mail.gmail.com
Add pg_regress tests that exercise the row compare logic that commit 7d9cd2d added to _bt_set_startikey. Also add tests that exercise the _bt_set_startikey SAOP array path. Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-Wz=KjQsD2W2a=b51uH905=0mF6Le4evhWkN2FL1+uRPhUg@mail.gmail.com Backpatch-through: 19
This replaces an O(N) hash_seq_search() loop by an O(1) lookup, removing a TODO item, making the invalidation callback faster when dealing with many relations. This can work because LogicalRepPartMap is keyed by a partition OID, and a relmapentry's localreloid matches with it. An assertion is added in logicalrep_partition_open() to enforce the fact that localreloid matches with the hash key. Author: DaeMyung Kang <charsyam@gmail.com> Discussion: https://postgr.es/m/20260417174450.4158878-1-charsyam@gmail.com
Noticed while doing some routine work. Oversight in e395fbd.
Commit 8d829f5 introduced the JSCTOR_JSON_ARRAY_QUERY constructor type so that ruleutils.c could deparse JSON_ARRAY(subquery) using its original syntax, storing the transformed subquery in a new orig_query field. However, the input FORMAT clause of JSON_ARRAY(subquery FORMAT ...) was not preserved for deparsing. The format was recorded only in the executable expression kept in the func field, which ruleutils.c does not inspect, so it is silently dropped. This is more than cosmetic, because FORMAT JSON changes the result: without it a text value is treated as a string to be quoted, while with it the value is treated as already-formatted JSON. To fix, record the input FORMAT in a new deparse-only field of JsonConstructorExpr, alongside orig_query, and emit it in ruleutils.c. Bump catalog version. Author: Chao Li <li.evan.chao@gmail.com> Reviewed-by: Ewan Young <kdbase.hack@gmail.com> Reviewed-by: Richard Guo <guofenglinux@gmail.com> Discussion: https://postgr.es/m/4C89B193-7D54-4705-9CF9-F0D484B9E099@gmail.com Backpatch-through: 19
1. Stop a running sequence synchronization worker when ALTER SUBSCRIPTION ... DISABLE is executed. The worker did not reread its subscription after starting a transaction, so it kept running with a stale copy and missed the disable. It now calls maybe_reread_subscription() after StartTransactionCommand(), matching the apply worker. 2. Restore the invariant that publisher-side synchronization slots are dropped last during ALTER SUBSCRIPTION ... REFRESH PUBLICATION. The slot-drop loop now runs after the sequence-removal loop, so the non-transactional slot drops happen only after all catalog changes that could still be rolled back on error. 3. Restore psql tab completion for ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (. 4. Make pg_stat_subscription report NULL for the fields that do not apply to a sequence synchronization worker, which does not stream from a walsender, and update the documentation accordingly. 5. Update the pg_subscription_rel.srsublsn catalog documentation to describe its semantics for sequence rows. Reported-by: Noah Misch <noah@leadboat.com> Author: vignesh C <vignesh21@gmail.com> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Backpatch-through: 19, where it was introduced Discussion: https://postgr.es/m/20260710045217.f0.noahmisch@microsoft.com
reshke
force-pushed
the
sa
branch
7 times, most recently
from
July 29, 2026 14:13
8d4ed68 to
82b6bd1
Compare
This adds a new archive_mode setting "shared" to prevent WAL history loss during standby promotion in HA streaming replication setups. In shared mode, the standby tracks which files have been archived by the primary. The standby refrains from recycling files that the primary has not yet archived, and at failover, the standby archives all those files too from the old timeline. This prevents WAL from being recycled before it's safely archived, addressing a possible gap in PITR continuity during failover. Primary sends last archived WAL segment every `archive_status_report_interval` ms via new walsender protocol message. Standby marks all segments <= reported segment as .done on current timeline. For any ancestor timeline, standby marks all segments which are in its history as .done. Cascading replication on each standby coordinates with immediate upstream. Standby relays its primary last archived WAL donwstream. Implementaion based on Heikki Linnakangas's 2014 design & patсh, also we grabbed some ideas & tests from Greenplum's production implementation[0], and modernized the whole thing for current HEAD (PostgreSQL 20 at time). Includes TAP tests covering basic synchronization, promotion, cascading replication. Also includes additional test for checkpoint wal recycling on standby logic in shared-archive mode. Author: Andrey Borodin <x4mmm@yandex-team.ru> Co-authored-by: Heikki Linnakangas <hlinnaka@iki.fi> (earlier versions) Co-authored-by: Kirill Reshke <reshkekirill@gmail.com> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> (earlier versions) Reviewed-by: Grigory Smolkin <smallkeen@gmail.com> Reviewed-by: Jaroslav Novikov <njrslv@yandex-team.ru> [0] open-gpdb/gpdb@4f2db19
Comes in-handy for monitoring shared archive feature. TAP tests for shared archive feature were extended to check for this column value. Bumps catversion.
Add a case to 055_archive_shared.pl where the primary runs with archive_mode=off while the standby runs in shared mode. Since the primary never starts an archiver and never sends archival status reports, the standby must keep received segments as .ready, must not mark any segment as .done, and pg_stat_wal_receiver.primary_last_archived must stay empty.
Add 057_archive_shared_cascade_on.pl covering a chain where the primary and the intermediate standby both run archive_mode=on and only the cascading standby runs archive_mode=shared. The cascading standby connects successfully because its upstream has archiving active, but the intermediate standby never requested archival reports from the primary and therefore has nothing to relay. The test pins down that the cascading standby keeps received segments as .ready, marks nothing as .done via a report, and leaves pg_stat_wal_receiver.primary_last_archived empty.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce a new archive_mode setting "shared" to prevent WAL history loss during standby promotion in HA streaming replication setups.
In shared mode, the primary proactively sends archival status updates to standbys via the replication protocol. The standby creates .ready files for received WAL segments but defers marking them as .done until the primary confirms archival. This prevents WAL from being recycled before it's safely archived, addressing a critical gap in PITR continuity during failover.
Key implementation details:
Based on Heikki Linnakangas's 2014 design and Greenplum's production implementation, modernized for current HEAD (PostgreSQL 20 at time).
Includes TAP tests covering basic synchronization, promotion, cascading replication, and multiple standbys scenarios.
Author: Andrey Borodin x4mmm@yandex-team.ru
Co-authored-by: Heikki Linnakangas hlinnaka@iki.fi (earlier versions)
Co-authored-by: Grigory Smolkin smallkeen@gmail.com
Reviewed-by: Jaroslav Novikov njrslv@yandex-team.ru