On Tue, Sep 15, 2026 at 2:01 PM vignesh C <[email protected]> wrote:
>
>
> The attached v2 version patch has the changes for the same. This also
> addresses Hou's comments from [1].
>
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2416,6 +2416,7 @@ typedef enum ObjectType
OBJECT_POLICY,
OBJECT_PROCEDURE,
OBJECT_PUBLICATION,
+ OBJECT_PUBLICATION_EXCLUDED_REL,
I was trying to evaluate whether the above change needs catversion
bump and reached conclusion that it doesn't need one because we never
store this enum on-disk as part of parse-trees. Do let me know if you
or others thinks differently.
*
static ObjectAddress
get_object_address_publication_rel(List *object,
- Relation *relp, bool missing_ok)
+ Relation *relp, bool missing_ok,
+ bool pubrel_is_exclusion)
It is better to use objtype here instead of boolean as we already use
at few other places.
*
+ if (!missing_ok)
+ {
+ if (pubrel_is_exclusion)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication excluded relation \"%s\" from publication \"%s\"
does not exist",
+ RelationGetRelationName(relation), pubname)));
+ else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
RelationGetRelationName(relation), pubname)));
I think these messages are misleading because actually here the object
type is wrong rather than object doesn't exist.
Please find a top-patch for the above suggestions.
--
With Regards,
Amit Kapila.
diff --git a/src/backend/catalog/objectaddress.c
b/src/backend/catalog/objectaddress.c
index 5b3aadf81f9..eebb10f2352 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -866,10 +866,10 @@ static ObjectAddress
get_object_address_opf_member(ObjectType objtype,
static ObjectAddress get_object_address_usermapping(List *object,
bool missing_ok);
-static ObjectAddress get_object_address_publication_rel(List *object,
+static ObjectAddress get_object_address_publication_rel(ObjectType objtype,
+
List *object,
Relation *relp,
-
bool missing_ok,
-
bool pubrel_is_exclusion);
+
bool missing_ok);
static ObjectAddress get_object_address_publication_schema(List *object,
bool missing_ok);
static ObjectAddress get_object_address_defacl(List *object,
@@ -1121,10 +1121,10 @@ get_object_address(ObjectType objtype, Node *object,
break;
case OBJECT_PUBLICATION_REL:
case OBJECT_PUBLICATION_EXCLUDED_REL:
- address =
get_object_address_publication_rel(castNode(List, object),
+ address =
get_object_address_publication_rel(objtype,
+
castNode(List, object),
&relation,
-
missing_ok,
-
objtype ==
OBJECT_PUBLICATION_EXCLUDED_REL);
+
missing_ok);
break;
case OBJECT_DEFACL:
address =
get_object_address_defacl(castNode(List, object),
@@ -1869,21 +1869,22 @@ get_object_address_usermapping(List *object, bool
missing_ok)
}
/*
- * Find the ObjectAddress for a publication relation or exclusion. The first
- * element of the object parameter is the relation name, the second is the
- * publication name.
+ * Find the ObjectAddress for a published or excluded publication relation.
+ * The first element of the object parameter is the relation name, the second
+ * is the publication name.
*/
static ObjectAddress
-get_object_address_publication_rel(List *object,
- Relation
*relp, bool missing_ok,
- bool
pubrel_is_exclusion)
+get_object_address_publication_rel(ObjectType objtype, List *object,
+ Relation
*relp, bool missing_ok)
{
ObjectAddress address;
Relation relation;
List *relname;
char *pubname;
Publication *pub;
+ Form_pg_publication_rel prform;
HeapTuple tup;
+ bool isexcept;
ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
@@ -1907,46 +1908,47 @@ get_object_address_publication_rel(List *object,
/*
* Find the publication relation mapping in syscache. Fetch the tuple
* rather than just its OID, so that prexcept can be checked without a
- * second lookup. A missing entry, or one of the other kind, falls
- * through to the not-found handling below.
+ * second lookup.
*/
tup = SearchSysCache2(PUBLICATIONRELMAP,
ObjectIdGetDatum(RelationGetRelid(relation)),
ObjectIdGetDatum(pub->oid));
- if (HeapTupleIsValid(tup))
+ if (!HeapTupleIsValid(tup))
{
- /* Found row in pg_publication_rel */
- Form_pg_publication_rel prform =
- (Form_pg_publication_rel) GETSTRUCT(tup);
- Oid pubreloid = prform->oid;
- bool isexcept = prform->prexcept;
-
- ReleaseSysCache(tup);
-
- /* Treat a prexcept mismatch as not found. */
- if (isexcept == pubrel_is_exclusion)
- {
- address.objectId = pubreloid;
- *relp = relation;
- return address;
- }
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication relation \"%s\" in
publication \"%s\" does not exist",
+
RelationGetRelationName(relation), pubname)));
+ relation_close(relation, AccessShareLock);
+ return address;
}
- if (!missing_ok)
+ prform = (Form_pg_publication_rel) GETSTRUCT(tup);
+ address.objectId = prform->oid;
+ isexcept = prform->prexcept;
+ ReleaseSysCache(tup);
+
+ /*
+ * The same relation and publication pair identifies either a published
or
+ * an excluded relation, so reject an entry of the kind that was not
asked
+ * for.
+ */
+ if (isexcept != (objtype == OBJECT_PUBLICATION_EXCLUDED_REL))
{
- if (pubrel_is_exclusion)
+ if (isexcept)
ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication excluded relation
\"%s\" from publication \"%s\" does not exist",
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a published
relation of publication \"%s\"",
RelationGetRelationName(relation), pubname)));
else
ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication relation \"%s\" in
publication \"%s\" does not exist",
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not an excluded
relation of publication \"%s\"",
RelationGetRelationName(relation), pubname)));
}
- relation_close(relation, AccessShareLock);
+ *relp = relation;
return address;
}
diff --git a/src/test/regress/expected/publication.out
b/src/test/regress/expected/publication.out
index 534b0f3f8af..7ccfb5810a6 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -283,15 +283,21 @@ JOIN pg_class c ON c.oid = pr.prrelid
WHERE p.pubname = 'testpub_foralltables_excepttable1'
AND c.relname = 'testpub_tbl1';
publication excluded relation|||public.testpub_tbl1 excluded from publication
testpub_foralltables_excepttable1
+-- testpub_describe publishes testpub_tbl1, testpub_foralltables_excepttable1
+-- excludes it; an entry of one kind must not be resolved as the other.
+CREATE PUBLICATION testpub_describe FOR TABLE testpub_tbl1;
SELECT pg_get_object_address('publication excluded relation',
- '{public, testpub_tbl1}', '{testpub_fortable}');
-ERROR: publication excluded relation "testpub_tbl1" from publication
"testpub_fortable" does not exist
+ '{public, testpub_tbl1}', '{testpub_describe}');
+ERROR: "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: publication relation "testpub_tbl1" in publication
"testpub_foralltables_excepttable1" does not exist
+ERROR: "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 relation "testpub_tbl1" in publication "testpub_default"
does not exist
-- Check pg_describe_object output for both included and excluded entries
-CREATE PUBLICATION testpub_describe FOR TABLE testpub_tbl1;
SELECT p.pubname,
pg_describe_object('pg_publication_rel'::regclass, pr.oid, 0) AS
description,
pr.prexcept
diff --git a/src/test/regress/sql/publication.sql
b/src/test/regress/sql/publication.sql
index 2e4bf749149..074482605d9 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -131,13 +131,18 @@ JOIN pg_publication p ON p.oid = pr.prpubid
JOIN pg_class c ON c.oid = pr.prrelid
WHERE p.pubname = 'testpub_foralltables_excepttable1'
AND c.relname = 'testpub_tbl1';
+-- testpub_describe publishes testpub_tbl1, testpub_foralltables_excepttable1
+-- excludes it; an entry of one kind must not be resolved as the other.
+CREATE PUBLICATION testpub_describe FOR TABLE testpub_tbl1;
SELECT pg_get_object_address('publication excluded relation',
- '{public, testpub_tbl1}', '{testpub_fortable}');
+ '{public, testpub_tbl1}', '{testpub_describe}');
SELECT pg_get_object_address('publication relation',
'{public, testpub_tbl1}',
'{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}');
-- Check pg_describe_object output for both included and excluded entries
-CREATE PUBLICATION testpub_describe FOR TABLE testpub_tbl1;
SELECT p.pubname,
pg_describe_object('pg_publication_rel'::regclass, pr.oid, 0) AS
description,
pr.prexcept