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",
131
132 /* Install hooks */
136}
explain_per_plan_hook_type explain_per_plan_hook
Definition explain.c:58
int GetExplainExtensionId(const char *extension_name)
void RegisterExtensionExplainOption(const char *option_name, ExplainOptionHandler handler, ExplainOptionGUCCheckHandler guc_check_handler)
bool GUCCheckBooleanExplainOption(const char *option_name, const char *option_value, NodeTag option_type)
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:5129
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:5049
void MarkGUCPrefixReserved(const char *className)
Definition guc.c:5186
@ 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(), GUCCheckBooleanExplainOption(), 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 448 of file pg_plan_advice.c.

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

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 205 of file pg_plan_advice.c.

206{
207 MemoryContext oldcontext;
208
211 MemoryContextSwitchTo(oldcontext);
212}
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 413 of file pg_plan_advice.c.

414{
415 MemoryContext oldcontext;
416 MemoryContext tmpcontext;
417 char *error;
418
419 if (*newval == NULL)
420 return true;
421
423 "pg_plan_advice.advice",
425 oldcontext = MemoryContextSwitchTo(tmpcontext);
426
427 /*
428 * It would be nice to save the parse tree that we construct here for
429 * eventual use when planning with this advice, but *extra can only point
430 * to a single guc_malloc'd chunk, and our parse tree involves an
431 * arbitrary number of memory allocations.
432 */
434
435 if (error != NULL)
436 GUC_check_errdetail("Could not parse advice: %s", error);
437
438 MemoryContextSwitchTo(oldcontext);
439 MemoryContextDelete(tmpcontext);
440
441 return (error == NULL);
442}
#define newval
#define GUC_check_errdetail
Definition guc.h:507
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 322 of file pg_plan_advice.c.

323{
325
328 {
329 int flags = defGetInt32(item);
330
331 appendStringInfo(&buf, "%s /* ", item->defname);
333 appendStringInfoString(&buf, " */\n");
334 }
335
336 pg_plan_advice_explain_text_multiline(es, "Supplied Plan Advice",
337 buf.data);
338}
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:345
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References appendStringInfo(), appendStringInfoString(), 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 257 of file pg_plan_advice.c.

259{
260 bool *plan_advice;
261
263
264 if (plan_advice == NULL)
265 {
268 }
269
271}
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 344 of file pg_plan_advice.c.

350{
351 bool should_explain;
354
356 prev_explain_per_plan(plannedstmt, into, es, queryString, params,
357 queryEnv);
358
359 /* Should an advice string be part of the EXPLAIN output? */
361
362 /* Find any data pgpa_planner_shutdown stashed in the PlannedStmt. */
364 "pg_plan_advice");
365 pgpa_list = pgpa_item == NULL ? NULL : (List *) pgpa_item->arg;
366
367 /*
368 * By default, if there is a record of attempting to apply advice during
369 * query planning, we always output that information, but the user can set
370 * pg_plan_advice.always_explain_supplied_advice = false to suppress that
371 * behavior. If they do, we'll only display it when the PLAN_ADVICE option
372 * was specified and not set to false.
373 *
374 * NB: If we're explaining a query planned beforehand -- i.e. a prepared
375 * statement -- the application of query advice may not have been
376 * recorded, and therefore this won't be able to show anything. Use
377 * pg_plan_advice.always_store_advice_details = true to work around this.
378 */
381 {
383
385 if (feedback != NULL)
387 }
388
389 /*
390 * If the PLAN_ADVICE option was specified -- and not set to FALSE -- show
391 * generated advice.
392 */
393 if (should_explain)
394 {
396 char *advice_string = NULL;
397
399 find_defelem_by_defname(pgpa_list, "advice_string");
401 {
402 advice_string = strVal(advice_string_item->arg);
403 pg_plan_advice_explain_text_multiline(es, "Generated Plan Advice",
404 advice_string);
405 }
406 }
407}
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 278 of file pg_plan_advice.c.

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

144{
147 "pg_plan_advice",
149
150 return pgpa_memory_context;
151}
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 170 of file pg_plan_advice.c.

175{
176 ListCell *lc;
177
178 /*
179 * If any advisors are loaded, consult them. The first one that produces a
180 * non-NULL string wins.
181 */
182 foreach(lc, advisor_hook_list)
183 {
185 char *advice_string;
186
187 advice_string = (*hook) (glob, parse, query_string, cursorOptions, es);
188 if (advice_string != NULL)
189 return advice_string;
190 }
191
192 /* Otherwise, just use the value of the GUC. */
194}
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 218 of file pg_plan_advice.c.

219{
220 MemoryContext oldcontext;
221
224 MemoryContextSwitchTo(oldcontext);
225}
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 242 of file pg_plan_advice.c.

243{
244 if (activate)
246 else
247 {
250 }
251}
#define Assert(condition)
Definition c.h:943
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 157 of file pg_plan_advice.c.

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

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().