summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements.c14
-rw-r--r--src/backend/commands/copyto.c2
-rw-r--r--src/backend/commands/createas.c2
-rw-r--r--src/backend/commands/explain.c2
-rw-r--r--src/backend/commands/matview.c2
-rw-r--r--src/backend/commands/portalcmds.c3
-rw-r--r--src/backend/optimizer/plan/planner.c27
-rw-r--r--src/backend/tcop/postgres.c7
-rw-r--r--src/include/optimizer/optimizer.h5
-rw-r--r--src/include/optimizer/planner.h8
-rw-r--r--src/include/tcop/tcopprot.h4
-rw-r--r--src/test/modules/delay_execution/delay_execution.c7
12 files changed, 58 insertions, 25 deletions
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index db1af36a705..f2187167c5c 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -338,7 +338,8 @@ static void pgss_post_parse_analyze(ParseState *pstate, Query *query,
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,
@@ -894,7 +895,8 @@ static PlannedStmt *
pgss_planner(Query *parse,
const char *query_string,
int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams,
+ ExplainState *es)
{
PlannedStmt *result;
@@ -929,10 +931,10 @@ pgss_planner(Query *parse,
{
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();
{
@@ -978,10 +980,10 @@ pgss_planner(Query *parse,
{
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();
{
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index 67b94b91cae..e5781155cdf 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -796,7 +796,7 @@ BeginCopyTo(ParseState *pstate,
/* 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
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index dfd2ab8e862..1ccc2e55c64 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -321,7 +321,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
/* 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
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 06191cd8a85..e6edae0845c 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -351,7 +351,7 @@ standard_ExplainOneQuery(Query *query, int cursorOptions,
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);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 188e26f0e6e..441de55ac24 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -426,7 +426,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
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
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index e7c8171c102..ec96c2efcd3 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -99,7 +99,8 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa
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.
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 6f06174cdab..c250433a2ef 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -279,6 +279,23 @@ static void create_partial_unique_paths(PlannerInfo *root, RelOptInfo *input_rel
*
* 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
@@ -290,14 +307,16 @@ static void create_partial_unique_paths(PlannerInfo *root, RelOptInfo *input_rel
*****************************************************************************/
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);
@@ -306,7 +325,7 @@ planner(Query *parse, const char *query_string, int cursorOptions,
PlannedStmt *
standard_planner(Query *parse, const char *query_string, int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, ExplainState *es)
{
PlannedStmt *result;
PlannerGlobal *glob;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index d356830f756..7dd75a490aa 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -37,6 +37,7 @@
#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"
@@ -884,7 +885,7 @@ pg_rewrite_query(Query *query)
*/
PlannedStmt *
pg_plan_query(Query *querytree, const char *query_string, int cursorOptions,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, ExplainState *es)
{
PlannedStmt *plan;
@@ -901,7 +902,7 @@ pg_plan_query(Query *querytree, const char *query_string, int cursorOptions,
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");
@@ -997,7 +998,7 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
else
{
stmt = pg_plan_query(query, query_string, cursorOptions,
- boundParams);
+ boundParams, NULL);
}
stmt_list = lappend(stmt_list, stmt);
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 04878f1f1c2..a34113903c0 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -24,6 +24,8 @@
#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.
@@ -104,7 +106,8 @@ extern PGDLLIMPORT bool enable_distinct_reordering;
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,
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index 1bbef0018d5..c7ab466f5f1 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -22,11 +22,14 @@
#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 */
@@ -40,7 +43,8 @@ extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;
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,
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index a83cc4f4850..c1bcfdec673 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -20,6 +20,7 @@
#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;
@@ -63,7 +64,8 @@ extern List *pg_analyze_and_rewrite_withcb(RawStmt *parsetree,
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);
diff --git a/src/test/modules/delay_execution/delay_execution.c b/src/test/modules/delay_execution/delay_execution.c
index 7bc97f84a1c..d933e9a6e53 100644
--- a/src/test/modules/delay_execution/delay_execution.c
+++ b/src/test/modules/delay_execution/delay_execution.c
@@ -40,17 +40,18 @@ static planner_hook_type prev_planner_hook = NULL;
/* 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)