From a34504d7bf48af5e3b0710396e217bac40723a97 Mon Sep 17 00:00:00 2001 From: Sait Talha Nisanci Date: Sun, 6 Dec 2020 12:55:43 +0300 Subject: [PATCH] Move recursive planning related function to recursive_planning --- .../planner/local_distributed_join_planner.c | 72 +----------- .../distributed/planner/recursive_planning.c | 105 ++++++++++++++---- .../local_distributed_join_planner.h | 6 +- src/include/distributed/recursive_planning.h | 3 +- 4 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/backend/distributed/planner/local_distributed_join_planner.c b/src/backend/distributed/planner/local_distributed_join_planner.c index 877616fa0..e819ada8b 100644 --- a/src/backend/distributed/planner/local_distributed_join_planner.c +++ b/src/backend/distributed/planner/local_distributed_join_planner.c @@ -75,10 +75,6 @@ typedef struct ConversionCandidates List *localTableList; /* local or citus local table */ }ConversionCandidates; -static bool ShouldConvertLocalTableJoinsToSubqueries(Query *query, List *rangeTableList, - Oid resultRelationId, - PlannerRestrictionContext * - plannerRestrictionContext); static bool HasConstantFilterOnUniqueColumn(FromExpr *joinTree, RangeTblEntry *rangeTableEntry, Index rteIndex); @@ -96,8 +92,6 @@ static RangeTableEntryDetails * GetNextRTEToConvertToSubquery(FromExpr *joinTree conversionCandidates, PlannerRestrictionContext * plannerRestrictionContext); -static void GetRangeTableEntriesFromJoinTree(Node *joinNode, List *rangeTableList, - List **joinRangeTableEntries); static void RemoveFromConversionCandidates(ConversionCandidates *conversionCandidates, Oid relationId); static bool AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList); @@ -109,32 +103,22 @@ static bool AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList */ void RecursivelyPlanLocalTableJoins(Query *query, - RecursivePlanningContext *context) + RecursivePlanningContext *context, List* rangeTableList) { + PlannerRestrictionContext *plannerRestrictionContext = context->plannerRestrictionContext; - List *rangeTableList = NIL; - GetRangeTableEntriesFromJoinTree((Node *) query->jointree, query->rtable, - &rangeTableList); - Oid resultRelationId = InvalidOid; if (IsModifyCommand(query)) { resultRelationId = ModifyQueryResultRelationId(query); - } - - if (!ShouldConvertLocalTableJoinsToSubqueries(query, rangeTableList, resultRelationId, - plannerRestrictionContext)) - { - return; - } + } ConversionCandidates *conversionCandidates = CreateConversionCandidates(query->jointree, plannerRestrictionContext, rangeTableList, resultRelationId); while (ShouldConvertLocalTableJoinsToSubqueries(query, rangeTableList, - resultRelationId, plannerRestrictionContext)) { FromExpr *joinTree = query->jointree; @@ -156,51 +140,6 @@ RecursivelyPlanLocalTableJoins(Query *query, } } - -/* - * GetRangeTableEntriesFromJoinTree gets the range table entries that are - * on the given join tree. - */ -static void -GetRangeTableEntriesFromJoinTree(Node *joinNode, List *rangeTableList, - List **joinRangeTableEntries) -{ - if (joinNode == NULL) - { - return; - } - else if (IsA(joinNode, FromExpr)) - { - FromExpr *fromExpr = (FromExpr *) joinNode; - Node *fromElement; - - foreach_ptr(fromElement, fromExpr->fromlist) - { - GetRangeTableEntriesFromJoinTree(fromElement, rangeTableList, - joinRangeTableEntries); - } - } - else if (IsA(joinNode, JoinExpr)) - { - JoinExpr *joinExpr = (JoinExpr *) joinNode; - GetRangeTableEntriesFromJoinTree(joinExpr->larg, rangeTableList, - joinRangeTableEntries); - GetRangeTableEntriesFromJoinTree(joinExpr->rarg, rangeTableList, - joinRangeTableEntries); - } - else if (IsA(joinNode, RangeTblRef)) - { - int rangeTableIndex = ((RangeTblRef *) joinNode)->rtindex; - RangeTblEntry *rte = rt_fetch(rangeTableIndex, rangeTableList); - *joinRangeTableEntries = lappend(*joinRangeTableEntries, rte); - } - else - { - pg_unreachable(); - } -} - - /* * GetNextRTEToConvertToSubquery returns the range table entry * which should be converted to a subquery. It considers the local join policy @@ -291,9 +230,8 @@ RemoveFromConversionCandidates(ConversionCandidates *conversionCandidates, Oid r * ShouldConvertLocalTableJoinsToSubqueries returns true if we should * convert local-dist table joins to subqueries. */ -static bool +bool ShouldConvertLocalTableJoinsToSubqueries(Query *query, List *rangeTableList, - Oid resultRelationId, PlannerRestrictionContext * plannerRestrictionContext) { @@ -303,7 +241,7 @@ ShouldConvertLocalTableJoinsToSubqueries(Query *query, List *rangeTableList, return false; } - if (!ContainsTableToBeConvertedToSubquery(rangeTableList, resultRelationId)) + if (!ContainsTableToBeConvertedToSubquery(rangeTableList)) { return false; } diff --git a/src/backend/distributed/planner/recursive_planning.c b/src/backend/distributed/planner/recursive_planning.c index 7fe70a4f3..a0c0a7b1d 100644 --- a/src/backend/distributed/planner/recursive_planning.c +++ b/src/backend/distributed/planner/recursive_planning.c @@ -178,9 +178,11 @@ static Query * BuildReadIntermediateResultsQuery(List *targetEntryList, List *columnAliasList, Const *resultIdConst, Oid functionOid, bool useBinaryCopyFormat); -static void UpdateVarNosInQualForSubquery(Query *query); -static bool ModifiesLocalTableWithRemoteCitusLocalTable(List *rangeTableList, Oid - resultRelationId); +static void +UpdateVarNosInNode(Query *query, Index newVarNo); +static bool ModifiesLocalTableWithRemoteCitusLocalTable(List *rangeTableList); +static void GetRangeTableEntriesFromJoinTree(Node *joinNode, List *rangeTableList, + List **joinRangeTableEntries); /* * GenerateSubplansForSubqueriesAndCTEs is a wrapper around RecursivelyPlanSubqueriesAndCTEs. @@ -336,18 +338,75 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context RecursivelyPlanNonColocatedSubqueries(query, context); } - /* - * Logical planner cannot handle "local_table" [OUTER] JOIN "dist_table", or - * a query with local table/citus local table and subquery. We convert local/citus local - * tables to a subquery until they can be planned. - * This is the last call in this function since we want the other calls to be finished - * so that we can check if the current plan is router plannable at any step within this function. - */ - RecursivelyPlanLocalTableJoins(query, context); + + PlannerRestrictionContext *plannerRestrictionContext = + context->plannerRestrictionContext; + + List *rangeTableList = NIL; + GetRangeTableEntriesFromJoinTree((Node *) query->jointree, query->rtable, + &rangeTableList); + + if (ShouldConvertLocalTableJoinsToSubqueries(query, rangeTableList, + plannerRestrictionContext)) { + /* + * Logical planner cannot handle "local_table" [OUTER] JOIN "dist_table", or + * a query with local table/citus local table and subquery. We convert local/citus local + * tables to a subquery until they can be planned. + * This is the last call in this function since we want the other calls to be finished + * so that we can check if the current plan is router plannable at any step within this function. + */ + RecursivelyPlanLocalTableJoins(query, context, rangeTableList); + + } + return NULL; } +/* + * GetRangeTableEntriesFromJoinTree gets the range table entries that are + * on the given join tree. + */ +static void +GetRangeTableEntriesFromJoinTree(Node *joinNode, List *rangeTableList, + List **joinRangeTableEntries) +{ + if (joinNode == NULL) + { + return; + } + else if (IsA(joinNode, FromExpr)) + { + FromExpr *fromExpr = (FromExpr *) joinNode; + Node *fromElement; + + foreach_ptr(fromElement, fromExpr->fromlist) + { + GetRangeTableEntriesFromJoinTree(fromElement, rangeTableList, + joinRangeTableEntries); + } + } + else if (IsA(joinNode, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) joinNode; + GetRangeTableEntriesFromJoinTree(joinExpr->larg, rangeTableList, + joinRangeTableEntries); + GetRangeTableEntriesFromJoinTree(joinExpr->rarg, rangeTableList, + joinRangeTableEntries); + } + else if (IsA(joinNode, RangeTblRef)) + { + int rangeTableIndex = ((RangeTblRef *) joinNode)->rtindex; + RangeTblEntry *rte = rt_fetch(rangeTableIndex, rangeTableList); + *joinRangeTableEntries = lappend(*joinRangeTableEntries, rte); + } + else + { + pg_unreachable(); + } +} + + /* * ShouldRecursivelyPlanNonColocatedSubqueries returns true if the input query contains joins @@ -1360,6 +1419,8 @@ NodeContainsSubqueryReferencingOuterQuery(Node *node) /* * ReplaceRTERelationWithRteSubquery replaces the input rte relation target entry * with a subquery. The function also pushes down the filters to the subquery. + * + * It then recursively plans the subquery. */ void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry, List *restrictionList, @@ -1369,10 +1430,7 @@ ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry, List *restrict Query *subquery = WrapRteRelationIntoSubquery(rangeTableEntry, requiredAttrNumbers); Expr *andedBoundExpressions = make_ands_explicit(restrictionList); subquery->jointree->quals = (Node *) andedBoundExpressions; - UpdateVarNosInQualForSubquery(subquery); - - /* force recursively planning of the newly created subquery */ - subquery->limitOffset = (Node *) MakeIntegerConst(0); + UpdateVarNosInNode(subquery, SINGLE_RTE_INDEX); /* replace the function with the constructed subquery */ rangeTableEntry->rtekind = RTE_SUBQUERY; @@ -1396,24 +1454,25 @@ ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry, List *restrict get_rel_name(rangeTableEntry->relid), ApplyLogRedaction(subqueryString->data)))); } + + /* as we created the subquery, now forcefully recursively plan it */ RecursivelyPlanSubquery(rangeTableEntry->subquery, context); } /* - * UpdateVarNosInQualForSubquery iterates the Vars in the - * given quals node and updates the varno's as 1 as there - * will be only one RTE in rtable, which is the subquery. + * UpdateVarNosInNode iterates the Vars in the + * given node and updates the varno's as the newVarNo. */ static void -UpdateVarNosInQualForSubquery(Query *query) +UpdateVarNosInNode(Query *query, Index newVarNo) { List *varList = pull_var_clause(query->jointree->quals, PVC_RECURSE_AGGREGATES | PVC_RECURSE_PLACEHOLDERS); Var *var = NULL; foreach_ptr(var, varList) { - var->varno = SINGLE_RTE_INDEX; + var->varno = newVarNo; } } @@ -1423,13 +1482,13 @@ UpdateVarNosInQualForSubquery(Query *query) * any table that should be converted to a subquery, which otherwise is not plannable. */ bool -ContainsTableToBeConvertedToSubquery(List *rangeTableList, Oid resultRelationId) +ContainsTableToBeConvertedToSubquery(List *rangeTableList) { if (ContainsLocalTableDistributedTableJoin(rangeTableList)) { return true; } - if (ModifiesLocalTableWithRemoteCitusLocalTable(rangeTableList, resultRelationId)) + if (ModifiesLocalTableWithRemoteCitusLocalTable(rangeTableList)) { return true; } @@ -1443,7 +1502,7 @@ ContainsTableToBeConvertedToSubquery(List *rangeTableList, Oid resultRelationId) * MX structure. */ static bool -ModifiesLocalTableWithRemoteCitusLocalTable(List *rangeTableList, Oid resultRelationId) +ModifiesLocalTableWithRemoteCitusLocalTable(List *rangeTableList) { bool containsLocalResultRelation = false; bool containsRemoteCitusLocalTable = false; diff --git a/src/include/distributed/local_distributed_join_planner.h b/src/include/distributed/local_distributed_join_planner.h index 690999bb2..88fa5e1be 100644 --- a/src/include/distributed/local_distributed_join_planner.h +++ b/src/include/distributed/local_distributed_join_planner.h @@ -27,7 +27,11 @@ typedef enum extern int LocalTableJoinPolicy; +extern bool +ShouldConvertLocalTableJoinsToSubqueries(Query *query, + List *rangeTableList, + PlannerRestrictionContext *plannerRestrictionContext); extern void RecursivelyPlanLocalTableJoins(Query *query, - RecursivePlanningContext *context); + RecursivePlanningContext *context, List *rangeTableList); #endif /* LOCAL_DISTRIBUTED_JOIN_PLANNER_H */ diff --git a/src/include/distributed/recursive_planning.h b/src/include/distributed/recursive_planning.h index 5a2484665..ed85f88ed 100644 --- a/src/include/distributed/recursive_planning.h +++ b/src/include/distributed/recursive_planning.h @@ -53,8 +53,7 @@ extern void ReplaceRTERelationWithRteSubquery(RangeTblEntry *rangeTableEntry, List *restrictionList, List *requiredAttrNumbers, RecursivePlanningContext *context); -extern bool ContainsTableToBeConvertedToSubquery(List *rangeTableList, Oid - resultRelationId); +extern bool ContainsTableToBeConvertedToSubquery(List *rangeTableList); extern bool IsRecursivelyPlannableRelation(RangeTblEntry *rangeTableEntry); extern bool IsRelationLocalTableOrMatView(Oid relationId); #endif /* RECURSIVE_PLANNING_H */