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 87 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 77 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 5865 of file explain.c.

5866 {
5867  SerializeDestReceiver *self;
5868 
5870 
5871  self->pub.receiveSlot = serializeAnalyzeReceive;
5872  self->pub.rStartup = serializeAnalyzeStartup;
5873  self->pub.rShutdown = serializeAnalyzeShutdown;
5874  self->pub.rDestroy = serializeAnalyzeDestroy;
5875  self->pub.mydest = DestExplainSerialize;
5876 
5877  self->es = es;
5878 
5879  return (DestReceiver *) self;
5880 }
@ DestExplainSerialize
Definition: dest.h:99
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: explain.c:5799
static void serializeAnalyzeDestroy(DestReceiver *self)
Definition: explain.c:5856
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
Definition: explain.c:5696
static void serializeAnalyzeShutdown(DestReceiver *self)
Definition: explain.c:5835
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 5432 of file explain.c.

5433 {
5434  switch (es->format)
5435  {
5436  case EXPLAIN_FORMAT_TEXT:
5437  /* nothing to do */
5438  break;
5439 
5440  case EXPLAIN_FORMAT_XML:
5442  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5443  es->indent++;
5444  break;
5445 
5446  case EXPLAIN_FORMAT_JSON:
5447  /* top-level structure is an array of plans */
5448  appendStringInfoChar(es->str, '[');
5449  es->grouping_stack = lcons_int(0, es->grouping_stack);
5450  es->indent++;
5451  break;
5452 
5453  case EXPLAIN_FORMAT_YAML:
5454  es->grouping_stack = lcons_int(0, es->grouping_stack);
5455  break;
5456  }
5457 }
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 5239 of file explain.c.

