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)
 
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 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 74 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 64 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 4099 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().

4100 {
4101  switch (es->format)
4102  {
4103  case EXPLAIN_FORMAT_TEXT:
4104  /* nothing to do */
4105  break;
4106 
4107  case EXPLAIN_FORMAT_XML:
4109  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
4110  es->indent++;
4111  break;
4112 
4113  case EXPLAIN_FORMAT_JSON:
4114  /* top-level structure is an array of plans */
4115  appendStringInfoChar(es->str, '[');
4116  es->grouping_stack = lcons_int(0, es->grouping_stack);
4117  es->indent++;
4118  break;
4119 
4120  case EXPLAIN_FORMAT_YAML:
4121  es->grouping_stack = lcons_int(0, es->grouping_stack);
4122  break;
4123  }
4124 }
List * lcons_int(int datum, List *list)
Definition: list.c:472
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
List * grouping_stack
Definition: explain.h:51
int indent
Definition: explain.h:50
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
ExplainFormat format
Definition: explain.h:48
StringInfo str
Definition: explain.h:39

◆ ExplainCloseGroup()

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

Definition at line 3906 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(), and show_modifytable_info().

3908 {
3909  switch (es->format)
3910  {
3911  case EXPLAIN_FORMAT_TEXT:
3912  /* nothing to do */
3913  break;
3914 
3915  case EXPLAIN_FORMAT_XML:
3916  es->indent--;
3917  ExplainXMLTag(objtype, X_CLOSING, es);
3918  break;
3919 
3920  case EXPLAIN_FORMAT_JSON:
3921  es->indent--;
3922  appendStringInfoChar(es->str, '\n');
3923  appendStringInfoSpaces(es->str, 2 * es->indent);
3924  appendStringInfoChar(es->str, labeled ? '}' : ']');
3926  break;
3927 
3928  case EXPLAIN_FORMAT_YAML:
3929  es->indent--;
3931  break;
3932  }
3933 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4188
#define X_CLOSING
Definition: explain.c:52
List * grouping_stack
Definition: explain.h:51
int indent
Definition: explain.h:50
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:48
StringInfo str
Definition: explain.h:39
List * list_delete_first(List *list)
Definition: list.c:861

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

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

4131 {
4132  switch (es->format)
4133  {
4134  case EXPLAIN_FORMAT_TEXT:
4135  /* nothing to do */
4136  break;
4137 
4138  case EXPLAIN_FORMAT_XML:
4139  es->indent--;
4140  appendStringInfoString(es->str, "</explain>");
4141  break;
4142 
4143  case EXPLAIN_FORMAT_JSON:
4144  es->indent--;
4145  appendStringInfoString(es->str, "\n]");
4147  break;
4148 
4149  case EXPLAIN_FORMAT_YAML:
4151  break;
4152  }
4153 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
List * grouping_stack
Definition: explain.h:51
int indent
Definition: explain.h:50
ExplainFormat format
Definition: explain.h:48
StringInfo str
Definition: explain.h:39
List * list_delete_first(List *list)
Definition: list.c:861

◆ ExplainOnePlan()

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

Definition at line 476 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, InvalidSnapshot, NoMovementScanDirection, None_Receiver, PopActiveSnapshot(), PushCopiedSnapshot(), IntoClause::skipData, ExplainState::summary, ExplainState::timing, and UpdateActiveSnapshotCommandId().

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

479 {
481  QueryDesc *queryDesc;
482  instr_time starttime;
483  double totaltime = 0;
484  int eflags;
485  int instrument_option = 0;
486 
487  Assert(plannedstmt->commandType != CMD_UTILITY);
488 
489  if (es->analyze && es->timing)
490  instrument_option |= INSTRUMENT_TIMER;
491  else if (es->analyze)
492  instrument_option |= INSTRUMENT_ROWS;
493 
494  if (es->buffers)
495  instrument_option |= INSTRUMENT_BUFFERS;
496 
497  /*
498  * We always collect timing for the entire statement, even when node-level
499  * timing is off, so we don't look at es->timing here. (We could skip
500  * this if !es->summary, but it's hardly worth the complication.)
501  */
502  INSTR_TIME_SET_CURRENT(starttime);
503 
504  /*
505  * Use a snapshot with an updated command ID to ensure this query sees
506  * results of any previously executed queries.
507  */
510 
511  /*
512  * Normally we discard the query's output, but if explaining CREATE TABLE
513  * AS, we'd better use the appropriate tuple receiver.
514  */
515  if (into)
516  dest = CreateIntoRelDestReceiver(into);
517  else
518  dest = None_Receiver;
519 
520  /* Create a QueryDesc for the query */
521  queryDesc = CreateQueryDesc(plannedstmt, queryString,
523  dest, params, queryEnv, instrument_option);
524 
525  /* Select execution options */
526  if (es->analyze)
527  eflags = 0; /* default run-to-completion flags */
528  else
529  eflags = EXEC_FLAG_EXPLAIN_ONLY;
530  if (into)
531  eflags |= GetIntoRelEFlags(into);
532 
533  /* call ExecutorStart to prepare the plan for execution */
534  ExecutorStart(queryDesc, eflags);
535 
536  /* Execute the plan for statistics if asked for */
537  if (es->analyze)
538  {
539  ScanDirection dir;
540 
541  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
542  if (into && into->skipData)
544  else
545  dir = ForwardScanDirection;
546 
547  /* run the plan */
548  ExecutorRun(queryDesc, dir, 0L, true);
549 
550  /* run cleanup too */
551  ExecutorFinish(queryDesc);
552 
553  /* We can't run ExecutorEnd 'till we're done printing the stats... */
554  totaltime += elapsed_time(&starttime);
555  }
556 
557  ExplainOpenGroup("Query", NULL, true, es);
558 
559  /* Create textual dump of plan tree */
560  ExplainPrintPlan(es, queryDesc);
561 
562  if (es->summary && planduration)
563  {
564  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
565 
566  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
567  }
568 
569  /* Print info about runtime of triggers */
570  if (es->analyze)
571  ExplainPrintTriggers(es, queryDesc);
572 
573  /*
574  * Print info about JITing. Tied to es->costs because we don't want to
575  * display this in regression tests, as it'd cause output differences
576  * depending on build options. Might want to separate that out from COSTS
577  * at a later stage.
578  */
579  if (es->costs)
580  ExplainPrintJITSummary(es, queryDesc);
581 
582  /*
583  * Close down the query and free resources. Include time for this in the
584  * total execution time (although it should be pretty minimal).
585  */
586  INSTR_TIME_SET_CURRENT(starttime);
587 
588  ExecutorEnd(queryDesc);
589 
590  FreeQueryDesc(queryDesc);
591 
593 
594  /* We need a CCI just in case query expanded to multiple plans */
595  if (es->analyze)
597 
598  totaltime += elapsed_time(&starttime);
599 
600  /*
601  * We only report execution time if we actually ran the query (that is,
602  * the user specified ANALYZE), and if summary reporting is enabled (the
603  * user can set SUMMARY OFF to not have the timing information included in
604  * the output). By default, ANALYZE sets SUMMARY to true.
605  */
606  if (es->summary && es->analyze)
607  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
608  es);
609 
610  ExplainCloseGroup("Query", NULL, true, es);
611 }
bool summary
Definition: explain.h:46
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:783
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:3814
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:841
void PopActiveSnapshot(void)
Definition: snapmgr.c:814
#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:394
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:737
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:688
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:301
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:771
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:412
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:402
bool timing
Definition: explain.h:45
#define InvalidSnapshot
Definition: snapshot.h:123
void CommandCounterIncrement(void)
Definition: xact.c:1005
CmdType commandType
Definition: plannodes.h:46
#define Assert(condition)
Definition: c.h:738
static double elapsed_time(instr_time *starttime)
Definition: explain.c:985
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
bool buffers
Definition: explain.h:44
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3906
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:783
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3843
#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 401 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().

404 {
405  if (utilityStmt == NULL)
406  return;
407 
408  if (IsA(utilityStmt, CreateTableAsStmt))
409  {
410  /*
411  * We have to rewrite the contained SELECT and then pass it back to
412  * ExplainOneQuery. It's probably not really necessary to copy the
413  * contained parsetree another time, but let's be safe.
414  */
415  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
416  List *rewritten;
417 
418  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
419  Assert(list_length(rewritten) == 1);
420  ExplainOneQuery(linitial_node(Query, rewritten),
421  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
422  queryString, params, queryEnv);
423  }
424  else if (IsA(utilityStmt, DeclareCursorStmt))
425  {
426  /*
427  * Likewise for DECLARE CURSOR.
428  *
429  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
430  * actually run the query. This is different from pre-8.3 behavior
431  * but seems more useful than not running the query. No cursor will
432  * be created, however.
433  */
434  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
435  List *rewritten;
436 
437  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
438  Assert(list_length(rewritten) == 1);
439  ExplainOneQuery(linitial_node(Query, rewritten),
440  dcs->options, NULL, es,
441  queryString, params, queryEnv);
442  }
443  else if (IsA(utilityStmt, ExecuteStmt))
444  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
445  queryString, params, queryEnv);
446  else if (IsA(utilityStmt, NotifyStmt))
447  {
448  if (es->format == EXPLAIN_FORMAT_TEXT)
449  appendStringInfoString(es->str, "NOTIFY\n");
450  else
451  ExplainDummyGroup("Notify", NULL, es);
452  }
453  else
454  {
455  if (es->format == EXPLAIN_FORMAT_TEXT)
457  "Utility statements have no plan structure\n");
458  else
459  ExplainDummyGroup("Utility Statement", NULL, es);
460  }
461 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * QueryRewrite(Query *parsetree)
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
#define linitial_node(type, l)
Definition: pg_list.h:198
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:4053
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:352
IntoClause * into
Definition: parsenodes.h:3261
#define Assert(condition)
Definition: c.h:738
static int list_length(const List *l)
Definition: pg_list.h:169
ExplainFormat format
Definition: explain.h:48
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2712
#define copyObject(obj)
Definition: nodes.h:641
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 3843 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(), and show_modifytable_info().

