v1-0001-Fixing-bug-in-logical-replication.patch
application/octet-stream
Filename: v1-0001-Fixing-bug-in-logical-replication.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: Fixing bug in logical replication
| File | + | − |
|---|---|---|
| src/backend/utils/cache/relcache.c | 20 | 1 |
| src/test/subscription/t/021_no_replica_identity.pl | 57 | 0 |
From b19cd78d656321f3bf5fa4015020f249f4419d81 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 16 Jun 2021 21:26:32 -0700
Subject: [PATCH v1] Fixing bug in logical replication
When replicating DML for a table with an index but no REPLICA
IDENTITY, the publisher was crashing with a segmentation fault, at
least under certain conditions. Adding a fix for that along with a
simple test demonstrating the problem.
---
src/backend/utils/cache/relcache.c | 21 ++++++-
.../subscription/t/021_no_replica_identity.pl | 57 +++++++++++++++++++
2 files changed, 77 insertions(+), 1 deletion(-)
create mode 100644 src/test/subscription/t/021_no_replica_identity.pl
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index fd05615e76..f40f294864 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5266,8 +5266,27 @@ RelationGetIdentityKeyBitmap(Relation relation)
if (indexoidlist == NIL)
return NULL;
- /* Add referenced attributes to idindexattrs */
+ /* Fall out if the replica identity index is invalid */
+ if (!OidIsValid(relation->rd_replidindex))
+ return NULL;
+
+ /* Look up the description for the replica identity index */
indexDesc = RelationIdGetRelation(relation->rd_replidindex);
+
+ /*
+ * Fall out if the description is not for an index, suggesting
+ * affairs have changed since we looked. XXX Should we log a
+ * complaint here?
+ */
+ if (!indexDesc)
+ return NULL;
+ if (!indexDesc->rd_index)
+ {
+ RelationClose(indexDesc);
+ return NULL;
+ }
+
+ /* Add referenced attributes to idindexattrs */
for (i = 0; i < indexDesc->rd_index->indnatts; i++)
{
int attrnum = indexDesc->rd_index->indkey.values[i];
diff --git a/src/test/subscription/t/021_no_replica_identity.pl b/src/test/subscription/t/021_no_replica_identity.pl
new file mode 100644
index 0000000000..9a6c8f5f74
--- /dev/null
+++ b/src/test/subscription/t/021_no_replica_identity.pl
@@ -0,0 +1,57 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test of logical replication in the absence of a proper replica
+# identity index
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 1;
+
+my $cmd;
+
+my $node_publisher = get_new_node('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = get_new_node('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+$cmd = qq(
+CREATE TABLE tbl (i INTEGER);
+CREATE INDEX tbl_idx ON tbl(i);
+);
+
+$node_publisher->safe_psql('postgres', $cmd);
+$node_subscriber->safe_psql('postgres', $cmd);
+
+$cmd = qq(
+CREATE PUBLICATION pub FOR TABLE tbl);
+$node_publisher->safe_psql('postgres', $cmd);
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+$cmd = qq(
+CREATE SUBSCRIPTION sub
+ CONNECTION '$publisher_connstr'
+ PUBLICATION pub);
+$node_subscriber->safe_psql('postgres', $cmd);
+
+$node_publisher->wait_for_catchup("sub");
+
+my $synced_query =
+ "SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+$cmd = qq(INSERT INTO tbl (i) VALUES (1));
+$node_publisher->safe_psql('postgres', $cmd);
+
+$node_publisher->wait_for_catchup("sub");
+
+is($node_subscriber->safe_psql('postgres', q(SELECT i FROM tbl)),
+ 1, "value replicated to subscriber without replica identity index");
+
+$node_subscriber->stop('smart');
+$node_publisher->stop('smart');
--
2.21.1 (Apple Git-122.3)