diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index 89cb0ff2d..05550ed28 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -85,17 +85,6 @@ static DeferredErrorMessage * DeferErrorIfUnsupportedSubqueryPushdown(Query * PlannerRestrictionContext * plannerRestrictionContext); -static RelationRestrictionContext * FilterRelationRestrictionContext( - RelationRestrictionContext *relationRestrictionContext, - Relids - queryRteIdentities); -static JoinRestrictionContext * FilterJoinRestrictionContext( - JoinRestrictionContext *joinRestrictionContext, Relids - queryRteIdentities); -static bool RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEntries, int - rangeTableArrayLength, Relids - queryRteIdentities); -static Relids QueryRteIdentities(Query *queryTree); static DeferredErrorMessage * DeferErrorIfFromClauseRecurs(Query *queryTree); static bool ExtractSetOperationStatmentWalker(Node *node, List **setOperationList); static DeferredErrorMessage * DeferErrorIfUnsupportedTableCombination(Query *queryTree); @@ -613,210 +602,6 @@ DeferErrorIfUnsupportedSubqueryPushdown(Query *originalQuery, } -/* - * FilterPlannerRestrictionForQuery gets a planner restriction context and - * set of rte identities. It returns the restrictions that that appear - * in the queryRteIdentities and returns a newly allocated - * PlannerRestrictionContext. The function also sets all the other fields of - * the PlannerRestrictionContext with respect to the filtered restrictions. - */ -PlannerRestrictionContext * -FilterPlannerRestrictionForQuery(PlannerRestrictionContext *plannerRestrictionContext, - Query *query) -{ - PlannerRestrictionContext *filteredPlannerRestrictionContext = NULL; - int referenceRelationCount = 0; - int totalRelationCount = 0; - - Relids queryRteIdentities = QueryRteIdentities(query); - - RelationRestrictionContext *relationRestrictionContext = - plannerRestrictionContext->relationRestrictionContext; - JoinRestrictionContext *joinRestrictionContext = - plannerRestrictionContext->joinRestrictionContext; - - RelationRestrictionContext *filteredRelationRestrictionContext = - FilterRelationRestrictionContext(relationRestrictionContext, queryRteIdentities); - - JoinRestrictionContext *filtererdJoinRestrictionContext = - FilterJoinRestrictionContext(joinRestrictionContext, queryRteIdentities); - - /* allocate the filtered planner restriction context and set all the fields */ - filteredPlannerRestrictionContext = palloc0(sizeof(PlannerRestrictionContext)); - - filteredPlannerRestrictionContext->memoryContext = - plannerRestrictionContext->memoryContext; - - totalRelationCount = list_length( - filteredRelationRestrictionContext->relationRestrictionList); - referenceRelationCount = ReferenceRelationCount(filteredRelationRestrictionContext); - - filteredRelationRestrictionContext->allReferenceTables = - (totalRelationCount == referenceRelationCount); - - /* we currently don't support local relations and we cannot come up to this point */ - filteredRelationRestrictionContext->hasLocalRelation = false; - filteredRelationRestrictionContext->hasDistributedRelation = true; - - /* finally set the relation and join restriction contexts */ - filteredPlannerRestrictionContext->relationRestrictionContext = - filteredRelationRestrictionContext; - filteredPlannerRestrictionContext->joinRestrictionContext = - filtererdJoinRestrictionContext; - - return filteredPlannerRestrictionContext; -} - - -/* - * FilterRelationRestrictionContext gets a relation restriction context and - * set of rte identities. It returns the relation restrictions that that appear - * in the queryRteIdentities and returns a newly allocated - * RelationRestrictionContext. - */ -static RelationRestrictionContext * -FilterRelationRestrictionContext(RelationRestrictionContext *relationRestrictionContext, - Relids queryRteIdentities) -{ - RelationRestrictionContext *filteredRestrictionContext = - palloc0(sizeof(RelationRestrictionContext)); - - ListCell *relationRestrictionCell = NULL; - - foreach(relationRestrictionCell, relationRestrictionContext->relationRestrictionList) - { - RelationRestriction *relationRestriction = - (RelationRestriction *) lfirst(relationRestrictionCell); - - int rteIdentity = GetRTEIdentity(relationRestriction->rte); - - if (bms_is_member(rteIdentity, queryRteIdentities)) - { - filteredRestrictionContext->relationRestrictionList = - lappend(filteredRestrictionContext->relationRestrictionList, - relationRestriction); - } - } - - return filteredRestrictionContext; -} - - -/* - * FilterJoinRestrictionContext gets a join restriction context and - * set of rte identities. It returns the join restrictions that that appear - * in the queryRteIdentities and returns a newly allocated - * JoinRestrictionContext. - * - * Note that the join restriction is added to the return context as soon as - * any range table entry that appear in the join belongs to queryRteIdentities. - */ -static JoinRestrictionContext * -FilterJoinRestrictionContext(JoinRestrictionContext *joinRestrictionContext, Relids - queryRteIdentities) -{ - JoinRestrictionContext *filtererdJoinRestrictionContext = - palloc0(sizeof(JoinRestrictionContext)); - - ListCell *joinRestrictionCell = NULL; - - foreach(joinRestrictionCell, joinRestrictionContext->joinRestrictionList) - { - JoinRestriction *joinRestriction = - (JoinRestriction *) lfirst(joinRestrictionCell); - RangeTblEntry **rangeTableEntries = - joinRestriction->plannerInfo->simple_rte_array; - int rangeTableArrayLength = joinRestriction->plannerInfo->simple_rel_array_size; - - if (RangeTableArrayContainsAnyRTEIdentities(rangeTableEntries, - rangeTableArrayLength, - queryRteIdentities)) - { - filtererdJoinRestrictionContext->joinRestrictionList = lappend( - filtererdJoinRestrictionContext->joinRestrictionList, - joinRestriction); - } - } - - return filtererdJoinRestrictionContext; -} - - -/* - * RangeTableArrayContainsAnyRTEIdentities returns true if any of the range table entries - * int rangeTableEntries array is an range table relation specified in queryRteIdentities. - */ -static bool -RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEntries, int - rangeTableArrayLength, Relids queryRteIdentities) -{ - int rteIndex = 0; - - /* simple_rte_array starts from 1, see plannerInfo struct */ - for (rteIndex = 1; rteIndex < rangeTableArrayLength; ++rteIndex) - { - RangeTblEntry *rangeTableEntry = rangeTableEntries[rteIndex]; - List *rangeTableRelationList = NULL; - ListCell *rteRelationCell = NULL; - - /* - * Get list of all RTE_RELATIONs in the given range table entry - * (i.e.,rangeTableEntry could be a subquery where we're interested - * in relations). - */ - ExtractRangeTableRelationWalker((Node *) rangeTableEntry, - &rangeTableRelationList); - - foreach(rteRelationCell, rangeTableRelationList) - { - RangeTblEntry *rteRelation = (RangeTblEntry *) lfirst(rteRelationCell); - int rteIdentity = 0; - - Assert(rteRelation->rtekind == RTE_RELATION); - - rteIdentity = GetRTEIdentity(rteRelation); - if (bms_is_member(rteIdentity, queryRteIdentities)) - { - return true; - } - } - } - - return false; -} - - -/* - * QueryRteIdentities gets a queryTree, find get all the rte identities assigned by - * us. - */ -static Relids -QueryRteIdentities(Query *queryTree) -{ - List *rangeTableList = NULL; - ListCell *rangeTableCell = NULL; - Relids queryRteIdentities = NULL; - - /* extract range table entries for simple relations only */ - ExtractRangeTableRelationWalker((Node *) queryTree, &rangeTableList); - - foreach(rangeTableCell, rangeTableList) - { - RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); - int rteIdentity = 0; - - /* we're only interested in relations */ - Assert(rangeTableEntry->rtekind == RTE_RELATION); - - rteIdentity = GetRTEIdentity(rangeTableEntry); - - queryRteIdentities = bms_add_member(queryRteIdentities, rteIdentity); - } - - return queryRteIdentities; -} - - /* * DeferErrorIfFromClauseRecurs returns a deferred error if the * given query is not suitable for subquery pushdown. diff --git a/src/backend/distributed/planner/relation_restriction_equivalence.c b/src/backend/distributed/planner/relation_restriction_equivalence.c index 204059b5e..84bf4d4f8 100644 --- a/src/backend/distributed/planner/relation_restriction_equivalence.c +++ b/src/backend/distributed/planner/relation_restriction_equivalence.c @@ -127,6 +127,17 @@ static void ListConcatUniqueAttributeClassMemberLists(AttributeEquivalenceClass secondClass); static Index RelationRestrictionPartitionKeyIndex(RelationRestriction * relationRestriction); +static RelationRestrictionContext * FilterRelationRestrictionContext( + RelationRestrictionContext *relationRestrictionContext, + Relids + queryRteIdentities); +static JoinRestrictionContext * FilterJoinRestrictionContext( + JoinRestrictionContext *joinRestrictionContext, Relids + queryRteIdentities); +static bool RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEntries, int + rangeTableArrayLength, Relids + queryRteIdentities); +static Relids QueryRteIdentities(Query *queryTree); /* @@ -1518,3 +1529,207 @@ RelationIdList(Query *query) return relationIdList; } + + +/* + * FilterPlannerRestrictionForQuery gets a planner restriction context and + * set of rte identities. It returns the restrictions that that appear + * in the queryRteIdentities and returns a newly allocated + * PlannerRestrictionContext. The function also sets all the other fields of + * the PlannerRestrictionContext with respect to the filtered restrictions. + */ +PlannerRestrictionContext * +FilterPlannerRestrictionForQuery(PlannerRestrictionContext *plannerRestrictionContext, + Query *query) +{ + PlannerRestrictionContext *filteredPlannerRestrictionContext = NULL; + int referenceRelationCount = 0; + int totalRelationCount = 0; + + Relids queryRteIdentities = QueryRteIdentities(query); + + RelationRestrictionContext *relationRestrictionContext = + plannerRestrictionContext->relationRestrictionContext; + JoinRestrictionContext *joinRestrictionContext = + plannerRestrictionContext->joinRestrictionContext; + + RelationRestrictionContext *filteredRelationRestrictionContext = + FilterRelationRestrictionContext(relationRestrictionContext, queryRteIdentities); + + JoinRestrictionContext *filtererdJoinRestrictionContext = + FilterJoinRestrictionContext(joinRestrictionContext, queryRteIdentities); + + /* allocate the filtered planner restriction context and set all the fields */ + filteredPlannerRestrictionContext = palloc0(sizeof(PlannerRestrictionContext)); + + filteredPlannerRestrictionContext->memoryContext = + plannerRestrictionContext->memoryContext; + + totalRelationCount = list_length( + filteredRelationRestrictionContext->relationRestrictionList); + referenceRelationCount = ReferenceRelationCount(filteredRelationRestrictionContext); + + filteredRelationRestrictionContext->allReferenceTables = + (totalRelationCount == referenceRelationCount); + + /* we currently don't support local relations and we cannot come up to this point */ + filteredRelationRestrictionContext->hasLocalRelation = false; + filteredRelationRestrictionContext->hasDistributedRelation = true; + + /* finally set the relation and join restriction contexts */ + filteredPlannerRestrictionContext->relationRestrictionContext = + filteredRelationRestrictionContext; + filteredPlannerRestrictionContext->joinRestrictionContext = + filtererdJoinRestrictionContext; + + return filteredPlannerRestrictionContext; +} + + +/* + * FilterRelationRestrictionContext gets a relation restriction context and + * set of rte identities. It returns the relation restrictions that that appear + * in the queryRteIdentities and returns a newly allocated + * RelationRestrictionContext. + */ +static RelationRestrictionContext * +FilterRelationRestrictionContext(RelationRestrictionContext *relationRestrictionContext, + Relids queryRteIdentities) +{ + RelationRestrictionContext *filteredRestrictionContext = + palloc0(sizeof(RelationRestrictionContext)); + + ListCell *relationRestrictionCell = NULL; + + foreach(relationRestrictionCell, relationRestrictionContext->relationRestrictionList) + { + RelationRestriction *relationRestriction = + (RelationRestriction *) lfirst(relationRestrictionCell); + + int rteIdentity = GetRTEIdentity(relationRestriction->rte); + + if (bms_is_member(rteIdentity, queryRteIdentities)) + { + filteredRestrictionContext->relationRestrictionList = + lappend(filteredRestrictionContext->relationRestrictionList, + relationRestriction); + } + } + + return filteredRestrictionContext; +} + + +/* + * FilterJoinRestrictionContext gets a join restriction context and + * set of rte identities. It returns the join restrictions that that appear + * in the queryRteIdentities and returns a newly allocated + * JoinRestrictionContext. + * + * Note that the join restriction is added to the return context as soon as + * any range table entry that appear in the join belongs to queryRteIdentities. + */ +static JoinRestrictionContext * +FilterJoinRestrictionContext(JoinRestrictionContext *joinRestrictionContext, Relids + queryRteIdentities) +{ + JoinRestrictionContext *filtererdJoinRestrictionContext = + palloc0(sizeof(JoinRestrictionContext)); + + ListCell *joinRestrictionCell = NULL; + + foreach(joinRestrictionCell, joinRestrictionContext->joinRestrictionList) + { + JoinRestriction *joinRestriction = + (JoinRestriction *) lfirst(joinRestrictionCell); + RangeTblEntry **rangeTableEntries = + joinRestriction->plannerInfo->simple_rte_array; + int rangeTableArrayLength = joinRestriction->plannerInfo->simple_rel_array_size; + + if (RangeTableArrayContainsAnyRTEIdentities(rangeTableEntries, + rangeTableArrayLength, + queryRteIdentities)) + { + filtererdJoinRestrictionContext->joinRestrictionList = lappend( + filtererdJoinRestrictionContext->joinRestrictionList, + joinRestriction); + } + } + + return filtererdJoinRestrictionContext; +} + + +/* + * RangeTableArrayContainsAnyRTEIdentities returns true if any of the range table entries + * int rangeTableEntries array is an range table relation specified in queryRteIdentities. + */ +static bool +RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEntries, int + rangeTableArrayLength, Relids queryRteIdentities) +{ + int rteIndex = 0; + + /* simple_rte_array starts from 1, see plannerInfo struct */ + for (rteIndex = 1; rteIndex < rangeTableArrayLength; ++rteIndex) + { + RangeTblEntry *rangeTableEntry = rangeTableEntries[rteIndex]; + List *rangeTableRelationList = NULL; + ListCell *rteRelationCell = NULL; + + /* + * Get list of all RTE_RELATIONs in the given range table entry + * (i.e.,rangeTableEntry could be a subquery where we're interested + * in relations). + */ + ExtractRangeTableRelationWalker((Node *) rangeTableEntry, + &rangeTableRelationList); + + foreach(rteRelationCell, rangeTableRelationList) + { + RangeTblEntry *rteRelation = (RangeTblEntry *) lfirst(rteRelationCell); + int rteIdentity = 0; + + Assert(rteRelation->rtekind == RTE_RELATION); + + rteIdentity = GetRTEIdentity(rteRelation); + if (bms_is_member(rteIdentity, queryRteIdentities)) + { + return true; + } + } + } + + return false; +} + + +/* + * QueryRteIdentities gets a queryTree, find get all the rte identities assigned by + * us. + */ +static Relids +QueryRteIdentities(Query *queryTree) +{ + List *rangeTableList = NULL; + ListCell *rangeTableCell = NULL; + Relids queryRteIdentities = NULL; + + /* extract range table entries for simple relations only */ + ExtractRangeTableRelationWalker((Node *) queryTree, &rangeTableList); + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + int rteIdentity = 0; + + /* we're only interested in relations */ + Assert(rangeTableEntry->rtekind == RTE_RELATION); + + rteIdentity = GetRTEIdentity(rangeTableEntry); + + queryRteIdentities = bms_add_member(queryRteIdentities, rteIdentity); + } + + return queryRteIdentities; +} diff --git a/src/include/distributed/multi_logical_planner.h b/src/include/distributed/multi_logical_planner.h index b96af6713..08f8cc2f5 100644 --- a/src/include/distributed/multi_logical_planner.h +++ b/src/include/distributed/multi_logical_planner.h @@ -192,9 +192,6 @@ extern DeferredErrorMessage * DeferErrorIfCannotPushdownSubquery(Query *subquery bool outerMostQueryHasLimit); extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree); -extern PlannerRestrictionContext * FilterPlannerRestrictionForQuery( - PlannerRestrictionContext *plannerRestrictionContext, - Query *query); extern bool SafeToPushdownWindowFunction(Query *query, StringInfo *errorDetail); extern bool TargetListOnPartitionColumn(Query *query, List *targetEntryList); extern bool FindNodeCheckInRangeTableList(List *rtable, bool (*check)(Node *)); diff --git a/src/include/distributed/relation_restriction_equivalence.h b/src/include/distributed/relation_restriction_equivalence.h index 051fde2f7..9dd0b8c90 100644 --- a/src/include/distributed/relation_restriction_equivalence.h +++ b/src/include/distributed/relation_restriction_equivalence.h @@ -22,6 +22,8 @@ extern uint32 ReferenceRelationCount(RelationRestrictionContext *restrictionCont extern bool SafeToPushdownUnionSubquery( PlannerRestrictionContext *plannerRestrictionContext); extern List * RelationIdList(Query *query); - +extern PlannerRestrictionContext * FilterPlannerRestrictionForQuery( + PlannerRestrictionContext *plannerRestrictionContext, + Query *query); #endif /* RELATION_RESTRICTION_EQUIVALENCE_H */