Don't duplicate planning logic in citus' explain hook.

Instead use pg_plan_query() like the normal explain does, and use that
to explain the query.  That's important because it allows to remove
the duplicated planner logic from multi_explain - and that logic is
about to get more complicated.
pull/1146/head
Andres Freund 2017-01-19 15:09:13 -08:00
parent 0f28a11970
commit 608bed0387
1 changed files with 43 additions and 66 deletions

View File

@ -77,6 +77,9 @@ static void ExplainTask(Task *task, int placementIndex, List *explainOutputList,
static void ExplainTaskPlacement(ShardPlacement *taskPlacement, List *explainOutputList, static void ExplainTaskPlacement(ShardPlacement *taskPlacement, List *explainOutputList,
ExplainState *es); ExplainState *es);
static StringInfo BuildRemoteExplainQuery(char *queryString, ExplainState *es); static StringInfo BuildRemoteExplainQuery(char *queryString, ExplainState *es);
static void MultiExplainOnePlan(PlannedStmt *plan, IntoClause *into,
ExplainState *es, const char *queryString,
ParamListInfo params, const instr_time *planDuration);
/* Static Explain functions copied from explain.c */ /* Static Explain functions copied from explain.c */
static void ExplainOpenGroup(const char *objtype, const char *labelname, static void ExplainOpenGroup(const char *objtype, const char *labelname,
@ -98,17 +101,10 @@ void
MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es, MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
const char *queryString, ParamListInfo params) const char *queryString, ParamListInfo params)
{ {
MultiPlan *multiPlan = NULL;
CmdType commandType = CMD_UNKNOWN;
PlannedStmt *initialPlan = NULL;
Job *workerJob = NULL;
bool routerExecutablePlan = false;
instr_time planStart; instr_time planStart;
instr_time planDuration; instr_time planDuration;
Query *originalQuery = NULL;
RelationRestrictionContext *restrictionContext = NULL;
bool localQuery = !NeedsDistributedPlanning(query);
int cursorOptions = 0; int cursorOptions = 0;
PlannedStmt *plan = NULL;
#if PG_VERSION_NUM >= 90600 #if PG_VERSION_NUM >= 90600
@ -122,11 +118,7 @@ MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
} }
#endif #endif
/* handle local queries in the same way as ExplainOneQuery */ /* plan query, just like ExplainOneQuery does */
if (localQuery)
{
PlannedStmt *plan = NULL;
INSTR_TIME_SET_CURRENT(planStart); INSTR_TIME_SET_CURRENT(planStart);
/* plan the query */ /* plan the query */
@ -135,29 +127,33 @@ MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
INSTR_TIME_SET_CURRENT(planDuration); INSTR_TIME_SET_CURRENT(planDuration);
INSTR_TIME_SUBTRACT(planDuration, planStart); INSTR_TIME_SUBTRACT(planDuration, planStart);
/* if not a distributed query, use plain explain infrastructure */
if (!HasCitusToplevelNode(plan))
{
/* run it (if needed) and produce output */ /* run it (if needed) and produce output */
ExplainOnePlan(plan, into, es, queryString, params, &planDuration); ExplainOnePlan(plan, into, es, queryString, params, &planDuration);
}
return; else
{
MultiExplainOnePlan(plan, into, es, queryString, params, &planDuration);
}
} }
/* /*
* standard_planner scribbles on it's input, but for deparsing we need the * MultiExplainOnePlan explains the plan for an individual distributed query.
* unmodified form. So copy once we're sure it's a distributed query.
*/ */
originalQuery = copyObject(query); static void
MultiExplainOnePlan(PlannedStmt *plan, IntoClause *into,
/* measure the full planning time to display in EXPLAIN ANALYZE */ ExplainState *es, const char *queryString,
INSTR_TIME_SET_CURRENT(planStart); ParamListInfo params, const instr_time *planDuration)
restrictionContext = CreateAndPushRestrictionContext();
PG_TRY();
{ {
/* call standard planner to modify the query structure before multi planning */ MultiPlan *multiPlan = NULL;
initialPlan = standard_planner(query, cursorOptions, params); CmdType commandType = CMD_UNKNOWN;
Job *workerJob = NULL;
bool routerExecutablePlan = false;
commandType = initialPlan->commandType; commandType = plan->commandType;
if (commandType == CMD_INSERT || commandType == CMD_UPDATE || if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
commandType == CMD_DELETE) commandType == CMD_DELETE)
{ {
@ -169,24 +165,7 @@ MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
} }
} }
multiPlan = CreatePhysicalPlan(originalQuery, query, restrictionContext); multiPlan = GetMultiPlan(plan);
}
PG_CATCH();
{
PopRestrictionContext();
PG_RE_THROW();
}
PG_END_TRY();
PopRestrictionContext();
INSTR_TIME_SET_CURRENT(planDuration);
INSTR_TIME_SUBTRACT(planDuration, planStart);
{
}
if (!ExplainDistributedQueries) if (!ExplainDistributedQueries)
{ {
@ -252,8 +231,6 @@ MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
if (!routerExecutablePlan) if (!routerExecutablePlan)
{ {
PlannedStmt *masterPlan = MultiQueryContainerNode(initialPlan, multiPlan);
if (es->format == EXPLAIN_FORMAT_TEXT) if (es->format == EXPLAIN_FORMAT_TEXT)
{ {
appendStringInfoSpaces(es->str, es->indent * 2); appendStringInfoSpaces(es->str, es->indent * 2);
@ -263,7 +240,7 @@ MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
ExplainOpenGroup("Master Query", "Master Query", false, es); ExplainOpenGroup("Master Query", "Master Query", false, es);
ExplainMasterPlan(masterPlan, into, es, queryString, params, &planDuration); ExplainMasterPlan(plan, into, es, queryString, params, planDuration);
ExplainCloseGroup("Master Query", "Master Query", false, es); ExplainCloseGroup("Master Query", "Master Query", false, es);