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, const MemoryContextCounters *mem_counters)
 
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 ExplainQueryParameters (ExplainState *es, ParamListInfo params, int maxlen)
 
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 77 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 67 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.

21 {
ExplainFormat
Definition: explain.h:21
@ EXPLAIN_FORMAT_XML
Definition: explain.h:23
@ EXPLAIN_FORMAT_YAML
Definition: explain.h:25
@ EXPLAIN_FORMAT_TEXT
Definition: explain.h:22
@ EXPLAIN_FORMAT_JSON
Definition: explain.h:24

Function Documentation

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 5005 of file explain.c.

5006 {
5007  switch (es->format)
5008  {
5009  case EXPLAIN_FORMAT_TEXT:
5010  /* nothing to do */
5011  break;
5012 
5013  case EXPLAIN_FORMAT_XML:
5015  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5016  es->indent++;
5017  break;
5018 
5019  case EXPLAIN_FORMAT_JSON:
5020  /* top-level structure is an array of plans */
5021  appendStringInfoChar(es->str, '[');
5022  es->grouping_stack = lcons_int(0, es->grouping_stack);
5023  es->indent++;
5024  break;
5025 
5026  case EXPLAIN_FORMAT_YAML:
5027  es->grouping_stack = lcons_int(0, es->grouping_stack);
5028  break;
5029  }
5030 }
List * lcons_int(int datum, List *list)
Definition: list.c:513
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
List * grouping_stack
Definition: explain.h:54
StringInfo str
Definition: explain.h:39
ExplainFormat format
Definition: explain.h:51
int indent
Definition: explain.h:53

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

◆ ExplainCloseGroup()

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

Definition at line 4812 of file explain.c.

4814 {
4815  switch (es->format)
4816  {
4817  case EXPLAIN_FORMAT_TEXT:
4818  /* nothing to do */
4819  break;
4820 
4821  case EXPLAIN_FORMAT_XML:
4822  es->indent--;
4823  ExplainXMLTag(objtype, X_CLOSING, es);
4824  break;
4825 
4826  case EXPLAIN_FORMAT_JSON:
4827  es->indent--;
4828  appendStringInfoChar(es->str, '\n');
4829  appendStringInfoSpaces(es->str, 2 * es->indent);
4830  appendStringInfoChar(es->str, labeled ? '}' : ']');
4832  break;
4833 
4834  case EXPLAIN_FORMAT_YAML:
4835  es->indent--;
4837  break;
4838  }
4839 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5094
#define X_CLOSING
Definition: explain.c:53
List * list_delete_first(List *list)
Definition: list.c:943
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:212

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

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 5036 of file explain.c.

5037 {
5038  switch (es->format)
5039  {
5040  case EXPLAIN_FORMAT_TEXT:
5041  /* nothing to do */
5042  break;
5043 
5044  case EXPLAIN_FORMAT_XML:
5045  es->indent--;
5046  appendStringInfoString(es->str, "</explain>");
5047  break;
5048 
5049  case EXPLAIN_FORMAT_JSON:
5050  es->indent--;
5051  appendStringInfoString(es->str, "\n]");
5053  break;
5054 
5055  case EXPLAIN_FORMAT_YAML:
5057  break;
5058  }
5059 }

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

◆ ExplainOnePlan()

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

Definition at line 557 of file explain.c.

562 {
564  QueryDesc *queryDesc;
565  instr_time starttime;
566  double totaltime = 0;
567  int eflags;
568  int instrument_option = 0;
569 
570  Assert(plannedstmt->commandType != CMD_UTILITY);
571 
572  if (es->analyze && es->timing)
573  instrument_option |= INSTRUMENT_TIMER;
574  else if (es->analyze)
575  instrument_option |= INSTRUMENT_ROWS;
576 
577  if (es->buffers)
578  instrument_option |= INSTRUMENT_BUFFERS;
579  if (es->wal)
580  instrument_option |= INSTRUMENT_WAL;
581 
582  /*
583  * We always collect timing for the entire statement, even when node-level
584  * timing is off, so we don't look at es->timing here. (We could skip
585  * this if !es->summary, but it's hardly worth the complication.)
586  */
587  INSTR_TIME_SET_CURRENT(starttime);
588 
589  /*
590  * Use a snapshot with an updated command ID to ensure this query sees
591  * results of any previously executed queries.
592  */
595 
596  /*
597  * Normally we discard the query's output, but if explaining CREATE TABLE
598  * AS, we'd better use the appropriate tuple receiver.
599  */
600  if (into)
602  else
604 
605  /* Create a QueryDesc for the query */
606  queryDesc = CreateQueryDesc(plannedstmt, queryString,
608  dest, params, queryEnv, instrument_option);
609 
610  /* Select execution options */
611  if (es->analyze)
612  eflags = 0; /* default run-to-completion flags */
613  else
614  eflags = EXEC_FLAG_EXPLAIN_ONLY;
615  if (es->generic)
616  eflags |= EXEC_FLAG_EXPLAIN_GENERIC;
617  if (into)
618  eflags |= GetIntoRelEFlags(into);
619 
620  /* call ExecutorStart to prepare the plan for execution */
621  ExecutorStart(queryDesc, eflags);
622 
623  /* Execute the plan for statistics if asked for */
624  if (es->analyze)
625  {
626  ScanDirection dir;
627 
628  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
629  if (into && into->skipData)
631  else
632  dir = ForwardScanDirection;
633 
634  /* run the plan */
635  ExecutorRun(queryDesc, dir, 0, true);
636 
637  /* run cleanup too */
638  ExecutorFinish(queryDesc);
639 
640  /* We can't run ExecutorEnd 'till we're done printing the stats... */
641  totaltime += elapsed_time(&starttime);
642  }
643 
644  ExplainOpenGroup("Query", NULL, true, es);
645 
646  /* Create textual dump of plan tree */
647  ExplainPrintPlan(es, queryDesc);
648 
649  /* Show buffer and/or memory usage in planning */
650  if (peek_buffer_usage(es, bufusage) || mem_counters)
651  {
652  ExplainOpenGroup("Planning", "Planning", true, es);
653 
654  if (es->format == EXPLAIN_FORMAT_TEXT)
655  {
656  ExplainIndentText(es);
657  appendStringInfoString(es->str, "Planning:\n");
658  es->indent++;
659  }
660 
661  if (bufusage)
662  show_buffer_usage(es, bufusage);
663 
664  if (mem_counters)
665  show_memory_counters(es, mem_counters);
666 
667  if (es->format == EXPLAIN_FORMAT_TEXT)
668  es->indent--;
669 
670  ExplainCloseGroup("Planning", "Planning", true, es);
671  }
672 
673  if (es->summary && planduration)
674  {
675  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
676 
677  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
678  }
679 
680  /* Print info about runtime of triggers */
681  if (es->analyze)
682  ExplainPrintTriggers(es, queryDesc);
683 
684  /*
685  * Print info about JITing. Tied to es->costs because we don't want to
686  * display this in regression tests, as it'd cause output differences
687  * depending on build options. Might want to separate that out from COSTS
688  * at a later stage.
689  */
690  if (es->costs)
691  ExplainPrintJITSummary(es, queryDesc);
692 
693  /*
694  * Close down the query and free resources. Include time for this in the
695  * total execution time (although it should be pretty minimal).
696  */
697  INSTR_TIME_SET_CURRENT(starttime);
698 
699  ExecutorEnd(queryDesc);
700 
701  FreeQueryDesc(queryDesc);
702 
704 
705  /* We need a CCI just in case query expanded to multiple plans */
706  if (es->analyze)
708 
709  totaltime += elapsed_time(&starttime);
710 
711  /*
712  * We only report execution time if we actually ran the query (that is,
713  * the user specified ANALYZE), and if summary reporting is enabled (the
714  * user can set SUMMARY OFF to not have the timing information included in
715  * the output). By default, ANALYZE sets SUMMARY to true.
716  */
717  if (es->summary && es->analyze)
718  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
719  es);
720 
721  ExplainCloseGroup("Query", NULL, true, es);
722 }
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:440
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:375
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:469
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:409
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:132
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:302
#define EXEC_FLAG_EXPLAIN_GENERIC
Definition: executor.h:66
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4749
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:3600
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:907
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:4720
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4812
static double elapsed_time(instr_time *starttime)
Definition: explain.c:1139
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:5121
static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)
Definition: explain.c:3847
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:799
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:864
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:3640
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:188
@ INSTRUMENT_TIMER
Definition: instrument.h:61
@ INSTRUMENT_BUFFERS
Definition: instrument.h:62
@ INSTRUMENT_WAL
Definition: instrument.h:64
@ INSTRUMENT_ROWS
Definition: instrument.h:63
Assert(fmt[strlen(fmt) - 1] !='\n')
@ CMD_UTILITY
Definition: nodes.h:260
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
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:25
@ NoMovementScanDirection
Definition: sdir.h:27
@ ForwardScanDirection
Definition: sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:719
void PopActiveSnapshot(void)
Definition: snapmgr.c:750
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:707
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:777
#define InvalidSnapshot
Definition: snapshot.h:123
bool timing
Definition: explain.h:46
bool analyze
Definition: explain.h:42
bool wal
Definition: explain.h:45
bool generic
Definition: explain.h:50
bool summary
Definition: explain.h:47
bool costs
Definition: explain.h:43
bool buffers
Definition: explain.h:44
bool skipData
Definition: primnodes.h:156
CmdType commandType
Definition: plannodes.h:52
void CommandCounterIncrement(void)
Definition: xact.c:1078

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

