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 ExplainSerializeOption ExplainSerializeOption
 
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  ExplainSerializeOption { EXPLAIN_SERIALIZE_NONE , EXPLAIN_SERIALIZE_TEXT , EXPLAIN_SERIALIZE_BINARY }
 
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)
 
void standard_ExplainOneQuery (Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
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)
 
DestReceiverCreateExplainSerializeDestReceiver (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 85 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 75 of file explain.h.

◆ ExplainSerializeOption

◆ 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 27 of file explain.h.

28 {
ExplainFormat
Definition: explain.h:28
@ EXPLAIN_FORMAT_XML
Definition: explain.h:30
@ EXPLAIN_FORMAT_YAML
Definition: explain.h:32
@ EXPLAIN_FORMAT_TEXT
Definition: explain.h:29
@ EXPLAIN_FORMAT_JSON
Definition: explain.h:31

◆ ExplainSerializeOption

Enumerator
EXPLAIN_SERIALIZE_NONE 
EXPLAIN_SERIALIZE_TEXT 
EXPLAIN_SERIALIZE_BINARY 

Definition at line 20 of file explain.h.

21 {
ExplainSerializeOption
Definition: explain.h:21
@ EXPLAIN_SERIALIZE_TEXT
Definition: explain.h:23
@ EXPLAIN_SERIALIZE_NONE
Definition: explain.h:22
@ EXPLAIN_SERIALIZE_BINARY
Definition: explain.h:24

Function Documentation

◆ CreateExplainSerializeDestReceiver()

DestReceiver* CreateExplainSerializeDestReceiver ( ExplainState es)

Definition at line 5549 of file explain.c.

5550 {
5551  SerializeDestReceiver *self;
5552 
5554 
5555  self->pub.receiveSlot = serializeAnalyzeReceive;
5556  self->pub.rStartup = serializeAnalyzeStartup;
5557  self->pub.rShutdown = serializeAnalyzeShutdown;
5558  self->pub.rDestroy = serializeAnalyzeDestroy;
5559  self->pub.mydest = DestExplainSerialize;
5560 
5561  self->es = es;
5562 
5563  return (DestReceiver *) self;
5564 }
@ DestExplainSerialize
Definition: dest.h:99
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: explain.c:5483
static void serializeAnalyzeDestroy(DestReceiver *self)
Definition: explain.c:5540
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
Definition: explain.c:5380
static void serializeAnalyzeShutdown(DestReceiver *self)
Definition: explain.c:5519
void * palloc0(Size size)
Definition: mcxt.c:1346

References DestExplainSerialize, palloc0(), serializeAnalyzeDestroy(), serializeAnalyzeReceive(), serializeAnalyzeShutdown(), and serializeAnalyzeStartup().

Referenced by CreateDestReceiver(), and ExplainOnePlan().

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 5116 of file explain.c.

5117 {
5118  switch (es->format)
5119  {
5120  case EXPLAIN_FORMAT_TEXT:
5121  /* nothing to do */
5122  break;
5123 
5124  case EXPLAIN_FORMAT_XML:
5126  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5127  es->indent++;
5128  break;
5129 
5130  case EXPLAIN_FORMAT_JSON:
5131  /* top-level structure is an array of plans */
5132  appendStringInfoChar(es->str, '[');
5133  es->grouping_stack = lcons_int(0, es->grouping_stack);
5134  es->indent++;
5135  break;
5136 
5137  case EXPLAIN_FORMAT_YAML:
5138  es->grouping_stack = lcons_int(0, es->grouping_stack);
5139  break;
5140  }
5141 }
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:62
StringInfo str
Definition: explain.h:46
ExplainFormat format
Definition: explain.h:59
int indent
Definition: explain.h:61

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 4923 of file explain.c.

4925 {
4926  switch (es->format)
4927  {
4928  case EXPLAIN_FORMAT_TEXT:
4929  /* nothing to do */
4930  break;
4931 
4932  case EXPLAIN_FORMAT_XML:
4933  es->indent--;
4934  ExplainXMLTag(objtype, X_CLOSING, es);
4935  break;
4936 
4937  case EXPLAIN_FORMAT_JSON:
4938  es->indent--;
4939  appendStringInfoChar(es->str, '\n');
4940  appendStringInfoSpaces(es->str, 2 * es->indent);
4941  appendStringInfoChar(es->str, labeled ? '}' : ']');
4943  break;
4944 
4945  case EXPLAIN_FORMAT_YAML:
4946  es->indent--;
4948  break;
4949  }
4950 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5205
#define X_CLOSING
Definition: explain.c:61
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(), ExplainPrintSerialize(), 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 5147 of file explain.c.

5148 {
5149  switch (es->format)
5150  {
5151  case EXPLAIN_FORMAT_TEXT:
5152  /* nothing to do */
5153  break;
5154 
5155  case EXPLAIN_FORMAT_XML:
5156  es->indent--;
5157  appendStringInfoString(es->str, "</explain>");
5158  break;
5159 
5160  case EXPLAIN_FORMAT_JSON:
5161  es->indent--;
5162  appendStringInfoString(es->str, "\n]");
5164  break;
5165 
5166  case EXPLAIN_FORMAT_YAML:
5168  break;
5169  }
5170 }

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 610 of file explain.c.

615 {
617  QueryDesc *queryDesc;
618  instr_time starttime;
619  double totaltime = 0;
620  int eflags;
621  int instrument_option = 0;
622  SerializeMetrics serializeMetrics = {0};
623 
624  Assert(plannedstmt->commandType != CMD_UTILITY);
625 
626  if (es->analyze && es->timing)
627  instrument_option |= INSTRUMENT_TIMER;
628  else if (es->analyze)
629  instrument_option |= INSTRUMENT_ROWS;
630 
631  if (es->buffers)
632  instrument_option |= INSTRUMENT_BUFFERS;
633  if (es->wal)
634  instrument_option |= INSTRUMENT_WAL;
635 
636  /*
637  * We always collect timing for the entire statement, even when node-level
638  * timing is off, so we don't look at es->timing here. (We could skip
639  * this if !es->summary, but it's hardly worth the complication.)
640  */
641  INSTR_TIME_SET_CURRENT(starttime);
642 
643  /*
644  * Use a snapshot with an updated command ID to ensure this query sees
645  * results of any previously executed queries.
646  */
649 
650  /*
651  * We discard the output if we have no use for it. If we're explaining
652  * CREATE TABLE AS, we'd better use the appropriate tuple receiver, while
653  * the SERIALIZE option requires its own tuple receiver. (If you specify
654  * SERIALIZE while explaining CREATE TABLE AS, you'll see zeroes for the
655  * results, which is appropriate since no data would have gone to the
656  * client.)
657  */
658  if (into)
660  else if (es->serialize != EXPLAIN_SERIALIZE_NONE)
662  else
664 
665  /* Create a QueryDesc for the query */
666  queryDesc = CreateQueryDesc(plannedstmt, queryString,
668  dest, params, queryEnv, instrument_option);
669 
670  /* Select execution options */
671  if (es->analyze)
672  eflags = 0; /* default run-to-completion flags */
673  else
674  eflags = EXEC_FLAG_EXPLAIN_ONLY;
675  if (es->generic)
676  eflags |= EXEC_FLAG_EXPLAIN_GENERIC;
677  if (into)
678  eflags |= GetIntoRelEFlags(into);
679 
680  /* call ExecutorStart to prepare the plan for execution */
681  ExecutorStart(queryDesc, eflags);
682 
683  /* Execute the plan for statistics if asked for */
684  if (es->analyze)
685  {
686  ScanDirection dir;
687 
688  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
689  if (into && into->skipData)
691  else
692  dir = ForwardScanDirection;
693 
694  /* run the plan */
695  ExecutorRun(queryDesc, dir, 0, true);
696 
697  /* run cleanup too */
698  ExecutorFinish(queryDesc);
699 
700  /* We can't run ExecutorEnd 'till we're done printing the stats... */
701  totaltime += elapsed_time(&starttime);
702  }
703 
704  /* grab serialization metrics before we destroy the DestReceiver */
706  serializeMetrics = GetSerializationMetrics(dest);
707 
708  /* call the DestReceiver's destroy method even during explain */
709  dest->rDestroy(dest);
710 
711  ExplainOpenGroup("Query", NULL, true, es);
712 
713  /* Create textual dump of plan tree */
714  ExplainPrintPlan(es, queryDesc);
715 
716  /* Show buffer and/or memory usage in planning */
717  if (peek_buffer_usage(es, bufusage) || mem_counters)
718  {
719  ExplainOpenGroup("Planning", "Planning", true, es);
720 
721  if (es->format == EXPLAIN_FORMAT_TEXT)
722  {
723  ExplainIndentText(es);
724  appendStringInfoString(es->str, "Planning:\n");
725  es->indent++;
726  }
727 
728  if (bufusage)
729  show_buffer_usage(es, bufusage);
730 
731  if (mem_counters)
732  show_memory_counters(es, mem_counters);
733 
734  if (es->format == EXPLAIN_FORMAT_TEXT)
735  es->indent--;
736 
737  ExplainCloseGroup("Planning", "Planning", true, es);
738  }
739 
740  if (es->summary && planduration)
741  {
742  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
743 
744  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
745  }
746 
747  /* Print info about runtime of triggers */
748  if (es->analyze)
749  ExplainPrintTriggers(es, queryDesc);
750 
751  /*
752  * Print info about JITing. Tied to es->costs because we don't want to
753  * display this in regression tests, as it'd cause output differences
754  * depending on build options. Might want to separate that out from COSTS
755  * at a later stage.
756  */
757  if (es->costs)
758  ExplainPrintJITSummary(es, queryDesc);
759 
760  /* Print info about serialization of output */
762  ExplainPrintSerialize(es, &serializeMetrics);
763 
764  /*
765  * Close down the query and free resources. Include time for this in the
766  * total execution time (although it should be pretty minimal).
767  */
768  INSTR_TIME_SET_CURRENT(starttime);
769 
770  ExecutorEnd(queryDesc);
771 
772  FreeQueryDesc(queryDesc);
773 
775 
776  /* We need a CCI just in case query expanded to multiple plans */
777  if (es->analyze)
779 
780  totaltime += elapsed_time(&starttime);
781 
782  /*
783  * We only report execution time if we actually ran the query (that is,
784  * the user specified ANALYZE), and if summary reporting is enabled (the
785  * user can set SUMMARY OFF to not have the timing information included in
786  * the output). By default, ANALYZE sets SUMMARY to true.
787  */
788  if (es->summary && es->analyze)
789  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
790  es);
791 
792  ExplainCloseGroup("Query", NULL, true, es);
793 }
#define Assert(condition)
Definition: c.h:858
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:435
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:370
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:467
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:407
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:124
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:297
#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:4860
DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)
Definition: explain.c:5549
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:3696
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:978
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:4831
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4923
static double elapsed_time(instr_time *starttime)
Definition: explain.c:1266
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:5232
static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)
Definition: explain.c:3943
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:870
static void ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)
Definition: explain.c:1102
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:935
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:3736
static SerializeMetrics GetSerializationMetrics(DestReceiver *dest)
Definition: explain.c:5574
#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
@ CMD_UTILITY
Definition: nodes.h:270
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:712
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:700
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:770
#define InvalidSnapshot
Definition: snapshot.h:123
bool timing
Definition: explain.h:53
bool analyze
Definition: explain.h:49
bool wal
Definition: explain.h:52
bool generic
Definition: explain.h:57
bool summary
Definition: explain.h:54
ExplainSerializeOption serialize
Definition: explain.h:58
bool costs
Definition: explain.h:50
bool buffers
Definition: explain.h:51
bool skipData
Definition: primnodes.h:170
CmdType commandType
Definition: plannodes.h:52
void CommandCounterIncrement(void)
Definition: xact.c:1097

References ExplainState::analyze, appendStringInfoString(), Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, ExplainState::costs, CreateExplainSerializeDestReceiver(), CreateIntoRelDestReceiver(), CreateQueryDesc(), generate_unaccent_rules::dest, elapsed_time(), EXEC_FLAG_EXPLAIN_GENERIC, EXEC_FLAG_EXPLAIN_ONLY, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), EXPLAIN_FORMAT_TEXT, EXPLAIN_SERIALIZE_NONE, ExplainCloseGroup(), ExplainIndentText(), ExplainOpenGroup(), ExplainPrintJITSummary(), ExplainPrintPlan(), ExplainPrintSerialize(), ExplainPrintTriggers(), ExplainPropertyFloat(), ExplainState::format, ForwardScanDirection, FreeQueryDesc(), ExplainState::generic, GetActiveSnapshot(), GetIntoRelEFlags(), GetSerializationMetrics(), 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(), ExplainState::serialize, show_buffer_usage(), show_memory_counters(), IntoClause::skipData, ExplainState::str, ExplainState::summary, ExplainState::timing, UpdateActiveSnapshotCommandId(), and ExplainState::wal.

Referenced by ExplainExecuteQuery(), and standard_ExplainOneQuery().

◆ ExplainOneUtility()

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

Definition at line 520 of file explain.c.

523 {
524  if (utilityStmt == NULL)
525  return;
526 
527  if (IsA(utilityStmt, CreateTableAsStmt))
528  {
529  /*
530  * We have to rewrite the contained SELECT and then pass it back to
531  * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case.
532  */
533  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
534  List *rewritten;
535 
536  /*
537  * Check if the relation exists or not. This is done at this stage to
538  * avoid query planning or execution.
539  */
540  if (CreateTableAsRelExists(ctas))
541  {
542  if (ctas->objtype == OBJECT_TABLE)
543  ExplainDummyGroup("CREATE TABLE AS", NULL, es);
544  else if (ctas->objtype == OBJECT_MATVIEW)
545  ExplainDummyGroup("CREATE MATERIALIZED VIEW", NULL, es);
546  else
547  elog(ERROR, "unexpected object type: %d",
548  (int) ctas->objtype);
549  return;
550  }
551 
552  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
553  Assert(list_length(rewritten) == 1);
554  ExplainOneQuery(linitial_node(Query, rewritten),
555  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
556  queryString, params, queryEnv);
557  }
558  else if (IsA(utilityStmt, DeclareCursorStmt))
559  {
560  /*
561  * Likewise for DECLARE CURSOR.
562  *
563  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
564  * actually run the query. This is different from pre-8.3 behavior
565  * but seems more useful than not running the query. No cursor will
566  * be created, however.
567  */
568  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
569  List *rewritten;
570 
571  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
572  Assert(list_length(rewritten) == 1);
573  ExplainOneQuery(linitial_node(Query, rewritten),
574  dcs->options, NULL, es,
575  queryString, params, queryEnv);
576  }
577  else if (IsA(utilityStmt, ExecuteStmt))
578  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
579  queryString, params, queryEnv);
580  else if (IsA(utilityStmt, NotifyStmt))
581  {
582  if (es->format == EXPLAIN_FORMAT_TEXT)
583  appendStringInfoString(es->str, "NOTIFY\n");
584  else
585  ExplainDummyGroup("Notify", NULL, es);
586  }
587  else
588  {
589  if (es->format == EXPLAIN_FORMAT_TEXT)
591  "Utility statements have no plan structure\n");
592  else
593  ExplainDummyGroup("Utility Statement", NULL, es);
594  }
595 }
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:568
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:388
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:5070
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:421
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
@ OBJECT_MATVIEW
Definition: parsenodes.h:2286
@ OBJECT_TABLE
Definition: parsenodes.h:2304
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3302
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:3904
ObjectType objtype
Definition: parsenodes.h:3905
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 4860 of file explain.c.

4862 {
4863  switch (es->format)
4864  {
4865  case EXPLAIN_FORMAT_TEXT:
4866  /* nothing to do */
4867  break;
4868 
4869  case EXPLAIN_FORMAT_XML:
4870  ExplainXMLTag(objtype, X_OPENING, es);
4871  es->indent++;
4872  break;
4873 
4874  case EXPLAIN_FORMAT_JSON:
4876  appendStringInfoSpaces(es->str, 2 * es->indent);
4877  if (labelname)
4878  {
4879  escape_json(es->str, labelname);
4880  appendStringInfoString(es->str, ": ");
4881  }
4882  appendStringInfoChar(es->str, labeled ? '{' : '[');
4883 
4884  /*
4885  * In JSON format, the grouping_stack is an integer list. 0 means
4886  * we've emitted nothing at this grouping level, 1 means we've
4887  * emitted something (and so the next item needs a comma). See
4888  * ExplainJSONLineEnding().
4889  */
4890  es->grouping_stack = lcons_int(0, es->grouping_stack);
4891  es->indent++;
4892  break;
4893 
4894  case EXPLAIN_FORMAT_YAML:
4895 
4896  /*
4897  * In YAML format, the grouping stack is an integer list. 0 means
4898  * we've emitted nothing at this grouping level AND this grouping
4899  * level is unlabeled and must be marked with "- ". See
4900  * ExplainYAMLLineStarting().
4901  */
4903  if (labelname)
4904  {
4905  appendStringInfo(es->str, "%s: ", labelname);
4906  es->grouping_stack = lcons_int(1, es->grouping_stack);
4907  }
4908  else
4909  {
4910  appendStringInfoString(es->str, "- ");
4911  es->grouping_stack = lcons_int(0, es->grouping_stack);
4912  }
4913  es->indent++;
4914  break;
4915  }
4916 }
#define X_OPENING
Definition: explain.c:60
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:5267
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:5247
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(), ExplainPrintSerialize(), 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 978 of file explain.c.

979 {
980  JitInstrumentation ji = {0};
981 
982  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
983  return;
984 
985  /*
986  * Work with a copy instead of modifying the leader state, since this
987  * function may be called twice
988  */
989  if (queryDesc->estate->es_jit)
990  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
991 
992  /* If this process has done JIT in parallel workers, merge stats */
993  if (queryDesc->estate->es_jit_worker_instr)
994  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
995 
996  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
997 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:1004
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:182
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:716
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:717
int es_jit_flags
Definition: execnodes.h:715
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 870 of file explain.c.

871 {
872  Bitmapset *rels_used = NULL;
873  PlanState *ps;
874 
875  /* Set up ExplainState fields associated with this plan tree */
876  Assert(queryDesc->plannedstmt != NULL);
877  es->pstmt = queryDesc->plannedstmt;
878  es->rtable = queryDesc->plannedstmt->rtable;
879  ExplainPreScanNode(queryDesc->planstate, &rels_used);
882  es->rtable_names);
883  es->printed_subplans = NULL;
884 
885  /*
886  * Sometimes we mark a Gather node as "invisible", which means that it's
887  * not to be displayed in EXPLAIN output. The purpose of this is to allow
888  * running regression tests with debug_parallel_query=regress to get the
889  * same results as running the same tests with debug_parallel_query=off.
890  * Such marking is currently only supported on a Gather at the top of the
891  * plan. We skip that node, and we must also hide per-worker detail data
892  * further down in the plan tree.
893  */
894  ps = queryDesc->planstate;
895  if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
896  {
897  ps = outerPlanState(ps);
898  es->hide_workers = true;
899  }
900  ExplainNode(ps, NIL, NULL, NULL, es);
901 
902  /*
903  * If requested, include information about GUC parameters with values that
904  * don't match the built-in defaults.
905  */
907 
908  /*
909  * COMPUTE_QUERY_ID_REGRESS means COMPUTE_QUERY_ID_AUTO, but we don't show
910  * the queryid in any of the EXPLAIN plans to keep stable the results
911  * generated by regression test suites.
912  */
913  if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) &&
915  {
916  /*
917  * Output the queryid as an int64 rather than a uint64 so we match
918  * what would be seen in the BIGINT pg_stat_statements.queryid column.
919  */
920  ExplainPropertyInteger("Query Identifier", NULL, (int64)
921  queryDesc->plannedstmt->queryId, es);
922  }
923 }
#define outerPlanState(node)
Definition: execnodes.h:1213
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1360
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1285
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:4804
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:800
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:3822
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3730
bool verbose
Definition: explain.h:48
Bitmapset * printed_subplans
Definition: explain.h:68
bool hide_workers
Definition: explain.h:69
List * rtable_names
Definition: explain.h:66
List * rtable
Definition: explain.h:65
PlannedStmt * pstmt
Definition: explain.h:64
List * deparse_cxt
Definition: explain.h:67
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 935 of file explain.c.

936 {
937  ResultRelInfo *rInfo;
938  bool show_relname;
939  List *resultrels;
940  List *routerels;
941  List *targrels;
942  ListCell *l;
943 
944  resultrels = queryDesc->estate->es_opened_result_relations;
945  routerels = queryDesc->estate->es_tuple_routing_result_relations;
946  targrels = queryDesc->estate->es_trig_target_relations;
947 
948  ExplainOpenGroup("Triggers", "Triggers", false, es);
949 
950  show_relname = (list_length(resultrels) > 1 ||
951  routerels != NIL || targrels != NIL);
952  foreach(l, resultrels)
953  {
954  rInfo = (ResultRelInfo *) lfirst(l);
955  report_triggers(rInfo, show_relname, es);
956  }
957 
958  foreach(l, routerels)
959  {
960  rInfo = (ResultRelInfo *) lfirst(l);
961  report_triggers(rInfo, show_relname, es);
962  }
963 
964  foreach(l, targrels)
965  {
966  rInfo = (ResultRelInfo *) lfirst(l);
967  report_triggers(rInfo, show_relname, es);
968  }
969 
970  ExplainCloseGroup("Triggers", "Triggers", false, es);
971 }
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:1195
#define lfirst(lc)
Definition: pg_list.h:172
List * es_tuple_routing_result_relations
Definition: execnodes.h:655
List * es_trig_target_relations
Definition: execnodes.h:658
List * es_opened_result_relations
Definition: execnodes.h:645

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 4845 of file explain.c.

