PostgreSQL Source Code  git master
explain.h File Reference
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "parser/parse_node.h"
Include dependency graph for explain.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ExplainState
 

Typedefs

typedef enum ExplainFormat ExplainFormat
 
typedef struct ExplainState ExplainState
 
typedef void(* ExplainOneQuery_hook_type) (Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
typedef const char *(* explain_get_index_name_hook_type) (Oid indexId)
 

Enumerations

enum  ExplainFormat { EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_YAML }
 

Functions

void ExplainQuery (ParseState *pstate, ExplainStmt *stmt, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest)
 
ExplainStateNewExplainState (void)
 
TupleDesc ExplainResultDesc (ExplainStmt *stmt)
 
void ExplainOneUtility (Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
void ExplainOnePlan (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration)
 
void ExplainPrintPlan (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintTriggers (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintJIT (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainQueryText (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainBeginOutput (ExplainState *es)
 
void ExplainEndOutput (ExplainState *es)
 
void ExplainSeparatePlans (ExplainState *es)
 
void ExplainPropertyList (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyListNested (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyText (const char *qlabel, const char *value, ExplainState *es)
 
void ExplainPropertyInteger (const char *qlabel, const char *unit, int64 value, ExplainState *es)
 
void ExplainPropertyFloat (const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
 
void ExplainPropertyBool (const char *qlabel, bool value, ExplainState *es)
 
void ExplainOpenGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 
void ExplainCloseGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 

Variables

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
 
PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
 

Typedef Documentation

◆ explain_get_index_name_hook_type

typedef const char*(* explain_get_index_name_hook_type) (Oid indexId)

Definition at line 61 of file explain.h.

◆ ExplainFormat

◆ ExplainOneQuery_hook_type

typedef void(* ExplainOneQuery_hook_type) (Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)

Definition at line 51 of file explain.h.

◆ ExplainState

Enumeration Type Documentation

◆ ExplainFormat

Enumerator
EXPLAIN_FORMAT_TEXT 
EXPLAIN_FORMAT_XML 
EXPLAIN_FORMAT_JSON 
EXPLAIN_FORMAT_YAML 

Definition at line 20 of file explain.h.

Function Documentation

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 3600 of file explain.c.

References appendStringInfoChar(), appendStringInfoString(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, lcons_int(), and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

3601 {
3602  switch (es->format)
3603  {
3604  case EXPLAIN_FORMAT_TEXT:
3605  /* nothing to do */
3606  break;
3607 
3608  case EXPLAIN_FORMAT_XML:
3610  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
3611  es->indent++;
3612  break;
3613 
3614  case EXPLAIN_FORMAT_JSON:
3615  /* top-level structure is an array of plans */
3616  appendStringInfoChar(es->str, '[');
3617  es->grouping_stack = lcons_int(0, es->grouping_stack);
3618  es->indent++;
3619  break;
3620 
3621  case EXPLAIN_FORMAT_YAML:
3622  es->grouping_stack = lcons_int(0, es->grouping_stack);
3623  break;
3624  }
3625 }
List * lcons_int(int datum, List *list)
Definition: list.c:277
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ ExplainCloseGroup()

void ExplainCloseGroup ( const char *  objtype,
const char *  labelname,
bool  labeled,
ExplainState es 
)

Definition at line 3518 of file explain.c.

References appendStringInfoChar(), appendStringInfoSpaces(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainXMLTag(), ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, list_delete_first(), ExplainState::str, and X_CLOSING.

Referenced by ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3520 {
3521  switch (es->format)
3522  {
3523  case EXPLAIN_FORMAT_TEXT:
3524  /* nothing to do */
3525  break;
3526 
3527  case EXPLAIN_FORMAT_XML:
3528  es->indent--;
3529  ExplainXMLTag(objtype, X_CLOSING, es);
3530  break;
3531 
3532  case EXPLAIN_FORMAT_JSON:
3533  es->indent--;
3534  appendStringInfoChar(es->str, '\n');
3535  appendStringInfoSpaces(es->str, 2 * es->indent);
3536  appendStringInfoChar(es->str, labeled ? '}' : ']');
3538  break;
3539 
3540  case EXPLAIN_FORMAT_YAML:
3541  es->indent--;
3543  break;
3544  }
3545 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3689
#define X_CLOSING
Definition: explain.c:53
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:666

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 3631 of file explain.c.

References appendStringInfoString(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, list_delete_first(), and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

3632 {
3633  switch (es->format)
3634  {
3635  case EXPLAIN_FORMAT_TEXT:
3636  /* nothing to do */
3637  break;
3638 
3639  case EXPLAIN_FORMAT_XML:
3640  es->indent--;
3641  appendStringInfoString(es->str, "</explain>");
3642  break;
3643 
3644  case EXPLAIN_FORMAT_JSON:
3645  es->indent--;
3646  appendStringInfoString(es->str, "\n]");
3648  break;
3649 
3650  case EXPLAIN_FORMAT_YAML:
3652  break;
3653  }
3654 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:666

◆ ExplainOnePlan()

void ExplainOnePlan ( PlannedStmt plannedstmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv,
const instr_time planduration 
)

Definition at line 463 of file explain.c.

References ExplainState::analyze, Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, ExplainState::costs, JitContext::created_functions, CreateIntoRelDestReceiver(), CreateQueryDesc(), generate_unaccent_rules::dest, elapsed_time(), EState::es_jit, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ExplainCloseGroup(), ExplainOpenGroup(), ExplainPrintJIT(), ExplainPrintPlan(), ExplainPrintTriggers(), ExplainPropertyFloat(), ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), GetIntoRelEFlags(), INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTRUMENT_BUFFERS, INSTRUMENT_ROWS, INSTRUMENT_TIMER, InvalidSnapshot, NoMovementScanDirection, None_Receiver, PopActiveSnapshot(), PushCopiedSnapshot(), IntoClause::skipData, ExplainState::summary, ExplainState::timing, and UpdateActiveSnapshotCommandId().

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

466 {
468  QueryDesc *queryDesc;
469  instr_time starttime;
470  double totaltime = 0;
471  int eflags;
472  int instrument_option = 0;
473 
474  Assert(plannedstmt->commandType != CMD_UTILITY);
475 
476  if (es->analyze && es->timing)
477  instrument_option |= INSTRUMENT_TIMER;
478  else if (es->analyze)
479  instrument_option |= INSTRUMENT_ROWS;
480 
481  if (es->buffers)
482  instrument_option |= INSTRUMENT_BUFFERS;
483 
484  /*
485  * We always collect timing for the entire statement, even when node-level
486  * timing is off, so we don't look at es->timing here. (We could skip
487  * this if !es->summary, but it's hardly worth the complication.)
488  */
489  INSTR_TIME_SET_CURRENT(starttime);
490 
491  /*
492  * Use a snapshot with an updated command ID to ensure this query sees
493  * results of any previously executed queries.
494  */
497 
498  /*
499  * Normally we discard the query's output, but if explaining CREATE TABLE
500  * AS, we'd better use the appropriate tuple receiver.
501  */
502  if (into)
503  dest = CreateIntoRelDestReceiver(into);
504  else
505  dest = None_Receiver;
506 
507  /* Create a QueryDesc for the query */
508  queryDesc = CreateQueryDesc(plannedstmt, queryString,
510  dest, params, queryEnv, instrument_option);
511 
512  /* Select execution options */
513  if (es->analyze)
514  eflags = 0; /* default run-to-completion flags */
515  else
516  eflags = EXEC_FLAG_EXPLAIN_ONLY;
517  if (into)
518  eflags |= GetIntoRelEFlags(into);
519 
520  /* call ExecutorStart to prepare the plan for execution */
521  ExecutorStart(queryDesc, eflags);
522 
523  /* Execute the plan for statistics if asked for */
524  if (es->analyze)
525  {
526  ScanDirection dir;
527 
528  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
529  if (into && into->skipData)
531  else
532  dir = ForwardScanDirection;
533 
534  /* run the plan */
535  ExecutorRun(queryDesc, dir, 0L, true);
536 
537  /* run cleanup too */
538  ExecutorFinish(queryDesc);
539 
540  /* We can't run ExecutorEnd 'till we're done printing the stats... */
541  totaltime += elapsed_time(&starttime);
542  }
543 
544  ExplainOpenGroup("Query", NULL, true, es);
545 
546  /* Create textual dump of plan tree */
547  ExplainPrintPlan(es, queryDesc);
548 
549  if (es->summary && planduration)
550  {
551  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
552 
553  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
554  }
555 
556  /* Print info about runtime of triggers */
557  if (es->analyze)
558  ExplainPrintTriggers(es, queryDesc);
559 
560  /*
561  * Print info about JITing. Tied to es->costs because we don't want to
562  * display this in regression tests, as it'd cause output differences
563  * depending on build options. Might want to separate that out from COSTS
564  * at a later stage.
565  */
566  if (queryDesc->estate->es_jit && es->costs &&
567  queryDesc->estate->es_jit->created_functions > 0)
568  ExplainPrintJIT(es, queryDesc);
569 
570  /*
571  * Close down the query and free resources. Include time for this in the
572  * total execution time (although it should be pretty minimal).
573  */
574  INSTR_TIME_SET_CURRENT(starttime);
575 
576  ExecutorEnd(queryDesc);
577 
578  FreeQueryDesc(queryDesc);
579 
581 
582  /* We need a CCI just in case query expanded to multiple plans */
583  if (es->analyze)
585 
586  totaltime += elapsed_time(&starttime);
587 
588  /*
589  * We only report execution time if we actually ran the query (that is,
590  * the user specified ANALYZE), and if summary reporting is enabled (the
591  * user can set SUMMARY OFF to not have the timing information included in
592  * the output). By default, ANALYZE sets SUMMARY to true.
593  */
594  if (es->summary && es->analyze)
595  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
596  es);
597 
598  ExplainCloseGroup("Query", NULL, true, es);
599 }
void ExplainPrintJIT(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:696
bool summary
Definition: explain.h:37
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:781
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:573
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:3426
struct timeval instr_time
Definition: instr_time.h:147
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:141
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
bool skipData
Definition: primnodes.h:116
bool costs
Definition: explain.h:34
DestReceiver * None_Receiver
Definition: dest.c:91
bool analyze
Definition: explain.h:33
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:461
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:392
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:650
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:613
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:299
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:769
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
ScanDirection
Definition: sdir.h:22
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:423
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:401
bool timing
Definition: explain.h:36
#define InvalidSnapshot
Definition: snapshot.h:25
void CommandCounterIncrement(void)
Definition: xact.c:914
CmdType commandType
Definition: plannodes.h:45
#define Assert(condition)
Definition: c.h:699
static double elapsed_time(instr_time *starttime)
Definition: explain.c:830
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
size_t created_functions
Definition: jit.h:35
bool buffers
Definition: explain.h:35
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3518
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3455
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58

◆ ExplainOneUtility()

void ExplainOneUtility ( Node utilityStmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv 
)

Definition at line 388 of file explain.c.

References appendStringInfoString(), Assert, castNode, copyObject, CURSOR_OPT_PARALLEL_OK, EXPLAIN_FORMAT_TEXT, ExplainDummyGroup(), ExplainExecuteQuery(), ExplainOneQuery(), ExplainState::format, CreateTableAsStmt::into, IsA, linitial_node, list_length(), DeclareCursorStmt::options, DeclareCursorStmt::query, CreateTableAsStmt::query, QueryRewrite(), and ExplainState::str.

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

391 {
392  if (utilityStmt == NULL)
393  return;
394 
395  if (IsA(utilityStmt, CreateTableAsStmt))
396  {
397  /*
398  * We have to rewrite the contained SELECT and then pass it back to
399  * ExplainOneQuery. It's probably not really necessary to copy the
400  * contained parsetree another time, but let's be safe.
401  */
402  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
403  List *rewritten;
404 
405  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
406  Assert(list_length(rewritten) == 1);
407  ExplainOneQuery(linitial_node(Query, rewritten),
408  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
409  queryString, params, queryEnv);
410  }
411  else if (IsA(utilityStmt, DeclareCursorStmt))
412  {
413  /*
414  * Likewise for DECLARE CURSOR.
415  *
416  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
417  * actually run the query. This is different from pre-8.3 behavior
418  * but seems more useful than not running the query. No cursor will
419  * be created, however.
420  */
421  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
422  List *rewritten;
423 
424  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
425  Assert(list_length(rewritten) == 1);
426  ExplainOneQuery(linitial_node(Query, rewritten),
427  dcs->options, NULL, es,
428  queryString, params, queryEnv);
429  }
430  else if (IsA(utilityStmt, ExecuteStmt))
431  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
432  queryString, params, queryEnv);
433  else if (IsA(utilityStmt, NotifyStmt))
434  {
435  if (es->format == EXPLAIN_FORMAT_TEXT)
436  appendStringInfoString(es->str, "NOTIFY\n");
437  else
438  ExplainDummyGroup("Notify", NULL, es);
439  }
440  else
441  {
442  if (es->format == EXPLAIN_FORMAT_TEXT)
444  "Utility statements have no plan structure\n");
445  else
446  ExplainDummyGroup("Utility Statement", NULL, es);
447  }
448 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
List * QueryRewrite(Query *parsetree)
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
#define linitial_node(type, l)
Definition: pg_list.h:114
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:3554
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:632
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:339
IntoClause * into
Definition: parsenodes.h:3197
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
ExplainFormat format
Definition: explain.h:38
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2653
#define copyObject(obj)
Definition: nodes.h:630
Definition: pg_list.h:45
StringInfo str
Definition: explain.h:30

◆ ExplainOpenGroup()

void ExplainOpenGroup ( const char *  objtype,
const char *  labelname,
bool  labeled,
ExplainState es 
)

Definition at line 3455 of file explain.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), escape_json(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainJSONLineEnding(), ExplainXMLTag(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, lcons_int(), ExplainState::str, and X_OPENING.

Referenced by ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3457 {
3458  switch (es->format)
3459  {
3460  case EXPLAIN_FORMAT_TEXT:
3461  /* nothing to do */
3462  break;
3463 
3464  case EXPLAIN_FORMAT_XML:
3465  ExplainXMLTag(objtype, X_OPENING, es);
3466  es->indent++;
3467  break;
3468 
3469  case EXPLAIN_FORMAT_JSON:
3471  appendStringInfoSpaces(es->str, 2 * es->indent);
3472  if (labelname)
3473  {
3474  escape_json(es->str, labelname);
3475  appendStringInfoString(es->str, ": ");
3476  }
3477  appendStringInfoChar(es->str, labeled ? '{' : '[');
3478 
3479  /*
3480  * In JSON format, the grouping_stack is an integer list. 0 means
3481  * we've emitted nothing at this grouping level, 1 means we've
3482  * emitted something (and so the next item needs a comma). See
3483  * ExplainJSONLineEnding().
3484  */
3485  es->grouping_stack = lcons_int(0, es->grouping_stack);
3486  es->indent++;
3487  break;
3488 
3489  case EXPLAIN_FORMAT_YAML:
3490 
3491  /*
3492  * In YAML format, the grouping stack is an integer list. 0 means
3493  * we've emitted nothing at this grouping level AND this grouping
3494  * level is unlabelled and must be marked with "- ". See
3495  * ExplainYAMLLineStarting().
3496  */
3498  if (labelname)
3499  {
3500  appendStringInfo(es->str, "%s: ", labelname);
3501  es->grouping_stack = lcons_int(1, es->grouping_stack);
3502  }
3503  else
3504  {
3505  appendStringInfoString(es->str, "- ");
3506  es->grouping_stack = lcons_int(0, es->grouping_stack);
3507  }
3508  es->indent++;
3509  break;
3510  }
3511 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2461
List * lcons_int(int datum, List *list)
Definition: list.c:277
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3689
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3736
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3716
#define X_OPENING
Definition: explain.c:52
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ ExplainPrintJIT()

void ExplainPrintJIT ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 696 of file explain.c.

References ExplainState::analyze, appendStringInfo(), JitContext::created_functions, JitContext::emission_counter, EState::es_jit, QueryDesc::estate, EXPLAIN_FORMAT_TEXT, ExplainCloseGroup(), ExplainOpenGroup(), ExplainPropertyBool(), ExplainPropertyFloat(), ExplainPropertyInteger(), JitContext::flags, ExplainState::format, JitContext::generation_counter, ExplainState::indent, JitContext::inlining_counter, INSTR_TIME_GET_DOUBLE, JitContext::optimization_counter, PGJIT_INLINE, PGJIT_OPT3, ExplainState::str, and ExplainState::timing.

Referenced by ExplainOnePlan().

697 {
698  JitContext *jc = queryDesc->estate->es_jit;
699 
700  ExplainOpenGroup("JIT", "JIT", true, es);
701 
702  if (es->format == EXPLAIN_FORMAT_TEXT)
703  {
704  es->indent += 1;
705  appendStringInfo(es->str, "JIT:\n");
706  }
707 
708  ExplainPropertyInteger("Functions", NULL, jc->created_functions, es);
709  if (es->analyze && es->timing)
710  ExplainPropertyFloat("Generation Time", "ms",
712  3, es);
713 
714  ExplainPropertyBool("Inlining", jc->flags & PGJIT_INLINE, es);
715 
716  if (es->analyze && es->timing)
717  ExplainPropertyFloat("Inlining Time", "ms",
719  3, es);
720 
721  ExplainPropertyBool("Optimization", jc->flags & PGJIT_OPT3, es);
722  if (es->analyze && es->timing)
723  ExplainPropertyFloat("Optimization Time", "ms",
725  3, es);
726 
727  if (es->analyze && es->timing)
728  ExplainPropertyFloat("Emission Time", "ms",
730  3, es);
731 
732  ExplainCloseGroup("JIT", "JIT", true, es);
733  if (es->format == EXPLAIN_FORMAT_TEXT)
734  {
735  es->indent -= 1;
736  }
737 }
instr_time optimization_counter
Definition: jit.h:44
void ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es)
Definition: explain.c:3440
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:3412
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:573
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:3426
Definition: jit.h:27
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
bool analyze
Definition: explain.h:33
#define PGJIT_OPT3
Definition: jit.h:21
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
instr_time inlining_counter
Definition: jit.h:41
int indent
Definition: explain.h:40
instr_time emission_counter
Definition: jit.h:47
bool timing
Definition: explain.h:36
#define PGJIT_INLINE
Definition: jit.h:22
instr_time generation_counter
Definition: jit.h:38
ExplainFormat format
Definition: explain.h:38
size_t created_functions
Definition: jit.h:35
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3518
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3455
StringInfo str
Definition: explain.h:30
int flags
Definition: jit.h:30

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 613 of file explain.c.

References Assert, deparse_context_for_plan_rtable(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), IsA, NIL, outerPlanState, PlanState::plan, QueryDesc::plannedstmt, QueryDesc::planstate, ExplainState::printed_subplans, ExplainState::pstmt, ExplainState::rtable, PlannedStmt::rtable, ExplainState::rtable_names, and select_rtable_names_for_explain().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

614 {
615  Bitmapset *rels_used = NULL;
616  PlanState *ps;
617 
618  /* Set up ExplainState fields associated with this plan tree */
619  Assert(queryDesc->plannedstmt != NULL);
620  es->pstmt = queryDesc->plannedstmt;
621  es->rtable = queryDesc->plannedstmt->rtable;
622  ExplainPreScanNode(queryDesc->planstate, &rels_used);
625  es->rtable_names);
626  es->printed_subplans = NULL;
627 
628  /*
629  * Sometimes we mark a Gather node as "invisible", which means that it's
630  * not displayed in EXPLAIN output. The purpose of this is to allow
631  * running regression tests with force_parallel_mode=regress to get the
632  * same results as running the same tests with force_parallel_mode=off.
633  */
634  ps = queryDesc->planstate;
635  if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
636  ps = outerPlanState(ps);
637  ExplainNode(ps, NIL, NULL, NULL, es);
638 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Bitmapset * printed_subplans
Definition: explain.h:47
List * deparse_cxt
Definition: explain.h:46
PlannedStmt * pstmt
Definition: explain.h:43
List * rtable_names
Definition: explain.h:45
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3247
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:914
PlanState * planstate
Definition: execdesc.h:49
#define outerPlanState(node)
Definition: execnodes.h:966
Plan * plan
Definition: execnodes.h:912
#define Assert(condition)
Definition: c.h:699
List * rtable
Definition: plannodes.h:65
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:849
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
Definition: ruleutils.c:3172
List * rtable
Definition: explain.h:44

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 650 of file explain.c.

References EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_result_relations, EState::es_root_result_relations, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, QueryDesc::estate, ExplainCloseGroup(), ExplainOpenGroup(), lfirst, NIL, and report_triggers().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

651 {
652  ResultRelInfo *rInfo;
653  bool show_relname;
654  int numrels = queryDesc->estate->es_num_result_relations;
655  int numrootrels = queryDesc->estate->es_num_root_result_relations;
656  List *routerels;
657  List *targrels;
658  int nr;
659  ListCell *l;
660 
661  routerels = queryDesc->estate->es_tuple_routing_result_relations;
662  targrels = queryDesc->estate->es_trig_target_relations;
663 
664  ExplainOpenGroup("Triggers", "Triggers", false, es);
665 
666  show_relname = (numrels > 1 || numrootrels > 0 ||
667  routerels != NIL || targrels != NIL);
668  rInfo = queryDesc->estate->es_result_relations;
669  for (nr = 0; nr < numrels; rInfo++, nr++)
670  report_triggers(rInfo, show_relname, es);
671 
672  rInfo = queryDesc->estate->es_root_result_relations;
673  for (nr = 0; nr < numrootrels; rInfo++, nr++)
674  report_triggers(rInfo, show_relname, es);
675 
676  foreach(l, routerels)
677  {
678  rInfo = (ResultRelInfo *) lfirst(l);
679  report_triggers(rInfo, show_relname, es);
680  }
681 
682  foreach(l, targrels)
683  {
684  rInfo = (ResultRelInfo *) lfirst(l);
685  report_triggers(rInfo, show_relname, es);
686  }
687 
688  ExplainCloseGroup("Triggers", "Triggers", false, es);
689 }
#define NIL
Definition: pg_list.h:69
EState * estate
Definition: execdesc.h:48
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:759
int es_num_root_result_relations
Definition: execnodes.h:502
List * es_trig_target_relations
Definition: execnodes.h:511
int es_num_result_relations
Definition: execnodes.h:491
List * es_tuple_routing_result_relations
Definition: execnodes.h:508
#define lfirst(lc)
Definition: pg_list.h:106
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3518
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3455
Definition: pg_list.h:45

◆ ExplainPropertyBool()

void ExplainPropertyBool ( const char *  qlabel,
bool  value,
ExplainState es 
)

Definition at line 3440 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode(), and ExplainPrintJIT().

3441 {
3442  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
3443 }
static struct @131 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3350

◆ ExplainPropertyFloat()

void ExplainPropertyFloat ( const char *  qlabel,
const char *  unit,
double  value,
int  ndigits,
ExplainState es 
)

Definition at line 3426 of file explain.c.

References buf, ExplainProperty(), pfree(), and psprintf().

Referenced by ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), report_triggers(), show_buffer_usage(), show_instrumentation_count(), and show_modifytable_info().

3428 {
3429  char *buf;
3430 
3431  buf = psprintf("%.*f", ndigits, value);
3432  ExplainProperty(qlabel, unit, buf, true, es);
3433  pfree(buf);
3434 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1031
static char * buf
Definition: pg_test_fsync.c:67
static struct @131 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3350

◆ ExplainPropertyInteger()

void ExplainPropertyInteger ( const char *  qlabel,
const char *  unit,
int64  value,
ExplainState es 
)

Definition at line 3412 of file explain.c.

References buf, ExplainProperty(), INT64_FORMAT, and snprintf().

Referenced by ExplainMemberNodes(), ExplainNode(), ExplainPrintJIT(), fileExplainForeignScan(), show_buffer_usage(), show_hash_info(), show_sort_info(), and show_tidbitmap_info().

3414 {
3415  char buf[32];
3416 
3417  snprintf(buf, sizeof(buf), INT64_FORMAT, value);
3418  ExplainProperty(qlabel, unit, buf, true, es);
3419 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:67
static struct @131 value
#define INT64_FORMAT
Definition: c.h:367
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3350

◆ ExplainPropertyList()

void ExplainPropertyList ( const char *  qlabel,
List data,
ExplainState es 
)

Definition at line 3227 of file explain.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), escape_json(), escape_xml(), escape_yaml(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainJSONLineEnding(), ExplainXMLTag(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::indent, lfirst, pfree(), ExplainState::str, generate_unaccent_rules::str, X_CLOSING, and X_OPENING.

Referenced by ExplainPropertyListNested(), show_eval_params(), show_modifytable_info(), show_plan_tlist(), show_sort_group_keys(), and show_tablesample().

3228 {
3229  ListCell *lc;
3230  bool first = true;
3231 
3232  switch (es->format)
3233  {
3234  case EXPLAIN_FORMAT_TEXT:
3235  appendStringInfoSpaces(es->str, es->indent * 2);
3236  appendStringInfo(es->str, "%s: ", qlabel);
3237  foreach(lc, data)
3238  {
3239  if (!first)
3240  appendStringInfoString(es->str, ", ");
3241  appendStringInfoString(es->str, (const char *) lfirst(lc));
3242  first = false;
3243  }
3244  appendStringInfoChar(es->str, '\n');
3245  break;
3246 
3247  case EXPLAIN_FORMAT_XML:
3248  ExplainXMLTag(qlabel, X_OPENING, es);
3249  foreach(lc, data)
3250  {
3251  char *str;
3252 
3253  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3254  appendStringInfoString(es->str, "<Item>");
3255  str = escape_xml((const char *) lfirst(lc));
3256  appendStringInfoString(es->str, str);
3257  pfree(str);
3258  appendStringInfoString(es->str, "</Item>\n");
3259  }
3260  ExplainXMLTag(qlabel, X_CLOSING, es);
3261  break;
3262 
3263  case EXPLAIN_FORMAT_JSON:
3265  appendStringInfoSpaces(es->str, es->indent * 2);
3266  escape_json(es->str, qlabel);
3267  appendStringInfoString(es->str, ": [");
3268  foreach(lc, data)
3269  {
3270  if (!first)
3271  appendStringInfoString(es->str, ", ");
3272  escape_json(es->str, (const char *) lfirst(lc));
3273  first = false;
3274  }
3275  appendStringInfoChar(es->str, ']');
3276  break;
3277 
3278  case EXPLAIN_FORMAT_YAML:
3280  appendStringInfo(es->str, "%s: ", qlabel);
3281  foreach(lc, data)
3282  {
3283  appendStringInfoChar(es->str, '\n');
3284  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3285  appendStringInfoString(es->str, "- ");
3286  escape_yaml(es->str, (const char *) lfirst(lc));
3287  }
3288  break;
3289  }
3290 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2461
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3689
#define X_CLOSING
Definition: explain.c:53
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3736
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3761
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3716
#define X_OPENING
Definition: explain.c:52
#define lfirst(lc)
Definition: pg_list.h:106
ExplainFormat format
Definition: explain.h:38
char * escape_xml(const char *str)
Definition: xml.c:2232
StringInfo str
Definition: explain.h:30

◆ ExplainPropertyListNested()

void ExplainPropertyListNested ( const char *  qlabel,
List data,
ExplainState es 
)

Definition at line 3297 of file explain.c.

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), escape_json(), escape_yaml(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainJSONLineEnding(), ExplainPropertyList(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::indent, lfirst, and ExplainState::str.

Referenced by show_grouping_set_keys().

3298 {
3299  ListCell *lc;
3300  bool first = true;
3301 
3302  switch (es->format)
3303  {
3304  case EXPLAIN_FORMAT_TEXT:
3305  case EXPLAIN_FORMAT_XML:
3306  ExplainPropertyList(qlabel, data, es);
3307  return;
3308 
3309  case EXPLAIN_FORMAT_JSON:
3311  appendStringInfoSpaces(es->str, es->indent * 2);
3312  appendStringInfoChar(es->str, '[');
3313  foreach(lc, data)
3314  {
3315  if (!first)
3316  appendStringInfoString(es->str, ", ");
3317  escape_json(es->str, (const char *) lfirst(lc));
3318  first = false;
3319  }
3320  appendStringInfoChar(es->str, ']');
3321  break;
3322 
3323  case EXPLAIN_FORMAT_YAML:
3325  appendStringInfoString(es->str, "- [");
3326  foreach(lc, data)
3327  {
3328  if (!first)
3329  appendStringInfoString(es->str, ", ");
3330  escape_yaml(es->str, (const char *) lfirst(lc));
3331  first = false;
3332  }
3333  appendStringInfoChar(es->str, ']');
3334  break;
3335  }
3336 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2461
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3736
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3761
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3716
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:3227
#define lfirst(lc)
Definition: pg_list.h:106
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ ExplainPropertyText()

void ExplainPropertyText ( const char *  qlabel,
const char *  value,
ExplainState es 
)

Definition at line 3403 of file explain.c.

References ExplainProperty().

Referenced by ExplainIndexScanDetails(), ExplainNode(), ExplainQueryText(), ExplainTargetRel(), fileExplainForeignScan(), postgresExplainDirectModify(), postgresExplainForeignModify(), postgresExplainForeignScan(), report_triggers(), show_expression(), show_grouping_set_keys(), show_modifytable_info(), show_sort_info(), and show_tablesample().

3404 {
3405  ExplainProperty(qlabel, NULL, value, false, es);
3406 }
static struct @131 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3350

◆ ExplainQuery()

void ExplainQuery ( ParseState pstate,
ExplainStmt stmt,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv,
DestReceiver dest 
)

Definition at line 143 of file explain.c.

References ExplainState::analyze, appendStringInfoString(), Assert, begin_tup_output_tupdesc(), ExplainState::buffers, castNode, copyObject, ExplainState::costs, CURSOR_OPT_PARALLEL_OK, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, do_text_output_multiline(), do_text_output_oneline, end_tup_output(), ereport, errcode(), errmsg(), ERROR, EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainBeginOutput(), ExplainEndOutput(), ExplainOneQuery(), ExplainResultDesc(), ExplainSeparatePlans(), ExplainState::format, ExplainState::indent, lfirst, lfirst_node, lnext, DefElem::location, NewExplainState(), NIL, ExplainStmt::options, parser_errposition(), pfree(), ExplainStmt::query, QueryRewrite(), ExplainState::str, ExplainState::summary, ExplainState::timing, and ExplainState::verbose.

Referenced by standard_ProcessUtility().

146 {
148  TupOutputState *tstate;
149  List *rewritten;
150  ListCell *lc;
151  bool timing_set = false;
152  bool summary_set = false;
153 
154  /* Parse options list. */
155  foreach(lc, stmt->options)
156  {
157  DefElem *opt = (DefElem *) lfirst(lc);
158 
159  if (strcmp(opt->defname, "analyze") == 0)
160  es->analyze = defGetBoolean(opt);
161  else if (strcmp(opt->defname, "verbose") == 0)
162  es->verbose = defGetBoolean(opt);
163  else if (strcmp(opt->defname, "costs") == 0)
164  es->costs = defGetBoolean(opt);
165  else if (strcmp(opt->defname, "buffers") == 0)
166  es->buffers = defGetBoolean(opt);
167  else if (strcmp(opt->defname, "timing") == 0)
168  {
169  timing_set = true;
170  es->timing = defGetBoolean(opt);
171  }
172  else if (strcmp(opt->defname, "summary") == 0)
173  {
174  summary_set = true;
175  es->summary = defGetBoolean(opt);
176  }
177  else if (strcmp(opt->defname, "format") == 0)
178  {
179  char *p = defGetString(opt);
180 
181  if (strcmp(p, "text") == 0)
183  else if (strcmp(p, "xml") == 0)
185  else if (strcmp(p, "json") == 0)
187  else if (strcmp(p, "yaml") == 0)
189  else
190  ereport(ERROR,
191  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
192  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
193  opt->defname, p),
194  parser_errposition(pstate, opt->location)));
195  }
196  else
197  ereport(ERROR,
198  (errcode(ERRCODE_SYNTAX_ERROR),
199  errmsg("unrecognized EXPLAIN option \"%s\"",
200  opt->defname),
201  parser_errposition(pstate, opt->location)));
202  }
203 
204  if (es->buffers && !es->analyze)
205  ereport(ERROR,
206  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
207  errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
208 
209  /* if the timing was not set explicitly, set default value */
210  es->timing = (timing_set) ? es->timing : es->analyze;
211 
212  /* check that timing is used with EXPLAIN ANALYZE */
213  if (es->timing && !es->analyze)
214  ereport(ERROR,
215  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
216  errmsg("EXPLAIN option TIMING requires ANALYZE")));
217 
218  /* if the summary was not set explicitly, set default value */
219  es->summary = (summary_set) ? es->summary : es->analyze;
220 
221  /*
222  * Parse analysis was done already, but we still have to run the rule
223  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
224  * came straight from the parser, or suitable locks were acquired by
225  * plancache.c.
226  *
227  * Because the rewriter and planner tend to scribble on the input, we make
228  * a preliminary copy of the source querytree. This prevents problems in
229  * the case that the EXPLAIN is in a portal or plpgsql function and is
230  * executed repeatedly. (See also the same hack in DECLARE CURSOR and
231  * PREPARE.) XXX FIXME someday.
232  */
233  rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
234 
235  /* emit opening boilerplate */
236  ExplainBeginOutput(es);
237 
238  if (rewritten == NIL)
239  {
240  /*
241  * In the case of an INSTEAD NOTHING, tell at least that. But in
242  * non-text format, the output is delimited, so this isn't necessary.
243  */
244  if (es->format == EXPLAIN_FORMAT_TEXT)
245  appendStringInfoString(es->str, "Query rewrites to nothing\n");
246  }
247  else
248  {
249  ListCell *l;
250 
251  /* Explain every plan */
252  foreach(l, rewritten)
253  {
255  CURSOR_OPT_PARALLEL_OK, NULL, es,
256  queryString, params, queryEnv);
257 
258  /* Separate plans with an appropriate separator */
259  if (lnext(l) != NULL)
261  }
262  }
263 
264  /* emit closing boilerplate */
265  ExplainEndOutput(es);
266  Assert(es->indent == 0);
267 
268  /* output tuples */
269  tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
270  if (es->format == EXPLAIN_FORMAT_TEXT)
271  do_text_output_multiline(tstate, es->str->data);
272  else
273  do_text_output_oneline(tstate, es->str->data);
274  end_tup_output(tstate);
275 
276  pfree(es->str->data);
277 }
#define NIL
Definition: pg_list.h:69
bool summary
Definition: explain.h:37
ExplainState * NewExplainState(void)
Definition: explain.c:283
List * QueryRewrite(Query *parsetree)
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:3660
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
int errcode(int sqlerrcode)
Definition: elog.c:575
List * options
Definition: parsenodes.h:3177
bool costs
Definition: explain.h:34
bool analyze
Definition: explain.h:33
Node * query
Definition: parsenodes.h:3176
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:3631
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:1031
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:1391
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:3600
#define ERROR
Definition: elog.h:43
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:300
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst_node(type, lc)
Definition: pg_list.h:109
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
int location
Definition: parsenodes.h:733
int indent
Definition: explain.h:40
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
bool timing
Definition: explain.h:36
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
Definition: execTuples.c:1315
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:339
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:1361
bool verbose
Definition: explain.h:32
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
ExplainFormat format
Definition: explain.h:38
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:462
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2653
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool buffers
Definition: explain.h:35
char * defname
Definition: parsenodes.h:730
#define copyObject(obj)
Definition: nodes.h:630
Definition: pg_list.h:45
StringInfo str
Definition: explain.h:30

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 748 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

749 {
750  if (queryDesc->sourceText)
751  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
752 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:3403
const char * sourceText
Definition: execdesc.h:38

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 300 of file explain.c.

References CreateTemplateTupleDesc(), defGetString(), DefElem::defname, lfirst, ExplainStmt::options, and TupleDescInitEntry().

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

301 {
302  TupleDesc tupdesc;
303  ListCell *lc;
304  Oid result_type = TEXTOID;
305 
306  /* Check for XML format option */
307  foreach(lc, stmt->options)
308  {
309  DefElem *opt = (DefElem *) lfirst(lc);
310 
311  if (strcmp(opt->defname, "format") == 0)
312  {
313  char *p = defGetString(opt);
314 
315  if (strcmp(p, "xml") == 0)
316  result_type = XMLOID;
317  else if (strcmp(p, "json") == 0)
318  result_type = JSONOID;
319  else
320  result_type = TEXTOID;
321  /* don't "break", as ExplainQuery will use the last value */
322  }
323  }
324 
325  /* Need a tuple descriptor representing a single TEXT or XML column */
326  tupdesc = CreateTemplateTupleDesc(1, false);
327  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
328  result_type, -1, 0);
329  return tupdesc;
330 }
List * options
Definition: parsenodes.h:3177
unsigned int Oid
Definition: postgres_ext.h:31
char * defGetString(DefElem *def)
Definition: define.c:49
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:600
#define lfirst(lc)
Definition: pg_list.h:106
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:45
char * defname
Definition: parsenodes.h:730
int16 AttrNumber
Definition: attnum.h:21

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 3660 of file explain.c.

References appendStringInfoChar(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, and ExplainState::str.

Referenced by ExplainExecuteQuery(), and ExplainQuery().

3661 {
3662  switch (es->format)
3663  {
3664  case EXPLAIN_FORMAT_TEXT:
3665  /* add a blank line */
3666  appendStringInfoChar(es->str, '\n');
3667  break;
3668 
3669  case EXPLAIN_FORMAT_XML:
3670  case EXPLAIN_FORMAT_JSON:
3671  case EXPLAIN_FORMAT_YAML:
3672  /* nothing to do */
3673  break;
3674  }
3675 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 283 of file explain.c.

References ExplainState::costs, makeStringInfo(), palloc0(), and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

284 {
285  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
286 
287  /* Set default options (most fields can be left as zeroes). */
288  es->costs = true;
289  /* Prepare output buffer. */
290  es->str = makeStringInfo();
291 
292  return es;
293 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
bool costs
Definition: explain.h:34
void * palloc0(Size size)
Definition: mcxt.c:955
StringInfo str
Definition: explain.h:30

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook

Definition at line 48 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook

Definition at line 45 of file explain.c.

Referenced by ExplainOneQuery().