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

Reply via email to