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

5638 {
5639  SerializeDestReceiver *self;
5640 
5642 
5643  self->pub.receiveSlot = serializeAnalyzeReceive;
5644  self->pub.rStartup = serializeAnalyzeStartup;
5645  self->pub.rShutdown = serializeAnalyzeShutdown;
5646  self->pub.rDestroy = serializeAnalyzeDestroy;
5647  self->pub.mydest = DestExplainSerialize;
5648 
5649  self->es = es;
5650 
5651  return (DestReceiver *) self;
5652 }
@ DestExplainSerialize
Definition: dest.h:99
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: explain.c:5571
static void serializeAnalyzeDestroy(DestReceiver *self)
Definition: explain.c:5628
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
Definition: explain.c:5468
static void serializeAnalyzeShutdown(DestReceiver *self)
Definition: explain.c:5607
void * palloc0(Size size)
Definition: mcxt.c:1347

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

Referenced by CreateDestReceiver(), and ExplainOnePlan().

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 5204 of file explain.c.

5205 {
5206  switch (es->format)
5207  {
5208  case EXPLAIN_FORMAT_TEXT:
5209  /* nothing to do */
5210  break;
5211 
5212  case EXPLAIN_FORMAT_XML:
5214  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5215  es->indent++;
5216  break;
5217 
5218  case EXPLAIN_FORMAT_JSON:
5219  /* top-level structure is an array of plans */
5220  appendStringInfoChar(es->str, '[');
5221  es->grouping_stack = lcons_int(0, es->grouping_stack);
5222  es->indent++;
5223  break;
5224 
5225  case EXPLAIN_FORMAT_YAML:
5226  es->grouping_stack = lcons_int(0, es->grouping_stack);
5227  break;
5228  }
5229 }
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 5011 of file explain.c.