◆ ExplainOneUtility()

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

Definition at line 467 of file explain.c.

470 {
471  if (utilityStmt == NULL)
472  return;
473 
474  if (IsA(utilityStmt, CreateTableAsStmt))
475  {
476  /*
477  * We have to rewrite the contained SELECT and then pass it back to
478  * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case.
479  */
480  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
481  List *rewritten;
482 
483  /*
484  * Check if the relation exists or not. This is done at this stage to
485  * avoid query planning or execution.
486  */
487  if (CreateTableAsRelExists(ctas))
488  {
489  if (ctas->objtype == OBJECT_TABLE)
490  ExplainDummyGroup("CREATE TABLE AS", NULL, es);
491  else if (ctas->objtype == OBJECT_MATVIEW)
492  ExplainDummyGroup("CREATE MATERIALIZED VIEW", NULL, es);
493  else
494  elog(ERROR, "unexpected object type: %d",
495  (int) ctas->objtype);
496  return;
497  }
498 
499  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
500  Assert(list_length(rewritten) == 1);
501  ExplainOneQuery(linitial_node(Query, rewritten),
502  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
503  queryString, params, queryEnv);
504  }
505  else if (IsA(utilityStmt, DeclareCursorStmt))
506  {
507  /*
508  * Likewise for DECLARE CURSOR.
509  *
510  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
511  * actually run the query. This is different from pre-8.3 behavior
512  * but seems more useful than not running the query. No cursor will
513  * be created, however.
514  */
515  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
516  List *rewritten;
517 
518  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
519  Assert(list_length(rewritten) == 1);
520  ExplainOneQuery(linitial_node(Query, rewritten),
521  dcs->options, NULL, es,
522  queryString, params, queryEnv);
523  }
524  else if (IsA(utilityStmt, ExecuteStmt))
525  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
526  queryString, params, queryEnv);
527  else if (IsA(utilityStmt, NotifyStmt))
528  {
529  if (es->format == EXPLAIN_FORMAT_TEXT)
530  appendStringInfoString(es->str, "NOTIFY\n");
531  else
532  ExplainDummyGroup("Notify", NULL, es);
533  }
534  else
535  {
536  if (es->format == EXPLAIN_FORMAT_TEXT)
538  "Utility statements have no plan structure\n");
539  else
540  ExplainDummyGroup("Utility Statement", NULL, es);
541  }
542 }
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:571
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:393
#define ERROR
Definition: elog.h:39
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:4959
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:380
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:223
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
@ OBJECT_MATVIEW
Definition: parsenodes.h:2119
@ OBJECT_TABLE
Definition: parsenodes.h:2137
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3143
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
List * QueryRewrite(Query *parsetree)
IntoClause * into
Definition: parsenodes.h:3745
ObjectType objtype
Definition: parsenodes.h:3746
Definition: pg_list.h:54

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

