mirror of https://github.com/citusdata/citus.git
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:naisila/check_router_fixa61b1f7482
a61b1f74823c9c4f79c95226a461f1e7a367764bb803b7d132
b803b7d132e3505ab77c29acf91f3d1caa298f95
parent
47cdc74a6f
commit
14181072cf
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue