v2-0001-fix-column-list-for-old-tuple.patch
application/octet-stream
Filename: v2-0001-fix-column-list-for-old-tuple.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: fix column list for old tuple
| File | + | − |
|---|---|---|
| src/backend/replication/logical/proto.c | 4 | 3 |
| src/backend/replication/pgoutput/pgoutput.c | 4 | 2 |
| src/include/replication/logicalproto.h | 1 | 1 |
| src/test/subscription/t/031_column_list.pl | 33 | 0 |
From 8f1f3bf03663a54b884681548910457f21810d73 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <houzj.fnst@cn.fujitsu.com>
Date: Sun, 27 Nov 2022 15:09:16 +0800
Subject: [PATCH] fix column list for old tuple
---
src/backend/replication/logical/proto.c | 7 +++---
src/backend/replication/pgoutput/pgoutput.c | 6 ++++--
src/include/replication/logicalproto.h | 2 +-
src/test/subscription/t/031_column_list.pl | 33 +++++++++++++++++++++++++++++
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c
index ff8513e..f5f2bc2 100644
--- a/src/backend/replication/logical/proto.c
+++ b/src/backend/replication/logical/proto.c
@@ -478,7 +478,7 @@ logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel,
pq_sendbyte(out, 'O'); /* old tuple follows */
else
pq_sendbyte(out, 'K'); /* old key follows */
- logicalrep_write_tuple(out, rel, oldslot, binary, NULL);
+ logicalrep_write_tuple(out, rel, oldslot, binary, columns);
}
pq_sendbyte(out, 'N'); /* new tuple follows */
@@ -531,7 +531,8 @@ logicalrep_read_update(StringInfo in, bool *has_oldtuple,
*/
void
logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
- TupleTableSlot *oldslot, bool binary)
+ TupleTableSlot *oldslot, bool binary,
+ Bitmapset *columns)
{
Assert(rel->rd_rel->relreplident == REPLICA_IDENTITY_DEFAULT ||
rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
@@ -551,7 +552,7 @@ logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
else
pq_sendbyte(out, 'K'); /* old key follows */
- logicalrep_write_tuple(out, rel, oldslot, binary, NULL);
+ logicalrep_write_tuple(out, rel, oldslot, binary, columns);
}
/*
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 2ecaa5b..aaeb313 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -1532,7 +1532,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
break;
case REORDER_BUFFER_CHANGE_DELETE:
logicalrep_write_delete(ctx->out, xid, targetrel,
- old_slot, data->binary);
+ old_slot, data->binary,
+ relentry->columns);
break;
default:
Assert(false);
@@ -1578,7 +1579,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
OutputPluginPrepareWrite(ctx, true);
logicalrep_write_delete(ctx->out, xid, targetrel,
- old_slot, data->binary);
+ old_slot, data->binary,
+ relentry->columns);
OutputPluginWrite(ctx, true);
}
else
diff --git a/src/include/replication/logicalproto.h b/src/include/replication/logicalproto.h
index 7eaa4c9..1eb7dda 100644
--- a/src/include/replication/logicalproto.h
+++ b/src/include/replication/logicalproto.h
@@ -220,7 +220,7 @@ extern LogicalRepRelId logicalrep_read_update(StringInfo in,
LogicalRepTupleData *newtup);
extern void logicalrep_write_delete(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *oldslot,
- bool binary);
+ bool binary, Bitmapset *columns);
extern LogicalRepRelId logicalrep_read_delete(StringInfo in,
LogicalRepTupleData *oldtup);
extern void logicalrep_write_truncate(StringInfo out, TransactionId xid,
diff --git a/src/test/subscription/t/031_column_list.pl b/src/test/subscription/t/031_column_list.pl
index ae022fa..593b852 100644
--- a/src/test/subscription/t/031_column_list.pl
+++ b/src/test/subscription/t/031_column_list.pl
@@ -1151,6 +1151,39 @@ is( $node_subscriber->safe_psql(
4||),
'publication containing both parent and child relation');
+# TEST: Only columns in the column list should exist in the old tuple of UPDATE
+# and DELETE.
+
+$node_publisher->safe_psql(
+ 'postgres', qq(
+ CREATE TABLE test_oldtuple_col (a int PRIMARY KEY, b int, c int);
+ CREATE PUBLICATION pub_check_oldtuple FOR TABLE test_oldtuple_col (a, b);
+ INSERT INTO test_oldtuple_col VALUES(1, 2, 3);
+ SELECT * FROM pg_create_logical_replication_slot('test_slot', 'pgoutput');
+ UPDATE test_oldtuple_col SET a = 2;
+ DELETE FROM test_oldtuple_col;
+));
+
+
+# Check at 7th byte of binary data for the number of columns in the old tuple.
+#
+# 7 = 1 (count from 1) + 1 byte (message type) + 4 byte (relid) + 1 byte (flag
+# for old key).
+#
+# The message type of UPDATE is 85('U').
+# The message type of DELETE is 68('D').
+$result = $node_publisher->safe_psql(
+ 'postgres', qq(
+ SELECT substr(data, 7, 2) = int2send(2::smallint)
+ FROM pg_logical_slot_peek_binary_changes('test_slot', NULL, NULL,
+ 'proto_version', '1',
+ 'publication_names', 'pub_check_oldtuple')
+ WHERE get_byte(data, 0) = 85 OR get_byte(data, 0) = 68
+));
+
+is( $result, qq(t
+t), 'check the number of columns in the old tuple');
+
# TEST: With a table included in multiple publications with different column
# lists, we should catch the error when creating the subscription.
--
2.7.2.windows.1