◆ ExplainOpenGroup()

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

Definition at line 4749 of file explain.c.

4751 {
4752  switch (es->format)
4753  {
4754  case EXPLAIN_FORMAT_TEXT:
4755  /* nothing to do */
4756  break;
4757 
4758  case EXPLAIN_FORMAT_XML:
4759  ExplainXMLTag(objtype, X_OPENING, es);
4760  es->indent++;
4761  break;
4762 
4763  case EXPLAIN_FORMAT_JSON:
4765  appendStringInfoSpaces(es->str, 2 * es->indent);
4766  if (labelname)
4767  {
4768  escape_json(es->str, labelname);
4769  appendStringInfoString(es->str, ": ");
4770  }
4771  appendStringInfoChar(es->str, labeled ? '{' : '[');
4772 
4773  /*
4774  * In JSON format, the grouping_stack is an integer list. 0 means
4775  * we've emitted nothing at this grouping level, 1 means we've
4776  * emitted something (and so the next item needs a comma). See
4777  * ExplainJSONLineEnding().
4778  */
4779  es->grouping_stack = lcons_int(0, es->grouping_stack);
4780  es->indent++;
4781  break;
4782 
4783  case EXPLAIN_FORMAT_YAML:
4784 
4785  /*
4786  * In YAML format, the grouping stack is an integer list. 0 means
4787  * we've emitted nothing at this grouping level AND this grouping
4788  * level is unlabeled and must be marked with "- ". See
4789  * ExplainYAMLLineStarting().
4790  */
4792  if (labelname)
4793  {
4794  appendStringInfo(es->str, "%s: ", labelname);
4795  es->grouping_stack = lcons_int(1, es->grouping_stack);
4796  }
4797  else
4798  {
4799  appendStringInfoString(es->str, "- ");
4800  es->grouping_stack = lcons_int(0, es->grouping_stack);
4801  }
4802  es->indent++;
4803  break;
4804  }
4805 }
#define X_OPENING
Definition: explain.c:52
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:5156
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:5136
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97

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

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 907 of file explain.c.

