PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_plan_advice.c File Reference
#include "postgres.h"
#include "pg_plan_advice.h"
#include "pgpa_ast.h"
#include "pgpa_identifier.h"
#include "pgpa_output.h"
#include "pgpa_planner.h"
#include "pgpa_trove.h"
#include "pgpa_walker.h"
#include "commands/defrem.h"
#include "commands/explain.h"
#include "commands/explain_format.h"
#include "commands/explain_state.h"
#include "funcapi.h"
#include "optimizer/planner.h"
#include "storage/dsm_registry.h"
#include "utils/guc.h"
Include dependency graph for pg_plan_advice.c:

Go to the source code of this file.

Functions

static void pg_plan_advice_explain_option_handler (ExplainState *es, DefElem *opt, ParseState *pstate)
 
static void pg_plan_advice_explain_per_plan_hook (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
static bool pg_plan_advice_advice_check_hook (char **newval, void **extra, GucSource source)
 
static DefElemfind_defelem_by_defname (List *deflist, char *defname)
 
void _PG_init (void)
 
MemoryContext pg_plan_advice_get_mcxt (void)
 
bool pg_plan_advice_should_explain (ExplainState *es)
 
charpg_plan_advice_get_supplied_query_advice (PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, ExplainState *es)
 
void pg_plan_advice_add_advisor (pg_plan_advice_advisor_hook hook)
 
void pg_plan_advice_remove_advisor (pg_plan_advice_advisor_hook hook)
 
void pg_plan_advice_request_advice_generation (bool activate)
 
static void pg_plan_advice_explain_text_multiline (ExplainState *es, char *qlabel, char *value)
 
static void pg_plan_advice_explain_feedback (ExplainState *es, List *feedback)
 

Variables

 PG_MODULE_MAGIC
 
charpg_plan_advice_advice = NULL
 
bool pg_plan_advice_always_store_advice_details = false
 
static bool pg_plan_advice_always_explain_supplied_advice = true
 
bool pg_plan_advice_feedback_warnings = false
 
bool pg_plan_advice_trace_mask = false
 
static explain_per_plan_hook_type prev_explain_per_plan = NULL
 
static int es_extension_id
 
static MemoryContext pgpa_memory_context = NULL
 
static Listadvisor_hook_list = NIL
 

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 65 of file pg_plan_advice.c.

66{
67 DefineCustomStringVariable("pg_plan_advice.advice",
68 "advice to apply during query planning",
69 NULL,
71 NULL,
73 0,
75 NULL,
76 NULL);
77
78 DefineCustomBoolVariable("pg_plan_advice.always_explain_supplied_advice",
79 "EXPLAIN output includes supplied advice even without EXPLAIN (PLAN_ADVICE)",
80 NULL,
82 true,
84 0,
85 NULL,
86 NULL,
87 NULL);
88
89 DefineCustomBoolVariable("pg_plan_advice.always_store_advice_details",
90 "Generate advice strings even when seemingly not required",
91 "Use this option to see generated advice for prepared queries.",
93 false,
95 0,
96 NULL,
97 NULL,
98 NULL);
99
100 DefineCustomBoolVariable("pg_plan_advice.feedback_warnings",
101 "Warn when supplied advice does not apply cleanly",
102 NULL,
104 false,
106 0,
107 NULL,
108 NULL,
109 NULL);
110
111 DefineCustomBoolVariable("pg_plan_advice.trace_mask",
112 "Emit debugging messages showing the computed strategy mask for each relation",
113 NULL,
115 false,
117 0,
118 NULL,
119 NULL,
120 NULL);
121
122 MarkGUCPrefixReserved("pg_plan_advice");
123
124 /* Get an ID that we can use to cache data in an ExplainState. */
125 es_extension_id = GetExplainExtensionId("pg_plan_advice");
126
127 /* Register the new EXPLAIN options implemented by this module. */
128 RegisterExtensionExplainOption("plan_advice",
130
131 /* Install hooks */
135}
explain_per_plan_hook_type explain_per_plan_hook
Definition explain.c:56
int GetExplainExtensionId(const char *extension_name)
void RegisterExtensionExplainOption(const char *option_name, ExplainOptionHandler handler)
void DefineCustomStringVariable(const char *name, const char *short_desc, const char *long_desc, char **valueAddr, const char *bootValue, GucContext context, int flags, GucStringCheckHook check_hook, GucStringAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5091
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5011
void MarkGUCPrefixReserved(const char *className)
Definition guc.c:5148
@ PGC_USERSET
Definition guc.h:79
char * pg_plan_advice_advice
bool pg_plan_advice_trace_mask
static explain_per_plan_hook_type prev_explain_per_plan
bool pg_plan_advice_always_store_advice_details
static bool pg_plan_advice_advice_check_hook(char **newval, void **extra, GucSource source)
static void pg_plan_advice_explain_per_plan_hook(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
static void pg_plan_advice_explain_option_handler(ExplainState *es, DefElem *opt, ParseState *pstate)
bool pg_plan_advice_feedback_warnings
static int es_extension_id
static bool pg_plan_advice_always_explain_supplied_advice
void pgpa_planner_install_hooks(void)
static int fb(int x)

References DefineCustomBoolVariable(), DefineCustomStringVariable(), es_extension_id, explain_per_plan_hook, fb(), GetExplainExtensionId(), MarkGUCPrefixReserved(), pg_plan_advice_advice, pg_plan_advice_advice_check_hook(), pg_plan_advice_always_explain_supplied_advice, pg_plan_advice_always_store_advice_details, pg_plan_advice_explain_option_handler(), pg_plan_advice_explain_per_plan_hook(), pg_plan_advice_feedback_warnings, pg_plan_advice_trace_mask, PGC_USERSET, pgpa_planner_install_hooks(), prev_explain_per_plan, and RegisterExtensionExplainOption().

◆ find_defelem_by_defname()

static DefElem * find_defelem_by_defname ( List deflist,
char defname 
)
static

Definition at line 447 of file pg_plan_advice.c.

448{
450 {
451 if (strcmp(item->defname, defname) == 0)
452 return item;
453 }
454
455 return NULL;
456}
#define foreach_node(type, var, lst)
Definition pg_list.h:496

References fb(), and foreach_node.

Referenced by pg_plan_advice_explain_per_plan_hook().

◆ pg_plan_advice_add_advisor()

void pg_plan_advice_add_advisor ( pg_plan_advice_advisor_hook  hook)

Definition at line 204 of file pg_plan_advice.c.

205{
206 MemoryContext oldcontext;
207
210 MemoryContextSwitchTo(oldcontext);
211}
List * lappend(List *list, void *datum)
Definition list.c:339
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
MemoryContext pg_plan_advice_get_mcxt(void)
static List * advisor_hook_list

References advisor_hook_list, lappend(), MemoryContextSwitchTo(), and pg_plan_advice_get_mcxt().

◆ pg_plan_advice_advice_check_hook()

static bool pg_plan_advice_advice_check_hook ( char **  newval,
void **  extra,
GucSource  source 
)
static

Definition at line 412 of file pg_plan_advice.c.

413{
414 MemoryContext oldcontext;
415 MemoryContext tmpcontext;
416 char *error;
417
418 if (*newval == NULL)
419 return true;
420
422 "pg_plan_advice.advice",
424 oldcontext = MemoryContextSwitchTo(tmpcontext);
425
426 /*
427 * It would be nice to save the parse tree that we construct here for
428 * eventual use when planning with this advice, but *extra can only point
429 * to a single guc_malloc'd chunk, and our parse tree involves an
430 * arbitrary number of memory allocations.
431 */
433
434 if (error != NULL)
435 GUC_check_errdetail("Could not parse advice: %s", error);
436
437 MemoryContextSwitchTo(oldcontext);
438 MemoryContextDelete(tmpcontext);
439
440 return (error == NULL);
441}
#define newval
#define GUC_check_errdetail
Definition guc.h:506
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
List * pgpa_parse(const char *advice_string, char **error_p)
static void error(void)

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, error(), fb(), GUC_check_errdetail, MemoryContextDelete(), MemoryContextSwitchTo(), newval, and pgpa_parse().

Referenced by _PG_init().

◆ pg_plan_advice_explain_feedback()

static void pg_plan_advice_explain_feedback ( ExplainState es,
List feedback 
)
static

Definition at line 321 of file pg_plan_advice.c.

322{
324
327 {
328 int flags = defGetInt32(item);
329
330 appendStringInfo(&buf, "%s /* ", item->defname);
332 appendStringInfo(&buf, " */\n");
333 }
334
335 pg_plan_advice_explain_text_multiline(es, "Supplied Plan Advice",
336 buf.data);
337}
int32 defGetInt32(DefElem *def)
Definition define.c:148
static void pg_plan_advice_explain_text_multiline(ExplainState *es, char *qlabel, char *value)
static char buf[DEFAULT_XLOG_SEG_SIZE]
void pgpa_trove_append_flags(StringInfo buf, int flags)
Definition pgpa_trove.c:343
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References appendStringInfo(), buf, defGetInt32(), fb(), foreach_node, initStringInfo(), pg_plan_advice_explain_text_multiline(), and pgpa_trove_append_flags().

Referenced by pg_plan_advice_explain_per_plan_hook().

◆ pg_plan_advice_explain_option_handler()

static void pg_plan_advice_explain_option_handler ( ExplainState es,
DefElem opt,
ParseState pstate 
)
static

Definition at line 256 of file pg_plan_advice.c.

258{
259 bool *plan_advice;
260
262
263 if (plan_advice == NULL)
264 {
267 }
268
270}
bool defGetBoolean(DefElem *def)
Definition define.c:93
void * GetExplainExtensionState(ExplainState *es, int extension_id)
void SetExplainExtensionState(ExplainState *es, int extension_id, void *opaque)
#define palloc0_object(type)
Definition fe_memutils.h:75

References defGetBoolean(), es_extension_id, fb(), GetExplainExtensionState(), palloc0_object, and SetExplainExtensionState().

Referenced by _PG_init().

◆ pg_plan_advice_explain_per_plan_hook()

static void pg_plan_advice_explain_per_plan_hook ( PlannedStmt plannedstmt,
IntoClause into,
ExplainState es,
const char queryString,
ParamListInfo  params,
QueryEnvironment queryEnv 
)
static

Definition at line 343 of file pg_plan_advice.c.

349{
350 bool should_explain;
353
355 prev_explain_per_plan(plannedstmt, into, es, queryString, params,
356 queryEnv);
357
358 /* Should an advice string be part of the EXPLAIN output? */
360
361 /* Find any data pgpa_planner_shutdown stashed in the PlannedStmt. */
363 "pg_plan_advice");
364 pgpa_list = pgpa_item == NULL ? NULL : (List *) pgpa_item->arg;
365
366 /*
367 * By default, if there is a record of attempting to apply advice during
368 * query planning, we always output that information, but the user can set
369 * pg_plan_advice.always_explain_supplied_advice = false to suppress that
370 * behavior. If they do, we'll only display it when the PLAN_ADVICE option
371 * was specified and not set to false.
372 *
373 * NB: If we're explaining a query planned beforehand -- i.e. a prepared
374 * statement -- the application of query advice may not have been
375 * recorded, and therefore this won't be able to show anything. Use
376 * pg_plan_advice.always_store_advice_details = true to work around this.
377 */
380 {
382
384 if (feedback != NULL)
386 }
387
388 /*
389 * If the PLAN_ADVICE option was specified -- and not set to FALSE -- show
390 * generated advice.
391 */
392 if (should_explain)
393 {
395 char *advice_string = NULL;
396
398 find_defelem_by_defname(pgpa_list, "advice_string");
400 {
402 pg_plan_advice_explain_text_multiline(es, "Generated Plan Advice",
404 }
405 }
406}
static DefElem * find_defelem_by_defname(List *deflist, char *defname)
bool pg_plan_advice_should_explain(ExplainState *es)
static void pg_plan_advice_explain_feedback(ExplainState *es, List *feedback)
Definition pg_list.h:54
List * extension_state
Definition plannodes.h:165
#define strVal(v)
Definition value.h:82

References PlannedStmt::extension_state, fb(), find_defelem_by_defname(), pg_plan_advice_always_explain_supplied_advice, pg_plan_advice_explain_feedback(), pg_plan_advice_explain_text_multiline(), pg_plan_advice_should_explain(), prev_explain_per_plan, and strVal.

Referenced by _PG_init().

◆ pg_plan_advice_explain_text_multiline()

static void pg_plan_advice_explain_text_multiline ( ExplainState es,
char qlabel,
char value 
)
static

Definition at line 277 of file pg_plan_advice.c.

279{
280 char *s;
281
282 /* For non-text formats, it's best not to add any special handling. */
283 if (es->format != EXPLAIN_FORMAT_TEXT)
284 {
286 return;
287 }
288
289 /* In text format, if there is no data, display nothing. */
290 if (*value == '\0')
291 return;
292
293 /*
294 * It looks nicest to indent each line of the advice separately, beginning
295 * on the line below the label.
296 */
298 appendStringInfo(es->str, "%s:\n", qlabel);
299 es->indent++;
300 while ((s = strchr(value, '\n')) != NULL)
301 {
303 appendBinaryStringInfo(es->str, value, (s - value) + 1);
304 value = s + 1;
305 }
306
307 /* Don't interpret a terminal newline as a request for an empty line. */
308 if (*value != '\0')
309 {
311 appendStringInfo(es->str, "%s\n", value);
312 }
313
314 es->indent--;
315}
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
void ExplainIndentText(ExplainState *es)
@ EXPLAIN_FORMAT_TEXT
static struct @174 value
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281
StringInfo str
ExplainFormat format

References appendBinaryStringInfo(), appendStringInfo(), EXPLAIN_FORMAT_TEXT, ExplainIndentText(), ExplainPropertyText(), fb(), ExplainState::format, ExplainState::indent, ExplainState::str, and value.

Referenced by pg_plan_advice_explain_feedback(), and pg_plan_advice_explain_per_plan_hook().

◆ pg_plan_advice_get_mcxt()

MemoryContext pg_plan_advice_get_mcxt ( void  )

Definition at line 142 of file pg_plan_advice.c.

143{
146 "pg_plan_advice",
148
149 return pgpa_memory_context;
150}
MemoryContext TopMemoryContext
Definition mcxt.c:166
static MemoryContext pgpa_memory_context

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, fb(), pgpa_memory_context, and TopMemoryContext.

Referenced by pg_plan_advice_add_advisor(), and pg_plan_advice_remove_advisor().

◆ pg_plan_advice_get_supplied_query_advice()

char * pg_plan_advice_get_supplied_query_advice ( PlannerGlobal glob,
Query parse,
const char query_string,
int  cursorOptions,
ExplainState es 
)

Definition at line 169 of file pg_plan_advice.c.

174{
175 ListCell *lc;
176
177 /*
178 * If any advisors are loaded, consult them. The first one that produces a
179 * non-NULL string wins.
180 */
181 foreach(lc, advisor_hook_list)
182 {
184 char *advice_string;
185
186 advice_string = (*hook) (glob, parse, query_string, cursorOptions, es);
187 if (advice_string != NULL)
188 return advice_string;
189 }
190
191 /* Otherwise, just use the value of the GUC. */
193}
void parse(int)
Definition parse.c:49
#define lfirst(lc)
Definition pg_list.h:172
char *(* pg_plan_advice_advisor_hook)(PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, ExplainState *es)

References advisor_hook_list, fb(), lfirst, parse(), and pg_plan_advice_advice.

Referenced by pgpa_planner_setup().

◆ pg_plan_advice_remove_advisor()

void pg_plan_advice_remove_advisor ( pg_plan_advice_advisor_hook  hook)

Definition at line 217 of file pg_plan_advice.c.

218{
219 MemoryContext oldcontext;
220
223 MemoryContextSwitchTo(oldcontext);
224}
List * list_delete_ptr(List *list, void *datum)
Definition list.c:872

References advisor_hook_list, list_delete_ptr(), MemoryContextSwitchTo(), and pg_plan_advice_get_mcxt().

◆ pg_plan_advice_request_advice_generation()

void pg_plan_advice_request_advice_generation ( bool  activate)

Definition at line 241 of file pg_plan_advice.c.

242{
243 if (activate)
245 else
246 {
249 }
250}
#define Assert(condition)
Definition c.h:927
int pgpa_planner_generate_advice

References Assert, fb(), and pgpa_planner_generate_advice.

◆ pg_plan_advice_should_explain()

bool pg_plan_advice_should_explain ( ExplainState es)

Definition at line 156 of file pg_plan_advice.c.

157{
158 bool *plan_advice = NULL;
159
160 if (es != NULL)
162 return plan_advice != NULL && *plan_advice;
163}

References es_extension_id, fb(), and GetExplainExtensionState().

Referenced by pg_plan_advice_explain_per_plan_hook(), and pgpa_planner_setup().

Variable Documentation

◆ advisor_hook_list

List* advisor_hook_list = NIL
static

◆ es_extension_id

int es_extension_id
static

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 31 of file pg_plan_advice.c.

◆ pg_plan_advice_advice

char* pg_plan_advice_advice = NULL

Definition at line 34 of file pg_plan_advice.c.

Referenced by _PG_init(), and pg_plan_advice_get_supplied_query_advice().

◆ pg_plan_advice_always_explain_supplied_advice

bool pg_plan_advice_always_explain_supplied_advice = true
static

Definition at line 36 of file pg_plan_advice.c.

Referenced by _PG_init(), and pg_plan_advice_explain_per_plan_hook().

◆ pg_plan_advice_always_store_advice_details

bool pg_plan_advice_always_store_advice_details = false

Definition at line 35 of file pg_plan_advice.c.

Referenced by _PG_init(), and pgpa_planner_setup().

◆ pg_plan_advice_feedback_warnings

bool pg_plan_advice_feedback_warnings = false

Definition at line 37 of file pg_plan_advice.c.

Referenced by _PG_init(), pgpa_planner_setup(), and pgpa_planner_shutdown().

◆ pg_plan_advice_trace_mask

bool pg_plan_advice_trace_mask = false

◆ pgpa_memory_context

MemoryContext pgpa_memory_context = NULL
static

Definition at line 45 of file pg_plan_advice.c.

Referenced by pg_plan_advice_get_mcxt().

◆ prev_explain_per_plan

explain_per_plan_hook_type prev_explain_per_plan = NULL
static

Definition at line 41 of file pg_plan_advice.c.

Referenced by _PG_init(), and pg_plan_advice_explain_per_plan_hook().