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

5556 {
5557  SerializeDestReceiver *self;
5558 
5560 
5561  self->pub.receiveSlot = serializeAnalyzeReceive;
5562  self->pub.rStartup = serializeAnalyzeStartup;
5563  self->pub.rShutdown = serializeAnalyzeShutdown;
5564  self->pub.rDestroy = serializeAnalyzeDestroy;
5565  self->pub.mydest = DestExplainSerialize;
5566 
5567  self->es = es;
5568 
5569  return (DestReceiver *) self;
5570 }
@ DestExplainSerialize
Definition: dest.h:99
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: explain.c:5489
static void serializeAnalyzeDestroy(DestReceiver *self)
Definition: explain.c:5546
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
Definition: explain.c:5386
static void serializeAnalyzeShutdown(DestReceiver *self)
Definition: explain.c:5525
void * palloc0(Size size)
Definition: mcxt.c:1346

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

Referenced by CreateDestReceiver(), and ExplainOnePlan().

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 5122 of file explain.c.

5123 {
5124  switch (es->format)
5125  {
5126  case EXPLAIN_FORMAT_TEXT:
5127  /* nothing to do */
5128  break;
5129 
5130  case EXPLAIN_FORMAT_XML:
5132  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5133  es->indent++;
5134  break;
5135 
5136  case EXPLAIN_FORMAT_JSON:
5137  /* top-level structure is an array of plans */
5138  appendStringInfoChar(es->str, '[');
5139  es->grouping_stack = lcons_int(0, es->grouping_stack);
5140  es->indent++;
5141  break;
5142 
5143  case EXPLAIN_FORMAT_YAML:
5144  es->grouping_stack = lcons_int(0, es->grouping_stack);
5145  break;
5146  }
5147 }
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 4929 of file explain.c.

4931 {
4932  switch (es->format)
4933  {
4934  case EXPLAIN_FORMAT_TEXT:
4935  /* nothing to do */
4936  break;
4937 
4938  case EXPLAIN_FORMAT_XML:
4939  es->indent--;
4940  ExplainXMLTag(objtype, X_CLOSING, es);
4941  break;
4942 
4943  case EXPLAIN_FORMAT_JSON:
4944  es->indent--;
4945  appendStringInfoChar(es->str, '\n');
4946  appendStringInfoSpaces(es->str, 2 * es->indent);
4947  appendStringInfoChar(es->str, labeled ? '}' : ']');
4949  break;
4950 
4951  case EXPLAIN_FORMAT_YAML:
4952  es->indent--;
4954  break;
4955  }
4956 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5211
#define X_CLOSING
Definition: explain.c:61
List * list_delete_first(List *list)
Definition: list.c:943
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:212

References appendStringInfoChar(), appendStringInfoSpaces(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainXMLTag(), ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, list_delete_first(), ExplainState::str, and X_CLOSING.

Referenced by ExplainFlushWorkersState(), ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintSerialize(), ExplainPrintSettings(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_incremental_sort_group_info(), and show_modifytable_info().

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 5153 of file explain.c.

5154 {
5155  switch (es->format)
5156  {
5157  case EXPLAIN_FORMAT_TEXT:
5158  /* nothing to do */
5159  break;
5160 
5161  case EXPLAIN_FORMAT_XML:
5162  es->indent--;
5163  appendStringInfoString(es->str, "</explain>");
5164  break;
5165 
5166  case EXPLAIN_FORMAT_JSON:
5167  es->indent--;
5168  appendStringInfoString(es->str, "\n]");
5170  break;
5171 
5172  case EXPLAIN_FORMAT_YAML:
5174  break;
5175  }
5176 }

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

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

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

Referenced by ExplainExecuteQuery(), and standard_ExplainOneQuery().

◆ ExplainOneUtility()

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

Definition at line 526 of file explain.c.

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

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

985 {
986  JitInstrumentation ji = {0};
987 
988  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
989  return;
990 
991  /*
992  * Work with a copy instead of modifying the leader state, since this
993  * function may be called twice
994  */
995  if (queryDesc->estate->es_jit)
996  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
997 
998  /* If this process has done JIT in parallel workers, merge stats */
999  if (queryDesc->estate->es_jit_worker_instr)
1000  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
1001 
1002  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
1003 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:1010
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:182
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:716
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:717
int es_jit_flags
Definition: execnodes.h:715
JitInstrumentation instr
Definition: jit.h:64
EState * estate
Definition: execdesc.h:48

References EState::es_jit, EState::es_jit_flags, EState::es_jit_worker_instr, QueryDesc::estate, ExplainPrintJIT(), JitContext::instr, InstrJitAgg(), and PGJIT_PERFORM.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 876 of file explain.c.

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

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

4852 {
4853  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4854 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4748
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 4837 of file explain.c.

4839 {
4840  char *buf;
4841 
4842  buf = psprintf("%.*f", ndigits, value);
4843  ExplainProperty(qlabel, unit, buf, true, es);
4844  pfree(buf);
4845 }
void pfree(void *pointer)
Definition: mcxt.c:1520
static char * buf
Definition: pg_test_fsync.c:73
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

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

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

◆ ExplainPropertyInteger()

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

◆ ExplainPropertyList()

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

Definition at line 4625 of file explain.c.

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

References appendStringInfo(), appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), data, escape_json(), escape_xml(), escape_yaml(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainIndentText(), ExplainJSONLineEnding(), ExplainXMLTag(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::indent, lfirst, pfree(), ExplainState::str, str, X_CLOSING, and X_OPENING.

Referenced by ExplainPropertyListNested(), show_incremental_sort_group_info(), show_modifytable_info(), show_plan_tlist(), show_sort_group_keys(), and show_tablesample().

◆ ExplainPropertyListNested()

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

Definition at line 4695 of file explain.c.

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

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

4825 {
4826  char buf[32];
4827 
4828  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4829  ExplainProperty(qlabel, unit, buf, true, es);
4830 }
#define UINT64_FORMAT
Definition: c.h:549

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

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

◆ ExplainQuery()

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

Definition at line 182 of file explain.c.

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

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

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

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 388 of file explain.c.

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

5183 {
5184  switch (es->format)
5185  {
5186  case EXPLAIN_FORMAT_TEXT:
5187  /* add a blank line */
5188  appendStringInfoChar(es->str, '\n');
5189  break;
5190 
5191  case EXPLAIN_FORMAT_XML:
5192  case EXPLAIN_FORMAT_JSON:
5193  case EXPLAIN_FORMAT_YAML:
5194  /* nothing to do */
5195  break;
5196  }
5197 }

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

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

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

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

Referenced by ExplainOneQuery().

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
extern

Definition at line 48 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 45 of file explain.c.

Referenced by ExplainOneQuery().