908 {
909  JitInstrumentation ji = {0};
910 
911  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
912  return;
913 
914  /*
915  * Work with a copy instead of modifying the leader state, since this
916  * function may be called twice
917  */
918  if (queryDesc->estate->es_jit)
919  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
920 
921  /* If this process has done JIT in parallel workers, merge stats */
922  if (queryDesc->estate->es_jit_worker_instr)
923  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
924 
925  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
926 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:933
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:181
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:714
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:715
int es_jit_flags
Definition: execnodes.h:713
JitInstrumentation instr
Definition: jit.h:64
EState * estate
Definition: execdesc.h:48

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

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 799 of file explain.c.

800 {
801  Bitmapset *rels_used = NULL;
802  PlanState *ps;
803 
804  /* Set up ExplainState fields associated with this plan tree */
805  Assert(queryDesc->plannedstmt != NULL);
806  es->pstmt = queryDesc->plannedstmt;
807  es->rtable = queryDesc->plannedstmt->rtable;
808  ExplainPreScanNode(queryDesc->planstate, &rels_used);
811  es->rtable_names);
812  es->printed_subplans = NULL;
813 
814  /*
815  * Sometimes we mark a Gather node as "invisible", which means that it's
816  * not to be displayed in EXPLAIN output. The purpose of this is to allow
817  * running regression tests with debug_parallel_query=regress to get the
818  * same results as running the same tests with debug_parallel_query=off.
819  * Such marking is currently only supported on a Gather at the top of the
820  * plan. We skip that node, and we must also hide per-worker detail data
821  * further down in the plan tree.
822  */
823  ps = queryDesc->planstate;
824  if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
825  {
826  ps = outerPlanState(ps);
827  es->hide_workers = true;
828  }
829  ExplainNode(ps, NIL, NULL, NULL, es);
830 
831  /*
832  * If requested, include information about GUC parameters with values that
833  * don't match the built-in defaults.
834  */
836 
837  /*
838  * COMPUTE_QUERY_ID_REGRESS means COMPUTE_QUERY_ID_AUTO, but we don't show
839  * the queryid in any of the EXPLAIN plans to keep stable the results
840  * generated by regression test suites.
841  */
842  if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) &&
844  {
845  /*
846  * Output the queryid as an int64 rather than a uint64 so we match
847  * what would be seen in the BIGINT pg_stat_statements.queryid column.
848  */
849  ExplainPropertyInteger("Query Identifier", NULL, (int64)
850  queryDesc->plannedstmt->queryId, es);
851  }
852 }
#define outerPlanState(node)
Definition: execnodes.h:1139
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1233
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1158
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:4693
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:729
struct parser_state ps
#define NIL
Definition: pg_list.h:68
@ COMPUTE_QUERY_ID_REGRESS
Definition: queryjumble.h:59
int compute_query_id
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3797
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3705
bool verbose
Definition: explain.h:41
Bitmapset * printed_subplans
Definition: explain.h:60
bool hide_workers
Definition: explain.h:61
List * rtable_names
Definition: explain.h:58
List * rtable
Definition: explain.h:57
PlannedStmt * pstmt
Definition: explain.h:56
List * deparse_cxt
Definition: explain.h:59
List * rtable
Definition: plannodes.h:72
uint64 queryId
Definition: plannodes.h:54
PlannedStmt * plannedstmt
Definition: execdesc.h:37
PlanState * planstate
Definition: execdesc.h:49

