From 944dc0f9cec7c3d33648f41aaecfbd976106e975 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 16 May 2017 22:57:16 -0400 Subject: [PATCH] Check relkind of tables in CREATE/ALTER SUBSCRIPTION We used to only check for a supported relkind on the subscriber during replication, which is needed to ensure that the setup is valid and we don't crash. But it's also useful to tell the user immediately when CREATE or ALTER SUBSCRIPTION is executed that the relation being added to the subscription is not of a supported relkind. Author: Petr Jelinek Reported-by: tushar --- src/backend/commands/subscriptioncmds.c | 11 +++++++++++ src/backend/executor/execReplication.c | 20 ++++++++++++++++++++ src/backend/replication/logical/relation.c | 13 ++++--------- src/include/executor/executor.h | 2 ++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index b80af275da..265f2efd62 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -33,6 +33,8 @@ #include "commands/event_trigger.h" #include "commands/subscriptioncmds.h" +#include "executor/executor.h" + #include "nodes/makefuncs.h" #include "replication/logicallauncher.h" @@ -417,6 +419,10 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel) relid = RangeVarGetRelid(rv, AccessShareLock, false); + /* Check for supported relkind. */ + CheckSubscriptionRelkind(get_rel_relkind(relid), + rv->schemaname, rv->relname); + SetSubscriptionRelState(subid, relid, table_state, InvalidXLogRecPtr); } @@ -529,6 +535,11 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data) Oid relid; relid = RangeVarGetRelid(rv, AccessShareLock, false); + + /* Check for supported relkind. */ + CheckSubscriptionRelkind(get_rel_relkind(relid), + rv->schemaname, rv->relname); + pubrel_local_oids[off++] = relid; if (!bsearch(&relid, subrel_local_oids, diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 327a0bad38..6af8018b71 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -551,3 +551,23 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) RelationGetRelationName(rel)), errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE."))); } + + +/* + * Check if we support writing into specific relkind. + * + * The nspname and relname are only needed for error reporting. + */ +void +CheckSubscriptionRelkind(char relkind, const char *nspname, + const char *relname) +{ + /* + * We currently only support writing to regular tables. + */ + if (relkind != RELKIND_RELATION) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("logical replication target relation \"%s.%s\" is not a table", + nspname, relname))); +} diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index 7c93bfb80a..590355a846 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -20,6 +20,7 @@ #include "access/sysattr.h" #include "catalog/namespace.h" #include "catalog/pg_subscription_rel.h" +#include "executor/executor.h" #include "nodes/makefuncs.h" #include "replication/logicalrelation.h" #include "replication/worker_internal.h" @@ -258,15 +259,9 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) remoterel->nspname, remoterel->relname))); entry->localrel = heap_open(relid, NoLock); - /* - * We currently only support writing to regular and partitioned - * tables. - */ - if (entry->localrel->rd_rel->relkind != RELKIND_RELATION) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("logical replication target relation \"%s.%s\" is not a table", - remoterel->nspname, remoterel->relname))); + /* Check for supported relkind. */ + CheckSubscriptionRelkind(entry->localrel->rd_rel->relkind, + remoterel->nspname, remoterel->relname); /* * Build the mapping of local attribute numbers to remote attribute diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 4f19579ee0..ab61d35a86 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -535,5 +535,7 @@ extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, TupleTableSlot *searchslot); extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); +extern void CheckSubscriptionRelkind(char relkind, const char *nspname, + const char *relname); #endif /* EXECUTOR_H */