5241 {
5242  switch (es->format)
5243  {
5244  case EXPLAIN_FORMAT_TEXT:
5245  /* nothing to do */
5246  break;
5247 
5248  case EXPLAIN_FORMAT_XML:
5249  es->indent--;
5250  ExplainXMLTag(objtype, X_CLOSING, es);
5251  break;
5252 
5253  case EXPLAIN_FORMAT_JSON:
5254  es->indent--;
5255  appendStringInfoChar(es->str, '\n');
5256  appendStringInfoSpaces(es->str, 2 * es->indent);
5257  appendStringInfoChar(es->str, labeled ? '}' : ']');
5259  break;
5260 
5261  case EXPLAIN_FORMAT_YAML:
5262  es->indent--;
5264  break;
5265  }
5266 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5521
#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 5463 of file explain.c.

5464 {
5465  switch (es->format)
5466  {
5467  case EXPLAIN_FORMAT_TEXT:
5468  /* nothing to do */
5469  break;
5470 
5471  case EXPLAIN_FORMAT_XML:
5472  es->indent--;
5473  appendStringInfoString(es->str, "</explain>");
5474  break;
5475 
5476  case EXPLAIN_FORMAT_JSON:
5477  es->indent--;
5478  appendStringInfoString(es->str, "\n]");
5480  break;
5481 
5482  case EXPLAIN_FORMAT_YAML:
5484  break;
5485  }
5486 }

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

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

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

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

5178 {
5179  switch (es->format)
5180  {
5181  case EXPLAIN_FORMAT_TEXT:
5182  /* nothing to do */
5183  break;
5184 
5185  case EXPLAIN_FORMAT_XML:
5186  ExplainXMLTag(objtype, X_OPENING, es);
5187  es->indent++;
5188  break;
5189 
5190  case EXPLAIN_FORMAT_JSON:
5192  appendStringInfoSpaces(es->str, 2 * es->indent);
5193  if (labelname)
5194  {
5195  escape_json(es->str, labelname);
5196  appendStringInfoString(es->str, ": ");
5197  }
5198  appendStringInfoChar(es->str, labeled ? '{' : '[');
5199 
5200  /*
5201  * In JSON format, the grouping_stack is an integer list. 0 means
5202  * we've emitted nothing at this grouping level, 1 means we've
5203  * emitted something (and so the next item needs a comma). See
5204  * ExplainJSONLineEnding().
5205  */
5206  es->grouping_stack = lcons_int(0, es->grouping_stack);
5207  es->indent++;
5208  break;
5209 
5210  case EXPLAIN_FORMAT_YAML:
5211 
5212  /*
5213  * In YAML format, the grouping stack is an integer list. 0 means
5214  * we've emitted nothing at this grouping level AND this grouping
5215  * level is unlabeled and must be marked with "- ". See
5216  * ExplainYAMLLineStarting().
5217  */
5219  if (labelname)
5220  {
5221  appendStringInfo(es->str, "%s: ", labelname);
5222  es->grouping_stack = lcons_int(1, es->grouping_stack);
5223  }
5224  else
5225  {
5226  appendStringInfoString(es->str, "- ");
5227  es->grouping_stack = lcons_int(0, es->grouping_stack);
5228  }
5229  es->indent++;
5230  break;
5231  }
5232 }
#define X_OPENING
Definition: explain.c:61
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:5583
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:5563
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1602
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 1006 of file explain.c.

1007 {
1008  JitInstrumentation ji = {0};
1009 
1010  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
1011  return;
1012 
1013  /*
1014  * Work with a copy instead of modifying the leader state, since this
1015  * function may be called twice
1016  */
1017  if (queryDesc->estate->es_jit)
1018  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
1019 
1020  /* If this process has done JIT in parallel workers, merge stats */
1021  if (queryDesc->estate->es_jit_worker_instr)
1022  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
1023 
1024  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
1025 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:1032
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:182
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:729
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:730
int es_jit_flags
Definition: execnodes.h:728
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 886 of file explain.c.

887 {
888  Bitmapset *rels_used = NULL;
889  PlanState *ps;
890  ListCell *lc;
891 
892  /* Set up ExplainState fields associated with this plan tree */
893  Assert(queryDesc->plannedstmt != NULL);
894  es->pstmt = queryDesc->plannedstmt;
895  es->rtable = queryDesc->plannedstmt->rtable;
896  ExplainPreScanNode(queryDesc->planstate, &rels_used);
899  es->rtable_names);
900  es->printed_subplans = NULL;
901  es->rtable_size = list_length(es->rtable);
902  foreach(lc, es->rtable)
903  {
905 
906  if (rte->rtekind == RTE_GROUP)
907  {
908  es->rtable_size--;
909  break;
910  }
911  }
912 
913  /*
914  * Sometimes we mark a Gather node as "invisible", which means that it's
915  * not to be displayed in EXPLAIN output. The purpose of this is to allow
916  * running regression tests with debug_parallel_query=regress to get the
917  * same results as running the same tests with debug_parallel_query=off.
918  * Such marking is currently only supported on a Gather at the top of the
919  * plan. We skip that node, and we must also hide per-worker detail data
920  * further down in the plan tree.
921  */
922  ps = queryDesc->planstate;
923  if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
924  {
925  ps = outerPlanState(ps);
926  es->hide_workers = true;
927  }
928  ExplainNode(ps, NIL, NULL, NULL, es);
929 
930  /*
931  * If requested, include information about GUC parameters with values that
932  * don't match the built-in defaults.
933  */
935 
936  /*
937  * COMPUTE_QUERY_ID_REGRESS means COMPUTE_QUERY_ID_AUTO, but we don't show
938  * the queryid in any of the EXPLAIN plans to keep stable the results
939  * generated by regression test suites.
940  */
941  if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) &&
943  {
944  /*
945  * Output the queryid as an int64 rather than a uint64 so we match
946  * what would be seen in the BIGINT pg_stat_statements.queryid column.
947  */
948  ExplainPropertyInteger("Query Identifier", NULL, (int64)
949  queryDesc->plannedstmt->queryId, es);
950  }
951 }
#define outerPlanState(node)
Definition: execnodes.h:1224
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1478
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1313
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:5120
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:816
struct parser_state ps
@ RTE_GROUP
Definition: parsenodes.h:1028
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#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:3813
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3721
bool verbose
Definition: explain.h:48
int rtable_size
Definition: explain.h:70
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
RTEKind rtekind
Definition: parsenodes.h:1047

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, lfirst_node, list_length(), NIL, outerPlanState, QueryDesc::plannedstmt, QueryDesc::planstate, ExplainState::printed_subplans, ps, ExplainState::pstmt, PlannedStmt::queryId, ExplainState::rtable, PlannedStmt::rtable, ExplainState::rtable_names, ExplainState::rtable_size, RTE_GROUP, RangeTblEntry::rtekind, select_rtable_names_for_explain(), and ExplainState::verbose.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 963 of file explain.c.

964 {
965  ResultRelInfo *rInfo;
966  bool show_relname;
967  List *resultrels;
968  List *routerels;
969  List *targrels;
970  ListCell *l;
971 
972  resultrels = queryDesc->estate->es_opened_result_relations;
973  routerels = queryDesc->estate->es_tuple_routing_result_relations;
974  targrels = queryDesc->estate->es_trig_target_relations;
975 
976  ExplainOpenGroup("Triggers", "Triggers", false, es);
977 
978  show_relname = (list_length(resultrels) > 1 ||
979  routerels != NIL || targrels != NIL);
980  foreach(l, resultrels)
981  {
982  rInfo = (ResultRelInfo *) lfirst(l);
983  report_triggers(rInfo, show_relname, es);
984  }
985 
986  foreach(l, routerels)
987  {
988  rInfo = (ResultRelInfo *) lfirst(l);
989  report_triggers(rInfo, show_relname, es);
990  }
991 
992  foreach(l, targrels)
993  {
994  rInfo = (ResultRelInfo *) lfirst(l);
995  report_triggers(rInfo, show_relname, es);
996  }
997 
998  ExplainCloseGroup("Triggers", "Triggers", false, es);
999 }
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:1223
#define lfirst(lc)
Definition: pg_list.h:172
List * es_tuple_routing_result_relations
Definition: execnodes.h:663
List * es_trig_target_relations
Definition: execnodes.h:666
List * es_opened_result_relations
Definition: execnodes.h:653

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