5013 {
5014  switch (es->format)
5015  {
5016  case EXPLAIN_FORMAT_TEXT:
5017  /* nothing to do */
5018  break;
5019 
5020  case EXPLAIN_FORMAT_XML:
5021  es->indent--;
5022  ExplainXMLTag(objtype, X_CLOSING, es);
5023  break;
5024 
5025  case EXPLAIN_FORMAT_JSON:
5026  es->indent--;
5027  appendStringInfoChar(es->str, '\n');
5028  appendStringInfoSpaces(es->str, 2 * es->indent);
5029  appendStringInfoChar(es->str, labeled ? '}' : ']');
5031  break;
5032 
5033  case EXPLAIN_FORMAT_YAML:
5034  es->indent--;
5036  break;
5037  }
5038 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5293
#define X_CLOSING
Definition: explain.c:62
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 5235 of file explain.c.

5236 {
5237  switch (es->format)
5238  {
5239  case EXPLAIN_FORMAT_TEXT:
5240  /* nothing to do */
5241  break;
5242 
5243  case EXPLAIN_FORMAT_XML:
5244  es->indent--;
5245  appendStringInfoString(es->str, "</explain>");
5246  break;
5247 
5248  case EXPLAIN_FORMAT_JSON:
5249  es->indent--;
5250  appendStringInfoString(es->str, "\n]");
5252  break;
5253 
5254  case EXPLAIN_FORMAT_YAML:
5256  break;
5257  }
5258 }

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

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

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

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

4950 {
4951  switch (es->format)
4952  {
4953  case EXPLAIN_FORMAT_TEXT:
4954  /* nothing to do */
4955  break;
4956 
4957  case EXPLAIN_FORMAT_XML:
4958  ExplainXMLTag(objtype, X_OPENING, es);
4959  es->indent++;
4960  break;
4961 
4962  case EXPLAIN_FORMAT_JSON:
4964  appendStringInfoSpaces(es->str, 2 * es->indent);
4965  if (labelname)
4966  {
4967  escape_json(es->str, labelname);
4968  appendStringInfoString(es->str, ": ");
4969  }
4970  appendStringInfoChar(es->str, labeled ? '{' : '[');
4971 
4972  /*
4973  * In JSON format, the grouping_stack is an integer list. 0 means
4974  * we've emitted nothing at this grouping level, 1 means we've
4975  * emitted something (and so the next item needs a comma). See
4976  * ExplainJSONLineEnding().
4977  */
4978  es->grouping_stack = lcons_int(0, es->grouping_stack);
4979  es->indent++;
4980  break;
4981 
4982  case EXPLAIN_FORMAT_YAML:
4983 
4984  /*
4985  * In YAML format, the grouping stack is an integer list. 0 means
4986  * we've emitted nothing at this grouping level AND this grouping
4987  * level is unlabeled and must be marked with "- ". See
4988  * ExplainYAMLLineStarting().
4989  */
4991  if (labelname)
4992  {
4993  appendStringInfo(es->str, "%s: ", labelname);
4994  es->grouping_stack = lcons_int(1, es->grouping_stack);
4995  }
4996  else
4997  {
4998  appendStringInfoString(es->str, "- ");
4999  es->grouping_stack = lcons_int(0, es->grouping_stack);
5000  }
5001  es->indent++;
5002  break;
5003  }
5004 }
#define X_OPENING
Definition: explain.c:61
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:5355
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:5335
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 986 of file explain.c.

987 {
988  JitInstrumentation ji = {0};
989 
990  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
991  return;
992 
993  /*
994  * Work with a copy instead of modifying the leader state, since this
995  * function may be called twice
996  */
997  if (queryDesc->estate->es_jit)
998  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
999 
1000  /* If this process has done JIT in parallel workers, merge stats */
1001  if (queryDesc->estate->es_jit_worker_instr)
1002  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
1003 
1004  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
1005 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:1012
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:62
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 878 of file explain.c.

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

944 {
945  ResultRelInfo *rInfo;
946  bool show_relname;
947  List *resultrels;
948  List *routerels;
949  List *targrels;
950  ListCell *l;
951 
952  resultrels = queryDesc->estate->es_opened_result_relations;
953  routerels = queryDesc->estate->es_tuple_routing_result_relations;
954  targrels = queryDesc->estate->es_trig_target_relations;
955 
956  ExplainOpenGroup("Triggers", "Triggers", false, es);
957 
958  show_relname = (list_length(resultrels) > 1 ||
959  routerels != NIL || targrels != NIL);
960  foreach(l, resultrels)
961  {
962  rInfo = (ResultRelInfo *) lfirst(l);
963  report_triggers(rInfo, show_relname, es);
964  }
965 
966  foreach(l, routerels)
967  {
968  rInfo = (ResultRelInfo *) lfirst(l);
969  report_triggers(rInfo, show_relname, es);
970  }
971 
972  foreach(l, targrels)
973  {
974  rInfo = (ResultRelInfo *) lfirst(l);
975  report_triggers(rInfo, show_relname, es);
976  }
977 
978  ExplainCloseGroup("Triggers", "Triggers", false, es);
979 }
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:1203
#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 4933 of file explain.c.

4934 {
4935  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4936 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4830
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 4919 of file explain.c.

4921 {
4922  char *buf;
4923 
4924  buf = psprintf("%.*f", ndigits, value);
4925  ExplainProperty(qlabel, unit, buf, true, es);
4926  pfree(buf);
4927 }
void pfree(void *pointer)
Definition: mcxt.c:1521
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 4707 of file explain.c.

4708 {
4709  ListCell *lc;
4710  bool first = true;
4711 
4712  switch (es->format)
4713  {
4714  case EXPLAIN_FORMAT_TEXT:
4715  ExplainIndentText(es);
4716  appendStringInfo(es->str, "%s: ", qlabel);
4717  foreach(lc, data)
4718  {
4719  if (!first)
4720  appendStringInfoString(es->str, ", ");
4721  appendStringInfoString(es->str, (const char *) lfirst(lc));
4722  first = false;
4723  }
4724  appendStringInfoChar(es->str, '\n');
4725  break;
4726 
4727  case EXPLAIN_FORMAT_XML:
4728  ExplainXMLTag(qlabel, X_OPENING, es);
4729  foreach(lc, data)
4730  {
4731  char *str;
4732 
4733  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4734  appendStringInfoString(es->str, "<Item>");
4735  str = escape_xml((const char *) lfirst(lc));
4737  pfree(str);
4738  appendStringInfoString(es->str, "</Item>\n");
4739  }
4740  ExplainXMLTag(qlabel, X_CLOSING, es);
4741  break;
4742 
4743  case EXPLAIN_FORMAT_JSON:
4745  appendStringInfoSpaces(es->str, es->indent * 2);
4746  escape_json(es->str, qlabel);
4747  appendStringInfoString(es->str, ": [");
4748  foreach(lc, data)
4749  {
4750  if (!first)
4751  appendStringInfoString(es->str, ", ");
4752  escape_json(es->str, (const char *) lfirst(lc));
4753  first = false;
4754  }
4755  appendStringInfoChar(es->str, ']');
4756  break;
4757 
4758  case EXPLAIN_FORMAT_YAML:
4760  appendStringInfo(es->str, "%s: ", qlabel);
4761  foreach(lc, data)
4762  {
4763  appendStringInfoChar(es->str, '\n');
4764  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4765  appendStringInfoString(es->str, "- ");
4766  escape_yaml(es->str, (const char *) lfirst(lc));
4767  }
4768  break;
4769  }
4770 }
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:5380
const char * str
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2674

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

4778 {
4779  ListCell *lc;
4780  bool first = true;
4781 
4782  switch (es->format)
4783  {
4784  case EXPLAIN_FORMAT_TEXT:
4785  case EXPLAIN_FORMAT_XML:
4786  ExplainPropertyList(qlabel, data, es);
4787  return;
4788 
4789  case EXPLAIN_FORMAT_JSON:
4791  appendStringInfoSpaces(es->str, es->indent * 2);
4792  appendStringInfoChar(es->str, '[');
4793  foreach(lc, data)
4794  {
4795  if (!first)
4796  appendStringInfoString(es->str, ", ");
4797  escape_json(es->str, (const char *) lfirst(lc));
4798  first = false;
4799  }
4800  appendStringInfoChar(es->str, ']');
4801  break;
4802 
4803  case EXPLAIN_FORMAT_YAML:
4805  appendStringInfoString(es->str, "- [");
4806  foreach(lc, data)
4807  {
4808  if (!first)
4809  appendStringInfoString(es->str, ", ");
4810  escape_yaml(es->str, (const char *) lfirst(lc));
4811  first = false;
4812  }
4813  appendStringInfoChar(es->str, ']');
4814  break;
4815  }
4816 }
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4707

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

4907 {
4908  char buf[32];
4909 
4910  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4911  ExplainProperty(qlabel, unit, buf, true, es);
4912 }
#define UINT64_FORMAT
Definition: c.h:549

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

Referenced by ExplainPrintSerialize(), show_hash_info(), show_tidbitmap_info(), and show_wal_usage().

◆ ExplainQuery()

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

Definition at line 184 of file explain.c.

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

1186 {
1187  char *str;
1188 
1189  /* This check is consistent with errdetail_params() */
1190  if (params == NULL || params->numParams <= 0 || maxlen == 0)
1191  return;
1192 
1193  str = BuildParamLogString(params, NULL, maxlen);
1194  if (str && str[0] != '\0')
1195  ExplainPropertyText("Query Parameters", str, es);
1196 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:4883
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 1170 of file explain.c.

1171 {
1172  if (queryDesc->sourceText)
1173  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1174 }
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 390 of file explain.c.

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

5265 {
5266  switch (es->format)
5267  {
5268  case EXPLAIN_FORMAT_TEXT:
5269  /* add a blank line */
5270  appendStringInfoChar(es->str, '\n');
5271  break;
5272 
5273  case EXPLAIN_FORMAT_XML:
5274  case EXPLAIN_FORMAT_JSON:
5275  case EXPLAIN_FORMAT_YAML:
5276  /* nothing to do */
5277  break;
5278  }
5279 }

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

374 {
375  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
376 
377  /* Set default options (most fields can be left as zeroes). */
378  es->costs = true;
379  /* Prepare output buffer. */
380  es->str = makeStringInfo();
381 
382  return es;
383 }
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 456 of file explain.c.

460 {
461  PlannedStmt *plan;
462  instr_time planstart,
463  planduration;
464  BufferUsage bufusage_start,
465  bufusage;
466  MemoryContextCounters mem_counters;
467  MemoryContext planner_ctx = NULL;
468  MemoryContext saved_ctx = NULL;
469 
470  if (es->memory)
471  {
472  /*
473  * Create a new memory context to measure planner's memory consumption
474  * accurately. Note that if the planner were to be modified to use a
475  * different memory context type, here we would be changing that to
476  * AllocSet, which might be undesirable. However, we don't have a way
477  * to create a context of the same type as another, so we pray and
478  * hope that this is OK.
479  */
481  "explain analyze planner context",
483  saved_ctx = MemoryContextSwitchTo(planner_ctx);
484  }
485 
486  if (es->buffers)
487  bufusage_start = pgBufferUsage;
488  INSTR_TIME_SET_CURRENT(planstart);
489 
490  /* plan the query */
491  plan = pg_plan_query(query, queryString, cursorOptions, params);
492 
493  INSTR_TIME_SET_CURRENT(planduration);
494  INSTR_TIME_SUBTRACT(planduration, planstart);
495 
496  if (es->memory)
497  {
498  MemoryContextSwitchTo(saved_ctx);
499  MemoryContextMemConsumed(planner_ctx, &mem_counters);
500  }
501 
502  /* calc differences of buffer counters. */
503  if (es->buffers)
504  {
505  memset(&bufusage, 0, sizeof(BufferUsage));
506  BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
507  }
508 
509  /* run it (if needed) and produce output */
510  ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
511  &planduration, (es->buffers ? &bufusage : NULL),
512  es->memory ? &mem_counters : NULL);
513 }
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:618
#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 49 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 46 of file explain.c.

Referenced by ExplainOneQuery().