Make multi_master_planner.c coding convention compliant

Changed order of function definitions and added
declarations in the beginning of the file
pull/1701/head
Murat Tuncer 2017-10-13 13:18:44 +03:00 committed by Murat Tuncer
parent f7ab901766
commit 4832abc7cb
1 changed files with 164 additions and 157 deletions

View File

@ -30,6 +30,37 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static List * MasterTargetList(List *workerTargetList);
static PlannedStmt * BuildSelectStatement(Query *masterQuery, List *masterTargetList,
CustomScan *remoteScan);
static Agg * BuildAggregatePlan(Query *masterQuery, Plan *subPlan);
static Plan * BuildDistinctPlan(Query *masterQuery, Plan *subPlan);
/*
* MasterNodeSelectPlan takes in a distributed plan and a custom scan node which
* wraps remote part of the plan. This function finds the master node query
* structure in the multi plan, and builds the final select plan to execute on
* the tuples returned by remote scan on the master node. Note that this select
* plan is executed after result files are retrieved from worker nodes and
* filled into the tuple store inside provided custom scan.
*/
PlannedStmt *
MasterNodeSelectPlan(MultiPlan *multiPlan, CustomScan *remoteScan)
{
Query *masterQuery = multiPlan->masterQuery;
PlannedStmt *masterSelectPlan = NULL;
Job *workerJob = multiPlan->workerJob;
List *workerTargetList = workerJob->jobQuery->targetList;
List *masterTargetList = MasterTargetList(workerTargetList);
masterSelectPlan = BuildSelectStatement(masterQuery, masterTargetList, remoteScan);
return masterSelectPlan;
}
/* /*
* MasterTargetList uses the given worker target list's expressions, and creates * MasterTargetList uses the given worker target list's expressions, and creates
* a target target list for the master node. This master target list keeps the * a target target list for the master node. This master target list keeps the
@ -68,6 +99,139 @@ MasterTargetList(List *workerTargetList)
} }
/*
* BuildSelectStatement builds the final select statement to run on the master
* node, before returning results to the user. The function first gets the custom
* scan node for all results fetched to the master, and layers aggregation, sort
* and limit plans on top of the scan statement if necessary.
*/
static PlannedStmt *
BuildSelectStatement(Query *masterQuery, List *masterTargetList, CustomScan *remoteScan)
{
PlannedStmt *selectStatement = NULL;
RangeTblEntry *customScanRangeTableEntry = NULL;
Agg *aggregationPlan = NULL;
Plan *topLevelPlan = NULL;
ListCell *targetEntryCell = NULL;
List *columnNameList = NULL;
List *sortClauseList = copyObject(masterQuery->sortClause);
/* (1) make PlannedStmt and set basic information */
selectStatement = makeNode(PlannedStmt);
selectStatement->canSetTag = true;
selectStatement->relationOids = NIL;
selectStatement->commandType = CMD_SELECT;
/* top level select query should have only one range table entry */
Assert(list_length(masterQuery->rtable) == 1);
/* compute column names for the custom range table entry */
foreach(targetEntryCell, masterTargetList)
{
TargetEntry *targetEntry = lfirst(targetEntryCell);
columnNameList = lappend(columnNameList, makeString(targetEntry->resname));
}
customScanRangeTableEntry = RemoteScanRangeTableEntry(columnNameList);
/* set the single element range table list */
selectStatement->rtable = list_make1(customScanRangeTableEntry);
/* (2) add an aggregation plan if needed */
if (masterQuery->hasAggs || masterQuery->groupClause)
{
remoteScan->scan.plan.targetlist = masterTargetList;
aggregationPlan = BuildAggregatePlan(masterQuery, &remoteScan->scan.plan);
topLevelPlan = (Plan *) aggregationPlan;
}
else
{
/* otherwise set the final projections on the scan plan directly */
remoteScan->scan.plan.targetlist = masterQuery->targetList;
topLevelPlan = &remoteScan->scan.plan;
}
/*
* (3) create distinct plan if needed.
*
* distinct on() requires sort + unique plans. Unique itself is not enough
* as it only compares the current value with previous one when checking
* uniqueness, thus ordering is necessary. If already has order by
* clause we append distinct clauses to the end of it. Postgresql requires
* that if both distinct on() and order by exists, ordering shall start
* on distinct clauses. Therefore we can safely append distinct clauses to
* the end of order by clauses. Although the same column may appear more
* than once in order by clauses, created plan uses only one instance, for
* example order by a,b,a,a,b,c is translated to equivalent order by a,b,c.
*
* If the query has distinct clause but not distinct on, we first create
* distinct plan that is either HashAggreate or Sort + Unique plans depending
* on hashable property of columns in distinct clause. If there is order by
* clause, it is handled after distinct planning.
*/
if (masterQuery->hasDistinctOn)
{
ListCell *distinctCell = NULL;
foreach(distinctCell, masterQuery->distinctClause)
{
SortGroupClause *singleDistinctClause = lfirst(distinctCell);
Index sortGroupRef = singleDistinctClause->tleSortGroupRef;
if (get_sortgroupref_clause_noerr(sortGroupRef, sortClauseList) == NULL)
{
sortClauseList = lappend(sortClauseList, singleDistinctClause);
}
}
}
else if (masterQuery->distinctClause)
{
Plan *distinctPlan = BuildDistinctPlan(masterQuery, topLevelPlan);
topLevelPlan = distinctPlan;
}
/* (4) add a sorting plan if needed */
if (sortClauseList)
{
Sort *sortPlan = make_sort_from_sortclauses(sortClauseList, topLevelPlan);
/* just for reproducible costs between different PostgreSQL versions */
sortPlan->plan.startup_cost = 0;
sortPlan->plan.total_cost = 0;
sortPlan->plan.plan_rows = 0;
topLevelPlan = (Plan *) sortPlan;
}
/*
* (5) add a unique plan for distinctOn.
* If the query has distinct on we add a sort clause in step 3. Therefore
* Step 4 always creates a sort plan.
* */
if (masterQuery->hasDistinctOn)
{
Assert(IsA(topLevelPlan, Sort));
topLevelPlan =
(Plan *) make_unique_from_sortclauses(topLevelPlan,
masterQuery->distinctClause);
}
/* (5) add a limit plan if needed */
if (masterQuery->limitCount || masterQuery->limitOffset)
{
Node *limitCount = masterQuery->limitCount;
Node *limitOffset = masterQuery->limitOffset;
Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount);
topLevelPlan = (Plan *) limitPlan;
}
/* (6) finally set our top level plan in the plan tree */
selectStatement->planTree = topLevelPlan;
return selectStatement;
}
/* /*
* BuildAggregatePlan creates and returns an aggregate plan. This aggregate plan * BuildAggregatePlan creates and returns an aggregate plan. This aggregate plan
* builds aggreation and grouping operators (if any) that are to be executed on * builds aggreation and grouping operators (if any) that are to be executed on
@ -216,160 +380,3 @@ BuildDistinctPlan(Query *masterQuery, Plan *subPlan)
return distinctPlan; return distinctPlan;
} }
/*
* BuildSelectStatement builds the final select statement to run on the master
* node, before returning results to the user. The function first gets the custom
* scan node for all results fetched to the master, and layers aggregation, sort
* and limit plans on top of the scan statement if necessary.
*/
static PlannedStmt *
BuildSelectStatement(Query *masterQuery, List *masterTargetList, CustomScan *remoteScan)
{
PlannedStmt *selectStatement = NULL;
RangeTblEntry *customScanRangeTableEntry = NULL;
Agg *aggregationPlan = NULL;
Plan *topLevelPlan = NULL;
ListCell *targetEntryCell = NULL;
List *columnNameList = NULL;
List *sortClauseList = copyObject(masterQuery->sortClause);
/* (1) make PlannedStmt and set basic information */
selectStatement = makeNode(PlannedStmt);
selectStatement->canSetTag = true;
selectStatement->relationOids = NIL;
selectStatement->commandType = CMD_SELECT;
/* top level select query should have only one range table entry */
Assert(list_length(masterQuery->rtable) == 1);
/* compute column names for the custom range table entry */
foreach(targetEntryCell, masterTargetList)
{
TargetEntry *targetEntry = lfirst(targetEntryCell);
columnNameList = lappend(columnNameList, makeString(targetEntry->resname));
}
customScanRangeTableEntry = RemoteScanRangeTableEntry(columnNameList);
/* set the single element range table list */
selectStatement->rtable = list_make1(customScanRangeTableEntry);
/* (2) add an aggregation plan if needed */
if (masterQuery->hasAggs || masterQuery->groupClause)
{
remoteScan->scan.plan.targetlist = masterTargetList;
aggregationPlan = BuildAggregatePlan(masterQuery, &remoteScan->scan.plan);
topLevelPlan = (Plan *) aggregationPlan;
}
else
{
/* otherwise set the final projections on the scan plan directly */
remoteScan->scan.plan.targetlist = masterQuery->targetList;
topLevelPlan = &remoteScan->scan.plan;
}
/*
* (3) create distinct plan if needed.
*
* distinct on() requires sort + unique plans. Unique itself is not enough
* as it only compares the current value with previous one when checking
* uniqueness, thus ordering is necessary. If already has order by
* clause we append distinct clauses to the end of it. Postgresql requires
* that if both distinct on() and order by exists, ordering shall start
* on distinct clauses. Therefore we can safely append distinct clauses to
* the end of order by clauses. Although the same column may appear more
* than once in order by clauses, created plan uses only one instance, for
* example order by a,b,a,a,b,c is translated to equivalent order by a,b,c.
*
* If the query has distinct clause but not distinct on, we first create
* distinct plan that is either HashAggreate or Sort + Unique plans depending
* on hashable property of columns in distinct clause. If there is order by
* clause, it is handled after distinct planning.
*/
if (masterQuery->hasDistinctOn)
{
ListCell *distinctCell = NULL;
foreach(distinctCell, masterQuery->distinctClause)
{
SortGroupClause *singleDistinctClause = lfirst(distinctCell);
Index sortGroupRef = singleDistinctClause->tleSortGroupRef;
if (get_sortgroupref_clause_noerr(sortGroupRef, sortClauseList) == NULL)
{
sortClauseList = lappend(sortClauseList, singleDistinctClause);
}
}
}
else if (masterQuery->distinctClause)
{
Plan *distinctPlan = BuildDistinctPlan(masterQuery, topLevelPlan);
topLevelPlan = distinctPlan;
}
/* (4) add a sorting plan if needed */
if (sortClauseList)
{
Sort *sortPlan = make_sort_from_sortclauses(sortClauseList, topLevelPlan);
/* just for reproducible costs between different PostgreSQL versions */
sortPlan->plan.startup_cost = 0;
sortPlan->plan.total_cost = 0;
sortPlan->plan.plan_rows = 0;
topLevelPlan = (Plan *) sortPlan;
}
/*
* (5) add a unique plan for distinctOn.
* If the query has distinct on we add a sort clause in step 3. Therefore
* Step 4 always creates a sort plan.
* */
if (masterQuery->hasDistinctOn)
{
Assert(IsA(topLevelPlan, Sort));
topLevelPlan =
(Plan *) make_unique_from_sortclauses(topLevelPlan,
masterQuery->distinctClause);
}
/* (5) add a limit plan if needed */
if (masterQuery->limitCount || masterQuery->limitOffset)
{
Node *limitCount = masterQuery->limitCount;
Node *limitOffset = masterQuery->limitOffset;
Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount);
topLevelPlan = (Plan *) limitPlan;
}
/* (6) finally set our top level plan in the plan tree */
selectStatement->planTree = topLevelPlan;
return selectStatement;
}
/*
* MasterNodeSelectPlan takes in a distributed plan and a custom scan node which
* wraps remote part of the plan. This function finds the master node query
* structure in the multi plan, and builds the final select plan to execute on
* the tuples returned by remote scan on the master node. Note that this select
* plan is executed after result files are retrieved from worker nodes and
* filled into the tuple store inside provided custom scan.
*/
PlannedStmt *
MasterNodeSelectPlan(MultiPlan *multiPlan, CustomScan *remoteScan)
{
Query *masterQuery = multiPlan->masterQuery;
PlannedStmt *masterSelectPlan = NULL;
Job *workerJob = multiPlan->workerJob;
List *workerTargetList = workerJob->jobQuery->targetList;
List *masterTargetList = MasterTargetList(workerTargetList);
masterSelectPlan = BuildSelectStatement(masterQuery, masterTargetList, remoteScan);
return masterSelectPlan;
}