References Assert(), compute_query_id, COMPUTE_QUERY_ID_REGRESS, deparse_context_for_plan_tree(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), ExplainPropertyInteger(), ExplainState::hide_workers, IsA, NIL, outerPlanState, QueryDesc::plannedstmt, QueryDesc::planstate, ExplainState::printed_subplans, ps, ExplainState::pstmt, PlannedStmt::queryId, ExplainState::rtable, PlannedStmt::rtable, ExplainState::rtable_names, select_rtable_names_for_explain(), and ExplainState::verbose.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 864 of file explain.c.

865 {
866  ResultRelInfo *rInfo;
867  bool show_relname;
868  List *resultrels;
869  List *routerels;
870  List *targrels;
871  ListCell *l;
872 
873  resultrels = queryDesc->estate->es_opened_result_relations;
874  routerels = queryDesc->estate->es_tuple_routing_result_relations;
875  targrels = queryDesc->estate->es_trig_target_relations;
876 
877  ExplainOpenGroup("Triggers", "Triggers", false, es);
878 
879  show_relname = (list_length(resultrels) > 1 ||
880  routerels != NIL || targrels != NIL);
881  foreach(l, resultrels)
882  {
883  rInfo = (ResultRelInfo *) lfirst(l);
884  report_triggers(rInfo, show_relname, es);
885  }
886 
887  foreach(l, routerels)
888  {
889  rInfo = (ResultRelInfo *) lfirst(l);
890  report_triggers(rInfo, show_relname, es);
891  }
892 
893  foreach(l, targrels)
894  {
895  rInfo = (ResultRelInfo *) lfirst(l);
896  report_triggers(rInfo, show_relname, es);
897  }
898 
899  ExplainCloseGroup("Triggers", "Triggers", false, es);
900 }
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:1068
#define lfirst(lc)
Definition: pg_list.h:172
List * es_tuple_routing_result_relations
Definition: execnodes.h:653
List * es_trig_target_relations
Definition: execnodes.h:656
List * es_opened_result_relations
Definition: execnodes.h:643

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

◆ ExplainPropertyBool()

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

Definition at line 4734 of file explain.c.

