From 7cc25c9125cf5bb66d50f6dac58b33dc7953c229 Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Tue, 7 Jul 2020 16:54:58 +0200 Subject: [PATCH] Add ability to fetch the restrictions per relation With this commit, we add the ability to add restrictions per relation. We simply rely on the restrictions that Postgres keeps per relation. --- .../relation_restriction_equivalence.c | 100 ++++++++++++++++++ .../relation_restriction_equivalence.h | 6 ++ 2 files changed, 106 insertions(+) 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);