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

 PG_MODULE_MAGIC_EXT (.name="pg_plan_advice",.version=PG_VERSION)
 
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

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

69{
70 DefineCustomStringVariable("pg_plan_advice.advice",
71 "advice to apply during query planning",
72 NULL,
74 NULL,
76 0,
78 NULL,
79 NULL);
80
81 DefineCustomBoolVariable("pg_plan_advice.always_explain_supplied_advice",
82 "EXPLAIN output includes supplied advice even without EXPLAIN (PLAN_ADVICE)",
83 NULL,
85 true,
87 0,
88 NULL,
89 NULL,
90 NULL);
91
92 DefineCustomBoolVariable("pg_plan_advice.always_store_advice_details",
93 "Generate advice strings even when seemingly not required",
94 "Use this option to see generated advice for prepared queries.",
96 false,
98 0,
99 NULL,
100 NULL,
101 NULL);
102
103 DefineCustomBoolVariable("pg_plan_advice.feedback_warnings",
104 "Warn when supplied advice does not apply cleanly",
105 NULL,
107 false,
109 0,
110 NULL,
111 NULL,
112 NULL);
113
114 DefineCustomBoolVariable("pg_plan_advice.trace_mask",
115 "Emit debugging messages showing the computed strategy mask for each relation",
116 NULL,
118 false,
120 0,
121 NULL,
122 NULL,
123 NULL);
124
125 MarkGUCPrefixReserved("pg_plan_advice");
126
127 /* Get an ID that we can use to cache data in an ExplainState. */
128 es_extension_id = GetExplainExtensionId("pg_plan_advice");
129
130 /* Register the new EXPLAIN options implemented by this module. */
131 RegisterExtensionExplainOption("plan_advice",
134
135 /* Install hooks */
139}
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 451 of file pg_plan_advice.c.

452{
454 {
455 if (strcmp(item->defname, defname) == 0)
456 return item;
457 }
458
459 return NULL;
460}
#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_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "pg_plan_advice",
version = PG_VERSION 
)

◆ pg_plan_advice_add_advisor()

void pg_plan_advice_add_advisor ( pg_plan_advice_advisor_hook  hook)

Definition at line 208 of file pg_plan_advice.c.

209{
210 MemoryContext oldcontext;
211
214 MemoryContextSwitchTo(oldcontext);
215}
List * lappend(List *list, void *datum)
Definition list.c:339
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
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 416 of file pg_plan_advice.c.

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

326{
328
331 {
332 int flags = defGetInt32(item);
333
334 appendStringInfo(&buf, "%s /* ", item->defname);
336 appendStringInfoString(&buf, " */\n");
337 }
338
339 pg_plan_advice_explain_text_multiline(es, "Supplied Plan Advice",
340 buf.data);
341}
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 260 of file pg_plan_advice.c.

262{
263 bool *plan_advice;
264
266
267 if (plan_advice == NULL)
268 {
271 }
272
274}
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:90

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

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

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

147{
150 "pg_plan_advice",
152
153 return pgpa_memory_context;
154}
MemoryContext TopMemoryContext
Definition mcxt.c:167
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 173 of file pg_plan_advice.c.

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

222{
223 MemoryContext oldcontext;
224
227 MemoryContextSwitchTo(oldcontext);
228}
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 245 of file pg_plan_advice.c.

246{
247 if (activate)
249 else
250 {
253 }
254}
#define Assert(condition)
Definition c.h:1002
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 160 of file pg_plan_advice.c.

161{
162 bool *plan_advice = NULL;
163
164 if (es != NULL)
166 return plan_advice != NULL && *plan_advice;
167}

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_plan_advice_advice

char* pg_plan_advice_advice = NULL

Definition at line 37 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 39 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 38 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 40 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 48 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 44 of file pg_plan_advice.c.

Referenced by _PG_init(), and pg_plan_advice_explain_per_plan_hook().