shveta malik <[email protected]> wrote:
> I agree that there is no confusion in above case. But I also don't see
> any harm in having a schema-qualified name. It makes the message
> clearer. The cases like below can become more understandable with
> schema qualified name.
[...]
> postgres=# SET search_path = s2;
> postgres=# SELECT pg_get_object_address('publication relation',
> '{t2}', '{pub}');
> ERROR: publication relation "t2" in publication "pub" does not exist
Zhijie is right that my own example was weak: the schema was right there
in the call. Your example is the one that matters, and it goes through
the "does not exist" message, which my first delta did not touch. The
attached 0001 now qualifies all four errors in
get_object_address_publication_rel(), so that case reads:
ERROR: publication relation "s2.t2" in publication "pub" does not exist
> If at all we plan to add it, it will be good to use
> 'RelationGetQualifiedRelationName' instead.
I tried it first, and it quotes the name twice when it needs quoting,
because it goes through quote_qualified_identifier() and these messages
already put the name in quotes:
ERROR: publication relation ""Sales Q3"."Big Table"" in
publication "pub" does not exist
So 0001 uses "\"%s.%s\"" with get_namespace_name(), which is the form of
55 errmsg() calls in src/backend, against 3 that put a quoted qualified
name inside quotes.
That also shows the same problem in commit a49b9cfd72d, which is in
REL_19_STABLE:
CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES
FROM (100) TO (200);
CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2");
ERROR: cannot specify relation "public."testpub Part2"" in the
publication EXCEPT clause
0002 fixes it by building the name the same way, without changing the
message text, and adds that case to publication.sql. Without the fix
the new test fails with the output above; with it, it passes. 0002 does
not depend on v5 and applies to both master and REL_19_STABLE.
Zhijie Hou (Fujitsu) <[email protected]> wrote:
> There is no harm, but it is not consistent with the other object
> messages used here (e.g., they do not report schema-qualified names):
That is true of objectaddress.c: none of its messages qualifies the name
today. The case for doing it here is the one a49b9cfd72d made for the
EXCEPT errors, that the same name can exist in several schemas, plus
shveta's search_path example. Whether that outweighs consistency with
the rest of objectaddress.c is Amit's call; if not, 0001 can simply be
dropped, and 0002 still stands on its own.
v5 plus 0001 and 0002: all 239 regression tests pass.
> Just a kind suggestion: the community prefers inline replies rather than
> top-posting
Thanks, noted.
Regards,
Manu
El mié, 16 sept 2026 a las 7:23, Zhijie Hou (Fujitsu)
(<[email protected]>) escribió:
>
> Hi,
>
> On Wednesday, September 16, 2026 6:14 PM shveta malik
> <[email protected]> wrote:
> > On Wed, Sep 16, 2026 at 3:24 PM Zhijie Hou (Fujitsu)
> > > On Wednesday, September 16, 2026 5:20 PM Manuel Reyes Bravo
> > <[email protected]> wrote:
> > > > CREATE TABLE t2(a int);
> > > > CREATE SCHEMA s2; CREATE TABLE s2.t2(a int);
> > > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE s2.t2);
> > > >
> > > > SELECT pg_get_object_address('publication
> > > > relation','{s2,t2}','{pub}');
> > > > ERROR: "t2" is not a published relation of publication "pub"
> > > >
> > > > So the message says that "t2" is not a published relation of pub, while
> > > > the catalog says that a t2 is. They are different tables, and the user
> > > > cannot tell which one the message is about.
> > >
> > > In this case, the user is explicitly passing s2.t2 as a parameter to get
> > > its
> > > object address. In that context, it's pretty clear to me that t2 in the
> > > message
> > > refers exactly to the object the user passed, I personally don't think it
> > > could
> > > point to any other table.
> >
> > I agree that there is no confusion in above case. But I also don't see
> > any harm in having a schema-qualified name. It makes the message
> > clearer. The cases like below can become more understandable with
> > schema qualified name.
>
> There is no harm, but it is not consistent with the other object
> messages used here (e.g., they do not report schema-qualified names):
>
> get_relation_by_qualified_name
> get_object_address_attribute
> get_object_address_attrdef
> get_object_address_unqualified
> get_object_address_type
> ...
>
> So it does not look necessary to me to add it for our publication case.
>
> The column list error message reports schema-qualified names because users can
> specify multiple tables with the same name from different schemas, so it's
> necessary there. But that's not our case.
>
> Best Regards,
> Zhijie Hou
From ebdd745f836f92de4e23d1f1579b8b2206408b81 Mon Sep 17 00:00:00 2001
From: Manu <[email protected]>
Date: Wed, 16 Sep 2026 09:36:24 -0300
Subject: [PATCH v2 on top of v5 2/2] Don't quote the relation name twice in
EXCEPT clause errors
Commit a49b9cfd72d made check_publication_add_relation() report the
relation of an EXCEPT clause with RelationGetQualifiedRelationName(),
which quotes identifiers when needed, inside a message that already puts
the name in quotes. A name that needs quoting came out quoted twice:
ERROR: cannot specify relation "public."testpub Part2"" in the publication EXCEPT clause
Build the qualified name without identifier quoting instead, which is
the "\"%s.%s\"" form used elsewhere in the backend. The message text,
and so its translations, is unchanged. Add a test with such a name.
---
src/backend/catalog/pg_publication.c | 8 +++++++-
src/test/regress/expected/publication.out | 7 ++++++-
src/test/regress/sql/publication.sql | 5 ++++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 6b752c4c738..72ac5c8db3e 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -62,7 +62,13 @@ check_publication_add_relation(PublicationRelInfo *pri)
if (pri->except)
{
- relname = RelationGetQualifiedRelationName(targetrel);
+ /*
+ * The message already quotes the name, so qualify it without the
+ * identifier quoting that RelationGetQualifiedRelationName() adds.
+ */
+ relname = psprintf("%s.%s",
+ get_namespace_name(RelationGetNamespace(targetrel)),
+ RelationGetRelationName(targetrel));
errormsg = gettext_noop("cannot specify relation \"%s\" in the publication EXCEPT clause");
}
else
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 3013e405422..6e4dec1d422 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -514,6 +514,11 @@ Number of partitions: 1 (Use \d+ to list them.)
CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1);
ERROR: cannot specify relation "public.testpub_part1" in the publication EXCEPT clause
DETAIL: This operation is not supported for individual partitions.
+-- A name that needs quoting must not be quoted twice in the message.
+CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200);
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2");
+ERROR: cannot specify relation "public.testpub Part2" 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
-- publication's EXCEPT clause.
@@ -522,7 +527,7 @@ ERROR: cannot attach table "testpub_root" as partition because it is referenced
DETAIL: The publication EXCEPT clause cannot contain tables that are partitions.
HINT: Change the publication's EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES.
RESET client_min_messages;
-DROP TABLE testpub_root, testpub_part1, tab_main;
+DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main;
DROP PUBLICATION testpub8;
--- Tests for publications with SEQUENCES
CREATE SEQUENCE regress_pub_seq0;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 074482605d9..e3dbb2bc57c 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -249,6 +249,9 @@ CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT (TABLE testpub_root);
\d testpub_part1
\d testpub_root
CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1);
+-- A name that needs quoting must not be quoted twice in the message.
+CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200);
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2");
CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
-- Attaching a partition is not allowed if the partitioned table appears in a
@@ -256,7 +259,7 @@ CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
ALTER TABLE tab_main ATTACH PARTITION testpub_root FOR VALUES FROM (0) TO (200);
RESET client_min_messages;
-DROP TABLE testpub_root, testpub_part1, tab_main;
+DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main;
DROP PUBLICATION testpub8;
--- Tests for publications with SEQUENCES
--
2.55.0
From 1b6833ca809895796b56c0c62375a1b416951618 Mon Sep 17 00:00:00 2001
From: Manu <[email protected]>
Date: Wed, 16 Sep 2026 09:35:09 -0300
Subject: [PATCH v2 on top of v5 1/2] Qualify the relation name in publication
relation object address errors
get_object_address_publication_rel() reports the relation by its bare
name in its four errors. When the relation was given without a schema,
the message does not say which one the search_path picked:
CREATE SCHEMA s1; CREATE TABLE s1.t2(a int);
CREATE SCHEMA s2; CREATE TABLE s2.t2(a int);
CREATE PUBLICATION pub FOR TABLE s1.t2;
SET search_path = s2;
SELECT pg_get_object_address('publication relation', '{t2}', '{pub}');
ERROR: publication relation "t2" in publication "pub" does not exist
Report the schema as well, as commit a49b9cfd72d did for the EXCEPT
clause errors, using the "\"%s.%s\"" form common in the backend rather
than a quoted qualified name inside quotes.
---
src/backend/catalog/objectaddress.c | 12 ++++++++----
src/test/regress/expected/publication.out | 6 +++---
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 1e24f4b80be..a97107d8529 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -1923,12 +1923,14 @@ get_object_address_publication_rel(ObjectType objtype, List *object,
if (objtype == OBJECT_PUBLICATION_EXCLUDED_REL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication excluded relation \"%s\" in publication \"%s\" does not exist",
+ errmsg("publication excluded relation \"%s.%s\" in publication \"%s\" does not exist",
+ get_namespace_name(RelationGetNamespace(relation)),
RelationGetRelationName(relation), pubname)));
else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
+ errmsg("publication relation \"%s.%s\" in publication \"%s\" does not exist",
+ get_namespace_name(RelationGetNamespace(relation)),
RelationGetRelationName(relation), pubname)));
}
relation_close(relation, AccessShareLock);
@@ -1948,12 +1950,14 @@ get_object_address_publication_rel(ObjectType objtype, List *object,
if (objtype == OBJECT_PUBLICATION_EXCLUDED_REL && !isexcept)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not an excluded relation of publication \"%s\"",
+ errmsg("\"%s.%s\" is not an excluded relation of publication \"%s\"",
+ get_namespace_name(RelationGetNamespace(relation)),
RelationGetRelationName(relation), pubname)));
else if (objtype == OBJECT_PUBLICATION_REL && isexcept)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a published relation of publication \"%s\"",
+ errmsg("\"%s.%s\" is not a published relation of publication \"%s\"",
+ get_namespace_name(RelationGetNamespace(relation)),
RelationGetRelationName(relation), pubname)));
*relp = relation;
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index d51b27d7d02..3013e405422 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -288,15 +288,15 @@ publication excluded relation|||public.testpub_tbl1 excluded from publication te
CREATE PUBLICATION testpub_describe FOR TABLE testpub_tbl1;
SELECT pg_get_object_address('publication excluded relation',
'{public, testpub_tbl1}', '{testpub_describe}');
-ERROR: "testpub_tbl1" is not an excluded relation of publication "testpub_describe"
+ERROR: "public.testpub_tbl1" is not an excluded relation of publication "testpub_describe"
SELECT pg_get_object_address('publication relation',
'{public, testpub_tbl1}',
'{testpub_foralltables_excepttable1}');
-ERROR: "testpub_tbl1" is not a published relation of publication "testpub_foralltables_excepttable1"
+ERROR: "public.testpub_tbl1" is not a published relation of publication "testpub_foralltables_excepttable1"
-- No entry of either kind. testpub_default publishes nothing.
SELECT pg_get_object_address('publication excluded relation',
'{public, testpub_tbl1}', '{testpub_default}');
-ERROR: publication excluded relation "testpub_tbl1" in publication "testpub_default" does not exist
+ERROR: publication excluded relation "public.testpub_tbl1" in publication "testpub_default" does not exist
-- Check pg_describe_object output for both included and excluded entries
SELECT p.pubname,
pg_describe_object('pg_publication_rel'::regclass, pr.oid, 0) AS description,
--
2.55.0