From e8f3e9a4d71f0075af5e93abb9715f2fe0b268c2 Mon Sep 17 00:00:00 2001 From: Rui Zhao Date: Sat, 19 Sep 2026 23:53:05 +0800 Subject: [PATCH v5 4/4] Fix XID count in initial decoding snapshots In v5-0001, newxcnt is incremented even for committed XIDs that are not added to newxip. This counts uninitialized array entries as part of the converted snapshot. Increment the count only when storing an XID in the array. Extend the USE_SNAPSHOT test to check that every XID in the resulting snapshot lies in [xmin, xmax). --- src/backend/replication/logical/snapbuild.c | 4 +--- src/test/recovery/t/057_snapshot_commit_race.pl | 10 +++++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 261f25a5cd..c03428b5e1 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -517,7 +517,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder) (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("initial slot snapshot too large"))); - newxip[newxcnt] = xid; + newxip[newxcnt++] = xid; } else { @@ -532,8 +532,6 @@ SnapBuildInitialSnapshot(SnapBuild *builder) XactLockTableWait(xid, NULL, NULL, XLTW_None); } - newxcnt++; - TransactionIdAdvance(xid); } diff --git a/src/test/recovery/t/057_snapshot_commit_race.pl b/src/test/recovery/t/057_snapshot_commit_race.pl index af11ad2869..a0d23d9a8c 100644 --- a/src/test/recovery/t/057_snapshot_commit_race.pl +++ b/src/test/recovery/t/057_snapshot_commit_race.pl @@ -106,7 +106,7 @@ is($state, 'waiting for s4', # If the slot got created without waiting, use its snapshot right away: # the scan takes s4 as aborted and sets hint bits accordingly, which is -# what the last two checks then report. +# what the two row checks below then report. if ($state eq 'slot created') { $walsender->query_until(qr/test_decoding/, ''); @@ -132,6 +132,14 @@ is( $node->safe_psql('postgres', 'SELECT i, j FROM tab ORDER BY i'), "1|2\n3|3", "a new session sees the transaction's changes"); +is( $walsender->query_safe( + q(WITH s AS (SELECT pg_current_snapshot() AS snap) + SELECT count(*) FROM s, LATERAL pg_snapshot_xip(snap) AS x(xid) + WHERE xid < pg_snapshot_xmin(snap) OR xid >= pg_snapshot_xmax(snap)) + ), + '0', + 'snapshot XIDs are all within xmin and xmax'); + $walsender->query_safe('ROLLBACK'); $walsender->quit; $s2->quit; -- 2.43.7