diff --git a/src/backend/distributed/planner/relation_restriction_equivalence.c b/src/backend/distributed/planner/relation_restriction_equivalence.c index 565e17c11..e9d30ade4 100644 --- a/src/backend/distributed/planner/relation_restriction_equivalence.c +++ b/src/backend/distributed/planner/relation_restriction_equivalence.c @@ -26,9 +26,13 @@ #include "nodes/primnodes.h" #if PG_VERSION_NUM >= PG_VERSION_12 #include "nodes/pathnodes.h" +#include "optimizer/optimizer.h" #else +#include "optimizer/cost.h" #include "nodes/relation.h" #endif +#include "optimizer/paths.h" +#include "optimizer/var.h" #include "parser/parsetree.h" #include "optimizer/pathnode.h" @@ -139,6 +143,7 @@ static Index RelationRestrictionPartitionKeyIndex(RelationRestriction * relationRestriction); static bool AllRelationsInRestrictionContextColocated(RelationRestrictionContext * restrictionContext); +static bool IsParam(Node *node); static RelationRestrictionContext * FilterRelationRestrictionContext( RelationRestrictionContext *relationRestrictionContext, Relids @@ -1832,6 +1837,101 @@ FilterPlannerRestrictionForQuery(PlannerRestrictionContext *plannerRestrictionCo } +/* + * GetRestrictInfoListForRelation gets a range table entry and planner + * restriction context. The function returns a list of expressions that + * appear in the restriction context for only the given relation. And, + * all the varnos are set to 1. + */ +List * +GetRestrictInfoListForRelation(RangeTblEntry *rangeTblEntry, + PlannerRestrictionContext *plannerRestrictionContext) +{ + int rteIdentity = GetRTEIdentity(rangeTblEntry); + RelationRestrictionContext *relationRestrictionContext = + plannerRestrictionContext->relationRestrictionContext; + Relids queryRteIdentities = bms_make_singleton(rteIdentity); + RelationRestrictionContext *filteredRelationRestrictionContext = + FilterRelationRestrictionContext(relationRestrictionContext, queryRteIdentities); + List *filteredRelationRestrictionList = + filteredRelationRestrictionContext->relationRestrictionList; + + if (list_length(filteredRelationRestrictionList) != 1) + { + return NIL; + } + + RelationRestriction *relationRestriction = + (RelationRestriction *) linitial(filteredRelationRestrictionList); + + RelOptInfo *relOptInfo = relationRestriction->relOptInfo; + List *baseRestrictInfo = relOptInfo->baserestrictinfo; + + List *restrictExprList = NIL; + ListCell *restrictCell = NULL; + foreach(restrictCell, baseRestrictInfo) + { + RestrictInfo *restrictInfo = (RestrictInfo *) lfirst(restrictCell); + Expr *restrictionClause = restrictInfo->clause; + List *varClauses = NIL; + ListCell *varClauseCell = NULL; + Relids varnos = NULL; + + Expr *copyOfRestrictClause = NULL; + + /* we cannot process Params beacuse they are not known at this point */ + if (FindNodeCheck((Node *) restrictionClause, IsParam)) + { + continue; + } + + /* + * If the restriction involves multiple tables, we cannot add it to + * input relation's expression list. + */ + varnos = pull_varnos((Node *) restrictionClause); + if (bms_num_members(varnos) != 1) + { + continue; + } + + /* + * We're going to add this restriction expression to a subquery + * which consists of only one relation in its jointree. Thus, + * simply set the varnos accordingly. + */ + copyOfRestrictClause = (Expr *) copyObject((Node *) restrictionClause); + varClauses = pull_var_clause_default((Node *) copyOfRestrictClause); + foreach(varClauseCell, varClauses) + { + Var *column = (Var *) lfirst(varClauseCell); + + column->varno = 1; + column->varnoold = 1; + } + + restrictExprList = lappend(restrictExprList, copyOfRestrictClause); + } + + return restrictExprList; +} + + +/* + * IsParam determines whether the given node is a param. + */ +static bool +IsParam(Node *node) +{ + if (IsA(node, Param)) + { + return true; + } + + return false; +} + + /* * FilterRelationRestrictionContext gets a relation restriction context and * set of rte identities. It returns the relation restrictions that that appear diff --git a/src/include/distributed/relation_restriction_equivalence.h b/src/include/distributed/relation_restriction_equivalence.h index 028b0587a..ba89ec972 100644 --- a/src/include/distributed/relation_restriction_equivalence.h +++ b/src/include/distributed/relation_restriction_equivalence.h @@ -36,6 +36,12 @@ extern List * DistributedRelationIdList(Query *query); extern PlannerRestrictionContext * FilterPlannerRestrictionForQuery( PlannerRestrictionContext *plannerRestrictionContext, Query *query); +extern List * GetRestrictInfoListForRelation(RangeTblEntry *rangeTblEntry, + PlannerRestrictionContext * + plannerRestrictionContext); +extern JoinRestrictionContext * RemoveDuplicateJoinRestrictions(JoinRestrictionContext * + joinRestrictionContext); + extern bool EquivalenceListContainsRelationsEquality(List *attributeEquivalenceList, RelationRestrictionContext * restrictionContext);