4846 {
4847  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4848 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4742
static struct @155 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 4831 of file explain.c.

4833 {
4834  char *buf;
4835 
4836  buf = psprintf("%.*f", ndigits, value);
4837  ExplainProperty(qlabel, unit, buf, true, es);
4838  pfree(buf);
4839 }
void pfree(void *pointer)
Definition: mcxt.c:1520
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(), ExplainPrintSerialize(), 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 4619 of file explain.c.

4620 {
4621  ListCell *lc;
4622  bool first = true;
4623 
4624  switch (es->format)
4625  {
4626  case EXPLAIN_FORMAT_TEXT:
4627  ExplainIndentText(es);
4628  appendStringInfo(es->str, "%s: ", qlabel);
4629  foreach(lc, data)
4630  {
4631  if (!first)
4632  appendStringInfoString(es->str, ", ");
4633  appendStringInfoString(es->str, (const char *) lfirst(lc));
4634  first = false;
4635  }
4636  appendStringInfoChar(es->str, '\n');
4637  break;
4638 
4639  case EXPLAIN_FORMAT_XML:
4640  ExplainXMLTag(qlabel, X_OPENING, es);
4641  foreach(lc, data)
4642  {
4643  char *str;
4644 
4645  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4646  appendStringInfoString(es->str, "<Item>");
4647  str = escape_xml((const char *) lfirst(lc));
4649  pfree(str);
4650  appendStringInfoString(es->str, "</Item>\n");
4651  }
4652  ExplainXMLTag(qlabel, X_CLOSING, es);
4653  break;
4654 
4655  case EXPLAIN_FORMAT_JSON:
4657  appendStringInfoSpaces(es->str, es->indent * 2);
4658  escape_json(es->str, qlabel);
4659  appendStringInfoString(es->str, ": [");
4660  foreach(lc, data)
4661  {
4662  if (!first)
4663  appendStringInfoString(es->str, ", ");
4664  escape_json(es->str, (const char *) lfirst(lc));
4665  first = false;
4666  }
4667  appendStringInfoChar(es->str, ']');
4668  break;
4669 
4670  case EXPLAIN_FORMAT_YAML:
4672  appendStringInfo(es->str, "%s: ", qlabel);
4673  foreach(lc, data)
4674  {
4675  appendStringInfoChar(es->str, '\n');
4676  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4677  appendStringInfoString(es->str, "- ");
4678  escape_yaml(es->str, (const char *) lfirst(lc));
4679  }
4680  break;
4681  }
4682 }
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:5292
const char * str
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2632

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(), ExplainState::str, str, X_CLOSING, and X_OPENING.

Referenced by ExplainPropertyListNested(), 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 4689 of file explain.c.

4690 {
4691  ListCell *lc;
4692  bool first = true;
4693 
4694  switch (es->format)
4695  {
4696  case EXPLAIN_FORMAT_TEXT:
4697  case EXPLAIN_FORMAT_XML:
4698  ExplainPropertyList(qlabel, data, es);
4699  return;
4700 
4701  case EXPLAIN_FORMAT_JSON:
4703  appendStringInfoSpaces(es->str, es->indent * 2);
4704  appendStringInfoChar(es->str, '[');
4705  foreach(lc, data)
4706  {
4707  if (!first)
4708  appendStringInfoString(es->str, ", ");
4709  escape_json(es->str, (const char *) lfirst(lc));
4710  first = false;
4711  }
4712  appendStringInfoChar(es->str, ']');
4713  break;
4714 
4715  case EXPLAIN_FORMAT_YAML:
4717  appendStringInfoString(es->str, "- [");
4718  foreach(lc, data)
4719  {
4720  if (!first)
4721  appendStringInfoString(es->str, ", ");
4722  escape_yaml(es->str, (const char *) lfirst(lc));
4723  first = false;
4724  }
4725  appendStringInfoChar(es->str, ']');
4726  break;
4727  }
4728 }
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4619

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 4817 of file explain.c.

4819 {
4820  char buf[32];
4821 
4822  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4823  ExplainProperty(qlabel, unit, buf, true, es);
4824 }
#define UINT64_FORMAT
Definition: c.h:549

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

Referenced by ExplainPrintSerialize(), and show_wal_usage().

◆ ExplainQuery()

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

Definition at line 176 of file explain.c.

178 {
180  TupOutputState *tstate;
181  JumbleState *jstate = NULL;
182  Query *query;
183  List *rewritten;
184  ListCell *lc;
185  bool timing_set = false;
186  bool summary_set = false;
187 
188  /* Parse options list. */
189  foreach(lc, stmt->options)
190  {
191  DefElem *opt = (DefElem *) lfirst(lc);
192 
193  if (strcmp(opt->defname, "analyze") == 0)
194  es->analyze = defGetBoolean(opt);
195  else if (strcmp(opt->defname, "verbose") == 0)
196  es->verbose = defGetBoolean(opt);
197  else if (strcmp(opt->defname, "costs") == 0)
198  es->costs = defGetBoolean(opt);
199  else if (strcmp(opt->defname, "buffers") == 0)
200  es->buffers = defGetBoolean(opt);
201  else if (strcmp(opt->defname, "wal") == 0)
202  es->wal = defGetBoolean(opt);
203  else if (strcmp(opt->defname, "settings") == 0)
204  es->settings = defGetBoolean(opt);
205  else if (strcmp(opt->defname, "generic_plan") == 0)
206  es->generic = defGetBoolean(opt);
207  else if (strcmp(opt->defname, "timing") == 0)
208  {
209  timing_set = true;
210  es->timing = defGetBoolean(opt);
211  }
212  else if (strcmp(opt->defname, "summary") == 0)
213  {
214  summary_set = true;
215  es->summary = defGetBoolean(opt);
216  }
217  else if (strcmp(opt->defname, "memory") == 0)
218  es->memory = defGetBoolean(opt);
219  else if (strcmp(opt->defname, "serialize") == 0)
220  {
221  if (opt->arg)
222  {
223  char *p = defGetString(opt);
224 
225  if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0)
227  else if (strcmp(p, "text") == 0)
229  else if (strcmp(p, "binary") == 0)
231  else
232  ereport(ERROR,
233  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
234  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
235  opt->defname, p),
236  parser_errposition(pstate, opt->location)));
237  }
238  else
239  {
240  /* SERIALIZE without an argument is taken as 'text' */
242  }
243  }
244  else if (strcmp(opt->defname, "format") == 0)
245  {
246  char *p = defGetString(opt);
247 
248  if (strcmp(p, "text") == 0)
250  else if (strcmp(p, "xml") == 0)
252  else if (strcmp(p, "json") == 0)
254  else if (strcmp(p, "yaml") == 0)
256  else
257  ereport(ERROR,
258  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
259  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
260  opt->defname, p),
261  parser_errposition(pstate, opt->location)));
262  }
263  else
264  ereport(ERROR,
265  (errcode(ERRCODE_SYNTAX_ERROR),
266  errmsg("unrecognized EXPLAIN option \"%s\"",
267  opt->defname),
268  parser_errposition(pstate, opt->location)));
269  }
270 
271  /* check that WAL is used with EXPLAIN ANALYZE */
272  if (es->wal && !es->analyze)
273  ereport(ERROR,
274  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
275  errmsg("EXPLAIN option WAL requires ANALYZE")));
276 
277  /* if the timing was not set explicitly, set default value */
278  es->timing = (timing_set) ? es->timing : es->analyze;
279 
280  /* check that timing is used with EXPLAIN ANALYZE */
281  if (es->timing && !es->analyze)
282  ereport(ERROR,
283  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
284  errmsg("EXPLAIN option TIMING requires ANALYZE")));
285 
286  /* check that serialize is used with EXPLAIN ANALYZE */
287  if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze)
288  ereport(ERROR,
289  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
290  errmsg("EXPLAIN option SERIALIZE requires ANALYZE")));
291 
292  /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */
293  if (es->generic && es->analyze)
294  ereport(ERROR,
295  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
296  errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together")));
297 
298  /* if the summary was not set explicitly, set default value */
299  es->summary = (summary_set) ? es->summary : es->analyze;
300 
301  query = castNode(Query, stmt->query);
302  if (IsQueryIdEnabled())
303  jstate = JumbleQuery(query);
304 
306  (*post_parse_analyze_hook) (pstate, query, jstate);
307 
308  /*
309  * Parse analysis was done already, but we still have to run the rule
310  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
311  * came straight from the parser, or suitable locks were acquired by
312  * plancache.c.
313  */
314  rewritten = QueryRewrite(castNode(Query, stmt->query));
315 
316  /* emit opening boilerplate */
317  ExplainBeginOutput(es);
318 
319  if (rewritten == NIL)
320  {
321  /*
322  * In the case of an INSTEAD NOTHING, tell at least that. But in
323  * non-text format, the output is delimited, so this isn't necessary.
324  */
325  if (es->format == EXPLAIN_FORMAT_TEXT)
326  appendStringInfoString(es->str, "Query rewrites to nothing\n");
327  }
328  else
329  {
330  ListCell *l;
331 
332  /* Explain every plan */
333  foreach(l, rewritten)
334  {
336  CURSOR_OPT_PARALLEL_OK, NULL, es,
337  pstate->p_sourcetext, params, pstate->p_queryEnv);
338 
339  /* Separate plans with an appropriate separator */
340  if (lnext(rewritten, l) != NULL)
342  }
343  }
344 
345  /* emit closing boilerplate */
346  ExplainEndOutput(es);
347  Assert(es->indent == 0);
348 
349  /* output tuples */
351  &TTSOpsVirtual);
352  if (es->format == EXPLAIN_FORMAT_TEXT)
353  do_text_output_multiline(tstate, es->str->data);
354  else
355  do_text_output_oneline(tstate, es->str->data);
356  end_tup_output(tstate);
357 
358  pfree(es->str->data);
359 }
bool defGetBoolean(DefElem *def)
Definition: define.c:107
char * defGetString(DefElem *def)
Definition: define.c:48
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2420
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2390
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2342
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:522
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:5176
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:5147
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:382
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:5116
ExplainState * NewExplainState(void)
Definition: explain.c:365
#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:106
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:58
#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:815
ParseLoc location
Definition: parsenodes.h:819
Node * arg
Definition: parsenodes.h:816
bool settings
Definition: explain.h:56
bool memory
Definition: explain.h:55

