Fill EState.es_rteperminfos more systematically.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Mar 2023 18:10:57 +0000 (13:10 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Mar 2023 18:10:57 +0000 (13:10 -0500)
While testing a fix for bug #17823, I discovered that EvalPlanQualStart
failed to copy es_rteperminfos from the parent EState, resulting in
failure if anything in EPQ execution wanted to consult that information.

This led me to conclude that commit a61b1f748 had been too haphazard
about where to fill es_rteperminfos, and that we need to be sure that
that happens exactly where es_range_table gets filled.  So I changed the
signature of ExecInitRangeTable to help ensure that this new requirement
doesn't get missed.  (Indeed, pgoutput.c was also failing to fill it.
Maybe we don't ever need it there, but I wouldn't bet on that.)

No test case yet; one will arrive with the fix for #17823.
But that needs to be back-patched, while this fix is HEAD-only.

Discussion: https://postgr.es/m/17823-b64909cf7d63de84@postgresql.org

src/backend/commands/copyfrom.c
src/backend/executor/execMain.c
src/backend/executor/execUtils.c
src/backend/replication/logical/worker.c
src/backend/replication/pgoutput/pgoutput.c
src/include/executor/executor.h

index af52faca6d4e9a9ba44726a1bd9c3a2bac971e37..29cd1cf4a6338e14890f361a10f258af87a87b5e 100644 (file)
@@ -757,16 +757,10 @@ CopyFrom(CopyFromState cstate)
         * index-entry-making machinery.  (There used to be a huge amount of code
         * here that basically duplicated execUtils.c ...)
         */
-       ExecInitRangeTable(estate, cstate->range_table);
+       ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos);
        resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo);
        ExecInitResultRelation(estate, resultRelInfo, 1);
 
-       /*
-        * Copy the RTEPermissionInfos into estate as well, so that
-        * ExecGetInsertedCols() et al will work correctly.
-        */
-       estate->es_rteperminfos = cstate->rteperminfos;
-
        /* Verify the named relation is a valid target for INSERT */
        CheckValidResultRel(resultRelInfo, CMD_INSERT);
 
index 39bfb48dc22527851f8628fe3202e4024241b9a1..7f5968db87341591f361559e1d44c7ed0437fefc 100644 (file)
@@ -807,15 +807,14 @@ InitPlan(QueryDesc *queryDesc, int eflags)
        int                     i;
 
        /*
-        * Do permissions checks and save the list for later use.
+        * Do permissions checks
         */
        ExecCheckPermissions(rangeTable, plannedstmt->permInfos, true);
-       estate->es_rteperminfos = plannedstmt->permInfos;
 
        /*
         * initialize the node's execution state
         */
-       ExecInitRangeTable(estate, rangeTable);
+       ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos);
 
        estate->es_plannedstmt = plannedstmt;
        estate->es_part_prune_infos = plannedstmt->partPruneInfos;
@@ -2805,11 +2804,12 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
        rcestate->es_range_table = parentestate->es_range_table;
        rcestate->es_range_table_size = parentestate->es_range_table_size;
        rcestate->es_relations = parentestate->es_relations;
-       rcestate->es_queryEnv = parentestate->es_queryEnv;
        rcestate->es_rowmarks = parentestate->es_rowmarks;
+       rcestate->es_rteperminfos = parentestate->es_rteperminfos;
        rcestate->es_plannedstmt = parentestate->es_plannedstmt;
        rcestate->es_junkFilter = parentestate->es_junkFilter;
        rcestate->es_output_cid = parentestate->es_output_cid;
+       rcestate->es_queryEnv = parentestate->es_queryEnv;
 
        /*
         * ResultRelInfos needed by subplans are initialized from scratch when the
index cfa95a07e40f82f6a508e3d091aae6b09d35347e..6eac5f354c3b9bb497fded7dd1e178e7a0acd4d0 100644 (file)
@@ -121,6 +121,7 @@ CreateExecutorState(void)
        estate->es_range_table_size = 0;
        estate->es_relations = NULL;
        estate->es_rowmarks = NULL;
+       estate->es_rteperminfos = NIL;
        estate->es_plannedstmt = NULL;
        estate->es_part_prune_infos = NIL;
 
@@ -755,11 +756,14 @@ ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
  * indexed by rangetable index.
  */
 void
-ExecInitRangeTable(EState *estate, List *rangeTable)
+ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos)
 {
        /* Remember the range table List as-is */
        estate->es_range_table = rangeTable;
 
+       /* ... and the RTEPermissionInfo List too */
+       estate->es_rteperminfos = permInfos;
+
        /* Set size of associated arrays */
        estate->es_range_table_size = list_length(rangeTable);
 
index cfb2ab62481975d36a983ec4f0a48e004add07ae..c7d1734a174c7d041c4f96bb5e6168f4061c734b 100644 (file)
@@ -671,6 +671,7 @@ create_edata_for_relation(LogicalRepRelMapEntry *rel)
        ApplyExecutionData *edata;
        EState     *estate;
        RangeTblEntry *rte;
+       List       *perminfos = NIL;
        ResultRelInfo *resultRelInfo;
 
        edata = (ApplyExecutionData *) palloc0(sizeof(ApplyExecutionData));
@@ -683,9 +684,10 @@ create_edata_for_relation(LogicalRepRelMapEntry *rel)
        rte->relid = RelationGetRelid(rel->localrel);
        rte->relkind = rel->localrel->rd_rel->relkind;
        rte->rellockmode = AccessShareLock;
-       ExecInitRangeTable(estate, list_make1(rte));
 
-       addRTEPermissionInfo(&estate->es_rteperminfos, rte);
+       addRTEPermissionInfo(&perminfos, rte);
+
+       ExecInitRangeTable(estate, list_make1(rte), perminfos);
 
        edata->targetRelInfo = resultRelInfo = makeNode(ResultRelInfo);
 
index 0df1acbb7a72d50bf6b60eabfa517acb326be2fd..00a2d73dab034b8da85bd8e3d4fe17a36a98611d 100644 (file)
@@ -23,6 +23,7 @@
 #include "fmgr.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/optimizer.h"
+#include "parser/parse_relation.h"
 #include "replication/logical.h"
 #include "replication/logicalproto.h"
 #include "replication/origin.h"
@@ -792,6 +793,7 @@ create_estate_for_relation(Relation rel)
 {
        EState     *estate;
        RangeTblEntry *rte;
+       List       *perminfos = NIL;
 
        estate = CreateExecutorState();
 
@@ -800,7 +802,10 @@ create_estate_for_relation(Relation rel)
        rte->relid = RelationGetRelid(rel);
        rte->relkind = rel->rd_rel->relkind;
        rte->rellockmode = AccessShareLock;
-       ExecInitRangeTable(estate, list_make1(rte));
+
+       addRTEPermissionInfo(&perminfos, rte);
+
+       ExecInitRangeTable(estate, list_make1(rte), perminfos);
 
        estate->es_output_cid = GetCurrentCommandId(false);
 
index e7e25c057efc00b3331be52c196c55eec4c3c56c..946abc0051c6c6dc0bf4395660a92262c8c52ad9 100644 (file)
@@ -568,7 +568,7 @@ extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
 
 extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags);
 
-extern void ExecInitRangeTable(EState *estate, List *rangeTable);
+extern void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos);
 extern void ExecCloseRangeTableRelations(EState *estate);
 extern void ExecCloseResultRelations(EState *estate);