citus/src/backend/distributed/planner/multi_explain.c

109 lines
3.3 KiB
C

/*-------------------------------------------------------------------------
*
* multi_explain.c
* Citus explain support.
*
* Copyright (c) 2012-2015, Citus Data, Inc.
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "commands/prepare.h"
#include "distributed/citus_nodefuncs.h"
#include "distributed/multi_explain.h"
#include "distributed/multi_planner.h"
#include "distributed/multi_logical_optimizer.h"
#include "distributed/multi_physical_planner.h"
#include "nodes/print.h"
#include "optimizer/planner.h"
#include "tcop/tcopprot.h"
/* Config variables that enable printing distributed query plans */
bool ExplainMultiLogicalPlan = false;
bool ExplainMultiPhysicalPlan = false;
/*
* MultiExplainOneQuery takes the given query, and checks if the query is local
* or distributed. If the query is local, the function runs the standard explain
* logic. If the query is distributed, the function looks up configuration and
* prints out the distributed logical and physical plans as appropriate.
*/
void
MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
const char *queryString, ParamListInfo params)
{
MultiTreeRoot *multiTree = NULL;
MultiPlan *multiPlan = NULL;
Query *queryCopy = NULL;
CmdType commandType = query->commandType;
/* if local query, run the standard explain and return */
bool localQuery = !NeedsDistributedPlanning(query);
if (localQuery)
{
PlannedStmt *plan = NULL;
instr_time planstart;
instr_time planduration;
INSTR_TIME_SET_CURRENT(planstart);
/* plan the query */
plan = pg_plan_query(query, 0, params);
INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planstart);
/* run it (if needed) and produce output */
ExplainOnePlan(plan, into, es, queryString, params, &planduration);
return;
}
/* error out early if the query is a modification */
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
commandType == CMD_DELETE)
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot show execution plan for distributed modification"),
errdetail("EXPLAIN commands are unsupported for distributed "
"modifications.")));
}
/* call standard planner to modify the query structure before multi planning */
standard_planner(query, 0, params);
queryCopy = copyObject(query);
/* create the logical and physical plan */
multiTree = MultiLogicalPlanCreate(queryCopy);
MultiLogicalPlanOptimize(multiTree);
multiPlan = MultiPhysicalPlanCreate(multiTree);
if (ExplainMultiLogicalPlan)
{
char *logicalPlanString = CitusNodeToString(multiTree);
char *formattedPlanString = pretty_format_node_dump(logicalPlanString);
appendStringInfo(es->str, "logical plan:\n");
appendStringInfo(es->str, "%s\n", formattedPlanString);
}
if (ExplainMultiPhysicalPlan)
{
char *physicalPlanString = CitusNodeToString(multiPlan);
char *formattedPlanString = pretty_format_node_dump(physicalPlanString);
appendStringInfo(es->str, "physical plan:\n");
appendStringInfo(es->str, "%s\n", formattedPlanString);
}
/* if explain printing isn't enabled, print error only after planning */
if (!ExplainMultiLogicalPlan && !ExplainMultiPhysicalPlan)
{
appendStringInfo(es->str, "explain statements for distributed queries ");
appendStringInfo(es->str, "are currently unsupported\n");
}
}