References ExplainState::analyze, appendStringInfoString(), DefElem::arg, 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, EXPLAIN_SERIALIZE_BINARY, EXPLAIN_SERIALIZE_NONE, EXPLAIN_SERIALIZE_TEXT, 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::serialize, 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 1177 of file explain.c.

1178 {
1179  char *str;
1180 
1181  /* This check is consistent with errdetail_params() */
1182  if (params == NULL || params->numParams <= 0 || maxlen == 0)
1183  return;
1184 
1185  str = BuildParamLogString(params, NULL, maxlen);
1186  if (str && str[0] != '\0')
1187  ExplainPropertyText("Query Parameters", str, es);
1188 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:4795
char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)
Definition: params.c:335

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

Referenced by explain_ExecutorEnd().

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 1162 of file explain.c.

1163 {
1164  if (queryDesc->sourceText)
1165  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1166 }
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 382 of file explain.c.

383 {
384  TupleDesc tupdesc;
385  ListCell *lc;
386  Oid result_type = TEXTOID;
387 
388  /* Check for XML format option */
389  foreach(lc, stmt->options)
390  {
391  DefElem *opt = (DefElem *) lfirst(lc);
392 
393  if (strcmp(opt->defname, "format") == 0)
394  {
395  char *p = defGetString(opt);
396 
397  if (strcmp(p, "xml") == 0)
398  result_type = XMLOID;
399  else if (strcmp(p, "json") == 0)
400  result_type = JSONOID;
401  else
402  result_type = TEXTOID;
403  /* don't "break", as ExplainQuery will use the last value */
404  }
405  }
406 
407  /* Need a tuple descriptor representing a single TEXT or XML column */
408  tupdesc = CreateTemplateTupleDesc(1);
409  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
410  result_type, -1, 0);
411  return tupdesc;
412 }
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:651

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 5176 of file explain.c.