4735 {
4736  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4737 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4631
static struct @148 value

References ExplainProperty(), and value.

Referenced by ExplainNode(), and ExplainPrintJIT().

◆ ExplainPropertyFloat()

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

Definition at line 4720 of file explain.c.

4722 {
4723  char *buf;
4724 
4725  buf = psprintf("%.*f", ndigits, value);
4726  ExplainProperty(qlabel, unit, buf, true, es);
4727  pfree(buf);
4728 }
void pfree(void *pointer)
Definition: mcxt.c:1431
static char * buf
Definition: pg_test_fsync.c:73
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

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

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

◆ ExplainPropertyInteger()

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

◆ ExplainPropertyList()

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

Definition at line 4508 of file explain.c.

4509 {
4510  ListCell *lc;
4511  bool first = true;
4512 
4513  switch (es->format)
4514  {
4515  case EXPLAIN_FORMAT_TEXT:
4516  ExplainIndentText(es);
4517  appendStringInfo(es->str, "%s: ", qlabel);
4518  foreach(lc, data)
4519  {
4520  if (!first)
4521  appendStringInfoString(es->str, ", ");
4522  appendStringInfoString(es->str, (const char *) lfirst(lc));
4523  first = false;
4524  }
4525  appendStringInfoChar(es->str, '\n');
4526  break;
4527 
4528  case EXPLAIN_FORMAT_XML:
4529  ExplainXMLTag(qlabel, X_OPENING, es);
4530  foreach(lc, data)
4531  {
4532  char *str;
4533 
4534  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4535  appendStringInfoString(es->str, "<Item>");
4536  str = escape_xml((const char *) lfirst(lc));
4538  pfree(str);
4539  appendStringInfoString(es->str, "</Item>\n");
4540  }
4541  ExplainXMLTag(qlabel, X_CLOSING, es);
4542  break;
4543 
4544  case EXPLAIN_FORMAT_JSON:
4546  appendStringInfoSpaces(es->str, es->indent * 2);
4547  escape_json(es->str, qlabel);
4548  appendStringInfoString(es->str, ": [");
4549  foreach(lc, data)
4550  {
4551  if (!first)
4552  appendStringInfoString(es->str, ", ");
4553  escape_json(es->str, (const char *) lfirst(lc));
4554  first = false;
4555  }
4556  appendStringInfoChar(es->str, ']');
4557  break;
4558 
4559  case EXPLAIN_FORMAT_YAML:
4561  appendStringInfo(es->str, "%s: ", qlabel);
4562  foreach(lc, data)
4563  {
4564  appendStringInfoChar(es->str, '\n');
4565  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4566  appendStringInfoString(es->str, "- ");
4567  escape_yaml(es->str, (const char *) lfirst(lc));
4568  }
4569  break;
4570  }
4571 }
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:5181
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2635

References appendStringInfo(), appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), data, 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(), generate_unaccent_rules::str, ExplainState::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().

◆ ExplainPropertyListNested()

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

Definition at line 4578 of file explain.c.

4579 {
4580  ListCell *lc;
4581  bool first = true;
4582 
4583  switch (es->format)
4584  {
4585  case EXPLAIN_FORMAT_TEXT:
4586  case EXPLAIN_FORMAT_XML:
4587  ExplainPropertyList(qlabel, data, es);
4588  return;
4589 
4590  case EXPLAIN_FORMAT_JSON:
4592  appendStringInfoSpaces(es->str, es->indent * 2);
4593  appendStringInfoChar(es->str, '[');
4594  foreach(lc, data)
4595  {
4596  if (!first)
4597  appendStringInfoString(es->str, ", ");
4598  escape_json(es->str, (const char *) lfirst(lc));
4599  first = false;
4600  }
4601  appendStringInfoChar(es->str, ']');
4602  break;
4603 
4604  case EXPLAIN_FORMAT_YAML:
4606  appendStringInfoString(es->str, "- [");
4607  foreach(lc, data)
4608  {
4609  if (!first)
4610  appendStringInfoString(es->str, ", ");
4611  escape_yaml(es->str, (const char *) lfirst(lc));
4612  first = false;
4613  }
4614  appendStringInfoChar(es->str, ']');
4615  break;
4616  }
4617 }
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4508

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), data, 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().

◆ ExplainPropertyText()

◆ ExplainPropertyUInteger()

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

Definition at line 4706 of file explain.c.

4708 {
4709  char buf[32];
4710 
4711  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4712  ExplainProperty(qlabel, unit, buf, true, es);
4713 }
#define UINT64_FORMAT
Definition: c.h:538

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

Referenced by show_wal_usage().

◆ ExplainQuery()

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

Definition at line 166 of file explain.c.

