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  ExplainState
 

Typedefs

typedef enum ExplainFormat ExplainFormat
 
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, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, 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)
 
void ExplainPrintPlan (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintTriggers (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintJITSummary (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintJIT (ExplainState *es, int jit_flags, struct JitInstrumentation *jit_instr, int worker_num)
 
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 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 62 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 52 of file explain.h.

◆ ExplainState

typedef struct ExplainState ExplainState

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.

Function Documentation

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 3772 of file explain.c.

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

3773 {
3774  switch (es->format)
3775  {
3776  case EXPLAIN_FORMAT_TEXT:
3777  /* nothing to do */
3778  break;
3779 
3780  case EXPLAIN_FORMAT_XML:
3782  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
3783  es->indent++;
3784  break;
3785 
3786  case EXPLAIN_FORMAT_JSON:
3787  /* top-level structure is an array of plans */
3788  appendStringInfoChar(es->str, '[');
3789  es->grouping_stack = lcons_int(0, es->grouping_stack);
3790  es->indent++;
3791  break;
3792 
3793  case EXPLAIN_FORMAT_YAML:
3794  es->grouping_stack = lcons_int(0, es->grouping_stack);
3795  break;
3796  }
3797 }
List * lcons_int(int datum, List *list)
Definition: list.c:472
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
List * grouping_stack
Definition: explain.h:42
int indent
Definition: explain.h:41
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30

◆ ExplainCloseGroup()

void ExplainCloseGroup ( const char *  objtype,
const char *  labelname,
bool  labeled,
ExplainState es 
)

Definition at line 3690 of file explain.c.

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 ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintSettings(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3692 {
3693  switch (es->format)
3694  {
3695  case EXPLAIN_FORMAT_TEXT:
3696  /* nothing to do */
3697  break;
3698 
3699  case EXPLAIN_FORMAT_XML:
3700  es->indent--;
3701  ExplainXMLTag(objtype, X_CLOSING, es);
3702  break;
3703 
3704  case EXPLAIN_FORMAT_JSON:
3705  es->indent--;
3706  appendStringInfoChar(es->str, '\n');
3707  appendStringInfoSpaces(es->str, 2 * es->indent);
3708  appendStringInfoChar(es->str, labeled ? '}' : ']');
3710  break;
3711 
3712  case EXPLAIN_FORMAT_YAML:
3713  es->indent--;
3715  break;
3716  }
3717 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3861
#define X_CLOSING
Definition: explain.c:52
List * grouping_stack
Definition: explain.h:42
int indent
Definition: explain.h:41
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:861

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 3803 of file explain.c.

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

3804 {
3805  switch (es->format)
3806  {
3807  case EXPLAIN_FORMAT_TEXT:
3808  /* nothing to do */
3809  break;
3810 
3811  case EXPLAIN_FORMAT_XML:
3812  es->indent--;
3813  appendStringInfoString(es->str, "</explain>");
3814  break;
3815 
3816  case EXPLAIN_FORMAT_JSON:
3817  es->indent--;
3818  appendStringInfoString(es->str, "\n]");
3820  break;
3821 
3822  case EXPLAIN_FORMAT_YAML:
3824  break;
3825  }
3826 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
List * grouping_stack
Definition: explain.h:42
int indent
Definition: explain.h:41
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:861

◆ ExplainOnePlan()

void ExplainOnePlan ( PlannedStmt plannedstmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv,
const instr_time planduration 
)

Definition at line 465 of file explain.c.

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(), ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), GetIntoRelEFlags(), INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTRUMENT_BUFFERS, INSTRUMENT_ROWS, INSTRUMENT_TIMER, InvalidSnapshot, NoMovementScanDirection, None_Receiver, PopActiveSnapshot(), PushCopiedSnapshot(), IntoClause::skipData, ExplainState::summary, ExplainState::timing, and UpdateActiveSnapshotCommandId().

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

468 {
470  QueryDesc *queryDesc;
471  instr_time starttime;
472  double totaltime = 0;
473  int eflags;
474  int instrument_option = 0;
475 
476  Assert(plannedstmt->commandType != CMD_UTILITY);
477 
478  if (es->analyze && es->timing)
479  instrument_option |= INSTRUMENT_TIMER;
480  else if (es->analyze)
481  instrument_option |= INSTRUMENT_ROWS;
482 
483  if (es->buffers)
484  instrument_option |= INSTRUMENT_BUFFERS;
485 
486  /*
487  * We always collect timing for the entire statement, even when node-level
488  * timing is off, so we don't look at es->timing here. (We could skip
489  * this if !es->summary, but it's hardly worth the complication.)
490  */
491  INSTR_TIME_SET_CURRENT(starttime);
492 
493  /*
494  * Use a snapshot with an updated command ID to ensure this query sees
495  * results of any previously executed queries.
496  */
499 
500  /*
501  * Normally we discard the query's output, but if explaining CREATE TABLE
502  * AS, we'd better use the appropriate tuple receiver.
503  */
504  if (into)
505  dest = CreateIntoRelDestReceiver(into);
506  else
507  dest = None_Receiver;
508 
509  /* Create a QueryDesc for the query */
510  queryDesc = CreateQueryDesc(plannedstmt, queryString,
512  dest, params, queryEnv, instrument_option);
513 
514  /* Select execution options */
515  if (es->analyze)
516  eflags = 0; /* default run-to-completion flags */
517  else
518  eflags = EXEC_FLAG_EXPLAIN_ONLY;
519  if (into)
520  eflags |= GetIntoRelEFlags(into);
521 
522  /* call ExecutorStart to prepare the plan for execution */
523  ExecutorStart(queryDesc, eflags);
524 
525  /* Execute the plan for statistics if asked for */
526  if (es->analyze)
527  {
528  ScanDirection dir;
529 
530  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
531  if (into && into->skipData)
533  else
534  dir = ForwardScanDirection;
535 
536  /* run the plan */
537  ExecutorRun(queryDesc, dir, 0L, true);
538 
539  /* run cleanup too */
540  ExecutorFinish(queryDesc);
541 
542  /* We can't run ExecutorEnd 'till we're done printing the stats... */
543  totaltime += elapsed_time(&starttime);
544  }
545 
546  ExplainOpenGroup("Query", NULL, true, es);
547 
548  /* Create textual dump of plan tree */
549  ExplainPrintPlan(es, queryDesc);
550 
551  if (es->summary && planduration)
552  {
553  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
554 
555  ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
556  }
557 
558  /* Print info about runtime of triggers */
559  if (es->analyze)
560  ExplainPrintTriggers(es, queryDesc);
561 
562  /*
563  * Print info about JITing. Tied to es->costs because we don't want to
564  * display this in regression tests, as it'd cause output differences
565  * depending on build options. Might want to separate that out from COSTS
566  * at a later stage.
567  */
568  if (es->costs)
569  ExplainPrintJITSummary(es, queryDesc);
570 
571  /*
572  * Close down the query and free resources. Include time for this in the
573  * total execution time (although it should be pretty minimal).
574  */
575  INSTR_TIME_SET_CURRENT(starttime);
576 
577  ExecutorEnd(queryDesc);
578 
579  FreeQueryDesc(queryDesc);
580 
582 
583  /* We need a CCI just in case query expanded to multiple plans */
584  if (es->analyze)
586 
587  totaltime += elapsed_time(&starttime);
588 
589  /*
590  * We only report execution time if we actually ran the query (that is,
591  * the user specified ANALYZE), and if summary reporting is enabled (the
592  * user can set SUMMARY OFF to not have the timing information included in
593  * the output). By default, ANALYZE sets SUMMARY to true.
594  */
595  if (es->summary && es->analyze)
596  ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
597  es);
598 
599  ExplainCloseGroup("Query", NULL, true, es);
600 }
bool summary
Definition: explain.h:37
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:783
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:3598
struct timeval instr_time
Definition: instr_time.h:150
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:143
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:841
void PopActiveSnapshot(void)
Definition: snapmgr.c:814
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:199
bool skipData
Definition: primnodes.h:119
bool costs
Definition: explain.h:34
DestReceiver * None_Receiver
Definition: dest.c:96
bool analyze
Definition: explain.h:33
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:462
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:395
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:724
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:681
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:301
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:771
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:22
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:413
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:402
bool timing
Definition: explain.h:36
#define InvalidSnapshot
Definition: snapshot.h:123
void CommandCounterIncrement(void)
Definition: xact.c:1003
CmdType commandType
Definition: plannodes.h:46
#define Assert(condition)
Definition: c.h:732
static double elapsed_time(instr_time *starttime)
Definition: explain.c:981
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
bool buffers
Definition: explain.h:35
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3690
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:770
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3627
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56

◆ ExplainOneUtility()

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

Definition at line 390 of file explain.c.

References appendStringInfoString(), Assert, castNode, copyObject, CURSOR_OPT_PARALLEL_OK, EXPLAIN_FORMAT_TEXT, ExplainDummyGroup(), ExplainExecuteQuery(), ExplainOneQuery(), ExplainState::format, CreateTableAsStmt::into, IsA, linitial_node, list_length(), DeclareCursorStmt::options, DeclareCursorStmt::query, CreateTableAsStmt::query, QueryRewrite(), and ExplainState::str.

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

393 {
394  if (utilityStmt == NULL)
395  return;
396 
397  if (IsA(utilityStmt, CreateTableAsStmt))
398  {
399  /*
400  * We have to rewrite the contained SELECT and then pass it back to
401  * ExplainOneQuery. It's probably not really necessary to copy the
402  * contained parsetree another time, but let's be safe.
403  */
404  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
405  List *rewritten;
406 
407  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
408  Assert(list_length(rewritten) == 1);
409  ExplainOneQuery(linitial_node(Query, rewritten),
410  CURSOR_OPT_PARALLEL_OK, ctas->into, es,
411  queryString, params, queryEnv);
412  }
413  else if (IsA(utilityStmt, DeclareCursorStmt))
414  {
415  /*
416  * Likewise for DECLARE CURSOR.
417  *
418  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
419  * actually run the query. This is different from pre-8.3 behavior
420  * but seems more useful than not running the query. No cursor will
421  * be created, however.
422  */
423  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
424  List *rewritten;
425 
426  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
427  Assert(list_length(rewritten) == 1);
428  ExplainOneQuery(linitial_node(Query, rewritten),
429  dcs->options, NULL, es,
430  queryString, params, queryEnv);
431  }
432  else if (IsA(utilityStmt, ExecuteStmt))
433  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
434  queryString, params, queryEnv);
435  else if (IsA(utilityStmt, NotifyStmt))
436  {
437  if (es->format == EXPLAIN_FORMAT_TEXT)
438  appendStringInfoString(es->str, "NOTIFY\n");
439  else
440  ExplainDummyGroup("Notify", NULL, es);
441  }
442  else
443  {
444  if (es->format == EXPLAIN_FORMAT_TEXT)
446  "Utility statements have no plan structure\n");
447  else
448  ExplainDummyGroup("Utility Statement", NULL, es);
449  }
450 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * QueryRewrite(Query *parsetree)
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
#define linitial_node(type, l)
Definition: pg_list.h:198
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:3726
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:622
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:341
IntoClause * into
Definition: parsenodes.h:3240
#define Assert(condition)
Definition: c.h:732
static int list_length(const List *l)
Definition: pg_list.h:169
ExplainFormat format
Definition: explain.h:39
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2692
#define copyObject(obj)
Definition: nodes.h:641
Definition: pg_list.h:50
StringInfo str
Definition: explain.h:30

◆ ExplainOpenGroup()

void ExplainOpenGroup ( const char *  objtype,
const char *  labelname,
bool  labeled,
ExplainState es 
)

Definition at line 3627 of file explain.c.

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 ExplainNode(), ExplainOnePlan(), ExplainPrintJIT(), ExplainPrintSettings(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3629 {
3630  switch (es->format)
3631  {
3632  case EXPLAIN_FORMAT_TEXT:
3633  /* nothing to do */
3634  break;
3635 
3636  case EXPLAIN_FORMAT_XML:
3637  ExplainXMLTag(objtype, X_OPENING, es);
3638  es->indent++;
3639  break;
3640 
3641  case EXPLAIN_FORMAT_JSON:
3643  appendStringInfoSpaces(es->str, 2 * es->indent);
3644  if (labelname)
3645  {
3646  escape_json(es->str, labelname);
3647  appendStringInfoString(es->str, ": ");
3648  }
3649  appendStringInfoChar(es->str, labeled ? '{' : '[');
3650 
3651  /*
3652  * In JSON format, the grouping_stack is an integer list. 0 means
3653  * we've emitted nothing at this grouping level, 1 means we've
3654  * emitted something (and so the next item needs a comma). See
3655  * ExplainJSONLineEnding().
3656  */
3657  es->grouping_stack = lcons_int(0, es->grouping_stack);
3658  es->indent++;
3659  break;
3660 
3661  case EXPLAIN_FORMAT_YAML:
3662 
3663  /*
3664  * In YAML format, the grouping stack is an integer list. 0 means
3665  * we've emitted nothing at this grouping level AND this grouping
3666  * level is unlabelled and must be marked with "- ". See
3667  * ExplainYAMLLineStarting().
3668  */
3670  if (labelname)
3671  {
3672  appendStringInfo(es->str, "%s: ", labelname);
3673  es->grouping_stack = lcons_int(1, es->grouping_stack);
3674  }
3675  else
3676  {
3677  appendStringInfoString(es->str, "- ");
3678  es->grouping_stack = lcons_int(0, es->grouping_stack);
3679  }
3680  es->indent++;
3681  break;
3682  }
3683 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
List * lcons_int(int datum, List *list)
Definition: list.c:472
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3861
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3908
List * grouping_stack
Definition: explain.h:42
int indent
Definition: explain.h:41
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3888
#define X_OPENING
Definition: explain.c:51
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30

◆ ExplainPrintJIT()

void ExplainPrintJIT ( ExplainState es,
int  jit_flags,
struct JitInstrumentation jit_instr,
int  worker_num 
)

Definition at line 799 of file explain.c.

References ExplainState::analyze, appendStringInfo(), appendStringInfoSpaces(), appendStringInfoString(), JitInstrumentation::created_functions, JitInstrumentation::emission_counter, EXPLAIN_FORMAT_TEXT, ExplainCloseGroup(), ExplainOpenGroup(), ExplainPropertyBool(), ExplainPropertyFloat(), ExplainPropertyInteger(), ExplainState::format, JitInstrumentation::generation_counter, ExplainState::indent, JitInstrumentation::inlining_counter, INSTR_TIME_ADD, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_ZERO, JitInstrumentation::optimization_counter, PGJIT_DEFORM, PGJIT_EXPR, PGJIT_INLINE, PGJIT_OPT3, ExplainState::str, and ExplainState::timing.

Referenced by ExplainNode(), and ExplainPrintJITSummary().

801 {
802  instr_time total_time;
803  bool for_workers = (worker_num >= 0);
804 
805  /* don't print information if no JITing happened */
806  if (!ji || ji->created_functions == 0)
807  return;
808 
809  /* calculate total time */
810  INSTR_TIME_SET_ZERO(total_time);
811  INSTR_TIME_ADD(total_time, ji->generation_counter);
812  INSTR_TIME_ADD(total_time, ji->inlining_counter);
813  INSTR_TIME_ADD(total_time, ji->optimization_counter);
814  INSTR_TIME_ADD(total_time, ji->emission_counter);
815 
816  ExplainOpenGroup("JIT", "JIT", true, es);
817 
818  /* for higher density, open code the text output format */
819  if (es->format == EXPLAIN_FORMAT_TEXT)
820  {
821  appendStringInfoSpaces(es->str, es->indent * 2);
822  if (for_workers)
823  appendStringInfo(es->str, "JIT for worker %u:\n", worker_num);
824  else
825  appendStringInfoString(es->str, "JIT:\n");
826  es->indent += 1;
827 
828  ExplainPropertyInteger("Functions", NULL, ji->created_functions, es);
829 
830  appendStringInfoSpaces(es->str, es->indent * 2);
831  appendStringInfo(es->str, "Options: %s %s, %s %s, %s %s, %s %s\n",
832  "Inlining", jit_flags & PGJIT_INLINE ? "true" : "false",
833  "Optimization", jit_flags & PGJIT_OPT3 ? "true" : "false",
834  "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",
835  "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");
836 
837  if (es->analyze && es->timing)
838  {
839  appendStringInfoSpaces(es->str, es->indent * 2);
840  appendStringInfo(es->str,
841  "Timing: %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",
842  "Generation", 1000.0 * INSTR_TIME_GET_DOUBLE(ji->generation_counter),
843  "Inlining", 1000.0 * INSTR_TIME_GET_DOUBLE(ji->inlining_counter),
844  "Optimization", 1000.0 * INSTR_TIME_GET_DOUBLE(ji->optimization_counter),
845  "Emission", 1000.0 * INSTR_TIME_GET_DOUBLE(ji->emission_counter),
846  "Total", 1000.0 * INSTR_TIME_GET_DOUBLE(total_time));
847  }
848 
849  es->indent -= 1;
850  }
851  else
852  {
853  ExplainPropertyInteger("Worker Number", NULL, worker_num, es);
854  ExplainPropertyInteger("Functions", NULL, ji->created_functions, es);
855 
856  ExplainOpenGroup("Options", "Options", true, es);
857  ExplainPropertyBool("Inlining", jit_flags & PGJIT_INLINE, es);
858  ExplainPropertyBool("Optimization", jit_flags & PGJIT_OPT3, es);
859  ExplainPropertyBool("Expressions", jit_flags & PGJIT_EXPR, es);
860  ExplainPropertyBool("Deforming", jit_flags & PGJIT_DEFORM, es);
861  ExplainCloseGroup("Options", "Options", true, es);
862 
863  if (es->analyze && es->timing)
864  {
865  ExplainOpenGroup("Timing", "Timing", true, es);
866 
867  ExplainPropertyFloat("Generation", "ms",
868  1000.0 * INSTR_TIME_GET_DOUBLE(ji->generation_counter),
869  3, es);
870  ExplainPropertyFloat("Inlining", "ms",
871  1000.0 * INSTR_TIME_GET_DOUBLE(ji->inlining_counter),
872  3, es);
873  ExplainPropertyFloat("Optimization", "ms",
874  1000.0 * INSTR_TIME_GET_DOUBLE(ji->optimization_counter),
875  3, es);
876  ExplainPropertyFloat("Emission", "ms",
877  1000.0 * INSTR_TIME_GET_DOUBLE(ji->emission_counter),
878  3, es);
879  ExplainPropertyFloat("Total", "ms",
880  1000.0 * INSTR_TIME_GET_DOUBLE(total_time),
881  3, es);
882 
883  ExplainCloseGroup("Timing", "Timing", true, es);
884  }
885  }
886 
887  ExplainCloseGroup("JIT", "JIT", true, es);
888 }
void ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es)
Definition: explain.c:3612
#define PGJIT_EXPR
Definition: jit.h:23
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:3584
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:3598
struct timeval instr_time
Definition: instr_time.h:150
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:154
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:199
bool analyze
Definition: explain.h:33
#define PGJIT_OPT3
Definition: jit.h:21
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:158
int indent
Definition: explain.h:41
bool timing
Definition: explain.h:36
#define PGJIT_INLINE
Definition: jit.h:22
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
ExplainFormat format
Definition: explain.h:39
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3690
#define PGJIT_DEFORM
Definition: jit.h:24
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3627
StringInfo str
Definition: explain.h:30

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 770 of file explain.c.

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

771 {
772  JitInstrumentation ji = {0};
773 
774  if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
775  return;
776 
777  /*
778  * Work with a copy instead of modifying the leader state, since this
779  * function may be called twice
780  */
781  if (queryDesc->estate->es_jit)
782  InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
783 
784  /* If this process has done JIT in parallel workers, merge stats */
785  if (queryDesc->estate->es_jit_worker_instr)
786  InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
787 
788  ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji, -1);
789 }
EState * estate
Definition: execdesc.h:48
struct JitContext * es_jit
Definition: execnodes.h:596
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:597
JitInstrumentation instr
Definition: jit.h:61
int es_jit_flags
Definition: execnodes.h:595
void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji, int worker_num)
Definition: explain.c:799
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:187
#define PGJIT_PERFORM
Definition: jit.h:20

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 681 of file explain.c.

References Assert, deparse_context_for_plan_rtable(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), 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().

682 {
683  Bitmapset *rels_used = NULL;
684  PlanState *ps;
685 
686  /* Set up ExplainState fields associated with this plan tree */
687  Assert(queryDesc->plannedstmt != NULL);
688  es->pstmt = queryDesc->plannedstmt;
689  es->rtable = queryDesc->plannedstmt->rtable;
690  ExplainPreScanNode(queryDesc->planstate, &rels_used);
693  es->rtable_names);
694  es->printed_subplans = NULL;
695 
696  /*
697  * Sometimes we mark a Gather node as "invisible", which means that it's
698  * not displayed in EXPLAIN output. The purpose of this is to allow
699  * running regression tests with force_parallel_mode=regress to get the
700  * same results as running the same tests with force_parallel_mode=off.
701  */
702  ps = queryDesc->planstate;
703  if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
704  ps = outerPlanState(ps);
705  ExplainNode(ps, NIL, NULL, NULL, es);
706 
707  /*
708  * If requested, include information about GUC parameters with values that
709  * don't match the built-in defaults.
710  */
712 }
#define NIL
Definition: pg_list.h:65
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:607
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Bitmapset * printed_subplans
Definition: explain.h:48
List * deparse_cxt
Definition: explain.h:47
PlannedStmt * pstmt
Definition: explain.h:44
List * rtable_names
Definition: explain.h:46
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3376
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1065
PlanState * planstate
Definition: execdesc.h:49
#define outerPlanState(node)
Definition: execnodes.h:1034
Plan * plan
Definition: execnodes.h:940
#define Assert(condition)
Definition: c.h:732
List * rtable
Definition: plannodes.h:66
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1000
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
Definition: ruleutils.c:3301
List * rtable
Definition: explain.h:45

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 724 of file explain.c.

References EState::es_num_result_relations, EState::es_num_root_result_relations, EState::es_result_relations, EState::es_root_result_relations, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, QueryDesc::estate, ExplainCloseGroup(), ExplainOpenGroup(), lfirst, NIL, and report_triggers().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

725 {
726  ResultRelInfo *rInfo;
727  bool show_relname;
728  int numrels = queryDesc->estate->es_num_result_relations;
729  int numrootrels = queryDesc->estate->es_num_root_result_relations;
730  List *routerels;
731  List *targrels;
732  int nr;
733  ListCell *l;
734 
735  routerels = queryDesc->estate->es_tuple_routing_result_relations;
736  targrels = queryDesc->estate->es_trig_target_relations;
737 
738  ExplainOpenGroup("Triggers", "Triggers", false, es);
739 
740  show_relname = (numrels > 1 || numrootrels > 0 ||
741  routerels != NIL || targrels != NIL);
742  rInfo = queryDesc->estate->es_result_relations;
743  for (nr = 0; nr < numrels; rInfo++, nr++)
744  report_triggers(rInfo, show_relname, es);
745 
746  rInfo = queryDesc->estate->es_root_result_relations;
747  for (nr = 0; nr < numrootrels; rInfo++, nr++)
748  report_triggers(rInfo, show_relname, es);
749 
750  foreach(l, routerels)
751  {
752  rInfo = (ResultRelInfo *) lfirst(l);
753  report_triggers(rInfo, show_relname, es);
754  }
755 
756  foreach(l, targrels)
757  {
758  rInfo = (ResultRelInfo *) lfirst(l);
759  report_triggers(rInfo, show_relname, es);
760  }
761 
762  ExplainCloseGroup("Triggers", "Triggers", false, es);
763 }
#define NIL
Definition: pg_list.h:65
EState * estate
Definition: execdesc.h:48
ResultRelInfo * es_result_relations
Definition: execnodes.h:520
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:910
int es_num_root_result_relations
Definition: execnodes.h:531
List * es_trig_target_relations
Definition: execnodes.h:541
int es_num_result_relations
Definition: execnodes.h:521
List * es_tuple_routing_result_relations
Definition: execnodes.h:538
#define lfirst(lc)
Definition: pg_list.h:190
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:530
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3690
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3627
Definition: pg_list.h:50

◆ ExplainPropertyBool()

void ExplainPropertyBool ( const char *  qlabel,
bool  value,
ExplainState es 
)

Definition at line 3612 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode(), and ExplainPrintJIT().

3613 {
3614  ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
3615 }
static struct @145 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3522

◆ ExplainPropertyFloat()

void ExplainPropertyFloat ( const char *  qlabel,
const char *  unit,
double  value,
int  ndigits,
ExplainState es 
)

Definition at line 3598 of file explain.c.

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

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

3600 {
3601  char *buf;
3602 
3603  buf = psprintf("%.*f", ndigits, value);
3604  ExplainProperty(qlabel, unit, buf, true, es);
3605  pfree(buf);
3606 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static struct @145 value
void pfree(void *pointer)
Definition: mcxt.c:1056
static char * buf
Definition: pg_test_fsync.c:68
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3522

◆ ExplainPropertyInteger()

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

Definition at line 3584 of file explain.c.

References buf, ExplainProperty(), INT64_FORMAT, and snprintf.

Referenced by ExplainMemberNodes(), ExplainNode(), ExplainPrintJIT(), fileExplainForeignScan(), show_buffer_usage(), show_hash_info(), show_sort_info(), and show_tidbitmap_info().

3586 {
3587  char buf[32];
3588 
3589  snprintf(buf, sizeof(buf), INT64_FORMAT, value);
3590  ExplainProperty(qlabel, unit, buf, true, es);
3591 }
static struct @145 value
static char * buf
Definition: pg_test_fsync.c:68
#define INT64_FORMAT
Definition: c.h:400
#define snprintf
Definition: port.h:192
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3522

◆ ExplainPropertyList()

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

Definition at line 3399 of file explain.c.

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

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

3400 {
3401  ListCell *lc;
3402  bool first = true;
3403 
3404  switch (es->format)
3405  {
3406  case EXPLAIN_FORMAT_TEXT:
3407  appendStringInfoSpaces(es->str, es->indent * 2);
3408  appendStringInfo(es->str, "%s: ", qlabel);
3409  foreach(lc, data)
3410  {
3411  if (!first)
3412  appendStringInfoString(es->str, ", ");
3413  appendStringInfoString(es->str, (const char *) lfirst(lc));
3414  first = false;
3415  }
3416  appendStringInfoChar(es->str, '\n');
3417  break;
3418 
3419  case EXPLAIN_FORMAT_XML:
3420  ExplainXMLTag(qlabel, X_OPENING, es);
3421  foreach(lc, data)
3422  {
3423  char *str;
3424 
3425  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3426  appendStringInfoString(es->str, "<Item>");
3427  str = escape_xml((const char *) lfirst(lc));
3428  appendStringInfoString(es->str, str);
3429  pfree(str);
3430  appendStringInfoString(es->str, "</Item>\n");
3431  }
3432  ExplainXMLTag(qlabel, X_CLOSING, es);
3433  break;
3434 
3435  case EXPLAIN_FORMAT_JSON:
3437  appendStringInfoSpaces(es->str, es->indent * 2);
3438  escape_json(es->str, qlabel);
3439  appendStringInfoString(es->str, ": [");
3440  foreach(lc, data)
3441  {
3442  if (!first)
3443  appendStringInfoString(es->str, ", ");
3444  escape_json(es->str, (const char *) lfirst(lc));
3445  first = false;
3446  }
3447  appendStringInfoChar(es->str, ']');
3448  break;
3449 
3450  case EXPLAIN_FORMAT_YAML:
3452  appendStringInfo(es->str, "%s: ", qlabel);
3453  foreach(lc, data)
3454  {
3455  appendStringInfoChar(es->str, '\n');
3456  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3457  appendStringInfoString(es->str, "- ");
3458  escape_yaml(es->str, (const char *) lfirst(lc));
3459  }
3460  break;
3461  }
3462 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3861
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3908
int indent
Definition: explain.h:41
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3933
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3888
#define X_OPENING
Definition: explain.c:51
#define lfirst(lc)
Definition: pg_list.h:190
ExplainFormat format
Definition: explain.h:39
char * escape_xml(const char *str)
Definition: xml.c:2373
StringInfo str
Definition: explain.h:30

◆ ExplainPropertyListNested()

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

Definition at line 3469 of file explain.c.

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), 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().

3470 {
3471  ListCell *lc;
3472  bool first = true;
3473 
3474  switch (es->format)
3475  {
3476  case EXPLAIN_FORMAT_TEXT:
3477  case EXPLAIN_FORMAT_XML:
3478  ExplainPropertyList(qlabel, data, es);
3479  return;
3480 
3481  case EXPLAIN_FORMAT_JSON:
3483  appendStringInfoSpaces(es->str, es->indent * 2);
3484  appendStringInfoChar(es->str, '[');
3485  foreach(lc, data)
3486  {
3487  if (!first)
3488  appendStringInfoString(es->str, ", ");
3489  escape_json(es->str, (const char *) lfirst(lc));
3490  first = false;
3491  }
3492  appendStringInfoChar(es->str, ']');
3493  break;
3494 
3495  case EXPLAIN_FORMAT_YAML:
3497  appendStringInfoString(es->str, "- [");
3498  foreach(lc, data)
3499  {
3500  if (!first)
3501  appendStringInfoString(es->str, ", ");
3502  escape_yaml(es->str, (const char *) lfirst(lc));
3503  first = false;
3504  }
3505  appendStringInfoChar(es->str, ']');
3506  break;
3507  }
3508 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2483
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3908
int indent
Definition: explain.h:41
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3933
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3888
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:3399
#define lfirst(lc)
Definition: pg_list.h:190
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30

◆ ExplainPropertyText()

void ExplainPropertyText ( const char *  qlabel,
const char *  value,
ExplainState es 
)

Definition at line 3575 of file explain.c.

References ExplainProperty().

Referenced by ExplainIndexScanDetails(), ExplainNode(), ExplainPrintSettings(), ExplainQueryText(), ExplainTargetRel(), fileExplainForeignScan(), postgresExplainDirectModify(), postgresExplainForeignModify(), postgresExplainForeignScan(), report_triggers(), show_expression(), show_grouping_set_keys(), show_modifytable_info(), show_sort_info(), and show_tablesample().

3576 {
3577  ExplainProperty(qlabel, NULL, value, false, es);
3578 }
static struct @145 value
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3522

◆ ExplainQuery()

void ExplainQuery ( ParseState pstate,
ExplainStmt stmt,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv,
DestReceiver dest 
)

Definition at line 142 of file explain.c.

References ExplainState::analyze, appendStringInfoString(), Assert, begin_tup_output_tupdesc(), ExplainState::buffers, castNode, copyObject, ExplainState::costs, CURSOR_OPT_PARALLEL_OK, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, 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, ExplainState::indent, lfirst, lfirst_node, lnext(), DefElem::location, NewExplainState(), NIL, ExplainStmt::options, parser_errposition(), pfree(), ExplainStmt::query, QueryRewrite(), ExplainState::settings, ExplainState::str, ExplainState::summary, ExplainState::timing, TTSOpsVirtual, and ExplainState::verbose.

Referenced by standard_ProcessUtility().

145 {
147  TupOutputState *tstate;
148  List *rewritten;
149  ListCell *lc;
150  bool timing_set = false;
151  bool summary_set = false;
152 
153  /* Parse options list. */
154  foreach(lc, stmt->options)
155  {
156  DefElem *opt = (DefElem *) lfirst(lc);
157 
158  if (strcmp(opt->defname, "analyze") == 0)
159  es->analyze = defGetBoolean(opt);
160  else if (strcmp(opt->defname, "verbose") == 0)
161  es->verbose = defGetBoolean(opt);
162  else if (strcmp(opt->defname, "costs") == 0)
163  es->costs = defGetBoolean(opt);
164  else if (strcmp(opt->defname, "buffers") == 0)
165  es->buffers = defGetBoolean(opt);
166  else if (strcmp(opt->defname, "settings") == 0)
167  es->settings = defGetBoolean(opt);
168  else if (strcmp(opt->defname, "timing") == 0)
169  {
170  timing_set = true;
171  es->timing = defGetBoolean(opt);
172  }
173  else if (strcmp(opt->defname, "summary") == 0)
174  {
175  summary_set = true;
176  es->summary = defGetBoolean(opt);
177  }
178  else if (strcmp(opt->defname, "format") == 0)
179  {
180  char *p = defGetString(opt);
181 
182  if (strcmp(p, "text") == 0)
184  else if (strcmp(p, "xml") == 0)
186  else if (strcmp(p, "json") == 0)
188  else if (strcmp(p, "yaml") == 0)
190  else
191  ereport(ERROR,
192  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
193  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
194  opt->defname, p),
195  parser_errposition(pstate, opt->location)));
196  }
197  else
198  ereport(ERROR,
199  (errcode(ERRCODE_SYNTAX_ERROR),
200  errmsg("unrecognized EXPLAIN option \"%s\"",
201  opt->defname),
202  parser_errposition(pstate, opt->location)));
203  }
204 
205  if (es->buffers && !es->analyze)
206  ereport(ERROR,
207  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
208  errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
209 
210  /* if the timing was not set explicitly, set default value */
211  es->timing = (timing_set) ? es->timing : es->analyze;
212 
213  /* check that timing is used with EXPLAIN ANALYZE */
214  if (es->timing && !es->analyze)
215  ereport(ERROR,
216  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
217  errmsg("EXPLAIN option TIMING requires ANALYZE")));
218 
219  /* if the summary was not set explicitly, set default value */
220  es->summary = (summary_set) ? es->summary : es->analyze;
221 
222  /*
223  * Parse analysis was done already, but we still have to run the rule
224  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
225  * came straight from the parser, or suitable locks were acquired by
226  * plancache.c.
227  *
228  * Because the rewriter and planner tend to scribble on the input, we make
229  * a preliminary copy of the source querytree. This prevents problems in
230  * the case that the EXPLAIN is in a portal or plpgsql function and is
231  * executed repeatedly. (See also the same hack in DECLARE CURSOR and
232  * PREPARE.) XXX FIXME someday.
233  */
234  rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
235 
236  /* emit opening boilerplate */
237  ExplainBeginOutput(es);
238 
239  if (rewritten == NIL)
240  {
241  /*
242  * In the case of an INSTEAD NOTHING, tell at least that. But in
243  * non-text format, the output is delimited, so this isn't necessary.
244  */
245  if (es->format == EXPLAIN_FORMAT_TEXT)
246  appendStringInfoString(es->str, "Query rewrites to nothing\n");
247  }
248  else
249  {
250  ListCell *l;
251 
252  /* Explain every plan */
253  foreach(l, rewritten)
254  {
256  CURSOR_OPT_PARALLEL_OK, NULL, es,
257  queryString, params, queryEnv);
258 
259  /* Separate plans with an appropriate separator */
260  if (lnext(rewritten, l) != NULL)
262  }
263  }
264 
265  /* emit closing boilerplate */
266  ExplainEndOutput(es);
267  Assert(es->indent == 0);
268 
269  /* output tuples */
270  tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt),
271  &TTSOpsVirtual);
272  if (es->format == EXPLAIN_FORMAT_TEXT)
273  do_text_output_multiline(tstate, es->str->data);
274  else
275  do_text_output_oneline(tstate, es->str->data);
276  end_tup_output(tstate);
277 
278  pfree(es->str->data);
279 }
#define NIL
Definition: pg_list.h:65
bool summary
Definition: explain.h:37
ExplainState * NewExplainState(void)
Definition: explain.c:285
List * QueryRewrite(Query *parsetree)
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:3832
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
int errcode(int sqlerrcode)
Definition: elog.c:570
List * options
Definition: parsenodes.h:3220
bool costs
Definition: explain.h:34
bool analyze
Definition: explain.h:33
Node * query
Definition: parsenodes.h:3219
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:3803
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:1056
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2310
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:3772
#define ERROR
Definition: elog.h:43
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:302
char * defGetString(DefElem *def)
Definition: define.c:49
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2232
#define lfirst_node(type, lc)
Definition: pg_list.h:193
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
int location
Definition: parsenodes.h:733
int indent
Definition: explain.h:41
#define ereport(elevel, rest)
Definition: elog.h:141
bool timing
Definition: explain.h:36
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:341
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2280
bool verbose
Definition: explain.h:32
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
ExplainFormat format
Definition: explain.h:39
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:474
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2692
int errmsg(const char *fmt,...)
Definition: elog.c:784
bool buffers
Definition: explain.h:35
char * defname
Definition: parsenodes.h:730
#define copyObject(obj)
Definition: nodes.h:641
Definition: pg_list.h:50
StringInfo str
Definition: explain.h:30
bool settings
Definition: explain.h:38

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 899 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

