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  ExplainWorkersState
 
struct  ExplainState
 

Typedefs

typedef enum ExplainFormat ExplainFormat
 
typedef struct ExplainWorkersState ExplainWorkersState
 
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, ParamListInfo params, 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, const BufferUsage *bufusage)
 
void ExplainPrintPlan (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintTriggers (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintJITSummary (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 ExplainPropertyUInteger (const char *qlabel, const char *unit, uint64 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 75 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 65 of file explain.h.

◆ ExplainState

typedef struct ExplainState ExplainState

◆ ExplainWorkersState

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

4547 {
4548  switch (es->format)
4549  {
4550  case EXPLAIN_FORMAT_TEXT:
4551  /* nothing to do */
4552  break;
4553 
4554  case EXPLAIN_FORMAT_XML:
4556  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
4557  es->indent++;
4558  break;
4559 
4560  case EXPLAIN_FORMAT_JSON:
4561  /* top-level structure is an array of plans */
4562  appendStringInfoChar(es->str, '[');
4563  es->grouping_stack = lcons_int(0, es->grouping_stack);
4564  es->indent++;
4565  break;
4566 
4567  case EXPLAIN_FORMAT_YAML:
4568  es->grouping_stack = lcons_int(0, es->grouping_stack);
4569  break;
4570  }
4571 }
List * lcons_int(int datum, List *list)
Definition: list.c:471
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
List * grouping_stack
Definition: explain.h:52
int indent
Definition: explain.h:51
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39

◆ ExplainCloseGroup()

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

Definition at line 4353 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 ExplainFlushWorkersState(), ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintSettings(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_incremental_sort_group_info(), and show_modifytable_info().

4355 {
4356  switch (es->format)
4357  {
4358  case EXPLAIN_FORMAT_TEXT:
4359  /* nothing to do */
4360  break;
4361 
4362  case EXPLAIN_FORMAT_XML:
4363  es->indent--;
4364  ExplainXMLTag(objtype, X_CLOSING, es);
4365  break;
4366 
4367  case EXPLAIN_FORMAT_JSON:
4368  es->indent--;
4369  appendStringInfoChar(es->str, '\n');
4370  appendStringInfoSpaces(es->str, 2 * es->indent);
4371  appendStringInfoChar(es->str, labeled ? '}' : ']');
4373  break;
4374 
4375  case EXPLAIN_FORMAT_YAML:
4376  es->indent--;
4378  break;
4379  }
4380 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4635
#define X_CLOSING
Definition: explain.c:52
List * grouping_stack
Definition: explain.h:52
int indent
Definition: explain.h:51
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39
List * list_delete_first(List *list)
Definition: list.c:860

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 4577 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().

4578 {
4579  switch (es->format)
4580  {
4581  case EXPLAIN_FORMAT_TEXT:
4582  /* nothing to do */
4583  break;
4584 
4585  case EXPLAIN_FORMAT_XML:
4586  es->indent--;
4587  appendStringInfoString(es->str, "</explain>");
4588  break;
4589 
4590  case EXPLAIN_FORMAT_JSON:
4591  es->indent--;
4592  appendStringInfoString(es->str, "\n]");
4594  break;
4595 
4596  case EXPLAIN_FORMAT_YAML:
4598  break;
4599  }
4600 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
List * grouping_stack
Definition: explain.h:52
int indent
Definition: explain.h:51
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39
List * list_delete_first(List *list)
Definition: list.c:860

◆ ExplainOnePlan()

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

Definition at line 496 of file explain.c.

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

500 {
502  QueryDesc *queryDesc;
503  instr_time starttime;
504  double totaltime = 0;
505  int eflags;
506  int instrument_option = 0;
507 
508  Assert(plannedstmt->commandType != CMD_UTILITY);
509 
510  if (es->analyze && es->timing)
511  instrument_option |= INSTRUMENT_TIMER;
512  else if (es->analyze)
513  instrument_option |= INSTRUMENT_ROWS;
514 
515  if (es->buffers)
516  instrument_option |= INSTRUMENT_BUFFERS;
517  if (es->wal)
518  instrument_option |= INSTRUMENT_WAL;
519 
520  /*
521  * We always collect timing for the entire statement, even when node-level
522  * timing is off, so we don't look at es->timing here. (We could skip
523  * this if !es->summary, but it's hardly worth the complication.)
524  */
525  INSTR_TIME_SET_CURRENT(starttime);
526 
527  /*
528  * Use a snapshot with an updated command ID to ensure this query sees
529  * results of any previously executed queries.
530  */
533 
534  /*
535  * Normally we discard the query's output, but if explaining CREATE TABLE
536  * AS, we'd better use the appropriate tuple receiver.
537  */
538  if (into)
539  dest = CreateIntoRelDestReceiver(into);
540  else
541  dest = None_Receiver;
542 
543  /* Create a QueryDesc for the query */
544  queryDesc = CreateQueryDesc(plannedstmt, queryString,
546  dest, params, queryEnv, instrument_option);
547 
548  /* Select execution options */
549  if (es->analyze)
550  eflags = 0; /* default run-to-completion flags */
551  else
552  eflags = EXEC_FLAG_EXPLAIN_ONLY;
553  if (into)
554  eflags |= GetIntoRelEFlags(into);
555 
556  /* call ExecutorStart to prepare the plan for execution */
557  ExecutorStart(queryDesc, eflags);
558 
559  /* Execute the plan for statistics if asked for */
560  if (es->analyze)
561  {
562  ScanDirection dir;
563 
564  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
565  if (into && into->skipData)
567  else
568  dir = ForwardScanDirection;
569 
570  /* run the plan */
571  ExecutorRun(queryDesc, dir, 0L, true);
572 
573  /* run cleanup too */
574  ExecutorFinish(queryDesc);
575 
576  /* We can't run ExecutorEnd 'till we're done printing the stats... */
577  totaltime += elapsed_time(&starttime);
578  }
579 
580  ExplainOpenGroup("Query", NULL, true, es);
581 
582  /* Create textual dump of plan tree */
583  ExplainPrintPlan(es, queryDesc);
584 
585  /* Show buffer usage in planning */
586  if (bufusage)
587  {
588  ExplainOpenGroup("Planning", "Planning", true, es);
589  show_buffer_usage(es, bufusage, true);
590  ExplainCloseGroup("Planning", "Planning", true, es);
591  }
592 
593  if (es->summary && planduration)
594  {
595  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
596 
597  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
598  }
599 
600  /* Print info about runtime of triggers */
601  if (es->analyze)
602  ExplainPrintTriggers(es, queryDesc);
603 
604  /*
605  * Print info about JITing. Tied to es->costs because we don't want to
606  * display this in regression tests, as it'd cause output differences
607  * depending on build options. Might want to separate that out from COSTS
608  * at a later stage.
609  */
610  if (es->costs)
611  ExplainPrintJITSummary(es, queryDesc);
612 
613  /*
614  * Close down the query and free resources. Include time for this in the
615  * total execution time (although it should be pretty minimal).
616  */
617  INSTR_TIME_SET_CURRENT(starttime);
618 
619  ExecutorEnd(queryDesc);
620 
621  FreeQueryDesc(queryDesc);
622 
624 
625  /* We need a CCI just in case query expanded to multiple plans */
626  if (es->analyze)
628 
629  totaltime += elapsed_time(&starttime);
630 
631  /*
632  * We only report execution time if we actually ran the query (that is,
633  * the user specified ANALYZE), and if summary reporting is enabled (the
634  * user can set SUMMARY OFF to not have the timing information included in
635  * the output). By default, ANALYZE sets SUMMARY to true.
636  */
637  if (es->summary && es->analyze)
638  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
639  es);
640 
641  ExplainCloseGroup("Query", NULL, true, es);
642 }
bool summary
Definition: explain.h:47
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:728
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:4261
struct timeval instr_time
Definition: instr_time.h:150
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:143
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
void PopActiveSnapshot(void)
Definition: snapmgr.c:759
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:199
bool skipData
Definition: primnodes.h:119
bool costs
Definition: explain.h:43
DestReceiver * None_Receiver
Definition: dest.c:96
bool analyze
Definition: explain.h:42
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:462
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:393
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:768
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:719
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:301
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:716
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:411
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:402
bool timing
Definition: explain.h:46
#define InvalidSnapshot
Definition: snapshot.h:123
void CommandCounterIncrement(void)
Definition: xact.c:1021
CmdType commandType
Definition: plannodes.h:46
#define Assert(condition)
Definition: c.h:746
bool wal
Definition: explain.h:45
static double elapsed_time(instr_time *starttime)
Definition: explain.c:1013
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage, bool planning)
Definition: explain.c:3289
bool buffers
Definition: explain.h:44
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4353
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:811
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4290
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56

◆ ExplainOneUtility()

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

Definition at line 421 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().

424 {
425  if (utilityStmt == NULL)
426  return;
427 
428  if (IsA(utilityStmt, CreateTableAsStmt))
429  {
430  /*
431  * We have to rewrite the contained SELECT and then pass it back to
432  * ExplainOneQuery. It's probably not really necessary to copy the
433  * contained parsetree another time, but let's be safe.
434  */
435  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
436  List *rewritten;
437 
438  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
439  Assert(list_length(rewritten) == 1);
440  ExplainOneQuery(linitial_node(Query, rewritten),
441  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
442  queryString, params, queryEnv);
443  }
444  else if (IsA(utilityStmt, DeclareCursorStmt))
445  {
446  /*
447  * Likewise for DECLARE CURSOR.
448  *
449  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
450  * actually run the query. This is different from pre-8.3 behavior
451  * but seems more useful than not running the query. No cursor will
452  * be created, however.
453  */
454  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
455  List *rewritten;
456 
457  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
458  Assert(list_length(rewritten) == 1);
459  ExplainOneQuery(linitial_node(Query, rewritten),
460  dcs->options, NULL, es,
461  queryString, params, queryEnv);
462  }
463  else if (IsA(utilityStmt, ExecuteStmt))
464  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
465  queryString, params, queryEnv);
466  else if (IsA(utilityStmt, NotifyStmt))
467  {
468  if (es->format == EXPLAIN_FORMAT_TEXT)
469  appendStringInfoString(es->str, "NOTIFY\n");
470  else
471  ExplainDummyGroup("Notify", NULL, es);
472  }
473  else
474  {
475  if (es->format == EXPLAIN_FORMAT_TEXT)
477  "Utility statements have no plan structure\n");
478  else
479  ExplainDummyGroup("Utility Statement", NULL, es);
480  }
481 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
List * QueryRewrite(Query *parsetree)
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
#define linitial_node(type, l)
Definition: pg_list.h:177
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:4500
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:606
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:361
IntoClause * into
Definition: parsenodes.h:3279
#define Assert(condition)
Definition: c.h:746
static int list_length(const List *l)
Definition: pg_list.h:149
ExplainFormat format
Definition: explain.h:49
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2717
#define copyObject(obj)
Definition: nodes.h:644
Definition: pg_list.h:50
StringInfo str
Definition: explain.h:39

◆ ExplainOpenGroup()

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

Definition at line 4290 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 ExplainFlushWorkersState(), ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintSettings(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_incremental_sort_group_info(), and show_modifytable_info().

4292 {
4293  switch (es->format)
4294  {
4295  case EXPLAIN_FORMAT_TEXT:
4296  /* nothing to do */
4297  break;
4298 
4299  case EXPLAIN_FORMAT_XML:
4300  ExplainXMLTag(objtype, X_OPENING, es);
4301  es->indent++;
4302  break;
4303 
4304  case EXPLAIN_FORMAT_JSON:
4306  appendStringInfoSpaces(es->str, 2 * es->indent);
4307  if (labelname)
4308  {
4309  escape_json(es->str, labelname);
4310  appendStringInfoString(es->str, ": ");
4311  }
4312  appendStringInfoChar(es->str, labeled ? '{' : '[');
4313 
4314  /*
4315  * In JSON format, the grouping_stack is an integer list. 0 means
4316  * we've emitted nothing at this grouping level, 1 means we've
4317  * emitted something (and so the next item needs a comma). See
4318  * ExplainJSONLineEnding().
4319  */
4320  es->grouping_stack = lcons_int(0, es->grouping_stack);
4321  es->indent++;
4322  break;
4323 
4324  case EXPLAIN_FORMAT_YAML:
4325 
4326  /*
4327  * In YAML format, the grouping stack is an integer list. 0 means
4328  * we've emitted nothing at this grouping level AND this grouping
4329  * level is unlabeled and must be marked with "- ". See
4330  * ExplainYAMLLineStarting().
4331  */
4333  if (labelname)
4334  {
4335  appendStringInfo(es->str, "%s: ", labelname);
4336  es->grouping_stack = lcons_int(1, es->grouping_stack);
4337  }
4338  else
4339  {
4340  appendStringInfoString(es->str, "- ");
4341  es->grouping_stack = lcons_int(0, es->grouping_stack);
4342  }
4343  es->indent++;
4344  break;
4345  }
4346 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
List * lcons_int(int datum, List *list)
Definition: list.c:471
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4635
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:4697
List * grouping_stack
Definition: explain.h:52
int indent
Definition: explain.h:51
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4677
#define X_OPENING
Definition: explain.c:51
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 811 of file explain.c.

References EState::es_jit, EState::es_jit_flags, EState::es_jit_worker_instr, QueryDesc::estate, ExplainPrintJIT(), JitContext::instr, InstrJitAgg(), and PGJIT_PERFORM.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

812 {
813  JitInstrumentation ji = {0};
814 
815  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
816  return;
817 
818  /*
819  * Work with a copy instead of modifying the leader state, since this
820  * function may be called twice
821  */
822  if (queryDesc->estate->es_jit)
823  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
824 
825  /* If this process has done JIT in parallel workers, merge stats */
826  if (queryDesc->estate->es_jit_worker_instr)
827  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
828 
829  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
830 }
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:605
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:606
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:837
JitInstrumentation instr
Definition: jit.h:61
int es_jit_flags
Definition: execnodes.h:604
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:184
#define PGJIT_PERFORM
Definition: jit.h:20

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 719 of file explain.c.

References Assert, deparse_context_for_plan_tree(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), ExplainState::hide_workers, 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().

720 {
721  Bitmapset *rels_used = NULL;
722  PlanState *ps;
723 
724  /* Set up ExplainState fields associated with this plan tree */
725  Assert(queryDesc->plannedstmt != NULL);
726  es->pstmt = queryDesc->plannedstmt;
727  es->rtable = queryDesc->plannedstmt->rtable;
728  ExplainPreScanNode(queryDesc->planstate, &rels_used);
731  es->rtable_names);
732  es->printed_subplans = NULL;
733 
734  /*
735  * Sometimes we mark a Gather node as "invisible", which means that it's
736  * not to be displayed in EXPLAIN output. The purpose of this is to allow
737  * running regression tests with force_parallel_mode=regress to get the
738  * same results as running the same tests with force_parallel_mode=off.
739  * Such marking is currently only supported on a Gather at the top of the
740  * plan. We skip that node, and we must also hide per-worker detail data
741  * further down in the plan tree.
742  */
743  ps = queryDesc->planstate;
744  if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
745  {
746  ps = outerPlanState(ps);
747  es->hide_workers = true;
748  }
749  ExplainNode(ps, NIL, NULL, NULL, es);
750 
751  /*
752  * If requested, include information about GUC parameters with values that
753  * don't match the built-in defaults.
754  */
756 }
#define NIL
Definition: pg_list.h:65
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:649
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
bool hide_workers
Definition: explain.h:59
Bitmapset * printed_subplans
Definition: explain.h:58
List * deparse_cxt
Definition: explain.h:57
PlannedStmt * pstmt
Definition: explain.h:54
List * rtable_names
Definition: explain.h:56
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3420
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1106
PlanState * planstate
Definition: execdesc.h:49
#define outerPlanState(node)
Definition: execnodes.h:1033
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3328
Plan * plan
Definition: execnodes.h:939
#define Assert(condition)
Definition: c.h:746
List * rtable
Definition: plannodes.h:66
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1032
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * rtable
Definition: explain.h:55

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 768 of file explain.c.

References EState::es_opened_result_relations, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, QueryDesc::estate, ExplainCloseGroup(), ExplainOpenGroup(), lfirst, list_length(), NIL, and report_triggers().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

769 {
770  ResultRelInfo *rInfo;
771  bool show_relname;
772  List *resultrels;
773  List *routerels;
774  List *targrels;
775  ListCell *l;
776 
777  resultrels = queryDesc->estate->es_opened_result_relations;
778  routerels = queryDesc->estate->es_tuple_routing_result_relations;
779  targrels = queryDesc->estate->es_trig_target_relations;
780 
781  ExplainOpenGroup("Triggers", "Triggers", false, es);
782 
783  show_relname = (list_length(resultrels) > 1 ||
784  routerels != NIL || targrels != NIL);
785  foreach(l, resultrels)
786  {
787  rInfo = (ResultRelInfo *) lfirst(l);
788  report_triggers(rInfo, show_relname, es);
789  }
790 
791  foreach(l, routerels)
792  {
793  rInfo = (ResultRelInfo *) lfirst(l);
794  report_triggers(rInfo, show_relname, es);
795  }
796 
797  foreach(l, targrels)
798  {
799  rInfo = (ResultRelInfo *) lfirst(l);
800  report_triggers(rInfo, show_relname, es);
801  }
802 
803  ExplainCloseGroup("Triggers", "Triggers", false, es);
804 }
#define NIL
Definition: pg_list.h:65
EState * estate
Definition: execdesc.h:48
List * es_opened_result_relations
Definition: execnodes.h:537
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:942
List * es_trig_target_relations
Definition: execnodes.h:550
List * es_tuple_routing_result_relations
Definition: execnodes.h:547
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4353
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4290
Definition: pg_list.h:50

◆ ExplainPropertyBool()

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

Definition at line 4275 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode(), and ExplainPrintJIT().

4276 {
4277  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4278 }
static struct @143 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4172

◆ ExplainPropertyFloat()

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

Definition at line 4261 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().

4263 {
4264  char *buf;
4265 
4266  buf = psprintf("%.*f", ndigits, value);
4267  ExplainProperty(qlabel, unit, buf, true, es);
4268  pfree(buf);
4269 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1057
static char * buf
Definition: pg_test_fsync.c:68
static struct @143 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4172

◆ ExplainPropertyInteger()

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

Definition at line 4234 of file explain.c.

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

Referenced by ExplainMissingMembers(), ExplainNode(), ExplainOpenWorker(), ExplainPrintJIT(), fileExplainForeignScan(), show_buffer_usage(), show_hash_info(), show_hashagg_info(), show_incremental_sort_group_info(), show_sort_info(), show_tidbitmap_info(), and show_wal_usage().

4236 {
4237  char buf[32];
4238 
4239  snprintf(buf, sizeof(buf), INT64_FORMAT, value);
4240  ExplainProperty(qlabel, unit, buf, true, es);
4241 }
static char * buf
Definition: pg_test_fsync.c:68
static struct @143 value
#define INT64_FORMAT
Definition: c.h:417
#define snprintf
Definition: port.h:215
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4172

◆ ExplainPropertyList()

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

Definition at line 4049 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, ExplainIndentText(), 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_incremental_sort_group_info(), show_modifytable_info(), show_plan_tlist(), show_sort_group_keys(), and show_tablesample().

4050 {
4051  ListCell *lc;
4052  bool first = true;
4053 
4054  switch (es->format)
4055  {
4056  case EXPLAIN_FORMAT_TEXT:
4057  ExplainIndentText(es);
4058  appendStringInfo(es->str, "%s: ", qlabel);
4059  foreach(lc, data)
4060  {
4061  if (!first)
4062  appendStringInfoString(es->str, ", ");
4063  appendStringInfoString(es->str, (const char *) lfirst(lc));
4064  first = false;
4065  }
4066  appendStringInfoChar(es->str, '\n');
4067  break;
4068 
4069  case EXPLAIN_FORMAT_XML:
4070  ExplainXMLTag(qlabel, X_OPENING, es);
4071  foreach(lc, data)
4072  {
4073  char *str;
4074 
4075  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4076  appendStringInfoString(es->str, "<Item>");
4077  str = escape_xml((const char *) lfirst(lc));
4078  appendStringInfoString(es->str, str);
4079  pfree(str);
4080  appendStringInfoString(es->str, "</Item>\n");
4081  }
4082  ExplainXMLTag(qlabel, X_CLOSING, es);
4083  break;
4084 
4085  case EXPLAIN_FORMAT_JSON:
4087  appendStringInfoSpaces(es->str, es->indent * 2);
4088  escape_json(es->str, qlabel);
4089  appendStringInfoString(es->str, ": [");
4090  foreach(lc, data)
4091  {
4092  if (!first)
4093  appendStringInfoString(es->str, ", ");
4094  escape_json(es->str, (const char *) lfirst(lc));
4095  first = false;
4096  }
4097  appendStringInfoChar(es->str, ']');
4098  break;
4099 
4100  case EXPLAIN_FORMAT_YAML:
4102  appendStringInfo(es->str, "%s: ", qlabel);
4103  foreach(lc, data)
4104  {
4105  appendStringInfoChar(es->str, '\n');
4106  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4107  appendStringInfoString(es->str, "- ");
4108  escape_yaml(es->str, (const char *) lfirst(lc));
4109  }
4110  break;
4111  }
4112 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4635
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:4697
int indent
Definition: explain.h:51
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:4722
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4677
#define X_OPENING
Definition: explain.c:51
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:4662
#define lfirst(lc)
Definition: pg_list.h:169
ExplainFormat format
Definition: explain.h:49
char * escape_xml(const char *str)
Definition: xml.c:2353
StringInfo str
Definition: explain.h:39

◆ ExplainPropertyListNested()

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

Definition at line 4119 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().

4120 {
4121  ListCell *lc;
4122  bool first = true;
4123 
4124  switch (es->format)
4125  {
4126  case EXPLAIN_FORMAT_TEXT:
4127  case EXPLAIN_FORMAT_XML:
4128  ExplainPropertyList(qlabel, data, es);
4129  return;
4130 
4131  case EXPLAIN_FORMAT_JSON:
4133  appendStringInfoSpaces(es->str, es->indent * 2);
4134  appendStringInfoChar(es->str, '[');
4135  foreach(lc, data)
4136  {
4137  if (!first)
4138  appendStringInfoString(es->str, ", ");
4139  escape_json(es->str, (const char *) lfirst(lc));
4140  first = false;
4141  }
4142  appendStringInfoChar(es->str, ']');
4143  break;
4144 
4145  case EXPLAIN_FORMAT_YAML:
4147  appendStringInfoString(es->str, "- [");
4148  foreach(lc, data)
4149  {
4150  if (!first)
4151  appendStringInfoString(es->str, ", ");
4152  escape_yaml(es->str, (const char *) lfirst(lc));
4153  first = false;
4154  }
4155  appendStringInfoChar(es->str, ']');
4156  break;
4157  }
4158 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:4697
int indent
Definition: explain.h:51
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:4722
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4677
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4049
#define lfirst(lc)
Definition: pg_list.h:169
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39

◆ ExplainPropertyText()

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

Definition at line 4225 of file explain.c.

References ExplainProperty().

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

4226 {
4227  ExplainProperty(qlabel, NULL, value, false, es);
4228 }
static struct @143 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4172

◆ ExplainPropertyUInteger()

void ExplainPropertyUInteger ( const char *  qlabel,
const char *  unit,
uint64  value,
ExplainState es 
)

Definition at line 4247 of file explain.c.

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

Referenced by show_wal_usage().

4249 {
4250  char buf[32];
4251 
4252  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4253  ExplainProperty(qlabel, unit, buf, true, es);
4254 }
static char * buf
Definition: pg_test_fsync.c:68
static struct @143 value
#define snprintf
Definition: port.h:215
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4172
#define UINT64_FORMAT
Definition: c.h:418

◆ ExplainQuery()

void ExplainQuery ( ParseState pstate,
ExplainStmt stmt,
ParamListInfo  params,
DestReceiver dest 
)

Definition at line 161 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, ParseState::p_queryEnv, ParseState::p_sourcetext, parser_errposition(), pfree(), ExplainStmt::query, QueryRewrite(), ExplainState::settings, ExplainState::str, ExplainState::summary, ExplainState::timing, TTSOpsVirtual, ExplainState::verbose, and ExplainState::wal.

Referenced by standard_ProcessUtility().

163 {
165  TupOutputState *tstate;
166  List *rewritten;
167  ListCell *lc;
168  bool timing_set = false;
169  bool summary_set = false;
170 
171  /* Parse options list. */
172  foreach(lc, stmt->options)
173  {
174  DefElem *opt = (DefElem *) lfirst(lc);
175 
176  if (strcmp(opt->defname, "analyze") == 0)
177  es->analyze = defGetBoolean(opt);
178  else if (strcmp(opt->defname, "verbose") == 0)
179  es->verbose = defGetBoolean(opt);
180  else if (strcmp(opt->defname, "costs") == 0)
181  es->costs = defGetBoolean(opt);
182  else if (strcmp(opt->defname, "buffers") == 0)
183  es->buffers = defGetBoolean(opt);
184  else if (strcmp(opt->defname, "wal") == 0)
185  es->wal = defGetBoolean(opt);
186  else if (strcmp(opt->defname, "settings") == 0)
187  es->settings = defGetBoolean(opt);
188  else if (strcmp(opt->defname, "timing") == 0)
189  {
190  timing_set = true;
191  es->timing = defGetBoolean(opt);
192  }
193  else if (strcmp(opt->defname, "summary") == 0)
194  {
195  summary_set = true;
196  es->summary = defGetBoolean(opt);
197  }
198  else if (strcmp(opt->defname, "format") == 0)
199  {
200  char *p = defGetString(opt);
201 
202  if (strcmp(p, "text") == 0)
204  else if (strcmp(p, "xml") == 0)
206  else if (strcmp(p, "json") == 0)
208  else if (strcmp(p, "yaml") == 0)
210  else
211  ereport(ERROR,
212  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
213  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
214  opt->defname, p),
215  parser_errposition(pstate, opt->location)));
216  }
217  else
218  ereport(ERROR,
219  (errcode(ERRCODE_SYNTAX_ERROR),
220  errmsg("unrecognized EXPLAIN option \"%s\"",
221  opt->defname),
222  parser_errposition(pstate, opt->location)));
223  }
224 
225  if (es->wal && !es->analyze)
226  ereport(ERROR,
227  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
228  errmsg("EXPLAIN option WAL requires ANALYZE")));
229 
230  /* if the timing was not set explicitly, set default value */
231  es->timing = (timing_set) ? es->timing : es->analyze;
232 
233  /* check that timing is used with EXPLAIN ANALYZE */
234  if (es->timing && !es->analyze)
235  ereport(ERROR,
236  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
237  errmsg("EXPLAIN option TIMING requires ANALYZE")));
238 
239  /* if the summary was not set explicitly, set default value */
240  es->summary = (summary_set) ? es->summary : es->analyze;
241 
242  /*
243  * Parse analysis was done already, but we still have to run the rule
244  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
245  * came straight from the parser, or suitable locks were acquired by
246  * plancache.c.
247  *
248  * Because the rewriter and planner tend to scribble on the input, we make
249  * a preliminary copy of the source querytree. This prevents problems in
250  * the case that the EXPLAIN is in a portal or plpgsql function and is
251  * executed repeatedly. (See also the same hack in DECLARE CURSOR and
252  * PREPARE.) XXX FIXME someday.
253  */
254  rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
255 
256  /* emit opening boilerplate */
257  ExplainBeginOutput(es);
258 
259  if (rewritten == NIL)
260  {
261  /*
262  * In the case of an INSTEAD NOTHING, tell at least that. But in
263  * non-text format, the output is delimited, so this isn't necessary.
264  */
265  if (es->format == EXPLAIN_FORMAT_TEXT)
266  appendStringInfoString(es->str, "Query rewrites to nothing\n");
267  }
268  else
269  {
270  ListCell *l;
271 
272  /* Explain every plan */
273  foreach(l, rewritten)
274  {
276  CURSOR_OPT_PARALLEL_OK, NULL, es,
277  pstate->p_sourcetext, params, pstate->p_queryEnv);
278 
279  /* Separate plans with an appropriate separator */
280  if (lnext(rewritten, l) != NULL)
282  }
283  }
284 
285  /* emit closing boilerplate */
286  ExplainEndOutput(es);
287  Assert(es->indent == 0);
288 
289  /* output tuples */
290  tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt),
291  &TTSOpsVirtual);
292  if (es->format == EXPLAIN_FORMAT_TEXT)
293  do_text_output_multiline(tstate, es->str->data);
294  else
295  do_text_output_oneline(tstate, es->str->data);
296  end_tup_output(tstate);
297 
298  pfree(es->str->data);
299 }
#define NIL
Definition: pg_list.h:65
bool summary
Definition: explain.h:47
ExplainState * NewExplainState(void)
Definition: explain.c:305
List * QueryRewrite(Query *parsetree)
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:4606
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
QueryEnvironment * p_queryEnv
Definition: parse_node.h:203
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
int errcode(int sqlerrcode)
Definition: elog.c:610
List * options
Definition: parsenodes.h:3259
bool costs
Definition: explain.h:43
bool analyze
Definition: explain.h:42
Node * query
Definition: parsenodes.h:3258
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:4577
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:1057
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2314
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:4546
#define ERROR
Definition: elog.h:43
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:322
char * defGetString(DefElem *def)
Definition: define.c:49
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2236
#define lfirst_node(type, lc)
Definition: pg_list.h:172
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
int location
Definition: parsenodes.h:736
int indent
Definition: explain.h:51
const char * p_sourcetext
Definition: parse_node.h:179
bool timing
Definition: explain.h:46
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:361
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2284
bool verbose
Definition: explain.h:41
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
bool wal
Definition: explain.h:45
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
ExplainFormat format
Definition: explain.h:49
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:478
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2717
int errmsg(const char *fmt,...)
Definition: elog.c:821
bool buffers
Definition: explain.h:44
char * defname
Definition: parsenodes.h:733
#define copyObject(obj)
Definition: nodes.h:644
Definition: pg_list.h:50
StringInfo str
Definition: explain.h:39
bool settings
Definition: explain.h:48

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 931 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

932 {
933  if (queryDesc->sourceText)
934  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
935 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:4225
const char * sourceText
Definition: execdesc.h:38

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 322 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

323 {
324  TupleDesc tupdesc;
325  ListCell *lc;
326  Oid result_type = TEXTOID;
327 
328  /* Check for XML format option */
329  foreach(lc, stmt->options)
330  {
331  DefElem *opt = (DefElem *) lfirst(lc);
332 
333  if (strcmp(opt->defname, "format") == 0)
334  {
335  char *p = defGetString(opt);
336 
337  if (strcmp(p, "xml") == 0)
338  result_type = XMLOID;
339  else if (strcmp(p, "json") == 0)
340  result_type = JSONOID;
341  else
342  result_type = TEXTOID;
343  /* don't "break", as ExplainQuery will use the last value */
344  }
345  }
346 
347  /* Need a tuple descriptor representing a single TEXT or XML column */
348  tupdesc = CreateTemplateTupleDesc(1);
349  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
350  result_type, -1, 0);
351  return tupdesc;
352 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
List * options
Definition: parsenodes.h:3259
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:603
#define lfirst(lc)
Definition: pg_list.h:169
char * defname
Definition: parsenodes.h:733
int16 AttrNumber
Definition: attnum.h:21

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 4606 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().

4607 {
4608  switch (es->format)
4609  {
4610  case EXPLAIN_FORMAT_TEXT:
4611  /* add a blank line */
4612  appendStringInfoChar(es->str, '\n');
4613  break;
4614 
4615  case EXPLAIN_FORMAT_XML:
4616  case EXPLAIN_FORMAT_JSON:
4617  case EXPLAIN_FORMAT_YAML:
4618  /* nothing to do */
4619  break;
4620  }
4621 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
ExplainFormat format
Definition: explain.h:49
StringInfo str
Definition: explain.h:39

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 305 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

306 {
307  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
308 
309  /* Set default options (most fields can be left as zeroes). */
310  es->costs = true;
311  /* Prepare output buffer. */
312  es->str = makeStringInfo();
313 
314  return es;
315 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
bool costs
Definition: explain.h:43
void * palloc0(Size size)
Definition: mcxt.c:981
StringInfo str
Definition: explain.h:39

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook

Definition at line 47 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook

Definition at line 44 of file explain.c.

Referenced by ExplainOneQuery().