Rework PlannedStmt and Query's Permission Info

The main issue lies in the following entries of PlannedStmt:
{
   rtable
   permInfos
}

Each rtable has an int perminfoindex, and its actual permission info
is obtained through the following:
permInfos[perminfoindex]

We had a crash because perminfoindexes were not updated in the
finalized planned statement after distributed planner hook.

So, basically, everywhere we set a query's or planned statement's
rtable entry, we need to set the rteperminfos/permInfos accordingly.

Relevant PG commits:
a61b1f7482
a61b1f74823c9c4f79c95226a461f1e7a367764b
b803b7d132
b803b7d132e3505ab77c29acf91f3d1caa298f95
naisila/check_router_fix
naisila 2023-06-09 16:32:27 +03:00
parent 47cdc74a6f
commit 14181072cf
6 changed files with 143 additions and 0 deletions

View File

@ -56,6 +56,9 @@
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/pg_list.h"
#if PG_VERSION_NUM >= PG_VERSION_16
#include "parser/parse_relation.h"
#endif
#include "parser/parsetree.h"
#include "parser/parse_type.h"
#include "optimizer/optimizer.h"
@ -1467,6 +1470,27 @@ FinalizeNonRouterPlan(PlannedStmt *localPlan, DistributedPlan *distributedPlan,
/* add original range table list for access permission checks */
finalPlan->rtable = list_concat(finalPlan->rtable, localPlan->rtable);
#if PG_VERSION_NUM >= PG_VERSION_16
/*
* Original range table list is concatented to final plan's range table list
* therefore all the perminfoindexes should be updated to their value
* PLUS the length of final plan's perminfos.
*/
int list_length_final_permInfos = list_length(finalPlan->permInfos);
finalPlan->permInfos = list_concat(finalPlan->permInfos, localPlan->permInfos);
ListCell *lc;
foreach(lc, localPlan->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
if (rte->perminfoindex != 0)
{
rte->perminfoindex = rte->perminfoindex + list_length_final_permInfos;
}
}
#endif
return finalPlan;
}
@ -1504,6 +1528,16 @@ FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan)
/* add original range table list for access permission checks */
routerPlan->rtable = list_concat(routerPlan->rtable, localPlan->rtable);
#if PG_VERSION_NUM >= PG_VERSION_16
/*
* We know that extra remoteScanRangeTableEntry has perminfoindex 0
* therefore we can simply use the perminfos we had in localplan
*/
Assert(remoteScanRangeTableEntry->perminfoindex == 0);
routerPlan->permInfos = localPlan->permInfos;
#endif
routerPlan->canSetTag = true;
routerPlan->relationOids = NIL;

View File

@ -136,6 +136,9 @@ GeneratePlaceHolderPlannedStmt(Query *parse)
result->stmt_len = parse->stmt_len;
result->rtable = copyObject(parse->rtable);
#if PG_VERSION_NUM >= PG_VERSION_16
result->permInfos = copyObject(parse->rteperminfos);
#endif
result->planTree = (Plan *) plan;
result->hasReturning = (parse->returningList != NIL);

View File

@ -31,6 +31,7 @@
#include "distributed/pg_dist_partition.h"
#include "distributed/query_pushdown_planning.h"
#include "distributed/recursive_planning.h"
#include "distributed/relation_utils.h"
#include "distributed/repartition_executor.h"
#include "distributed/resource_lock.h"
#include "distributed/version_compat.h"
@ -602,6 +603,22 @@ CreateCombineQueryForRouterPlan(DistributedPlan *distPlan)
combineQuery->querySource = QSRC_ORIGINAL;
combineQuery->canSetTag = true;
combineQuery->rtable = list_make1(rangeTableEntry);
#if PG_VERSION_NUM >= PG_VERSION_16
combineQuery->rteperminfos = NIL;
if (rangeTableEntry->perminfoindex != 0)
{
/* create permission info for newRangeTableEntry */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(rangeTableEntry->relid,
rangeTableEntry->inh,
CMD_SELECT);
/* update the subquery's rteperminfos accordingly */
rangeTableEntry->perminfoindex = 1;
combineQuery->rteperminfos = list_make1(perminfo);
}
#endif
combineQuery->targetList = targetList;
combineQuery->jointree = joinTree;
return combineQuery;
@ -1539,6 +1556,21 @@ WrapSubquery(Query *subquery)
selectAlias, false, true));
outerQuery->rtable = list_make1(newRangeTableEntry);
#if PG_VERSION_NUM >= PG_VERSION_16
outerQuery->rteperminfos = NIL;
if (newRangeTableEntry->perminfoindex != 0)
{
/* create permission info for newRangeTableEntry */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(newRangeTableEntry->relid,
newRangeTableEntry->inh,
CMD_SELECT);
/* update the subquery's rteperminfos accordingly */
newRangeTableEntry->perminfoindex = 1;
outerQuery->rteperminfos = list_make1(perminfo);
}
#endif
/* set the FROM expression to the subquery */
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
newRangeTableRef->rtindex = 1;

View File

