From 4272e15faefadc692e89ba06dcde64f07f4e075f Mon Sep 17 00:00:00 2001
From: Petr Jelinek <pjmodos@pjmodos.net>
Date: Mon, 5 Feb 2018 16:09:37 +0100
Subject: [PATCH] Fix filtering of unsupported relations in pgoutput

For normal publications this was already handled when such relation was
requested to be added to given publication by user. However the
alltables publications don't use relation membership check so we have to
handle filtering of unsupported relation kinds directly in pgoutput.
---
 src/backend/replication/pgoutput/pgoutput.c | 33 ++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 40a1ef3c1d..37756474b9 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -509,15 +509,16 @@ get_rel_sync_entry(PGOutputData *data, Oid relid)
 			Publication *pub = lfirst(lc);
 
 			/*
-			 * Skip tables that look like they are from a heap rewrite (see
-			 * make_new_heap()).  We need to skip them because the subscriber
-			 * won't have a table by that name to receive the data.  That
-			 * means we won't ship the new data in, say, an added column with
-			 * a DEFAULT, but if the user applies the same DDL manually on the
-			 * subscriber, then this will work out for them.
+			 * We might see changes here from relations which we don't know
+			 * how to handle correcly, hence we have to filter them out.
 			 *
-			 * We only need to consider the alltables case, because such a
-			 * transient heap won't be an explicit member of a publication.
+			 * These include:
+			 * a) materialized views
+			 * b) temporary relations used for heap rewrite
+			 *
+			 * We only care about those in alltables publications because
+			 * for normal publications they will fail membership test. Also
+			 * see check_publication_add_relation().
 			 */
 			if (pub->alltables)
 			{
@@ -525,12 +526,20 @@ get_rel_sync_entry(PGOutputData *data, Oid relid)
 				unsigned int u;
 				int			n;
 
+				/*
+				 * We don't allow publishing of anything that's not a
+				 * relation.
+				 */
+				if (get_rel_relkind(relid) != RELKIND_RELATION)
+					break;
+
+				/*
+				 * We also don't allow publishing temporary heaps for relation
+				 * rewrite.  See make_new_heap().
+				 */
 				if (sscanf(relname, "pg_temp_%u%n", &u, &n) == 1 &&
 					relname[n] == '\0')
-				{
-					if (get_rel_relkind(u) == RELKIND_RELATION)
-						break;
-				}
+					break;
 			}
 
 			if (pub->alltables || list_member_oid(pubids, pub->oid))
-- 
2.14.1