5162 {
5163  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
5164 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:5058
static struct @157 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 5147 of file explain.c.

5149 {
5150  char *buf;
5151 
5152  buf = psprintf("%.*f", ndigits, value);
5153  ExplainProperty(qlabel, unit, buf, true, es);
5154  pfree(buf);
5155 }
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 4935 of file explain.c.

4936 {
4937  ListCell *lc;
4938  bool first = true;
4939 
4940  switch (es->format)
4941  {
4942  case EXPLAIN_FORMAT_TEXT:
4943  ExplainIndentText(es);
4944  appendStringInfo(es->str, "%s: ", qlabel);
4945  foreach(lc, data)
4946  {
4947  if (!first)
4948  appendStringInfoString(es->str, ", ");
4949  appendStringInfoString(es->str, (const char *) lfirst(lc));
4950  first = false;
4951  }
4952  appendStringInfoChar(es->str, '\n');
4953  break;
4954 
4955  case EXPLAIN_FORMAT_XML:
4956  ExplainXMLTag(qlabel, X_OPENING, es);
4957  foreach(lc, data)
4958  {
4959  char *str;
4960 
4961  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4962  appendStringInfoString(es->str, "<Item>");
4963  str = escape_xml((const char *) lfirst(lc));
4965  pfree(str);
4966  appendStringInfoString(es->str, "</Item>\n");
4967  }
4968  ExplainXMLTag(qlabel, X_CLOSING, es);
4969  break;
4970 
4971  case EXPLAIN_FORMAT_JSON:
4973  appendStringInfoSpaces(es->str, es->indent * 2);
4974  escape_json(es->str, qlabel);
4975  appendStringInfoString(es->str, ": [");
4976  foreach(lc, data)
4977  {
4978  if (!first)
4979  appendStringInfoString(es->str, ", ");
4980  escape_json(es->str, (const char *) lfirst(lc));
4981  first = false;
4982  }
4983  appendStringInfoChar(es->str, ']');
4984  break;
4985 
4986  case EXPLAIN_FORMAT_YAML:
4988  appendStringInfo(es->str, "%s: ", qlabel);
4989  foreach(lc, data)
4990  {
4991  appendStringInfoChar(es->str, '\n');
4992  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4993  appendStringInfoString(es->str, "- ");
4994  escape_yaml(es->str, (const char *) lfirst(lc));
4995  }
4996  break;
4997  }
4998 }
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:5608
const char * str
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2695

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

5006 {
5007  ListCell *lc;
5008  bool first = true;
5009 
5010  switch (es->format)
5011  {
5012  case EXPLAIN_FORMAT_TEXT:
5013  case EXPLAIN_FORMAT_XML:
5014  ExplainPropertyList(qlabel, data, es);
5015  return;
5016 
5017  case EXPLAIN_FORMAT_JSON:
5019  appendStringInfoSpaces(es->str, es->indent * 2);
5020  appendStringInfoChar(es->str, '[');
5021  foreach(lc, data)
5022  {
5023  if (!first)
5024  appendStringInfoString(es->str, ", ");
5025  escape_json(es->str, (const char *) lfirst(lc));
5026  first = false;
5027  }
5028  appendStringInfoChar(es->str, ']');
5029  break;
5030 
5031  case EXPLAIN_FORMAT_YAML:
5033  appendStringInfoString(es->str, "- [");
5034  foreach(lc, data)
5035  {
5036  if (!first)
5037  appendStringInfoString(es->str, ", ");
5038  escape_yaml(es->str, (const char *) lfirst(lc));
5039  first = false;
5040  }
5041  appendStringInfoChar(es->str, ']');
5042  break;
5043  }
5044 }
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4935

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

5135 {
5136  char buf[32];
5137 
5138  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
5139  ExplainProperty(qlabel, unit, buf, true, es);
5140 }
#define UINT64_FORMAT
Definition: c.h:540

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

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

1206 {
1207  char *str;
1208 
1209  /* This check is consistent with errdetail_params() */
1210  if (params == NULL || params->numParams <= 0 || maxlen == 0)
1211  return;
1212 
1213  str = BuildParamLogString(params, NULL, maxlen);
1214  if (str && str[0] != '\0')
1215  ExplainPropertyText("Query Parameters", str, es);
1216 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:5111
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 1190 of file explain.c.

1191 {
1192  if (queryDesc->sourceText)
1193  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1194 }
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 398 of file explain.c.

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

5493 {
5494  switch (es->format)
5495  {
5496  case EXPLAIN_FORMAT_TEXT:
5497  /* add a blank line */
5498  appendStringInfoChar(es->str, '\n');
5499  break;
5500 
5501  case EXPLAIN_FORMAT_XML:
5502  case EXPLAIN_FORMAT_JSON:
5503  case EXPLAIN_FORMAT_YAML:
5504  /* nothing to do */
5505  break;
5506  }
5507 }

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

382 {
383  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
384 
385  /* Set default options (most fields can be left as zeroes). */
386  es->costs = true;
387  /* Prepare output buffer. */
388  es->str = makeStringInfo();
389 
390  return es;
391 }
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 464 of file explain.c.

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