5177 {
5178  switch (es->format)
5179  {
5180  case EXPLAIN_FORMAT_TEXT:
5181  /* add a blank line */
5182  appendStringInfoChar(es->str, '\n');
5183  break;
5184 
5185  case EXPLAIN_FORMAT_XML:
5186  case EXPLAIN_FORMAT_JSON:
5187  case EXPLAIN_FORMAT_YAML:
5188  /* nothing to do */
5189  break;
5190  }
5191 }

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 365 of file explain.c.

366 {
367  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
368 
369  /* Set default options (most fields can be left as zeroes). */
370  es->costs = true;
371  /* Prepare output buffer. */
372  es->str = makeStringInfo();
373 
374  return es;
375 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

◆ standard_ExplainOneQuery()

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

Definition at line 448 of file explain.c.

452 {
453  PlannedStmt *plan;
454  instr_time planstart,
455  planduration;
456  BufferUsage bufusage_start,
457  bufusage;
458  MemoryContextCounters mem_counters;
459  MemoryContext planner_ctx = NULL;
460  MemoryContext saved_ctx = NULL;
461 
462  if (es->memory)
463  {
464  /*
465  * Create a new memory context to measure planner's memory consumption
466  * accurately. Note that if the planner were to be modified to use a
467  * different memory context type, here we would be changing that to
468  * AllocSet, which might be undesirable. However, we don't have a way
469  * to create a context of the same type as another, so we pray and
470  * hope that this is OK.
471  */
473  "explain analyze planner context",
475  saved_ctx = MemoryContextSwitchTo(planner_ctx);
476  }
477 
478  if (es->buffers)
479  bufusage_start = pgBufferUsage;
480  INSTR_TIME_SET_CURRENT(planstart);
481 
482  /* plan the query */
483  plan = pg_plan_query(query, queryString, cursorOptions, params);
484 
485  INSTR_TIME_SET_CURRENT(planduration);
486  INSTR_TIME_SUBTRACT(planduration, planstart);
487 
488  if (es->memory)
489  {
490  MemoryContextSwitchTo(saved_ctx);
491  MemoryContextMemConsumed(planner_ctx, &mem_counters);
492  }
493 
494  /* calc differences of buffer counters. */
495  if (es->buffers)
496  {
497  memset(&bufusage, 0, sizeof(BufferUsage));
498  BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
499  }
500 
501  /* run it (if needed) and produce output */
502  ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
503  &planduration, (es->buffers ? &bufusage : NULL),
504  es->memory ? &mem_counters : NULL);
505 }
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: explain.c:610
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:181
BufferUsage pgBufferUsage
Definition: instrument.c:20
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition: instrument.c:248
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition: mcxt.c:786
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define plan(x)
Definition: pg_regress.c:162
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:886
MemoryContextSwitchTo(old_ctx)

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ExplainState::buffers, BufferUsageAccumDiff(), CurrentMemoryContext, ExplainOnePlan(), INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, ExplainState::memory, MemoryContextMemConsumed(), MemoryContextSwitchTo(), pg_plan_query(), pgBufferUsage, and plan.

Referenced by ExplainOneQuery().

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