From 96f1fce8fb50f527b958de13a60f7324dd1ef052 Mon Sep 17 00:00:00 2001 From: Ilya Gladyshev Date: Fri, 28 Oct 2022 23:25:20 +0400 Subject: [PATCH] check relkind of subscription target recursively --- src/backend/commands/subscriptioncmds.c | 13 ++++--- src/backend/executor/execReplication.c | 45 ++++++++++++++++++---- src/backend/replication/logical/relation.c | 7 ++-- src/include/executor/executor.h | 4 +- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index f0cec2ad5e..e2dd6425e4 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -703,9 +703,10 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, relid = RangeVarGetRelid(rv, AccessShareLock, false); - /* Check for supported relkind. */ - CheckSubscriptionRelkind(get_rel_relkind(relid), - rv->schemaname, rv->relname); + /* Check for supported relkind recursively. */ + CheckSubscriptionRelation(relid, + get_rel_relkind(relid), + rv->schemaname, rv->relname); AddSubscriptionRelState(subid, relid, table_state, InvalidXLogRecPtr); @@ -864,9 +865,9 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data, relid = RangeVarGetRelid(rv, AccessShareLock, false); - /* Check for supported relkind. */ - CheckSubscriptionRelkind(get_rel_relkind(relid), - rv->schemaname, rv->relname); + /* Check for supported relkind recursively. */ + CheckSubscriptionRelation(relid, get_rel_relkind(relid), + rv->schemaname, rv->relname); pubrel_local_oids[off++] = relid; diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 6014f2e248..98bc4a6618 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -16,9 +16,11 @@ #include "access/genam.h" #include "access/relscan.h" +#include "access/table.h" #include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" +#include "catalog/pg_inherits.h" #include "commands/trigger.h" #include "executor/executor.h" #include "executor/nodeModifyTable.h" @@ -645,13 +647,7 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) 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 +static void CheckSubscriptionRelkind(char relkind, const char *nspname, const char *relname) { @@ -662,3 +658,38 @@ CheckSubscriptionRelkind(char relkind, const char *nspname, nspname, relname), errdetail_relkind_not_supported(relkind))); } + +/* + * Recursively check if we support writing into specific relkind. + * + * The nspname and relname are only needed for error reporting. + */ +void +CheckSubscriptionRelation(Oid relid, char relkind, const char *nspname, + const char *relname) +{ + CheckSubscriptionRelkind(relkind, nspname, relname); + + if (relkind == RELKIND_PARTITIONED_TABLE) + { + List *inheritors; + ListCell *lc; + + inheritors = find_all_inheritors(relid, + AccessShareLock, + NULL); + foreach (lc, inheritors) + { + Oid child_oid = lfirst_oid(lc); + Relation child_rel = RelationIdGetRelation(child_oid); + char *relname; + char *nspname; + + relname = RelationGetRelationName(child_rel); + nspname = get_namespace_name(RelationGetNamespace(child_rel)); + + CheckSubscriptionRelkind(child_rel->rd_rel->relkind, nspname, relname); + table_close(child_rel, AccessShareLock); + } + } +} diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index e989047681..307ab0b559 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -392,9 +392,10 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) entry->localrel = table_open(relid, NoLock); entry->localreloid = relid; - /* Check for supported relkind. */ - CheckSubscriptionRelkind(entry->localrel->rd_rel->relkind, - remoterel->nspname, remoterel->relname); + /* Check for supported relkind recursively. */ + CheckSubscriptionRelation(entry->localrel->rd_rel->oid, + 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 ed95ed1176..757a8fa780 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -646,8 +646,8 @@ extern void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo, TupleTableSlot *searchslot); extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); -extern void CheckSubscriptionRelkind(char relkind, const char *nspname, - const char *relname); +extern void CheckSubscriptionRelation(Oid relid, char relkind, const char *nspname, + const char *relname); /* * prototypes from functions in nodeModifyTable.c -- 2.30.2