PostgreSQL Source Code  git master
explain.h File Reference
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "parser/parse_node.h"
Include dependency graph for explain.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ExplainWorkersState
 
struct  ExplainState
 

Typedefs

typedef enum ExplainFormat ExplainFormat
 
typedef struct ExplainWorkersState ExplainWorkersState
 
typedef struct ExplainState ExplainState
 
typedef void(* ExplainOneQuery_hook_type) (Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
typedef const char *(* explain_get_index_name_hook_type) (Oid indexId)
 

Enumerations

enum  ExplainFormat { EXPLAIN_FORMAT_TEXT , EXPLAIN_FORMAT_XML , EXPLAIN_FORMAT_JSON , EXPLAIN_FORMAT_YAML }
 

Functions

void ExplainQuery (ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest)
 
ExplainStateNewExplainState (void)
 
TupleDesc ExplainResultDesc (ExplainStmt *stmt)
 
void ExplainOneUtility (Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
void ExplainOnePlan (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage)
 
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 ExplainBeginOutput (ExplainState *es)
 
void ExplainEndOutput (ExplainState *es)
 
void ExplainSeparatePlans (ExplainState *es)
 
void ExplainPropertyList (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyListNested (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyText (const char *qlabel, const char *value, ExplainState *es)
 
void ExplainPropertyInteger (const char *qlabel, const char *unit, int64 value, ExplainState *es)
 
void ExplainPropertyUInteger (const char *qlabel, const char *unit, uint64 value, ExplainState *es)
 
void ExplainPropertyFloat (const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
 
void ExplainPropertyBool (const char *qlabel, bool value, ExplainState *es)
 
void ExplainOpenGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 
void ExplainCloseGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 

Variables

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
 
PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
 

Typedef Documentation

◆ explain_get_index_name_hook_type

typedef const char*(* explain_get_index_name_hook_type) (Oid indexId)

Definition at line 75 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 65 of file explain.h.

◆ ExplainState

typedef struct ExplainState ExplainState

◆ ExplainWorkersState

Enumeration Type Documentation

◆ ExplainFormat

Enumerator
EXPLAIN_FORMAT_TEXT 
EXPLAIN_FORMAT_XML 
EXPLAIN_FORMAT_JSON 
EXPLAIN_FORMAT_YAML 

Definition at line 20 of file explain.h.

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

Function Documentation

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 4748 of file explain.c.

4749 {
4750  switch (es->format)
4751  {
4752  case EXPLAIN_FORMAT_TEXT:
4753  /* nothing to do */
4754  break;
4755 
4756  case EXPLAIN_FORMAT_XML:
4758  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
4759  es->indent++;
4760  break;
4761 
4762  case EXPLAIN_FORMAT_JSON:
4763  /* top-level structure is an array of plans */
4764  appendStringInfoChar(es->str, '[');
4765  es->grouping_stack = lcons_int(0, es->grouping_stack);
4766  es->indent++;
4767  break;
4768 
4769  case EXPLAIN_FORMAT_YAML:
4770  es->grouping_stack = lcons_int(0, es->grouping_stack);
4771  break;
4772  }
4773 }
List * lcons_int(int datum, List *list)
Definition: list.c:492
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
List * grouping_stack
Definition: explain.h:52
StringInfo str
Definition: explain.h:39
ExplainFormat format
Definition: explain.h:49
int indent
Definition: explain.h:51

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

4557 {
4558  switch (es->format)
4559  {
4560  case EXPLAIN_FORMAT_TEXT:
4561  /* nothing to do */
4562  break;
4563 
4564  case EXPLAIN_FORMAT_XML:
4565  es->indent--;
4566  ExplainXMLTag(objtype, X_CLOSING, es);
4567  break;
4568 
4569  case EXPLAIN_FORMAT_JSON:
4570  es->indent--;
4571  appendStringInfoChar(es->str, '\n');
4572  appendStringInfoSpaces(es->str, 2 * es->indent);
4573  appendStringInfoChar(es->str, labeled ? '}' : ']');
4575  break;
4576 
4577  case EXPLAIN_FORMAT_YAML:
4578  es->indent--;
4580  break;
4581  }
4582 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:4837
#define X_CLOSING
Definition: explain.c:53
List * list_delete_first(List *list)
Definition: list.c:902
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206

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

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

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 4779 of file explain.c.

4780 {
4781  switch (es->format)
4782  {
4783  case EXPLAIN_FORMAT_TEXT:
4784  /* nothing to do */
4785  break;
4786 
4787  case EXPLAIN_FORMAT_XML:
4788  es->indent--;
4789  appendStringInfoString(es->str, "</explain>");
4790  break;
4791 
4792  case EXPLAIN_FORMAT_JSON:
4793  es->indent--;
4794  appendStringInfoString(es->str, "\n]");
4796  break;
4797 
4798  case EXPLAIN_FORMAT_YAML:
4800  break;
4801  }
4802 }

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 
)

Definition at line 518 of file explain.c.

522 {
524  QueryDesc *queryDesc;
525  instr_time starttime;
526  double totaltime = 0;
527  int eflags;
528  int instrument_option = 0;
529 
530  Assert(plannedstmt->commandType != CMD_UTILITY);
531 
532  if (es->analyze && es->timing)
533  instrument_option |= INSTRUMENT_TIMER;
534  else if (es->analyze)
535  instrument_option |= INSTRUMENT_ROWS;
536 
537  if (es->buffers)
538  instrument_option |= INSTRUMENT_BUFFERS;
539  if (es->wal)
540  instrument_option |= INSTRUMENT_WAL;
541 
542  /*
543  * We always collect timing for the entire statement, even when node-level
544  * timing is off, so we don't look at es->timing here. (We could skip
545  * this if !es->summary, but it's hardly worth the complication.)
546  */
547  INSTR_TIME_SET_CURRENT(starttime);
548 
549  /*
550  * Use a snapshot with an updated command ID to ensure this query sees
551  * results of any previously executed queries.
552  */
555 
556  /*
557  * Normally we discard the query's output, but if explaining CREATE TABLE
558  * AS, we'd better use the appropriate tuple receiver.
559  */
560  if (into)
562  else
564 
565  /* Create a QueryDesc for the query */
566  queryDesc = CreateQueryDesc(plannedstmt, queryString,
568  dest, params, queryEnv, instrument_option);
569 
570  /* Select execution options */
571  if (es->analyze)
572  eflags = 0; /* default run-to-completion flags */
573  else
574  eflags = EXEC_FLAG_EXPLAIN_ONLY;
575  if (into)
576  eflags |= GetIntoRelEFlags(into);
577 
578  /* call ExecutorStart to prepare the plan for execution */
579  ExecutorStart(queryDesc, eflags);
580 
581  /* Execute the plan for statistics if asked for */
582  if (es->analyze)
583  {
584  ScanDirection dir;
585 
586  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
587  if (into && into->skipData)
589  else
590  dir = ForwardScanDirection;
591 
592  /* run the plan */
593  ExecutorRun(queryDesc, dir, 0L, true);
594 
595  /* run cleanup too */
596  ExecutorFinish(queryDesc);
597 
598  /* We can't run ExecutorEnd 'till we're done printing the stats... */
599  totaltime += elapsed_time(&starttime);
600  }
601 
602  ExplainOpenGroup("Query", NULL, true, es);
603 
604  /* Create textual dump of plan tree */
605  ExplainPrintPlan(es, queryDesc);
606 
607  if (es->verbose && plannedstmt->queryId != UINT64CONST(0))
608  {
609  /*
610  * Output the queryid as an int64 rather than a uint64 so we match
611  * what would be seen in the BIGINT pg_stat_statements.queryid column.
612  */
613  ExplainPropertyInteger("Query Identifier", NULL, (int64)
614  plannedstmt->queryId, es);
615  }
616 
617  /* Show buffer usage in planning */
618  if (bufusage)
619  {
620  ExplainOpenGroup("Planning", "Planning", true, es);
621  show_buffer_usage(es, bufusage, true);
622  ExplainCloseGroup("Planning", "Planning", true, es);
623  }
624 
625  if (es->summary && planduration)
626  {
627  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
628 
629  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
630  }
631 
632  /* Print info about runtime of triggers */
633  if (es->analyze)
634  ExplainPrintTriggers(es, queryDesc);
635 
636  /*
637  * Print info about JITing. Tied to es->costs because we don't want to
638  * display this in regression tests, as it'd cause output differences
639  * depending on build options. Might want to separate that out from COSTS
640  * at a later stage.
641  */
642  if (es->costs)
643  ExplainPrintJITSummary(es, queryDesc);
644 
645  /*
646  * Close down the query and free resources. Include time for this in the
647  * total execution time (although it should be pretty minimal).
648  */
649  INSTR_TIME_SET_CURRENT(starttime);
650 
651  ExecutorEnd(queryDesc);
652 
653  FreeQueryDesc(queryDesc);
654 
656 
657  /* We need a CCI just in case query expanded to multiple plans */
658  if (es->analyze)
660 
661  totaltime += elapsed_time(&starttime);
662 
663  /*
664  * We only report execution time if we actually ran the query (that is,
665  * the user specified ANALYZE), and if summary reporting is enabled (the
666  * user can set SUMMARY OFF to not have the timing information included in
667  * the output). By default, ANALYZE sets SUMMARY to true.
668  */
669  if (es->summary && es->analyze)
670  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
671  es);
672 
673  ExplainCloseGroup("Query", NULL, true, es);
674 }
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:428
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:375
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:459
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:399
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:130
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:298
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4492
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:4436
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:843
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:4463
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:4555
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage, bool planning)
Definition: explain.c:3491
static double elapsed_time(instr_time *starttime)
Definition: explain.c:1045
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:751
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:800
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:199
struct timeval instr_time
Definition: instr_time.h:150
@ INSTRUMENT_TIMER
Definition: instrument.h:57
@ INSTRUMENT_BUFFERS
Definition: instrument.h:58
@ INSTRUMENT_WAL
Definition: instrument.h:60
@ INSTRUMENT_ROWS
Definition: instrument.h:59
Assert(fmt[strlen(fmt) - 1] !='\n')
@ CMD_UTILITY
Definition: nodes.h:690
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:23
@ NoMovementScanDirection
Definition: sdir.h:25
@ ForwardScanDirection
Definition: sdir.h:26
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:743
void PopActiveSnapshot(void)
Definition: snapmgr.c:774
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:731
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:801
#define InvalidSnapshot
Definition: snapshot.h:123
bool verbose
Definition: explain.h:41
bool timing
Definition: explain.h:46
bool analyze
Definition: explain.h:42
bool wal
Definition: explain.h:45
bool summary
Definition: explain.h:47
bool costs
Definition: explain.h:43
bool buffers
Definition: explain.h:44
bool skipData
Definition: primnodes.h:119
CmdType commandType
Definition: plannodes.h:46
uint64 queryId
Definition: plannodes.h:48
void CommandCounterIncrement(void)
Definition: xact.c:1073

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

◆ ExplainOneUtility()

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

Definition at line 428 of file explain.c.

431 {
432  if (utilityStmt == NULL)
433  return;
434 
435  if (IsA(utilityStmt, CreateTableAsStmt))
436  {
437  /*
438  * We have to rewrite the contained SELECT and then pass it back to
439  * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case.
440  */
441  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
442  List *rewritten;
443 
444  /*
445  * Check if the relation exists or not. This is done at this stage to
446  * avoid query planning or execution.
447  */
448  if (CreateTableAsRelExists(ctas))
449  {
450  if (ctas->objtype == OBJECT_TABLE)
451  ExplainDummyGroup("CREATE TABLE AS", NULL, es);
452  else if (ctas->objtype == OBJECT_MATVIEW)
453  ExplainDummyGroup("CREATE MATERIALIZED VIEW", NULL, es);
454  else
455  elog(ERROR, "unexpected object type: %d",
456  (int) ctas->objtype);
457  return;
458  }
459 
460  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
461  Assert(list_length(rewritten) == 1);
462  ExplainOneQuery(linitial_node(Query, rewritten),
463  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
464  queryString, params, queryEnv);
465  }
466  else if (IsA(utilityStmt, DeclareCursorStmt))
467  {
468  /*
469  * Likewise for DECLARE CURSOR.
470  *
471  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
472  * actually run the query. This is different from pre-8.3 behavior
473  * but seems more useful than not running the query. No cursor will
474  * be created, however.
475  */
476  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
477  List *rewritten;
478 
479  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
480  Assert(list_length(rewritten) == 1);
481  ExplainOneQuery(linitial_node(Query, rewritten),
482  dcs->options, NULL, es,
483  queryString, params, queryEnv);
484  }
485  else if (IsA(utilityStmt, ExecuteStmt))
486  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
487  queryString, params, queryEnv);
488  else if (IsA(utilityStmt, NotifyStmt))
489  {
490  if (es->format == EXPLAIN_FORMAT_TEXT)
491  appendStringInfoString(es->str, "NOTIFY\n");
492  else
493  ExplainDummyGroup("Notify", NULL, es);
494  }
495  else
496  {
497  if (es->format == EXPLAIN_FORMAT_TEXT)
499  "Utility statements have no plan structure\n");
500  else
501  ExplainDummyGroup("Utility Statement", NULL, es);
502  }
503 }
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:605
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:393
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:4702
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:367
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
#define copyObject(obj)
Definition: nodes.h:655
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
@ OBJECT_MATVIEW
Definition: parsenodes.h:1812
@ OBJECT_TABLE
Definition: parsenodes.h:1829
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2830
static int list_length(const List *l)
Definition: pg_list.h:149
#define linitial_node(type, l)
Definition: pg_list.h:177
List * QueryRewrite(Query *parsetree)
IntoClause * into
Definition: parsenodes.h:3411
ObjectType objtype
Definition: parsenodes.h:3412
Definition: pg_list.h:51

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

4494 {
4495  switch (es->format)
4496  {
4497  case EXPLAIN_FORMAT_TEXT:
4498  /* nothing to do */
4499  break;
4500 
4501  case EXPLAIN_FORMAT_XML:
4502  ExplainXMLTag(objtype, X_OPENING, es);
4503  es->indent++;
4504  break;
4505 
4506  case EXPLAIN_FORMAT_JSON:
4508  appendStringInfoSpaces(es->str, 2 * es->indent);
4509  if (labelname)
4510  {
4511  escape_json(es->str, labelname);
4512  appendStringInfoString(es->str, ": ");
4513  }
4514  appendStringInfoChar(es->str, labeled ? '{' : '[');
4515 
4516  /*
4517  * In JSON format, the grouping_stack is an integer list. 0 means
4518  * we've emitted nothing at this grouping level, 1 means we've
4519  * emitted something (and so the next item needs a comma). See
4520  * ExplainJSONLineEnding().
4521  */
4522  es->grouping_stack = lcons_int(0, es->grouping_stack);
4523  es->indent++;
4524  break;
4525 
4526  case EXPLAIN_FORMAT_YAML:
4527 
4528  /*
4529  * In YAML format, the grouping stack is an integer list. 0 means
4530  * we've emitted nothing at this grouping level AND this grouping
4531  * level is unlabeled and must be marked with "- ". See
4532  * ExplainYAMLLineStarting().
4533  */
4535  if (labelname)
4536  {
4537  appendStringInfo(es->str, "%s: ", labelname);
4538  es->grouping_stack = lcons_int(1, es->grouping_stack);
4539  }
4540  else
4541  {
4542  appendStringInfoString(es->str, "- ");
4543  es->grouping_stack = lcons_int(0, es->grouping_stack);
4544  }
4545  es->indent++;
4546  break;
4547  }
4548 }
#define X_OPENING
Definition: explain.c:52
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:4899
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:4879
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1279
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91

References appendStringInfo(), appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), escape_json(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainJSONLineEnding(), ExplainXMLTag(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, lcons_int(), ExplainState::str, and X_OPENING.

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

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 843 of file explain.c.

844 {
845  JitInstrumentation ji = {0};
846 
847  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
848  return;
849 
850  /*
851  * Work with a copy instead of modifying the leader state, since this
852  * function may be called twice
853  */
854  if (queryDesc->estate->es_jit)
855  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
856 
857  /* If this process has done JIT in parallel workers, merge stats */
858  if (queryDesc->estate->es_jit_worker_instr)
859  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
860 
861  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
862 }
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:869
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:184
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:651
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:652
int es_jit_flags
Definition: execnodes.h:650
JitInstrumentation instr
Definition: jit.h:61
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 751 of file explain.c.

752 {
753  Bitmapset *rels_used = NULL;
754  PlanState *ps;
755 
756  /* Set up ExplainState fields associated with this plan tree */
757  Assert(queryDesc->plannedstmt != NULL);
758  es->pstmt = queryDesc->plannedstmt;
759  es->rtable = queryDesc->plannedstmt->rtable;
760  ExplainPreScanNode(queryDesc->planstate, &rels_used);
763  es->rtable_names);
764  es->printed_subplans = NULL;
765 
766  /*
767  * Sometimes we mark a Gather node as "invisible", which means that it's
768  * not to be displayed in EXPLAIN output. The purpose of this is to allow
769  * running regression tests with force_parallel_mode=regress to get the
770  * same results as running the same tests with force_parallel_mode=off.
771  * Such marking is currently only supported on a Gather at the top of the
772  * plan. We skip that node, and we must also hide per-worker detail data
773  * further down in the plan tree.
774  */
775  ps = queryDesc->planstate;
776  if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
777  {
778  ps = outerPlanState(ps);
779  es->hide_workers = true;
780  }
781  ExplainNode(ps, NIL, NULL, NULL, es);
782 
783  /*
784  * If requested, include information about GUC parameters with values that
785  * don't match the built-in defaults.
786  */
788 }
#define outerPlanState(node)
Definition: execnodes.h:1067
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1139
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1064
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:681
#define NIL
Definition: pg_list.h:65
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3752
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3660
Bitmapset * printed_subplans
Definition: explain.h:58
bool hide_workers
Definition: explain.h:59
List * rtable_names
Definition: explain.h:56
List * rtable
Definition: explain.h:55
PlannedStmt * pstmt
Definition: explain.h:54
List * deparse_cxt
Definition: explain.h:57
Plan * plan
Definition: execnodes.h:971
List * rtable
Definition: plannodes.h:66
PlannedStmt * plannedstmt
Definition: execdesc.h:37
PlanState * planstate
Definition: execdesc.h:49

References Assert(), deparse_context_for_plan_tree(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), ExplainState::hide_workers, IsA, NIL, outerPlanState, PlanState::plan, QueryDesc::plannedstmt, QueryDesc::planstate, ExplainState::printed_subplans, ExplainState::pstmt, ExplainState::rtable, PlannedStmt::rtable, ExplainState::rtable_names, and select_rtable_names_for_explain().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 800 of file explain.c.

801 {
802  ResultRelInfo *rInfo;
803  bool show_relname;
804  List *resultrels;
805  List *routerels;
806  List *targrels;
807  ListCell *l;
808 
809  resultrels = queryDesc->estate->es_opened_result_relations;
810  routerels = queryDesc->estate->es_tuple_routing_result_relations;
811  targrels = queryDesc->estate->es_trig_target_relations;
812 
813  ExplainOpenGroup("Triggers", "Triggers", false, es);
814 
815  show_relname = (list_length(resultrels) > 1 ||
816  routerels != NIL || targrels != NIL);
817  foreach(l, resultrels)
818  {
819  rInfo = (ResultRelInfo *) lfirst(l);
820  report_triggers(rInfo, show_relname, es);
821  }
822 
823  foreach(l, routerels)
824  {
825  rInfo = (ResultRelInfo *) lfirst(l);
826  report_triggers(rInfo, show_relname, es);
827  }
828 
829  foreach(l, targrels)
830  {
831  rInfo = (ResultRelInfo *) lfirst(l);
832  report_triggers(rInfo, show_relname, es);
833  }
834 
835  ExplainCloseGroup("Triggers", "Triggers", false, es);
836 }
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:974
#define lfirst(lc)
Definition: pg_list.h:169
List * es_tuple_routing_result_relations
Definition: execnodes.h:593
List * es_trig_target_relations
Definition: execnodes.h:596
List * es_opened_result_relations
Definition: execnodes.h:583

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

4478 {
4479  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
4480 }
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:4374
static struct @142 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 4463 of file explain.c.

4465 {
4466  char *buf;
4467 
4468  buf = psprintf("%.*f", ndigits, value);
4469  ExplainProperty(qlabel, unit, buf, true, es);
4470  pfree(buf);
4471 }
void pfree(void *pointer)
Definition: mcxt.c:1169
static char * buf
Definition: pg_test_fsync.c:70
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

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

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

◆ ExplainPropertyInteger()

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

◆ ExplainPropertyList()

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

Definition at line 4251 of file explain.c.

4252 {
4253  ListCell *lc;
4254  bool first = true;
4255 
4256  switch (es->format)
4257  {
4258  case EXPLAIN_FORMAT_TEXT:
4259  ExplainIndentText(es);
4260  appendStringInfo(es->str, "%s: ", qlabel);
4261  foreach(lc, data)
4262  {
4263  if (!first)
4264  appendStringInfoString(es->str, ", ");
4265  appendStringInfoString(es->str, (const char *) lfirst(lc));
4266  first = false;
4267  }
4268  appendStringInfoChar(es->str, '\n');
4269  break;
4270 
4271  case EXPLAIN_FORMAT_XML:
4272  ExplainXMLTag(qlabel, X_OPENING, es);
4273  foreach(lc, data)
4274  {
4275  char *str;
4276 
4277  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4278  appendStringInfoString(es->str, "<Item>");
4279  str = escape_xml((const char *) lfirst(lc));
4281  pfree(str);
4282  appendStringInfoString(es->str, "</Item>\n");
4283  }
4284  ExplainXMLTag(qlabel, X_CLOSING, es);
4285  break;
4286 
4287  case EXPLAIN_FORMAT_JSON:
4289  appendStringInfoSpaces(es->str, es->indent * 2);
4290  escape_json(es->str, qlabel);
4291  appendStringInfoString(es->str, ": [");
4292  foreach(lc, data)
4293  {
4294  if (!first)
4295  appendStringInfoString(es->str, ", ");
4296  escape_json(es->str, (const char *) lfirst(lc));
4297  first = false;
4298  }
4299  appendStringInfoChar(es->str, ']');
4300  break;
4301 
4302  case EXPLAIN_FORMAT_YAML:
4304  appendStringInfo(es->str, "%s: ", qlabel);
4305  foreach(lc, data)
4306  {
4307  appendStringInfoChar(es->str, '\n');
4308  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4309  appendStringInfoString(es->str, "- ");
4310  escape_yaml(es->str, (const char *) lfirst(lc));
4311  }
4312  break;
4313  }
4314 }
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:4864
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:4924
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2353

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

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

◆ ExplainPropertyListNested()

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

Definition at line 4321 of file explain.c.

4322 {
4323  ListCell *lc;
4324  bool first = true;
4325 
4326  switch (es->format)
4327  {
4328  case EXPLAIN_FORMAT_TEXT:
4329  case EXPLAIN_FORMAT_XML:
4330  ExplainPropertyList(qlabel, data, es);
4331  return;
4332 
4333  case EXPLAIN_FORMAT_JSON:
4335  appendStringInfoSpaces(es->str, es->indent * 2);
4336  appendStringInfoChar(es->str, '[');
4337  foreach(lc, data)
4338  {
4339  if (!first)
4340  appendStringInfoString(es->str, ", ");
4341  escape_json(es->str, (const char *) lfirst(lc));
4342  first = false;
4343  }
4344  appendStringInfoChar(es->str, ']');
4345  break;
4346 
4347  case EXPLAIN_FORMAT_YAML:
4349  appendStringInfoString(es->str, "- [");
4350  foreach(lc, data)
4351  {
4352  if (!first)
4353  appendStringInfoString(es->str, ", ");
4354  escape_yaml(es->str, (const char *) lfirst(lc));
4355  first = false;
4356  }
4357  appendStringInfoChar(es->str, ']');
4358  break;
4359  }
4360 }
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4251

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

4451 {
4452  char buf[32];
4453 
4454  snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
4455  ExplainProperty(qlabel, unit, buf, true, es);
4456 }
#define UINT64_FORMAT
Definition: c.h:484

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

Referenced by show_wal_usage().

◆ ExplainQuery()

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

Definition at line 164 of file explain.c.

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

References ExplainState::analyze, appendStringInfoString(), Assert(), begin_tup_output_tupdesc(), ExplainState::buffers, castNode, ExplainState::costs, CURSOR_OPT_PARALLEL_OK, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, generate_unaccent_rules::dest, do_text_output_multiline(), do_text_output_oneline, end_tup_output(), ereport, errcode(), errmsg(), ERROR, EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainBeginOutput(), ExplainEndOutput(), ExplainOneQuery(), ExplainResultDesc(), ExplainSeparatePlans(), ExplainState::format, if(), ExplainState::indent, IsQueryIdEnabled(), JumbleQuery(), lfirst, lfirst_node, lnext(), DefElem::location, NewExplainState(), NIL, ExplainStmt::options, ParseState::p_queryEnv, ParseState::p_sourcetext, parser_errposition(), pfree(), post_parse_analyze_hook, ExplainStmt::query, QueryRewrite(), ExplainState::settings, ExplainState::str, ExplainState::summary, ExplainState::timing, TTSOpsVirtual, ExplainState::verbose, and ExplainState::wal.

Referenced by standard_ProcessUtility().

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 963 of file explain.c.

964 {
965  if (queryDesc->sourceText)
966  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
967 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:4427
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 328 of file explain.c.

329 {
330  TupleDesc tupdesc;
331  ListCell *lc;
332  Oid result_type = TEXTOID;
333 
334  /* Check for XML format option */
335  foreach(lc, stmt->options)
336  {
337  DefElem *opt = (DefElem *) lfirst(lc);
338 
339  if (strcmp(opt->defname, "format") == 0)
340  {
341  char *p = defGetString(opt);
342 
343  if (strcmp(p, "xml") == 0)
344  result_type = XMLOID;
345  else if (strcmp(p, "json") == 0)
346  result_type = JSONOID;
347  else
348  result_type = TEXTOID;
349  /* don't "break", as ExplainQuery will use the last value */
350  }
351  }
352 
353  /* Need a tuple descriptor representing a single TEXT or XML column */
354  tupdesc = CreateTemplateTupleDesc(1);
355  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
356  result_type, -1, 0);
357  return tupdesc;
358 }
int16 AttrNumber
Definition: attnum.h:21
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 4808 of file explain.c.

4809 {
4810  switch (es->format)
4811  {
4812  case EXPLAIN_FORMAT_TEXT:
4813  /* add a blank line */
4814  appendStringInfoChar(es->str, '\n');
4815  break;
4816 
4817  case EXPLAIN_FORMAT_XML:
4818  case EXPLAIN_FORMAT_JSON:
4819  case EXPLAIN_FORMAT_YAML:
4820  /* nothing to do */
4821  break;
4822  }
4823 }

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

312 {
313  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
314 
315  /* Set default options (most fields can be left as zeroes). */
316  es->costs = true;
317  /* Prepare output buffer. */
318  es->str = makeStringInfo();
319 
320  return es;
321 }
void * palloc0(Size size)
Definition: mcxt.c:1093
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
extern

Definition at line 48 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 45 of file explain.c.

Referenced by ExplainOneQuery().