168 {
170  TupOutputState *tstate;
171  JumbleState *jstate = NULL;
172  Query *query;
173  List *rewritten;
174  ListCell *lc;
175  bool timing_set = false;
176  bool summary_set = false;
177 
178  /* Parse options list. */
179  foreach(lc, stmt->options)
180  {
181  DefElem *opt = (DefElem *) lfirst(lc);
182 
183  if (strcmp(opt->defname, "analyze") == 0)
184  es->analyze = defGetBoolean(opt);
185  else if (strcmp(opt->defname, "verbose") == 0)
186  es->verbose = defGetBoolean(opt);
187  else if (strcmp(opt->defname, "costs") == 0)
188  es->costs = defGetBoolean(opt);
189  else if (strcmp(opt->defname, "buffers") == 0)
190  es->buffers = defGetBoolean(opt);
191  else if (strcmp(opt->defname, "wal") == 0)
192  es->wal = defGetBoolean(opt);
193  else if (strcmp(opt->defname, "settings") == 0)
194  es->settings = defGetBoolean(opt);
195  else if (strcmp(opt->defname, "generic_plan") == 0)
196  es->generic = defGetBoolean(opt);
197  else if (strcmp(opt->defname, "timing") == 0)
198  {
199  timing_set = true;
200  es->timing = defGetBoolean(opt);
201  }
202  else if (strcmp(opt->defname, "summary") == 0)
203  {
204  summary_set = true;
205  es->summary = defGetBoolean(opt);
206  }
207  else if (strcmp(opt->defname, "memory") == 0)
208  es->memory = defGetBoolean(opt);
209  else if (strcmp(opt->defname, "format") == 0)
210  {
211  char *p = defGetString(opt);
212 
213  if (strcmp(p, "text") == 0)
215  else if (strcmp(p, "xml") == 0)
217  else if (strcmp(p, "json") == 0)
219  else if (strcmp(p, "yaml") == 0)
221  else
222  ereport(ERROR,
223  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
224  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
225  opt->defname, p),
226  parser_errposition(pstate, opt->location)));
227  }
228  else
229  ereport(ERROR,
230  (errcode(ERRCODE_SYNTAX_ERROR),
231  errmsg("unrecognized EXPLAIN option \"%s\"",
232  opt->defname),
233  parser_errposition(pstate, opt->location)));
234  }
235 
236  /* check that WAL is used with EXPLAIN ANALYZE */
237  if (es->wal && !es->analyze)
238  ereport(ERROR,
239  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
240  errmsg("EXPLAIN option WAL requires ANALYZE")));
241 
242  /* if the timing was not set explicitly, set default value */
243  es->timing = (timing_set) ? es->timing : es->analyze;
244 
245  /* check that timing is used with EXPLAIN ANALYZE */
246  if (es->timing && !es->analyze)
247  ereport(ERROR,
248  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
249  errmsg("EXPLAIN option TIMING requires ANALYZE")));
250 
251  /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */
252  if (es->generic && es->analyze)
253  ereport(ERROR,
254  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
255  errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together")));
256 
257  /* if the summary was not set explicitly, set default value */
258  es->summary = (summary_set) ? es->summary : es->analyze;
259 
260  query = castNode(Query, stmt->query);
261  if (IsQueryIdEnabled())
262  jstate = JumbleQuery(query);
263 
265  (*post_parse_analyze_hook) (pstate, query, jstate);
266 
267  /*
268  * Parse analysis was done already, but we still have to run the rule
269  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
270  * came straight from the parser, or suitable locks were acquired by
271  * plancache.c.
272  */
273  rewritten = QueryRewrite(castNode(Query, stmt->query));
274 
275  /* emit opening boilerplate */
276  ExplainBeginOutput(es);
277 
278  if (rewritten == NIL)
279  {
280  /*
281  * In the case of an INSTEAD NOTHING, tell at least that. But in
282  * non-text format, the output is delimited, so this isn't necessary.
283  */
284  if (es->format == EXPLAIN_FORMAT_TEXT)
285  appendStringInfoString(es->str, "Query rewrites to nothing\n");
286  }
287  else
288  {
289  ListCell *l;
290 
291  /* Explain every plan */
292  foreach(l, rewritten)
293  {
295  CURSOR_OPT_PARALLEL_OK, NULL, es,
296  pstate->p_sourcetext, params, pstate->p_queryEnv);
297 
298  /* Separate plans with an appropriate separator */
299  if (lnext(rewritten, l) != NULL)
301  }
302  }
303 
304  /* emit closing boilerplate */
305  ExplainEndOutput(es);
306  Assert(es->indent == 0);
307 
308  /* output tuples */
310  &TTSOpsVirtual);
311  if (es->format == EXPLAIN_FORMAT_TEXT)
312  do_text_output_multiline(tstate, es->str->data);
313  else
314  do_text_output_oneline(tstate, es->str->data);
315  end_tup_output(tstate);
316 
317  pfree(es->str->data);
318 }
bool defGetBoolean(DefElem *def)
Definition: define.c:108
char * defGetString(DefElem *def)
Definition: define.c:49
int errcode(int sqlerrcode)
Definition: elog.c:860
int errmsg(const char *fmt,...)
Definition: elog.c:1075
#define ereport(elevel,...)
Definition: elog.h:149
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2332
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2302
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2254
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:521
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:5065
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:5036
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:341
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:5005
ExplainState * NewExplainState(void)
Definition: explain.c:324
#define stmt
Definition: indent_codes.h:59
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:60
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
JumbleState * JumbleQuery(Query *query)
char * defname
Definition: parsenodes.h:802
int location
Definition: parsenodes.h:806
bool settings
Definition: explain.h:49
bool memory
Definition: explain.h:48