3845 {
3846  switch (es->format)
3847  {
3848  case EXPLAIN_FORMAT_TEXT:
3849  /* nothing to do */
3850  break;
3851 
3852  case EXPLAIN_FORMAT_XML:
3853  ExplainXMLTag(objtype, X_OPENING, es);
3854  es->indent++;
3855  break;
3856 
3857  case EXPLAIN_FORMAT_JSON:
3859  appendStringInfoSpaces(es->str, 2 * es->indent);
3860  if (labelname)
3861  {
3862  escape_json(es->str, labelname);
3863  appendStringInfoString(es->str, ": ");
3864  }
3865  appendStringInfoChar(es->str, labeled ? '{' : '[');
3866 
3867  /*
3868  * In JSON format, the grouping_stack is an integer list. 0 means
3869  * we've emitted nothing at this grouping level, 1 means we've
3870  * emitted something (and so the next item needs a comma). See
3871  * ExplainJSONLineEnding().
3872  */
3873  es->grouping_stack = lcons_int(0, es->grouping_stack);
3874  es->indent++;
3875  break;
3876 
3877  case EXPLAIN_FORMAT_YAML:
3878 
3879  /*
3880  * In YAML format, the grouping stack is an integer list. 0 means
3881  * we've emitted nothing at this grouping level AND this grouping
3882  * level is unlabelled and must be marked with "- ". See
3883  * ExplainYAMLLineStarting().
3884  */
3886  if (labelname)
3887  {
3888  appendStringInfo(es->str, "%s: ", labelname);
3889  es->grouping_stack = lcons_int(1, es->grouping_stack);
3890  }
3891  else
3892  {
3893  appendStringInfoString(es->str, "- ");
3894  es->grouping_stack = lcons_int(0, es->grouping_stack);
3895  }
3896  es->indent++;
3897  break;
3898  }
3899 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
List * lcons_int(int datum, List *list)
Definition: list.c:472
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4188
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:4250
List * grouping_stack
Definition: explain.h:51
int indent
Definition: explain.h:50
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:4230
#define X_OPENING
Definition: explain.c:51
ExplainFormat format
Definition: explain.h:48
StringInfo str
Definition: explain.h:39

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

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

784 {
785  JitInstrumentation ji = {0};
786 
787  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
788  return;
789 
790  /*
791  * Work with a copy instead of modifying the leader state, since this
792  * function may be called twice
793  */
794  if (queryDesc->estate->es_jit)
795  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
796 
797  /* If this process has done JIT in parallel workers, merge stats */
798  if (queryDesc->estate->es_jit_worker_instr)
799  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
800 
801  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
802 }
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:599
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:600
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:809
JitInstrumentation instr
Definition: jit.h:61
int es_jit_flags
Definition: execnodes.h:598
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 688 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().

689 {
690  Bitmapset *rels_used = NULL;
691  PlanState *ps;
692 
693  /* Set up ExplainState fields associated with this plan tree */
694  Assert(queryDesc->plannedstmt != NULL);
695  es->pstmt = queryDesc->plannedstmt;
696  es->rtable = queryDesc->plannedstmt->rtable;
697  ExplainPreScanNode(queryDesc->planstate, &rels_used);
700  es->rtable_names);
701  es->printed_subplans = NULL;
702 
703  /*
704  * Sometimes we mark a Gather node as "invisible", which means that it's
705  * not to be displayed in EXPLAIN output. The purpose of this is to allow
706  * running regression tests with force_parallel_mode=regress to get the
707  * same results as running the same tests with force_parallel_mode=off.
708  * Such marking is currently only supported on a Gather at the top of the
709  * plan. We skip that node, and we must also hide per-worker detail data
710  * further down in the plan tree.
711  */
712  ps = queryDesc->planstate;
713  if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
714  {
715  ps = outerPlanState(ps);
716  es->hide_workers = true;
717  }
718  ExplainNode(ps, NIL, NULL, NULL, es);
719 
720  /*
721  * If requested, include information about GUC parameters with values that
722  * don't match the built-in defaults.
723  */
725 }
#define NIL
Definition: pg_list.h:65
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:618
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool hide_workers
Definition: explain.h:58
Bitmapset * printed_subplans
Definition: explain.h:57
List * deparse_cxt
Definition: explain.h:56
PlannedStmt * pstmt
Definition: explain.h:53
List * rtable_names
Definition: explain.h:55
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3409
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1078
PlanState * planstate
Definition: execdesc.h:49
#define outerPlanState(node)
Definition: execnodes.h:1037
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3317
Plan * plan
Definition: execnodes.h:943
#define Assert(condition)
Definition: c.h:738
List * rtable
Definition: plannodes.h:66
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1004
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * rtable
Definition: explain.h:54

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

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

