From: Amit Kapila Date: Fri, 8 May 2026 04:30:26 +0000 (+0530) Subject: Use schema-qualified names in EXCEPT clause error messages. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a49b9cfd72d89a8fd68c90e84c38aa7e2ada756b;p=thirdparty%2Fpostgresql.git Use schema-qualified names in EXCEPT clause error messages. Error messages in check_publication_add_relation() previously reported only the relation name when a table in an EXCEPT clause could not be processed, which is ambiguous when the same name exists in multiple schemas. Use schema-qualified names instead, consistent with other error messages that reference relation names. Author: Dilip Kumar Author: vignesh C Reviewed-by: shveta malik Reviewed-by: Euler Taveira Reviewed-by: Amit Kapila Reviewed-by: Peter Smith Discussion: https://postgr.es/m/CAFiTN-scG7b11Jsp+VoDRT8ZFE84eSKLcDsSB18dZ8AaP=R-mw@mail.gmail.com --- diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index a43d385c605..5c457d9aca8 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -56,18 +56,25 @@ static void check_publication_add_relation(PublicationRelInfo *pri) { Relation targetrel = pri->relation; + const char *relname; const char *errormsg; if (pri->except) + { + relname = RelationGetQualifiedRelationName(targetrel); errormsg = gettext_noop("cannot specify relation \"%s\" in the publication EXCEPT clause"); + } else + { + relname = RelationGetRelationName(targetrel); errormsg = gettext_noop("cannot add relation \"%s\" to publication"); + } /* If in EXCEPT clause, must be root partitioned table */ if (pri->except && targetrel->rd_rel->relispartition) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, RelationGetRelationName(targetrel)), + errmsg(errormsg, relname), errdetail("This operation is not supported for individual partitions."))); /* Must be a regular or partitioned table */ @@ -75,26 +82,26 @@ check_publication_add_relation(PublicationRelInfo *pri) RelationGetForm(targetrel)->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, RelationGetRelationName(targetrel)), + errmsg(errormsg, relname), errdetail_relkind_not_supported(RelationGetForm(targetrel)->relkind))); /* Can't be system table */ if (IsCatalogRelation(targetrel)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, RelationGetRelationName(targetrel)), + errmsg(errormsg, relname), errdetail("This operation is not supported for system tables."))); /* UNLOGGED and TEMP relations cannot be part of publication. */ if (targetrel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, RelationGetRelationName(targetrel)), + errmsg(errormsg, relname), errdetail("This operation is not supported for temporary tables."))); else if (targetrel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, RelationGetRelationName(targetrel)), + errmsg(errormsg, relname), errdetail("This operation is not supported for unlogged tables."))); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 75b77bb39f1..88de5c0481c 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -13876,23 +13876,15 @@ generate_qualified_relation_name(Oid relid) { HeapTuple tp; Form_pg_class reltup; - char *relname; - char *nspname; char *result; tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for relation %u", relid); reltup = (Form_pg_class) GETSTRUCT(tp); - relname = NameStr(reltup->relname); - - nspname = get_namespace_name_or_temp(reltup->relnamespace); - if (!nspname) - elog(ERROR, "cache lookup failed for namespace %u", - reltup->relnamespace); - - result = quote_qualified_identifier(nspname, relname); + result = get_qualified_objname(reltup->relnamespace, + NameStr(reltup->relname)); ReleaseSysCache(tp); return result; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 3de10d4df7e..036086057d7 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -3628,6 +3628,26 @@ get_namespace_name_or_temp(Oid nspid) return get_namespace_name(nspid); } +/* + * get_qualified_objname + * Returns a palloc'd string containing the schema-qualified name of the + * object for the given namespace ID and object name. + */ +char * +get_qualified_objname(Oid nspid, char *objname) +{ + char *nspname; + char *result; + + nspname = get_namespace_name_or_temp(nspid); + if (!nspname) + elog(ERROR, "cache lookup failed for namespace %u", nspid); + + result = quote_qualified_identifier(nspname, objname); + + return result; +} + /* ---------- PG_RANGE CACHES ---------- */ /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index e19f0d3e51c..0572ab424e7 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -2135,6 +2135,16 @@ RelationIdGetRelation(Oid relationId) return rd; } +/* + * Returns a schema-qualified name of the relation. + */ +char * +RelationGetQualifiedRelationName(Relation rel) +{ + return get_qualified_objname(RelationGetNamespace(rel), + RelationGetRelationName(rel)); +} + /* ---------------------------------------------------------------- * cache invalidation support routines * ---------------------------------------------------------------- diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 8d5e92e07be..8545e67a632 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -200,6 +200,7 @@ extern bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, extern void free_attstatsslot(AttStatsSlot *sslot); extern char *get_namespace_name(Oid nspid); extern char *get_namespace_name_or_temp(Oid nspid); +extern char *get_qualified_objname(Oid nspid, char *objname); extern Oid get_range_subtype(Oid rangeOid); extern Oid get_range_collation(Oid rangeOid); extern Oid get_range_constructor2(Oid rangeOid); diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 2700224939a..89c27aa1529 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -46,6 +46,7 @@ AssertCouldGetRelation(void) } #endif extern Relation RelationIdGetRelation(Oid relationId); +extern char *RelationGetQualifiedRelationName(Relation rel); extern void RelationClose(Relation relation); /* diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 0345f6c5e47..29e54b214a0 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -458,7 +458,7 @@ Excluded from publications: Number of partitions: 1 (Use \d+ to list them.) CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1); -ERROR: cannot specify relation "testpub_part1" in the publication EXCEPT clause +ERROR: cannot specify relation "public.testpub_part1" in the publication EXCEPT clause DETAIL: This operation is not supported for individual partitions. CREATE TABLE tab_main (a int) PARTITION BY RANGE(a); -- Attaching a partition is not allowed if the partitioned table appears in a