900 {
901  if (queryDesc->sourceText)
902  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
903 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:3575
const char * sourceText
Definition: execdesc.h:38

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 302 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

303 {
304  TupleDesc tupdesc;
305  ListCell *lc;
306  Oid result_type = TEXTOID;
307 
308  /* Check for XML format option */
309  foreach(lc, stmt->options)
310  {
311  DefElem *opt = (DefElem *) lfirst(lc);
312 
313  if (strcmp(opt->defname, "format") == 0)
314  {
315  char *p = defGetString(opt);
316 
317  if (strcmp(p, "xml") == 0)
318  result_type = XMLOID;
319  else if (strcmp(p, "json") == 0)
320  result_type = JSONOID;
321  else
322  result_type = TEXTOID;
323  /* don't "break", as ExplainQuery will use the last value */
324  }
325  }
326 
327  /* Need a tuple descriptor representing a single TEXT or XML column */
328  tupdesc = CreateTemplateTupleDesc(1);
329  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
330  result_type, -1, 0);
331  return tupdesc;
332 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
List * options
Definition: parsenodes.h:3220
unsigned int Oid
Definition: postgres_ext.h:31
char * defGetString(DefElem *def)
Definition: define.c:49
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define lfirst(lc)
Definition: pg_list.h:190
char * defname
Definition: parsenodes.h:730
int16 AttrNumber
Definition: attnum.h:21

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 3832 of file explain.c.

References appendStringInfoChar(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, and ExplainState::str.

Referenced by ExplainExecuteQuery(), and ExplainQuery().

3833 {
3834  switch (es->format)
3835  {
3836  case EXPLAIN_FORMAT_TEXT:
3837  /* add a blank line */
3838  appendStringInfoChar(es->str, '\n');
3839  break;
3840 
3841  case EXPLAIN_FORMAT_XML:
3842  case EXPLAIN_FORMAT_JSON:
3843  case EXPLAIN_FORMAT_YAML:
3844  /* nothing to do */
3845  break;
3846  }
3847 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
ExplainFormat format
Definition: explain.h:39
StringInfo str
Definition: explain.h:30

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 285 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

286 {
287  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
288 
289  /* Set default options (most fields can be left as zeroes). */
290  es->costs = true;
291  /* Prepare output buffer. */
292  es->str = makeStringInfo();
293 
294  return es;
295 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
bool costs
Definition: explain.h:34
void * palloc0(Size size)
Definition: mcxt.c:980
StringInfo str
Definition: explain.h:30

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook

Definition at line 47 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook

Definition at line 44 of file explain.c.

Referenced by ExplainOneQuery().