738 {
739  ResultRelInfo *rInfo;
740  bool show_relname;
741  int numrels = queryDesc->estate->es_num_result_relations;
742  int numrootrels = queryDesc->estate->es_num_root_result_relations;
743  List *routerels;
744  List *targrels;
745  int nr;
746  ListCell *l;
747 
748  routerels = queryDesc->estate->es_tuple_routing_result_relations;
749  targrels = queryDesc->estate->es_trig_target_relations;
750 
751  ExplainOpenGroup("Triggers", "Triggers", false, es);
752 
753  show_relname = (numrels > 1 || numrootrels > 0 ||
754  routerels != NIL || targrels != NIL);
755  rInfo = queryDesc->estate->es_result_relations;
756  for (nr = 0; nr < numrels; rInfo++, nr++)
757  report_triggers(rInfo, show_relname, es);
758 
759  rInfo = queryDesc->estate->es_root_result_relations;
760  for (nr = 0; nr < numrootrels; rInfo++, nr++)
761  report_triggers(rInfo, show_relname, es);
762 
763  foreach(l, routerels)
764  {
765  rInfo = (ResultRelInfo *) lfirst(l);
766  report_triggers(rInfo, show_relname, es);
767  }
768 
769  foreach(l, targrels)
770  {
771  rInfo = (ResultRelInfo *) lfirst(l);
772  report_triggers(rInfo, show_relname, es);
773  }
774 
775  ExplainCloseGroup("Triggers", "Triggers", false, es);
776 }
#define NIL
Definition: pg_list.h:65
EState * estate
Definition: execdesc.h:48
ResultRelInfo * es_result_relations
Definition: execnodes.h:523
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:914
int es_num_root_result_relations
Definition: execnodes.h:534
List * es_trig_target_relations
Definition: execnodes.h:544
int es_num_result_relations
Definition: execnodes.h:524
List * es_tuple_routing_result_relations
Definition: execnodes.h:541
#define lfirst(lc)
Definition: pg_list.h:190
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:533
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3906
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3843
Definition: pg_list.h:50

