static PlannedStmt *pgss_planner(Query *parse,
const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void pgss_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
pgss_planner(Query *parse,
const char *query_string,
int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams,
+ ExplainState *es)
{
PlannedStmt *result;
{
if (prev_planner_hook)
result = prev_planner_hook(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
else
result = standard_planner(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
}
PG_FINALLY();
{
{
if (prev_planner_hook)
result = prev_planner_hook(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
else
result = standard_planner(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
}
PG_FINALLY();
{
/* plan the query */
plan = pg_plan_query(query, pstate->p_sourcetext,
- CURSOR_OPT_PARALLEL_OK, NULL);
+ CURSOR_OPT_PARALLEL_OK, NULL, NULL);
/*
* With row-level security and a user using "COPY relation TO", we
/* plan the query */
plan = pg_plan_query(query, pstate->p_sourcetext,
- CURSOR_OPT_PARALLEL_OK, params);
+ CURSOR_OPT_PARALLEL_OK, params, NULL);
/*
* Use a snapshot with an updated command ID to ensure this query sees
INSTR_TIME_SET_CURRENT(planstart);
/* plan the query */
- plan = pg_plan_query(query, queryString, cursorOptions, params);
+ plan = pg_plan_query(query, queryString, cursorOptions, params, es);
INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planstart);
CHECK_FOR_INTERRUPTS();
/* Plan the query which will generate data for the refresh. */
- plan = pg_plan_query(query, queryString, CURSOR_OPT_PARALLEL_OK, NULL);
+ plan = pg_plan_query(query, queryString, CURSOR_OPT_PARALLEL_OK, NULL, NULL);
/*
* Use a snapshot with an updated command ID to ensure this query sees
elog(ERROR, "non-SELECT statement in DECLARE CURSOR");
/* Plan the query, applying the specified options */
- plan = pg_plan_query(query, pstate->p_sourcetext, cstmt->options, params);
+ plan = pg_plan_query(query, pstate->p_sourcetext, cstmt->options, params,
+ NULL);
/*
* Create a portal and copy the plan and query string into its memory.
*
* Query optimizer entry point
*
+ * Inputs:
+ * parse: an analyzed-and-rewritten query tree for an optimizable statement
+ * query_string: source text for the query tree (used for error reports)
+ * cursorOptions: bitmask of CURSOR_OPT_XXX flags, see parsenodes.h
+ * boundParams: passed-in parameter values, or NULL if none
+ * es: ExplainState if being called from EXPLAIN, else NULL
+ *
+ * The result is a PlannedStmt tree.
+ *
+ * PARAM_EXTERN Param nodes within the parse tree can be replaced by Consts
+ * using values from boundParams, if those values are marked PARAM_FLAG_CONST.
+ * Parameter values not so marked are still relied on for estimation purposes.
+ *
+ * The ExplainState pointer is not currently used by the core planner, but it
+ * is passed through to some planner hooks so that they can report information
+ * back to EXPLAIN extension hooks.
+ *
* To support loadable plugins that monitor or modify planner behavior,
* we provide a hook variable that lets a plugin get control before and
* after the standard planning process. The plugin would normally call
*****************************************************************************/
PlannedStmt *
planner(Query *parse, const char *query_string, int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, ExplainState *es)
{
PlannedStmt *result;
if (planner_hook)
- result = (*planner_hook) (parse, query_string, cursorOptions, boundParams);
+ result = (*planner_hook) (parse, query_string, cursorOptions,
+ boundParams, es);
else
- result = standard_planner(parse, query_string, cursorOptions, boundParams);
+ result = standard_planner(parse, query_string, cursorOptions,
+ boundParams, es);
pgstat_report_plan_id(result->planId, false);
PlannedStmt *
standard_planner(Query *parse, const char *query_string, int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, ExplainState *es)
{
PlannedStmt *result;
PlannerGlobal *glob;
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/event_trigger.h"
+#include "commands/explain_state.h"
#include "commands/prepare.h"
#include "common/pg_prng.h"
#include "jit/jit.h"
*/
PlannedStmt *
pg_plan_query(Query *querytree, const char *query_string, int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, ExplainState *es)
{
PlannedStmt *plan;
ResetUsage();
/* call the optimizer */
- plan = planner(querytree, query_string, cursorOptions, boundParams);
+ plan = planner(querytree, query_string, cursorOptions, boundParams, es);
if (log_planner_stats)
ShowUsage("PLANNER STATISTICS");
else
{
stmt = pg_plan_query(query, query_string, cursorOptions,
- boundParams);
+ boundParams, NULL);
}
stmt_list = lappend(stmt_list, stmt);
#include "nodes/parsenodes.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
+
/*
* We don't want to include nodes/pathnodes.h here, because non-planner
* code should generally treat PlannerInfo as an opaque typedef.
extern PlannedStmt *planner(Query *parse, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern Expr *expression_planner(Expr *expr);
extern Expr *expression_planner_with_deps(Expr *expr,
#include "nodes/plannodes.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
+
/* Hook for plugins to get control in planner() */
typedef PlannedStmt *(*planner_hook_type) (Query *parse,
const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern PGDLLIMPORT planner_hook_type planner_hook;
/* Hook for plugins to get control when grouping_planner() plans upper rels */
extern PlannedStmt *standard_planner(Query *parse, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern PlannerInfo *subquery_planner(PlannerGlobal *glob, Query *parse,
char *plan_name,
#include "utils/guc.h"
#include "utils/queryenvironment.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
extern PGDLLIMPORT CommandDest whereToSendOutput;
extern PGDLLIMPORT const char *debug_query_string;
QueryEnvironment *queryEnv);
extern PlannedStmt *pg_plan_query(Query *querytree, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern List *pg_plan_queries(List *querytrees, const char *query_string,
int cursorOptions,
ParamListInfo boundParams);
/* planner_hook function to provide the desired delay */
static PlannedStmt *
delay_execution_planner(Query *parse, const char *query_string,
- int cursorOptions, ParamListInfo boundParams)
+ int cursorOptions, ParamListInfo boundParams,
+ ExplainState *es)
{
PlannedStmt *result;
/* Invoke the planner, possibly via a previous hook user */
if (prev_planner_hook)
result = prev_planner_hook(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
else
result = standard_planner(parse, query_string, cursorOptions,
- boundParams);
+ boundParams, es);
/* If enabled, delay by taking and releasing the specified lock */
if (post_planning_lock_id != 0)