@ -28,6 +28,7 @@
#include "distributed/query_colocation_checker.h"
#include "distributed/pg_dist_partition.h"
#include "distributed/relation_restriction_equivalence.h"
#include "distributed/relation_utils.h"
#include "distributed/metadata_cache.h"
#include "distributed/multi_logical_planner.h" /* only to access utility functions */
@ -277,6 +278,22 @@ WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation, List *requiredAttributes
RangeTblEntry *newRangeTableEntry = copyObject(rteRelation);
subquery->rtable = list_make1(newRangeTableEntry);
#if PG_VERSION_NUM >= PG_VERSION_16
subquery->rteperminfos = NIL;
newRangeTableEntry->perminfoindex = 0;
if (rteRelation->perminfoindex != 0)
{
/* create permission info for newRangeTableEntry */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(newRangeTableEntry->relid,
newRangeTableEntry->inh,
ACL_SELECT);
/* update the subquery's rteperminfos accordingly */
newRangeTableEntry->perminfoindex = 1;
subquery->rteperminfos = list_make1(perminfo);
}
#endif
/* set the FROM expression to the subquery */
newRangeTableRef = makeNode(RangeTblRef);
newRangeTableRef->rtindex = SINGLE_RTE_INDEX;

View File

@ -1915,6 +1915,9 @@ SubqueryPushdownMultiNodeTree(Query *originalQuery)
pushedDownQuery->targetList = subqueryTargetEntryList;
pushedDownQuery->jointree = copyObject(queryTree->jointree);
pushedDownQuery->rtable = copyObject(queryTree->rtable);
#if PG_VERSION_NUM >= PG_VERSION_16
pushedDownQuery->rteperminfos = copyObject(queryTree->rteperminfos);
#endif
pushedDownQuery->setOperations = copyObject(queryTree->setOperations);
pushedDownQuery->querySource = queryTree->querySource;
pushedDownQuery->hasSubLinks = queryTree->hasSubLinks;

View File

@ -72,6 +72,7 @@
#include "distributed/query_pushdown_planning.h"
#include "distributed/recursive_planning.h"
#include "distributed/relation_restriction_equivalence.h"
#include "distributed/relation_utils.h"
#include "distributed/log_utils.h"
#include "distributed/shard_pruning.h"
#include "distributed/version_compat.h"
@ -88,6 +89,7 @@
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
#include "nodes/pathnodes.h"
#include "parser/parse_relation.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
@ -1850,6 +1852,24 @@ CreateOuterSubquery(RangeTblEntry *rangeTableEntry, List *outerSubqueryTargetLis
innerSubqueryRTE->eref->colnames = innerSubqueryColNames;
outerSubquery->rtable = list_make1(innerSubqueryRTE);
#if PG_VERSION_NUM >= PG_VERSION_16
outerSubquery->rteperminfos = NIL;
innerSubqueryRTE->perminfoindex = 0;
if (rangeTableEntry->perminfoindex != 0)
{
/* create permission info for innerSubqueryRTE */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(innerSubqueryRTE->relid,
innerSubqueryRTE->inh,
ACL_SELECT);
/* update the outerSubquery's rteperminfos accordingly */
innerSubqueryRTE->perminfoindex = 1;
outerSubquery->rteperminfos = list_make1(perminfo);
}
#endif
/* set the FROM expression to the subquery */
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
newRangeTableRef->rtindex = 1;
@ -2022,6 +2042,24 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
/* set the FROM expression to the subquery */
subquery->rtable = list_make1(newRangeTableEntry);
#if PG_VERSION_NUM >= PG_VERSION_16
subquery->rteperminfos = NIL;
newRangeTableEntry->perminfoindex = 0;
if (rangeTblEntry->perminfoindex != 0)
{
/* create permission info for newRangeTableEntry */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(newRangeTableEntry->relid,
newRangeTableEntry->inh,
CMD_SELECT);
/* update the subquery's rteperminfos accordingly */
newRangeTableEntry->perminfoindex = 1;
subquery->rteperminfos = list_make1(perminfo);
}
#endif
newRangeTableRef->rtindex = 1;
subquery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
@ -2392,6 +2430,22 @@ BuildReadIntermediateResultsQuery(List *targetEntryList, List *columnAliasList,
Query *resultQuery = makeNode(Query);
resultQuery->commandType = CMD_SELECT;
resultQuery->rtable = list_make1(rangeTableEntry);
#if PG_VERSION_NUM >= PG_VERSION_16
resultQuery->rteperminfos = NIL;
if (rangeTableEntry->perminfoindex != 0)
{
/* create permission info for newRangeTableEntry */
RTEPermissionInfo *perminfo = GetFilledPermissionInfo(rangeTableEntry->relid,
rangeTableEntry->inh,
CMD_SELECT);
/* update the subquery's rteperminfos accordingly */
rangeTableEntry->perminfoindex = 1;
resultQuery->rteperminfos = list_make1(perminfo);
}
#endif
resultQuery->jointree = joinTree;
resultQuery->targetList = targetList;