From 96d781e0e95738d1bea91648e43e30e9d2208ee5 Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Mon, 27 Mar 2017 16:43:36 +0300 Subject: [PATCH] Subquery pushdown planner uses original query With this commit, we change the input to the logical planner for subquery pushdown. Before this commit, the planner was relying on the query tree that is transformed by the postgresql planner. After this commit, the planner uses the original query. The main motivation behind this change is the simplify deparsing of subqueries. --- .../planner/multi_logical_planner.c | 24 ++++++++++++------- .../distributed/planner/multi_planner.c | 2 +- .../distributed/multi_logical_planner.h | 2 +- src/test/regress/output/multi_subquery.source | 3 ++- .../regress/output/multi_subquery_0.source | 3 ++- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index 1d2e071cd..51ae92940 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -104,28 +104,35 @@ static MultiNode * ApplyCartesianProduct(MultiNode *leftNode, MultiNode *rightNo * Local functions forward declarations for subquery pushdown. Note that these * functions will be removed with upcoming subqery changes. */ -static MultiNode * SubqueryPushdownMultiPlanTree(Query *queryTree, - List *subqueryEntryList); +static MultiNode * SubqueryPushdownMultiPlanTree(Query *queryTree); static void ErrorIfSubqueryJoin(Query *queryTree); static MultiTable * MultiSubqueryPushdownTable(RangeTblEntry *subqueryRangeTableEntry); /* - * MultiLogicalPlanCreate takes in a parsed query tree, uses helper functions to - * create logical plan and adds a root node to top of it. + * MultiLogicalPlanCreate takes in both the original query and its corresponding modified + * query tree yield by the standard planner. It uses helper functions to create logical + * plan and adds a root node to top of it. The original query is only used for subquery + * pushdown planning. */ MultiTreeRoot * -MultiLogicalPlanCreate(Query *queryTree) +MultiLogicalPlanCreate(Query *originalQuery, Query *queryTree) { MultiNode *multiQueryNode = NULL; MultiTreeRoot *rootNode = NULL; + List *subqueryEntryList = NULL; - List *subqueryEntryList = SubqueryEntryList(queryTree); + /* + * We check the existence of subqueries in the modified query given that + * if postgres already flattened the subqueries, MultiPlanTree() can plan + * corresponding distributed plan. + */ + subqueryEntryList = SubqueryEntryList(queryTree); if (subqueryEntryList != NIL) { if (SubqueryPushdown) { - multiQueryNode = SubqueryPushdownMultiPlanTree(queryTree, subqueryEntryList); + multiQueryNode = SubqueryPushdownMultiPlanTree(originalQuery); } else { @@ -1982,7 +1989,7 @@ ApplyCartesianProduct(MultiNode *leftNode, MultiNode *rightNode, * from other parts of code although it causes some code duplication. */ static MultiNode * -SubqueryPushdownMultiPlanTree(Query *queryTree, List *subqueryEntryList) +SubqueryPushdownMultiPlanTree(Query *queryTree) { List *targetEntryList = queryTree->targetList; List *qualifierList = NIL; @@ -1997,6 +2004,7 @@ SubqueryPushdownMultiPlanTree(Query *queryTree, List *subqueryEntryList) MultiExtendedOp *extendedOpNode = NULL; MultiNode *currentTopNode = NULL; RangeTblEntry *subqueryRangeTableEntry = NULL; + List *subqueryEntryList = SubqueryEntryList(queryTree); /* verify we can perform distributed planning on this query */ ErrorIfQueryNotSupported(queryTree); diff --git a/src/backend/distributed/planner/multi_planner.c b/src/backend/distributed/planner/multi_planner.c index f2da3370b..1c124e0df 100644 --- a/src/backend/distributed/planner/multi_planner.c +++ b/src/backend/distributed/planner/multi_planner.c @@ -311,7 +311,7 @@ CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query if ((!distributedPlan || distributedPlan->planningError) && !hasUnresolvedParams) { /* Create and optimize logical plan */ - MultiTreeRoot *logicalPlan = MultiLogicalPlanCreate(query); + MultiTreeRoot *logicalPlan = MultiLogicalPlanCreate(originalQuery, query); MultiLogicalPlanOptimize(logicalPlan, plannerRestrictionContext); /* diff --git a/src/include/distributed/multi_logical_planner.h b/src/include/distributed/multi_logical_planner.h index 48dba38ca..8745f53e2 100644 --- a/src/include/distributed/multi_logical_planner.h +++ b/src/include/distributed/multi_logical_planner.h @@ -180,7 +180,7 @@ extern bool SubqueryPushdown; /* Function declarations for building logical plans */ -extern MultiTreeRoot * MultiLogicalPlanCreate(Query *queryTree); +extern MultiTreeRoot * MultiLogicalPlanCreate(Query *originalQuery, Query *queryTree); extern bool NeedsDistributedPlanning(Query *queryTree); extern MultiNode * ParentNode(MultiNode *multiNode); extern MultiNode * ChildNode(MultiUnaryNode *multiNode); diff --git a/src/test/regress/output/multi_subquery.source b/src/test/regress/output/multi_subquery.source index 669b07e8f..c96274281 100644 --- a/src/test/regress/output/multi_subquery.source +++ b/src/test/regress/output/multi_subquery.source @@ -177,7 +177,8 @@ SELECT count(*) FROM (SELECT l_orderkey FROM lineitem_subquery) UNION ALL (SELECT 1::bigint) ) b; -ERROR: could not run distributed query with complex table expressions +ERROR: cannot push down this subquery +DETAIL: Union All clauses are currently unsupported --- -- TEMPORARLY DISABLE UNIONS WITHOUT JOINS --- diff --git a/src/test/regress/output/multi_subquery_0.source b/src/test/regress/output/multi_subquery_0.source index 0a8942c2e..ba1e1495f 100644 --- a/src/test/regress/output/multi_subquery_0.source +++ b/src/test/regress/output/multi_subquery_0.source @@ -177,7 +177,8 @@ SELECT count(*) FROM (SELECT l_orderkey FROM lineitem_subquery) UNION ALL (SELECT 1::bigint) ) b; -ERROR: could not run distributed query with complex table expressions +ERROR: cannot push down this subquery +DETAIL: Union All clauses are currently unsupported --- -- TEMPORARLY DISABLE UNIONS WITHOUT JOINS ---