Retain relkind too in RTE_SUBQUERY entries for views.
authorAmit Langote <amitlan@postgresql.org>
Tue, 13 Jun 2023 03:52:47 +0000 (12:52 +0900)
committerAmit Langote <amitlan@postgresql.org>
Wed, 14 Jun 2023 03:00:10 +0000 (12:00 +0900)
47bb9db75 modified the ApplyRetrieveRule()'s conversion of a view's
original RTE_RELATION entry into an RTE_SUBQUERY one to retain relid,
rellockmode, and perminfoindex so that the executor can lock the view
and check its permissions.  It seems better to also retain
relkind for cross-checking that the exception of an
RTE_SUBQUERY entry being allowed to carry relation details only
applies to views, so do so.

Bump catversion because this changes the output format of
RTE_SUBQUERY RTEs.

Suggested-by: David Steele <david@pgmasters.net>
Reviewed-by: David Steele <david@pgmasters.net>
Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://postgr.es/m/3953179e-9540-e5d1-a743-4bef368785b0%40pgmasters.net

src/backend/executor/execMain.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/rewrite/rewriteHandler.c
src/include/catalog/catversion.h
src/include/nodes/parsenodes.h

index c76fdf59ec44efe2aceffca7a1ae248bbc128b1f..4c5a7bbf620a93c6dbc9972bcf475051584b64d9 100644 (file)
@@ -595,6 +595,15 @@ ExecCheckPermissions(List *rangeTable, List *rteperminfos,
                if (rte->perminfoindex != 0)
                {
                        /* Sanity checks */
+
+                       /*
+                        * Only relation RTEs and subquery RTEs that were once relation
+                        * RTEs (views) have their perminfoindex set.
+                        */
+                       Assert(rte->rtekind == RTE_RELATION ||
+                                  (rte->rtekind == RTE_SUBQUERY &&
+                                       rte->relkind == RELKIND_VIEW));
+
                        (void) getRTEPermissionInfo(rteperminfos, rte);
                        /* Many-to-one mapping not allowed */
                        Assert(!bms_is_member(rte->perminfoindex, indexset));
index ba00b99249f5f47b29524f1c31eff12eb6db35dd..955286513d24faa4170e24307e68fc9db5d2b61f 100644 (file)
@@ -513,6 +513,7 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
                        WRITE_BOOL_FIELD(security_barrier);
                        /* we re-use these RELATION fields, too: */
                        WRITE_OID_FIELD(relid);
+                       WRITE_CHAR_FIELD(relkind);
                        WRITE_INT_FIELD(rellockmode);
                        WRITE_UINT_FIELD(perminfoindex);
                        break;
index 597e5b3ea8b94d055693d9a698f7b16844200fae..a136ae1d602a46003160bd7f03946c4b28ca58e9 100644 (file)
@@ -503,6 +503,7 @@ _readRangeTblEntry(void)
                        READ_BOOL_FIELD(security_barrier);
                        /* we re-use these RELATION fields, too: */
                        READ_OID_FIELD(relid);
+                       READ_CHAR_FIELD(relkind);
                        READ_INT_FIELD(rellockmode);
                        READ_UINT_FIELD(perminfoindex);
                        break;
index 6e724010c0424a83055a76376274c5d658bd45a7..5a7b914183abb33a2d11388559e80132af551117 100644 (file)
@@ -1851,11 +1851,10 @@ ApplyRetrieveRule(Query *parsetree,
 
        /*
         * Clear fields that should not be set in a subquery RTE.  Note that we
-        * leave the relid, rellockmode, and perminfoindex fields set, so that the
-        * view relation can be appropriately locked before execution and its
-        * permissions checked.
+        * leave the relid, relkind, rellockmode, and perminfoindex fields set, so
+        * that the view relation can be appropriately locked before execution and
+        * its permissions checked.
         */
-       rte->relkind = 0;
        rte->tablesample = NULL;
        rte->inh = false;                       /* must not be set for a subquery */
 
index c784937a0ebee434c843030a584873fb1d62861a..fe70d8396d6c54e346311806ea78f68522c3d264 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202305211
+#define CATALOG_VERSION_NO     202306141
 
 #endif
index 0ca298f5a1b97d745184cbe9e5d30dc230589d79..b3bec90e526a5c0956c74ab36d7b4e71eb9e960b 100644 (file)
@@ -1056,13 +1056,13 @@ typedef struct RangeTblEntry
         * this RTE in the containing struct's list of same; 0 if permissions need
         * not be checked for this RTE.
         *
-        * As a special case, relid, rellockmode, and perminfoindex can also be
-        * set (nonzero) in an RTE_SUBQUERY RTE.  This occurs when we convert an
-        * RTE_RELATION RTE naming a view into an RTE_SUBQUERY containing the
-        * view's query.  We still need to perform run-time locking and permission
-        * checks on the view, even though it's not directly used in the query
-        * anymore, and the most expedient way to do that is to retain these
-        * fields from the old state of the RTE.
+        * As a special case, relid, relkind, rellockmode, and perminfoindex can
+        * also be set (nonzero) in an RTE_SUBQUERY RTE.  This occurs when we
+        * convert an RTE_RELATION RTE naming a view into an RTE_SUBQUERY
+        * containing the view's query.  We still need to perform run-time locking
+        * and permission checks on the view, even though it's not directly used
+        * in the query anymore, and the most expedient way to do that is to
+        * retain these fields from the old state of the RTE.
         *
         * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
         * that the tuple format of the tuplestore is the same as the referenced