mirror of https://github.com/citusdata/citus.git
PG16 compatibility - Rework PlannedStmt and Query's Permission Info (#7098)
PG16 compatibility - Part 6 Check out part 1pull/7115/head42d956888d
part 20d503dd5ac
part 3907d72e60d
part 47c6b4ce103
part 56056cb2c29
This commit is in the series of PG16 compatibility commits. It handles the Permission Info changes in PG16. See below: 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 crashes 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
a61b1f74823c9c4f79c95226a461f1e7a367764bb803b7d132
b803b7d132e3505ab77c29acf91f3d1caa298f95 More PG16 compatibility commits are coming soon ...
parent
6056cb2c29
commit
b36c431abb
|
@ -358,6 +358,11 @@ ConvertRteToSubqueryWithEmptyResult(RangeTblEntry *rte)
|
||||||
subquery->jointree = joinTree;
|
subquery->jointree = joinTree;
|
||||||
|
|
||||||
rte->rtekind = RTE_SUBQUERY;
|
rte->rtekind = RTE_SUBQUERY;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/* no permission checking for this RTE */
|
||||||
|
rte->perminfoindex = 0;
|
||||||
|
#endif
|
||||||
rte->subquery = subquery;
|
rte->subquery = subquery;
|
||||||
rte->alias = copyObject(rte->eref);
|
rte->alias = copyObject(rte->eref);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,9 @@
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "nodes/pg_list.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/parsetree.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "optimizer/optimizer.h"
|
#include "optimizer/optimizer.h"
|
||||||
|
@ -145,6 +148,8 @@ static void WarnIfListHasForeignDistributedTable(List *rangeTableList);
|
||||||
static RouterPlanType GetRouterPlanType(Query *query,
|
static RouterPlanType GetRouterPlanType(Query *query,
|
||||||
Query *originalQuery,
|
Query *originalQuery,
|
||||||
bool hasUnresolvedParams);
|
bool hasUnresolvedParams);
|
||||||
|
static void ConcatenateRTablesAndPerminfos(PlannedStmt *mainPlan,
|
||||||
|
PlannedStmt *concatPlan);
|
||||||
|
|
||||||
|
|
||||||
/* Distributed planner hook */
|
/* Distributed planner hook */
|
||||||
|
@ -1081,6 +1086,11 @@ CreateDistributedPlan(uint64 planId, bool allowRecursivePlanning, Query *origina
|
||||||
/*
|
/*
|
||||||
* Plan subqueries and CTEs that cannot be pushed down by recursively
|
* Plan subqueries and CTEs that cannot be pushed down by recursively
|
||||||
* calling the planner and return the resulting plans to subPlanList.
|
* calling the planner and return the resulting plans to subPlanList.
|
||||||
|
* Note that GenerateSubplansForSubqueriesAndCTEs will reset perminfoindexes
|
||||||
|
* for some RTEs in originalQuery->rtable list, while not changing
|
||||||
|
* originalQuery->rteperminfos. That's fine because we will go through
|
||||||
|
* standard_planner again, which will adjust things accordingly in
|
||||||
|
* set_plan_references>add_rtes_to_flat_rtable>add_rte_to_flat_rtable.
|
||||||
*/
|
*/
|
||||||
List *subPlanList = GenerateSubplansForSubqueriesAndCTEs(planId, originalQuery,
|
List *subPlanList = GenerateSubplansForSubqueriesAndCTEs(planId, originalQuery,
|
||||||
plannerRestrictionContext);
|
plannerRestrictionContext);
|
||||||
|
@ -1480,12 +1490,42 @@ FinalizeNonRouterPlan(PlannedStmt *localPlan, DistributedPlan *distributedPlan,
|
||||||
finalPlan->utilityStmt = localPlan->utilityStmt;
|
finalPlan->utilityStmt = localPlan->utilityStmt;
|
||||||
|
|
||||||
/* add original range table list for access permission checks */
|
/* add original range table list for access permission checks */
|
||||||
finalPlan->rtable = list_concat(finalPlan->rtable, localPlan->rtable);
|
ConcatenateRTablesAndPerminfos(finalPlan, localPlan);
|
||||||
|
|
||||||
return finalPlan;
|
return finalPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ConcatenateRTablesAndPerminfos(PlannedStmt *mainPlan, PlannedStmt *concatPlan)
|
||||||
|
{
|
||||||
|
mainPlan->rtable = list_concat(mainPlan->rtable, concatPlan->rtable);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* concatPlan's range table list is concatenated to mainPlan's range table list
|
||||||
|
* therefore all the perminfoindexes should be updated to their value
|
||||||
|
* PLUS the highest perminfoindex in mainPlan's perminfos, which is exactly
|
||||||
|
* the list length.
|
||||||
|
*/
|
||||||
|
int mainPlan_highest_perminfoindex = list_length(mainPlan->permInfos);
|
||||||
|
|
||||||
|
ListCell *lc;
|
||||||
|
foreach(lc, concatPlan->rtable)
|
||||||
|
{
|
||||||
|
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
|
||||||
|
if (rte->perminfoindex != 0)
|
||||||
|
{
|
||||||
|
rte->perminfoindex = rte->perminfoindex + mainPlan_highest_perminfoindex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* finally, concatenate perminfos as well */
|
||||||
|
mainPlan->permInfos = list_concat(mainPlan->permInfos, concatPlan->permInfos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FinalizeRouterPlan gets a CustomScan node which already wrapped distributed
|
* FinalizeRouterPlan gets a CustomScan node which already wrapped distributed
|
||||||
* part of a router plan and sets it as the direct child of the router plan
|
* part of a router plan and sets it as the direct child of the router plan
|
||||||
|
@ -1517,7 +1557,7 @@ FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan)
|
||||||
routerPlan->rtable = list_make1(remoteScanRangeTableEntry);
|
routerPlan->rtable = list_make1(remoteScanRangeTableEntry);
|
||||||
|
|
||||||
/* add original range table list for access permission checks */
|
/* add original range table list for access permission checks */
|
||||||
routerPlan->rtable = list_concat(routerPlan->rtable, localPlan->rtable);
|
ConcatenateRTablesAndPerminfos(routerPlan, localPlan);
|
||||||
|
|
||||||
routerPlan->canSetTag = true;
|
routerPlan->canSetTag = true;
|
||||||
routerPlan->relationOids = NIL;
|
routerPlan->relationOids = NIL;
|
||||||
|
|
|
@ -136,6 +136,9 @@ GeneratePlaceHolderPlannedStmt(Query *parse)
|
||||||
result->stmt_len = parse->stmt_len;
|
result->stmt_len = parse->stmt_len;
|
||||||
|
|
||||||
result->rtable = copyObject(parse->rtable);
|
result->rtable = copyObject(parse->rtable);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
result->permInfos = copyObject(parse->rteperminfos);
|
||||||
|
#endif
|
||||||
result->planTree = (Plan *) plan;
|
result->planTree = (Plan *) plan;
|
||||||
result->hasReturning = (parse->returningList != NIL);
|
result->hasReturning = (parse->returningList != NIL);
|
||||||
|
|
||||||
|
|
|
@ -604,6 +604,22 @@ CreateCombineQueryForRouterPlan(DistributedPlan *distPlan)
|
||||||
combineQuery->querySource = QSRC_ORIGINAL;
|
combineQuery->querySource = QSRC_ORIGINAL;
|
||||||
combineQuery->canSetTag = true;
|
combineQuery->canSetTag = true;
|
||||||
combineQuery->rtable = list_make1(rangeTableEntry);
|
combineQuery->rtable = list_make1(rangeTableEntry);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This part of the code is more of a sanity check for readability,
|
||||||
|
* it doesn't really do anything.
|
||||||
|
* We know that Only relation RTEs and subquery RTEs that were once relation
|
||||||
|
* RTEs (views) have their perminfoindex set. (see ExecCheckPermissions function)
|
||||||
|
* DerivedRangeTableEntry sets the rtekind to RTE_FUNCTION
|
||||||
|
* Hence we should have no perminfos here.
|
||||||
|
*/
|
||||||
|
Assert(rangeTableEntry->rtekind == RTE_FUNCTION &&
|
||||||
|
rangeTableEntry->perminfoindex == 0);
|
||||||
|
combineQuery->rteperminfos = NIL;
|
||||||
|
#endif
|
||||||
|
|
||||||
combineQuery->targetList = targetList;
|
combineQuery->targetList = targetList;
|
||||||
combineQuery->jointree = joinTree;
|
combineQuery->jointree = joinTree;
|
||||||
return combineQuery;
|
return combineQuery;
|
||||||
|
@ -1533,6 +1549,20 @@ WrapSubquery(Query *subquery)
|
||||||
selectAlias, false, true));
|
selectAlias, false, true));
|
||||||
outerQuery->rtable = list_make1(newRangeTableEntry);
|
outerQuery->rtable = list_make1(newRangeTableEntry);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This part of the code is more of a sanity check for readability,
|
||||||
|
* it doesn't really do anything.
|
||||||
|
* addRangeTableEntryForSubquery doesn't add permission info
|
||||||
|
* because the range table is set to be RTE_SUBQUERY.
|
||||||
|
* Hence we should also have no perminfos here.
|
||||||
|
*/
|
||||||
|
Assert(newRangeTableEntry->rtekind == RTE_SUBQUERY &&
|
||||||
|
newRangeTableEntry->perminfoindex == 0);
|
||||||
|
outerQuery->rteperminfos = NIL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set the FROM expression to the subquery */
|
/* set the FROM expression to the subquery */
|
||||||
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
||||||
newRangeTableRef->rtindex = 1;
|
newRangeTableRef->rtindex = 1;
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
#include "optimizer/optimizer.h"
|
#include "optimizer/optimizer.h"
|
||||||
#include "optimizer/planner.h"
|
#include "optimizer/planner.h"
|
||||||
#include "optimizer/prep.h"
|
#include "optimizer/prep.h"
|
||||||
|
#include "parser/parse_relation.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
|
@ -136,6 +137,9 @@ typedef struct RangeTableEntryDetails
|
||||||
RangeTblEntry *rangeTableEntry;
|
RangeTblEntry *rangeTableEntry;
|
||||||
List *requiredAttributeNumbers;
|
List *requiredAttributeNumbers;
|
||||||
bool hasConstantFilterOnUniqueColumn;
|
bool hasConstantFilterOnUniqueColumn;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
RTEPermissionInfo *perminfo;
|
||||||
|
#endif
|
||||||
} RangeTableEntryDetails;
|
} RangeTableEntryDetails;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -176,7 +180,8 @@ static bool HasConstantFilterOnUniqueColumn(RangeTblEntry *rangeTableEntry,
|
||||||
static ConversionCandidates * CreateConversionCandidates(PlannerRestrictionContext *
|
static ConversionCandidates * CreateConversionCandidates(PlannerRestrictionContext *
|
||||||
plannerRestrictionContext,
|
plannerRestrictionContext,
|
||||||
List *rangeTableList,
|
List *rangeTableList,
|
||||||
int resultRTEIdentity);
|
int resultRTEIdentity,
|
||||||
|
List *rteperminfos);
|
||||||
static void AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexes,
|
static void AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexes,
|
||||||
int flags);
|
int flags);
|
||||||
static ConversionChoice GetConversionChoice(ConversionCandidates *
|
static ConversionChoice GetConversionChoice(ConversionCandidates *
|
||||||
|
@ -205,10 +210,17 @@ RecursivelyPlanLocalTableJoins(Query *query,
|
||||||
GetPlannerRestrictionContext(context);
|
GetPlannerRestrictionContext(context);
|
||||||
|
|
||||||
List *rangeTableList = query->rtable;
|
List *rangeTableList = query->rtable;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
List *rteperminfos = query->rteperminfos;
|
||||||
|
#endif
|
||||||
int resultRTEIdentity = ResultRTEIdentity(query);
|
int resultRTEIdentity = ResultRTEIdentity(query);
|
||||||
ConversionCandidates *conversionCandidates =
|
ConversionCandidates *conversionCandidates =
|
||||||
CreateConversionCandidates(plannerRestrictionContext,
|
CreateConversionCandidates(plannerRestrictionContext,
|
||||||
rangeTableList, resultRTEIdentity);
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
rangeTableList, resultRTEIdentity, rteperminfos);
|
||||||
|
#else
|
||||||
|
rangeTableList, resultRTEIdentity, NIL);
|
||||||
|
#endif
|
||||||
|
|
||||||
ConversionChoice conversionChoise =
|
ConversionChoice conversionChoise =
|
||||||
GetConversionChoice(conversionCandidates, plannerRestrictionContext);
|
GetConversionChoice(conversionCandidates, plannerRestrictionContext);
|
||||||
|
@ -323,7 +335,12 @@ ConvertRTEsToSubquery(List *rangeTableEntryDetailsList, RecursivePlanningContext
|
||||||
RangeTblEntry *rangeTableEntry = rangeTableEntryDetails->rangeTableEntry;
|
RangeTblEntry *rangeTableEntry = rangeTableEntryDetails->rangeTableEntry;
|
||||||
List *requiredAttributeNumbers = rangeTableEntryDetails->requiredAttributeNumbers;
|
List *requiredAttributeNumbers = rangeTableEntryDetails->requiredAttributeNumbers;
|
||||||
ReplaceRTERelationWithRteSubquery(rangeTableEntry,
|
ReplaceRTERelationWithRteSubquery(rangeTableEntry,
|
||||||
requiredAttributeNumbers, context);
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
requiredAttributeNumbers, context,
|
||||||
|
rangeTableEntryDetails->perminfo);
|
||||||
|
#else
|
||||||
|
requiredAttributeNumbers, context, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +547,9 @@ RequiredAttrNumbersForRelationInternal(Query *queryToProcess, int rteIndex)
|
||||||
*/
|
*/
|
||||||
static ConversionCandidates *
|
static ConversionCandidates *
|
||||||
CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
|
CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
|
||||||
List *rangeTableList, int resultRTEIdentity)
|
List *rangeTableList,
|
||||||
|
int resultRTEIdentity,
|
||||||
|
List *rteperminfos)
|
||||||
{
|
{
|
||||||
ConversionCandidates *conversionCandidates =
|
ConversionCandidates *conversionCandidates =
|
||||||
palloc0(sizeof(ConversionCandidates));
|
palloc0(sizeof(ConversionCandidates));
|
||||||
|
@ -564,6 +583,14 @@ CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
|
||||||
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
|
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
|
||||||
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
|
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
|
||||||
HasConstantFilterOnUniqueColumn(rangeTableEntry, relationRestriction);
|
HasConstantFilterOnUniqueColumn(rangeTableEntry, relationRestriction);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
rangeTableEntryDetails->perminfo = NULL;
|
||||||
|
if (rangeTableEntry->perminfoindex)
|
||||||
|
{
|
||||||
|
rangeTableEntryDetails->perminfo = getRTEPermissionInfo(rteperminfos,
|
||||||
|
rangeTableEntry);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool referenceOrDistributedTable =
|
bool referenceOrDistributedTable =
|
||||||
IsCitusTableType(rangeTableEntry->relid, REFERENCE_TABLE) ||
|
IsCitusTableType(rangeTableEntry->relid, REFERENCE_TABLE) ||
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "optimizer/optimizer.h"
|
#include "optimizer/optimizer.h"
|
||||||
|
#include "parser/parse_relation.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
@ -777,6 +778,11 @@ ConvertCteRTEIntoSubquery(Query *mergeQuery, RangeTblEntry *sourceRte)
|
||||||
Query *cteQuery = (Query *) copyObject(sourceCte->ctequery);
|
Query *cteQuery = (Query *) copyObject(sourceCte->ctequery);
|
||||||
|
|
||||||
sourceRte->rtekind = RTE_SUBQUERY;
|
sourceRte->rtekind = RTE_SUBQUERY;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/* sanity check - sourceRte was RTE_CTE previously so it should have no perminfo */
|
||||||
|
Assert(sourceRte->perminfoindex == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As we are delinking the CTE from main query, we have to walk through the
|
* As we are delinking the CTE from main query, we have to walk through the
|
||||||
|
@ -827,6 +833,20 @@ ConvertRelationRTEIntoSubquery(Query *mergeQuery, RangeTblEntry *sourceRte,
|
||||||
RangeTblEntry *newRangeTableEntry = copyObject(sourceRte);
|
RangeTblEntry *newRangeTableEntry = copyObject(sourceRte);
|
||||||
sourceResultsQuery->rtable = list_make1(newRangeTableEntry);
|
sourceResultsQuery->rtable = list_make1(newRangeTableEntry);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
sourceResultsQuery->rteperminfos = NIL;
|
||||||
|
if (sourceRte->perminfoindex)
|
||||||
|
{
|
||||||
|
/* create permission info for newRangeTableEntry */
|
||||||
|
RTEPermissionInfo *perminfo = getRTEPermissionInfo(mergeQuery->rteperminfos,
|
||||||
|
sourceRte);
|
||||||
|
|
||||||
|
/* update the sourceResultsQuery's rteperminfos accordingly */
|
||||||
|
newRangeTableEntry->perminfoindex = 1;
|
||||||
|
sourceResultsQuery->rteperminfos = list_make1(perminfo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set the FROM expression to the subquery */
|
/* set the FROM expression to the subquery */
|
||||||
newRangeTableRef->rtindex = SINGLE_RTE_INDEX;
|
newRangeTableRef->rtindex = SINGLE_RTE_INDEX;
|
||||||
sourceResultsQuery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
sourceResultsQuery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
||||||
|
@ -852,6 +872,9 @@ ConvertRelationRTEIntoSubquery(Query *mergeQuery, RangeTblEntry *sourceRte,
|
||||||
|
|
||||||
/* replace the function with the constructed subquery */
|
/* replace the function with the constructed subquery */
|
||||||
sourceRte->rtekind = RTE_SUBQUERY;
|
sourceRte->rtekind = RTE_SUBQUERY;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
sourceRte->perminfoindex = 0;
|
||||||
|
#endif
|
||||||
sourceRte->subquery = sourceResultsQuery;
|
sourceRte->subquery = sourceResultsQuery;
|
||||||
sourceRte->inh = false;
|
sourceRte->inh = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,16 @@ CreateColocatedJoinChecker(Query *subquery, PlannerRestrictionContext *restricti
|
||||||
* functions (i.e., FilterPlannerRestrictionForQuery()) rely on queries
|
* functions (i.e., FilterPlannerRestrictionForQuery()) rely on queries
|
||||||
* not relations.
|
* not relations.
|
||||||
*/
|
*/
|
||||||
anchorSubquery = WrapRteRelationIntoSubquery(anchorRangeTblEntry, NIL);
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
RTEPermissionInfo *perminfo = NULL;
|
||||||
|
if (anchorRangeTblEntry->perminfoindex)
|
||||||
|
{
|
||||||
|
perminfo = getRTEPermissionInfo(subquery->rteperminfos, anchorRangeTblEntry);
|
||||||
|
}
|
||||||
|
anchorSubquery = WrapRteRelationIntoSubquery(anchorRangeTblEntry, NIL, perminfo);
|
||||||
|
#else
|
||||||
|
anchorSubquery = WrapRteRelationIntoSubquery(anchorRangeTblEntry, NIL, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (anchorRangeTblEntry->rtekind == RTE_SUBQUERY)
|
else if (anchorRangeTblEntry->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +275,9 @@ SubqueryColocated(Query *subquery, ColocatedJoinChecker *checker)
|
||||||
* designed for generating a stub query.
|
* designed for generating a stub query.
|
||||||
*/
|
*/
|
||||||
Query *
|
Query *
|
||||||
WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation, List *requiredAttributes)
|
WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation,
|
||||||
|
List *requiredAttributes,
|
||||||
|
RTEPermissionInfo *perminfo)
|
||||||
{
|
{
|
||||||
Query *subquery = makeNode(Query);
|
Query *subquery = makeNode(Query);
|
||||||
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
||||||
|
@ -277,6 +288,14 @@ WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation, List *requiredAttributes
|
||||||
RangeTblEntry *newRangeTableEntry = copyObject(rteRelation);
|
RangeTblEntry *newRangeTableEntry = copyObject(rteRelation);
|
||||||
subquery->rtable = list_make1(newRangeTableEntry);
|
subquery->rtable = list_make1(newRangeTableEntry);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
if (perminfo)
|
||||||
|
{
|
||||||
|
newRangeTableEntry->perminfoindex = 1;
|
||||||
|
subquery->rteperminfos = list_make1(perminfo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set the FROM expression to the subquery */
|
/* set the FROM expression to the subquery */
|
||||||
newRangeTableRef = makeNode(RangeTblRef);
|
newRangeTableRef = makeNode(RangeTblRef);
|
||||||
newRangeTableRef->rtindex = SINGLE_RTE_INDEX;
|
newRangeTableRef->rtindex = SINGLE_RTE_INDEX;
|
||||||
|
|
|
@ -1915,6 +1915,9 @@ SubqueryPushdownMultiNodeTree(Query *originalQuery)
|
||||||
pushedDownQuery->targetList = subqueryTargetEntryList;
|
pushedDownQuery->targetList = subqueryTargetEntryList;
|
||||||
pushedDownQuery->jointree = copyObject(queryTree->jointree);
|
pushedDownQuery->jointree = copyObject(queryTree->jointree);
|
||||||
pushedDownQuery->rtable = copyObject(queryTree->rtable);
|
pushedDownQuery->rtable = copyObject(queryTree->rtable);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
pushedDownQuery->rteperminfos = copyObject(queryTree->rteperminfos);
|
||||||
|
#endif
|
||||||
pushedDownQuery->setOperations = copyObject(queryTree->setOperations);
|
pushedDownQuery->setOperations = copyObject(queryTree->setOperations);
|
||||||
pushedDownQuery->querySource = queryTree->querySource;
|
pushedDownQuery->querySource = queryTree->querySource;
|
||||||
pushedDownQuery->hasSubLinks = queryTree->hasSubLinks;
|
pushedDownQuery->hasSubLinks = queryTree->hasSubLinks;
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#include "optimizer/optimizer.h"
|
#include "optimizer/optimizer.h"
|
||||||
#include "optimizer/planner.h"
|
#include "optimizer/planner.h"
|
||||||
#include "optimizer/prep.h"
|
#include "optimizer/prep.h"
|
||||||
|
#include "parser/parse_relation.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
|
@ -886,8 +887,19 @@ RecursivelyPlanDistributedJoinNode(Node *node, Query *query,
|
||||||
List *requiredAttributes =
|
List *requiredAttributes =
|
||||||
RequiredAttrNumbersForRelation(distributedRte, restrictionContext);
|
RequiredAttrNumbersForRelation(distributedRte, restrictionContext);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
RTEPermissionInfo *perminfo = NULL;
|
||||||
|
if (distributedRte->perminfoindex)
|
||||||
|
{
|
||||||
|
perminfo = getRTEPermissionInfo(query->rteperminfos, distributedRte);
|
||||||
|
}
|
||||||
|
|
||||||
ReplaceRTERelationWithRteSubquery(distributedRte, requiredAttributes,
|
ReplaceRTERelationWithRteSubquery(distributedRte, requiredAttributes,
|
||||||
recursivePlanningContext);
|
recursivePlanningContext, perminfo);
|
||||||
|
#else
|
||||||
|
ReplaceRTERelationWithRteSubquery(distributedRte, requiredAttributes,
|
||||||
|
recursivePlanningContext, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (distributedRte->rtekind == RTE_SUBQUERY)
|
else if (distributedRte->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
|
@ -1751,9 +1763,11 @@ NodeContainsSubqueryReferencingOuterQuery(Node *node)
|
||||||
void
|
void
|
||||||
ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
|
ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
|
||||||
List *requiredAttrNumbers,
|
List *requiredAttrNumbers,
|
||||||
RecursivePlanningContext *context)
|
RecursivePlanningContext *context,
|
||||||
|
RTEPermissionInfo *perminfo)
|
||||||
{
|
{
|
||||||
Query *subquery = WrapRteRelationIntoSubquery(rangeTableEntry, requiredAttrNumbers);
|
Query *subquery = WrapRteRelationIntoSubquery(rangeTableEntry, requiredAttrNumbers,
|
||||||
|
perminfo);
|
||||||
List *outerQueryTargetList = CreateAllTargetListForRelation(rangeTableEntry->relid,
|
List *outerQueryTargetList = CreateAllTargetListForRelation(rangeTableEntry->relid,
|
||||||
requiredAttrNumbers);
|
requiredAttrNumbers);
|
||||||
|
|
||||||
|
@ -1778,6 +1792,9 @@ ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
|
||||||
|
|
||||||
/* replace the function with the constructed subquery */
|
/* replace the function with the constructed subquery */
|
||||||
rangeTableEntry->rtekind = RTE_SUBQUERY;
|
rangeTableEntry->rtekind = RTE_SUBQUERY;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
rangeTableEntry->perminfoindex = 0;
|
||||||
|
#endif
|
||||||
rangeTableEntry->subquery = subquery;
|
rangeTableEntry->subquery = subquery;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1850,6 +1867,15 @@ CreateOuterSubquery(RangeTblEntry *rangeTableEntry, List *outerSubqueryTargetLis
|
||||||
innerSubqueryRTE->eref->colnames = innerSubqueryColNames;
|
innerSubqueryRTE->eref->colnames = innerSubqueryColNames;
|
||||||
outerSubquery->rtable = list_make1(innerSubqueryRTE);
|
outerSubquery->rtable = list_make1(innerSubqueryRTE);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
Assert(innerSubqueryRTE->rtekind == RTE_SUBQUERY &&
|
||||||
|
innerSubqueryRTE->perminfoindex == 0);
|
||||||
|
outerSubquery->rteperminfos = NIL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* set the FROM expression to the subquery */
|
/* set the FROM expression to the subquery */
|
||||||
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
||||||
newRangeTableRef->rtindex = 1;
|
newRangeTableRef->rtindex = 1;
|
||||||
|
@ -2022,6 +2048,15 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
||||||
|
|
||||||
/* set the FROM expression to the subquery */
|
/* set the FROM expression to the subquery */
|
||||||
subquery->rtable = list_make1(newRangeTableEntry);
|
subquery->rtable = list_make1(newRangeTableEntry);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
Assert(newRangeTableEntry->rtekind == RTE_FUNCTION &&
|
||||||
|
newRangeTableEntry->perminfoindex == 0);
|
||||||
|
subquery->rteperminfos = NIL;
|
||||||
|
#endif
|
||||||
|
|
||||||
newRangeTableRef->rtindex = 1;
|
newRangeTableRef->rtindex = 1;
|
||||||
subquery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
subquery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
||||||
|
|
||||||
|
@ -2392,6 +2427,9 @@ BuildReadIntermediateResultsQuery(List *targetEntryList, List *columnAliasList,
|
||||||
Query *resultQuery = makeNode(Query);
|
Query *resultQuery = makeNode(Query);
|
||||||
resultQuery->commandType = CMD_SELECT;
|
resultQuery->commandType = CMD_SELECT;
|
||||||
resultQuery->rtable = list_make1(rangeTableEntry);
|
resultQuery->rtable = list_make1(rangeTableEntry);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||||
|
resultQuery->rteperminfos = NIL;
|
||||||
|
#endif
|
||||||
resultQuery->jointree = joinTree;
|
resultQuery->jointree = joinTree;
|
||||||
resultQuery->targetList = targetList;
|
resultQuery->targetList = targetList;
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,6 @@ RelationGetNamespaceName(Relation relation)
|
||||||
* we are dealing with GetUserId().
|
* we are dealing with GetUserId().
|
||||||
* Currently the following entries are filled like this:
|
* Currently the following entries are filled like this:
|
||||||
* perminfo->checkAsUser = GetUserId();
|
* perminfo->checkAsUser = GetUserId();
|
||||||
* perminfo->selectedCols = NULL;
|
|
||||||
* perminfo->insertedCols = NULL;
|
|
||||||
* perminfo->updatedCols = NULL;
|
|
||||||
*/
|
*/
|
||||||
RTEPermissionInfo *
|
RTEPermissionInfo *
|
||||||
GetFilledPermissionInfo(Oid relid, bool inh, AclMode requiredPerms)
|
GetFilledPermissionInfo(Oid relid, bool inh, AclMode requiredPerms)
|
||||||
|
@ -57,9 +54,6 @@ GetFilledPermissionInfo(Oid relid, bool inh, AclMode requiredPerms)
|
||||||
perminfo->inh = inh;
|
perminfo->inh = inh;
|
||||||
perminfo->requiredPerms = requiredPerms;
|
perminfo->requiredPerms = requiredPerms;
|
||||||
perminfo->checkAsUser = GetUserId();
|
perminfo->checkAsUser = GetUserId();
|
||||||
perminfo->selectedCols = NULL;
|
|
||||||
perminfo->insertedCols = NULL;
|
|
||||||
perminfo->updatedCols = NULL;
|
|
||||||
return perminfo;
|
return perminfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ extern ColocatedJoinChecker CreateColocatedJoinChecker(Query *subquery,
|
||||||
restrictionContext);
|
restrictionContext);
|
||||||
extern bool SubqueryColocated(Query *subquery, ColocatedJoinChecker *context);
|
extern bool SubqueryColocated(Query *subquery, ColocatedJoinChecker *context);
|
||||||
extern Query * WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation,
|
extern Query * WrapRteRelationIntoSubquery(RangeTblEntry *rteRelation,
|
||||||
List *requiredAttributes);
|
List *requiredAttributes,
|
||||||
|
RTEPermissionInfo *perminfo);
|
||||||
extern List * CreateAllTargetListForRelation(Oid relationId, List *requiredAttributes);
|
extern List * CreateAllTargetListForRelation(Oid relationId, List *requiredAttributes);
|
||||||
|
|
||||||
#endif /* QUERY_COLOCATION_CHECKER_H */
|
#endif /* QUERY_COLOCATION_CHECKER_H */
|
||||||
|
|
|
@ -42,7 +42,8 @@ extern bool GeneratingSubplans(void);
|
||||||
extern bool ContainsLocalTableDistributedTableJoin(List *rangeTableList);
|
extern bool ContainsLocalTableDistributedTableJoin(List *rangeTableList);
|
||||||
extern void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
|
extern void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry,
|
||||||
List *requiredAttrNumbers,
|
List *requiredAttrNumbers,
|
||||||
RecursivePlanningContext *context);
|
RecursivePlanningContext *context,
|
||||||
|
RTEPermissionInfo *perminfo);
|
||||||
extern bool IsRecursivelyPlannableRelation(RangeTblEntry *rangeTableEntry);
|
extern bool IsRecursivelyPlannableRelation(RangeTblEntry *rangeTableEntry);
|
||||||
extern bool IsRelationLocalTableOrMatView(Oid relationId);
|
extern bool IsRelationLocalTableOrMatView(Oid relationId);
|
||||||
extern bool ContainsReferencesToOuterQuery(Query *query);
|
extern bool ContainsReferencesToOuterQuery(Query *query);
|
||||||
|
|
|
@ -144,6 +144,13 @@ object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
|
||||||
|
|
||||||
typedef bool TU_UpdateIndexes;
|
typedef bool TU_UpdateIndexes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we define RTEPermissionInfo for PG16 compatibility
|
||||||
|
* There are some functions that need to include RTEPermissionInfo in their signature
|
||||||
|
* for PG14/PG15 we pass a NULL argument in these functions
|
||||||
|
*/
|
||||||
|
typedef RangeTblEntry RTEPermissionInfo;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= PG_VERSION_15
|
#if PG_VERSION_NUM >= PG_VERSION_15
|
||||||
|
|
Loading…
Reference in New Issue