On Wed, 2022-11-02 at 12:37 -0400, Tom Lane wrote: > Since we're getting pretty close to the next set of back-branch > releases, > I went ahead and pushed a minimal fix along the lines suggested by > Shi Yu. > (I realized that there's a second ExecFindPartition call in worker.c > that > also needs a check.) We still can at leisure think about refactoring > CheckSubscriptionRelkind to avoid unnecessary lookups. I think that > is something we should do only in HEAD; it'll just be a marginal > savings, > not worth the risks of API changes in stable branches. The other > loose > end is whether to worry about a regression test case. I'm inclined > not > to bother. The only thing that isn't getting exercised is the actual > ereport, which probably isn't in great need of routine testing. > > regards, tom lane
I agree that early checks limit some of the functionality that was available before, so I guess the only way to preserve it is to do only the last-minute checks after routing, fair enough. As for the refactoring of the premature lookup, I have done some work on that in the previous patch, I think we can just use it. Attached a separate patch with the refactoring.
From 004c63a8eba777be739f062cdc9b7ddcf2eac253 Mon Sep 17 00:00:00 2001 From: Ilya Gladyshev <ilya.v.gladys...@gmail.com> Date: Thu, 3 Nov 2022 11:39:24 +0400 Subject: [PATCH] Delay namespace and relname lookups until error --- src/backend/commands/subscriptioncmds.c | 12 ++++++++---- src/backend/executor/execReplication.c | 13 ++++++++++--- src/backend/replication/logical/relation.c | 2 +- src/backend/replication/logical/worker.c | 8 ++------ src/include/executor/executor.h | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index f0cec2ad5e..0c3ad698eb 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -700,12 +700,14 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, { RangeVar *rv = (RangeVar *) lfirst(lc); Oid relid; + Relation sub_rel; relid = RangeVarGetRelid(rv, AccessShareLock, false); + sub_rel = RelationIdGetRelation(relid); /* Check for supported relkind. */ - CheckSubscriptionRelkind(get_rel_relkind(relid), - rv->schemaname, rv->relname); + CheckSubscriptionRelkind(sub_rel, rv->schemaname, rv->relname); + RelationClose(sub_rel); AddSubscriptionRelState(subid, relid, table_state, InvalidXLogRecPtr); @@ -861,12 +863,14 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data, { RangeVar *rv = (RangeVar *) lfirst(lc); Oid relid; + Relation sub_rel; relid = RangeVarGetRelid(rv, AccessShareLock, false); + sub_rel = RelationIdGetRelation(relid); /* Check for supported relkind. */ - CheckSubscriptionRelkind(get_rel_relkind(relid), - rv->schemaname, rv->relname); + CheckSubscriptionRelkind(sub_rel, rv->schemaname, rv->relname); + RelationClose(sub_rel); pubrel_local_oids[off++] = relid; diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 6014f2e248..a0a2d326db 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -649,16 +649,23 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) /* * Check if we support writing into specific relkind. * - * The nspname and relname are only needed for error reporting. + * If nspname and relname are not NULL, they are used for error reporting, otherwise these values are fetched from relcache. */ void -CheckSubscriptionRelkind(char relkind, const char *nspname, - const char *relname) +CheckSubscriptionRelkind(Relation rel, const char *nspname, const char *relname) { + char relkind = rel->rd_rel->relkind; + if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE) + { + if (relname == NULL) + relname = RelationGetRelationName(rel); + if (nspname == NULL) + nspname = get_namespace_name(RelationGetNamespace(rel)); ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot use relation \"%s.%s\" as logical replication target", nspname, relname), errdetail_relkind_not_supported(relkind))); + } } diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index e989047681..e98031e272 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -393,7 +393,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) entry->localreloid = relid; /* Check for supported relkind. */ - CheckSubscriptionRelkind(entry->localrel->rd_rel->relkind, + CheckSubscriptionRelkind(entry->localrel, remoterel->nspname, remoterel->relname); /* diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index e48a3f589a..e00e383968 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -2181,9 +2181,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, * unsupported relkinds; and the set of partitions can change, so checking * at CREATE/ALTER SUBSCRIPTION would be insufficient. */ - CheckSubscriptionRelkind(partrel->rd_rel->relkind, - get_namespace_name(RelationGetNamespace(partrel)), - RelationGetRelationName(partrel)); + CheckSubscriptionRelkind(partrel, NULL, NULL); /* * To perform any of the operations below, the tuple must match the @@ -2334,9 +2332,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, partrel_new = partrelinfo_new->ri_RelationDesc; /* Check that new partition also has supported relkind. */ - CheckSubscriptionRelkind(partrel_new->rd_rel->relkind, - get_namespace_name(RelationGetNamespace(partrel_new)), - RelationGetRelationName(partrel_new)); + CheckSubscriptionRelkind(partrel_new, NULL, NULL); /* DELETE old tuple found in the old partition. */ apply_handle_delete_internal(edata, partrelinfo, diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index ed95ed1176..188e783b5e 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -646,7 +646,7 @@ extern void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo, TupleTableSlot *searchslot); extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); -extern void CheckSubscriptionRelkind(char relkind, const char *nspname, +extern void CheckSubscriptionRelkind(Relation rel, const char *nspname, const char *relname); /* -- 2.30.2