References ExplainState::analyze, appendStringInfoString(), Assert(), begin_tup_output_tupdesc(), ExplainState::buffers, castNode, ExplainState::costs, CURSOR_OPT_PARALLEL_OK, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, generate_unaccent_rules::dest, 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::generic, if(), ExplainState::indent, IsQueryIdEnabled(), JumbleQuery(), lfirst, lfirst_node, lnext(), DefElem::location, ExplainState::memory, NewExplainState(), NIL, ParseState::p_queryEnv, ParseState::p_sourcetext, parser_errposition(), pfree(), post_parse_analyze_hook, QueryRewrite(), ExplainState::settings, stmt, ExplainState::str, ExplainState::summary, ExplainState::timing, TTSOpsVirtual, ExplainState::verbose, and ExplainState::wal.

Referenced by standard_ProcessUtility().

◆ ExplainQueryParameters()

void ExplainQueryParameters ( ExplainState es,
ParamListInfo  params,
int  maxlen 
)

Definition at line 1050 of file explain.c.

1051 {
1052  char *str;
1053 
1054  /* This check is consistent with errdetail_params() */
1055  if (params == NULL || params->numParams <= 0 || maxlen == 0)
1056  return;
1057 
1058  str = BuildParamLogString(params, NULL, maxlen);
1059  if (str && str[0] != '\0')
1060  ExplainPropertyText("Query Parameters", str, es);
1061 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:4684
char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)
Definition: params.c:335

References BuildParamLogString(), ExplainPropertyText(), ParamListInfoData::numParams, and generate_unaccent_rules::str.

Referenced by explain_ExecutorEnd().

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 1035 of file explain.c.

1036 {
1037  if (queryDesc->sourceText)
1038  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1039 }
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 341 of file explain.c.

342 {
343  TupleDesc tupdesc;
344  ListCell *lc;
345  Oid result_type = TEXTOID;
346 
347  /* Check for XML format option */
348  foreach(lc, stmt->options)
349  {
350  DefElem *opt = (DefElem *) lfirst(lc);
351 
352  if (strcmp(opt->defname, "format") == 0)
353  {
354  char *p = defGetString(opt);
355 
356  if (strcmp(p, "xml") == 0)
357  result_type = XMLOID;
358  else if (strcmp(p, "json") == 0)
359  result_type = JSONOID;
360  else
361  result_type = TEXTOID;
362  /* don't "break", as ExplainQuery will use the last value */
363  }
364  }
365 
366  /* Need a tuple descriptor representing a single TEXT or XML column */
367  tupdesc = CreateTemplateTupleDesc(1);
368  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
369  result_type, -1, 0);
370  return tupdesc;
371 }
int16 AttrNumber
Definition: attnum.h:21
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:67
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 5065 of file explain.c.

5066 {
5067  switch (es->format)
5068  {
5069  case EXPLAIN_FORMAT_TEXT:
5070  /* add a blank line */
5071  appendStringInfoChar(es->str, '\n');
5072  break;
5073 
5074  case EXPLAIN_FORMAT_XML:
5075  case EXPLAIN_FORMAT_JSON:
5076  case EXPLAIN_FORMAT_YAML:
5077  /* nothing to do */
5078  break;
5079  }
5080 }

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

Referenced by ExplainExecuteQuery(), and ExplainQuery().

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 324 of file explain.c.

325 {
326  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
327 
328  /* Set default options (most fields can be left as zeroes). */
329  es->costs = true;
330  /* Prepare output buffer. */
331  es->str = makeStringInfo();
332 
333  return es;
334 }
void * palloc0(Size size)
Definition: mcxt.c:1232
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
extern

Definition at line 48 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 45 of file explain.c.

Referenced by ExplainOneQuery().