From 64697f8c0f4b685bb6cf8aaa662e2b8823e820f0 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas.vondra@postgresql.org>
Date: Thu, 23 Mar 2023 22:27:31 +0100
Subject: [PATCH 6/7] Reconstruct the right state from the on-disk sequence
 state

---
 src/backend/replication/logical/tablesync.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 89c0c94159..64c397babb 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -1291,6 +1291,22 @@ copy_sequence(Relation rel)
 
 	fetch_sequence_data(lrel.nspname, lrel.relname, &last_value, &log_cnt, &is_called);
 
+	/*
+	 * Logical replication of sequences is based on decoding WAL records,
+	 * describing the "next" state of the sequence, a the current state
+	 * in the relfilenode is yet to reach. But that's what we read during
+	 * the initial sync, so we need to reconstruct the WAL record when we
+	 * started this batch of values.
+	 *
+	 * Otherwise we might get duplicate values (on subscriber) if we failed
+	 * over right after the sync.
+	 */
+	if (is_called)
+	{
+		last_value += log_cnt;
+		log_cnt = 0;
+	}
+
 	/* tablesync sets the sequences in non-transactional way */
 	SetSequence(RelationGetRelid(rel), false, last_value, log_cnt, is_called);
 
-- 
2.39.2