◆ ExplainPropertyBool()

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

Definition at line 3828 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode(), and ExplainPrintJIT().

3829 {
3830  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
3831 }
static struct @145 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3738

◆ ExplainPropertyFloat()

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

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

3816 {
3817  char *buf;
3818 
3819  buf = psprintf("%.*f", ndigits, value);
3820  ExplainProperty(qlabel, unit, buf, true, es);
3821  pfree(buf);
3822 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static struct @145 value
void pfree(void *pointer)
Definition: mcxt.c:1056
static char * buf
Definition: pg_test_fsync.c:67
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3738

◆ ExplainPropertyInteger()

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

Definition at line 3800 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_sort_info(), and show_tidbitmap_info().

3802 {
3803  char buf[32];
3804 
3805  snprintf(buf, sizeof(buf), INT64_FORMAT, value);
3806  ExplainProperty(qlabel, unit, buf, true, es);
3807 }
static struct @145 value
static char * buf
Definition: pg_test_fsync.c:67
#define INT64_FORMAT
Definition: c.h:409
#define snprintf
Definition: port.h:192
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3738

◆ ExplainPropertyList()

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

Definition at line 3615 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_modifytable_info(), show_plan_tlist(), show_sort_group_keys(), and show_tablesample().

3616 {
3617  ListCell *lc;
3618  bool first = true;
3619 
3620  switch (es->format)
3621  {
3622  case EXPLAIN_FORMAT_TEXT:
3623  ExplainIndentText(es);
3624  appendStringInfo(es->str, "%s: ", qlabel);
3625  foreach(lc, data)
3626  {
3627  if (!first)
3628  appendStringInfoString(es->str, ", ");
3629  appendStringInfoString(es->str, (const char *) lfirst(lc));
3630  first = false;
3631  }
3632  appendStringInfoChar(es->str, '\n');
3633  break;
3634 
3635  case EXPLAIN_FORMAT_XML:
3636  ExplainXMLTag(qlabel, X_OPENING, es);
3637  foreach(lc, data)
3638  {
3639  char *str;
3640 
3641  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3642  appendStringInfoString(es->str, "<Item>");
3643  str = escape_xml((const char *) lfirst(lc));
3644  appendStringInfoString(es->str, str);
3645  pfree(str);
3646  appendStringInfoString(es->str, "</Item>\n");
3647  }
3648  ExplainXMLTag(qlabel, X_CLOSING, es);
3649  break;
3650 
3651  case EXPLAIN_FORMAT_JSON:
3653  appendStringInfoSpaces(es->str, es->indent * 2);
3654  escape_json(es->str, qlabel);
3655  appendStringInfoString(es->str, ": [");
3656  foreach(lc, data)
3657  {
3658  if (!first)
3659  appendStringInfoString(es->str, ", ");
3660  escape_json(es->str, (const char *) lfirst(lc));
3661  first = false;
3662  }
3663  appendStringInfoChar(es->str, ']');
3664  break;
3665 
3666  case EXPLAIN_FORMAT_YAML:
3668  appendStringInfo(es->str, "%s: ", qlabel);
3669  foreach(lc, data)
3670  {
3671  appendStringInfoChar(es->str, '\n');
3672  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3673  appendStringInfoString(es->str, "- ");
3674  escape_yaml(es->str, (const char *) lfirst(lc));
3675  }
3676  break;
3677  }
3678 }
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:4188
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:1056
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:4250
int indent
Definition: explain.h:50
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:4275
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4230
#define X_OPENING
Definition: explain.c:51
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:4215
#define lfirst(lc)
Definition: pg_list.h:190
ExplainFormat format
Definition: explain.h:48
char * escape_xml(const char *str)
Definition: xml.c:2371
StringInfo str
Definition: explain.h:39

◆ ExplainPropertyListNested()

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

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

3686 {
3687  ListCell *lc;
3688  bool first = true;
3689 
3690  switch (es->format)
3691  {
3692  case EXPLAIN_FORMAT_TEXT:
3693  case EXPLAIN_FORMAT_XML:
3694  ExplainPropertyList(qlabel, data, es);
3695  return;
3696 
3697  case EXPLAIN_FORMAT_JSON:
3699  appendStringInfoSpaces(es->str, es->indent * 2);
3700  appendStringInfoChar(es->str, '[');
3701  foreach(lc, data)
3702  {
3703  if (!first)
3704  appendStringInfoString(es->str, ", ");
3705  escape_json(es->str, (const char *) lfirst(lc));
3706  first = false;
3707  }
3708  appendStringInfoChar(es->str, ']');
3709  break;
3710 
3711  case EXPLAIN_FORMAT_YAML:
3713  appendStringInfoString(es->str, "- [");
3714  foreach(lc, data)
3715  {
3716  if (!first)
3717  appendStringInfoString(es->str, ", ");
3718  escape_yaml(es->str, (const char *) lfirst(lc));
3719  first = false;
3720  }
3721  appendStringInfoChar(es->str, ']');
3722  break;
3723  }
3724 }
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:4250
int indent
Definition: explain.h:50
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:4275
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4230
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:3615
#define lfirst(lc)
Definition: pg_list.h:190
ExplainFormat format
Definition: explain.h:48
StringInfo str
Definition: explain.h:39

◆ ExplainPropertyText()

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

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

3792 {
3793  ExplainProperty(qlabel, NULL, value, false, es);
3794 }
static struct @145 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3738

◆ ExplainQuery()

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

Definition at line 154 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, and ExplainState::verbose.

Referenced by standard_ProcessUtility().

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

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 903 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

904 {
905  if (queryDesc->sourceText)
906  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
907 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:3791
const char * sourceText
Definition: execdesc.h:38

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 313 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

314 {
315  TupleDesc tupdesc;
316  ListCell *lc;
317  Oid result_type = TEXTOID;
318 
319  /* Check for XML format option */
320  foreach(lc, stmt->options)
321  {
322  DefElem *opt = (DefElem *) lfirst(lc);
323 
324  if (strcmp(opt->defname, "format") == 0)
325  {
326  char *p = defGetString(opt);
327 
328  if (strcmp(p, "xml") == 0)
329  result_type = XMLOID;
330  else if (strcmp(p, "json") == 0)
331  result_type = JSONOID;
332  else
333  result_type = TEXTOID;
334  /* don't "break", as ExplainQuery will use the last value */
335  }
336  }
337 
338  /* Need a tuple descriptor representing a single TEXT or XML column */
339  tupdesc = CreateTemplateTupleDesc(1);
340  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
341  result_type, -1, 0);
342  return tupdesc;
343 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
List * options
Definition: parsenodes.h:3241
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:190
char * defname
Definition: parsenodes.h:730
int16 AttrNumber
Definition: attnum.h:21

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

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

4160 {
4161  switch (es->format)
4162  {
4163  case EXPLAIN_FORMAT_TEXT:
4164  /* add a blank line */
4165  appendStringInfoChar(es->str, '\n');
4166  break;
4167 
4168  case EXPLAIN_FORMAT_XML:
4169  case EXPLAIN_FORMAT_JSON:
4170  case EXPLAIN_FORMAT_YAML:
4171  /* nothing to do */
4172  break;
4173  }
4174 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
ExplainFormat format
Definition: explain.h:48
StringInfo str
Definition: explain.h:39

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 296 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

297 {
298  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
299 
300  /* Set default options (most fields can be left as zeroes). */
301  es->costs = true;
302  /* Prepare output buffer. */
303  es->str = makeStringInfo();
304 
305  return es;
306 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
bool costs
Definition: explain.h:43
void * palloc0(Size size)
Definition: mcxt.c:980
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().