If a FOR ALL TABLES publication exists, unlogged tables are ignored
for publishing changes.  But CheckCmdReplicaIdentity() would still
check in that case that such a table has a replica identity set before
accepting updates.  That is useless, so check first whether the given
table is publishable and skip the check if not.

Example:

CREATE PUBLICATION pub FOR ALL TABLES;
CREATE UNLOGGED TABLE logical_replication_test AS SELECT 1 AS number;
UPDATE logical_replication_test SET number = 2;
ERROR:  cannot update table "logical_replication_test" because it does
not have a replica identity and publishes updates

Patch attached.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 95f78d4ef499410c5f5a0fbcd86b658a2cdabbd9 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 13 Mar 2019 13:00:09 +0100
Subject: [PATCH] Fix handling of unlogged tables in FOR ALL TABLES
 publications

If a FOR ALL TABLES publication exists, unlogged tables are ignored
for publishing changes.  But CheckCmdReplicaIdentity() would still
check in that case that such a table has a replica identity set before
accepting updates.  That is useless, so check first whether the given
table is publishable and skip the check if not.
---
 src/backend/executor/execReplication.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/backend/executor/execReplication.c 
b/src/backend/executor/execReplication.c
index 95dfc4987d..3b79629a4a 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -566,6 +566,13 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
 {
        PublicationActions *pubactions;
 
+       /*
+        * If not publishable, we don't care, since it's not going to be
+        * replicated.  (pgoutput_change() will ignore it.)
+        */
+       if (!is_publishable_relation(rel))
+               return;
+
        /* We only need to do checks for UPDATE and DELETE. */
        if (cmd != CMD_UPDATE && cmd != CMD_DELETE)
                return;
-- 
2.21.0

Reply via email to