agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedFrom: Antonin Houska <ah@cybertec.at>
Subject: [PATCH 1/2] Reproduce failure when only the TOAST tuple is logically decoded.
Date: Wed, 2 Sep 2026 19:17:53 +0200
The bug was introduced by commit 28d534e2ae, in which REPACK (CONCURRENTLY)
suppresses decoding of DML commands in the new heap during repacking. The
problem is that for UPDATE we only disabled decoding of the main tuple, but
not for its TOAST tuple(s).
---
.../expected/repack_toast_bug.out | 36 ++++++++++++
.../specs/repack_toast_bug.spec | 57 +++++++++++++++++++
2 files changed, 93 insertions(+)
create mode 100644 src/test/modules/injection_points/expected/repack_toast_bug.out
create mode 100644 src/test/modules/injection_points/specs/repack_toast_bug.spec
diff --git a/src/test/modules/injection_points/expected/repack_toast_bug.out b/src/test/modules/injection_points/expected/repack_toast_bug.out
new file mode 100644
index 00000000000..0de24241bfb
--- /dev/null
+++ b/src/test/modules/injection_points/expected/repack_toast_bug.out
@@ -0,0 +1,36 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1_wait_before_lock s2_changes s2_wakeup_before_lock s1_decode
+injection_points_attach
+-----------------------
+
+(1 row)
+
+step s1_wait_before_lock:
+ REPACK (CONCURRENTLY) repack_toast;
+ <waiting ...>
+step s2_changes:
+ UPDATE repack_toast SET t = gen_external() WHERE i=1;
+
+step s2_wakeup_before_lock:
+ SELECT injection_points_wakeup('repack-concurrently-before-lock');
+
+injection_points_wakeup
+-----------------------
+
+(1 row)
+
+step s1_wait_before_lock: <... completed>
+step s1_decode:
+ SELECT count(*) FROM pg_logical_slot_peek_changes('s', NULL, NULL, 'include-rewrites', '1');
+
+count
+-----
+ 9
+(1 row)
+
+pg_drop_replication_slot
+------------------------
+
+(1 row)
+
diff --git a/src/test/modules/injection_points/specs/repack_toast_bug.spec b/src/test/modules/injection_points/specs/repack_toast_bug.spec
new file mode 100644
index 00000000000..a09fd8753e0
--- /dev/null
+++ b/src/test/modules/injection_points/specs/repack_toast_bug.spec
@@ -0,0 +1,57 @@
+setup
+{
+ SELECT pg_create_logical_replication_slot('s', 'test_decoding');
+
+ CREATE EXTENSION IF NOT EXISTS injection_points;
+
+ -- Generate a string of random characters that is not likely to be
+ -- compressed, but is big enough to be stored externally.
+ CREATE FUNCTION gen_external()
+ RETURNS text
+ LANGUAGE sql as $$
+ SELECT string_agg(chr(65 + trunc(25 * random())::int), '')
+ FROM generate_series(1, 2048) s(x);
+ $$;
+
+ CREATE TABLE repack_toast(i int PRIMARY KEY, t text);
+ INSERT INTO repack_toast(i, t) VALUES (1, gen_external());
+}
+
+teardown
+{
+ DROP TABLE repack_toast;
+ SELECT pg_drop_replication_slot('s');
+}
+
+session s1
+setup
+{
+ SELECT injection_points_set_local();
+ SELECT injection_points_attach('repack-concurrently-before-lock', 'wait');
+}
+# Perform the initial load and wait for s2 to do some data changes.
+step s1_wait_before_lock
+{
+ REPACK (CONCURRENTLY) repack_toast;
+}
+step s1_decode
+{
+ SELECT count(*) FROM pg_logical_slot_peek_changes('s', NULL, NULL, 'include-rewrites', '1');
+}
+
+session s2
+step s2_changes
+{
+ UPDATE repack_toast SET t = gen_external() WHERE i=1;
+}
+step s2_wakeup_before_lock
+{
+ SELECT injection_points_wakeup('repack-concurrently-before-lock');
+}
+
+permutation
+ s1_wait_before_lock
+ s2_changes
+ s2_wakeup_before_lock
+ s1_decode
+
--
2.52.0
--=-=-=
Content-Type: text/x-diff
Content-Disposition: attachment;
filename=0002-Suppress-decoding-of-both-main-and-TOAST-tuple-in-RE.patch
Message-ID: <no-message-id-1863633@localhost>
Permalink: ../no-message-id-1863633@localhost/
Also on: postgresql.org/message-id/no-message-id-1863633@localhost
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: ah@cybertec.at
Subject: Re: [PATCH 1/2] Reproduce failure when only the TOAST tuple is logically decoded.
In-Reply-To: <no-message-id-1863633@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox