PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
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, DestReceiver *dest)
 
ExplainStateNewExplainState (void)
 
TupleDesc ExplainResultDesc (ExplainStmt *stmt)
 
void ExplainOneUtility (Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params)
 
void ExplainOnePlan (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, const instr_time *planduration)
 
void ExplainPrintPlan (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintTriggers (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, int value, ExplainState *es)
 
void ExplainPropertyLong (const char *qlabel, long value, ExplainState *es)
 
void ExplainPropertyFloat (const char *qlabel, double value, int ndigits, ExplainState *es)
 
void ExplainPropertyBool (const char *qlabel, bool value, ExplainState *es)
 

Variables

PGDLLIMPORT
ExplainOneQuery_hook_type 
ExplainOneQuery_hook
 
PGDLLIMPORT
explain_get_index_name_hook_type 
explain_get_index_name_hook
 

Typedef Documentation

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

Definition at line 60 of file explain.h.

typedef void(* ExplainOneQuery_hook_type)(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params)

Definition at line 51 of file explain.h.

Enumeration Type Documentation

Enumerator
EXPLAIN_FORMAT_TEXT 
EXPLAIN_FORMAT_XML 
EXPLAIN_FORMAT_JSON 
EXPLAIN_FORMAT_YAML 

Definition at line 20 of file explain.h.

Function Documentation

void ExplainBeginOutput ( ExplainState es)

Definition at line 3253 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().

3254 {
3255  switch (es->format)
3256  {
3257  case EXPLAIN_FORMAT_TEXT:
3258  /* nothing to do */
3259  break;
3260 
3261  case EXPLAIN_FORMAT_XML:
3263  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
3264  es->indent++;
3265  break;
3266 
3267  case EXPLAIN_FORMAT_JSON:
3268  /* top-level structure is an array of plans */
3269  appendStringInfoChar(es->str, '[');
3270  es->grouping_stack = lcons_int(0, es->grouping_stack);
3271  es->indent++;
3272  break;
3273 
3274  case EXPLAIN_FORMAT_YAML:
3275  es->grouping_stack = lcons_int(0, es->grouping_stack);
3276  break;
3277  }
3278 }
List * lcons_int(int datum, List *list)
Definition: list.c:277
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
void ExplainEndOutput ( ExplainState es)

Definition at line 3284 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().

3285 {
3286  switch (es->format)
3287  {
3288  case EXPLAIN_FORMAT_TEXT:
3289  /* nothing to do */
3290  break;
3291 
3292  case EXPLAIN_FORMAT_XML:
3293  es->indent--;
3294  appendStringInfoString(es->str, "</explain>");
3295  break;
3296 
3297  case EXPLAIN_FORMAT_JSON:
3298  es->indent--;
3299  appendStringInfoString(es->str, "\n]");
3301  break;
3302 
3303  case EXPLAIN_FORMAT_YAML:
3305  break;
3306  }
3307 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:666
void ExplainOnePlan ( PlannedStmt plannedstmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
const instr_time planduration 
)

Definition at line 455 of file explain.c.

References ExplainState::analyze, appendStringInfo(), Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, CreateIntoRelDestReceiver(), CreateQueryDesc(), elapsed_time(), EXEC_FLAG_EXPLAIN_ONLY, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), EXPLAIN_FORMAT_TEXT, ExplainCloseGroup(), ExplainOpenGroup(), ExplainPrintPlan(), ExplainPrintTriggers(), ExplainPropertyFloat(), ExplainState::format, ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), GetIntoRelEFlags(), INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTRUMENT_BUFFERS, INSTRUMENT_ROWS, INSTRUMENT_TIMER, InvalidSnapshot, NoMovementScanDirection, None_Receiver, NULL, PopActiveSnapshot(), PushCopiedSnapshot(), IntoClause::skipData, ExplainState::str, ExplainState::summary, ExplainState::timing, and UpdateActiveSnapshotCommandId().

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

458 {
459  DestReceiver *dest;
460  QueryDesc *queryDesc;
461  instr_time starttime;
462  double totaltime = 0;
463  int eflags;
464  int instrument_option = 0;
465 
466  Assert(plannedstmt->commandType != CMD_UTILITY);
467 
468  if (es->analyze && es->timing)
469  instrument_option |= INSTRUMENT_TIMER;
470  else if (es->analyze)
471  instrument_option |= INSTRUMENT_ROWS;
472 
473  if (es->buffers)
474  instrument_option |= INSTRUMENT_BUFFERS;
475 
476  /*
477  * We always collect timing for the entire statement, even when node-level
478  * timing is off, so we don't look at es->timing here. (We could skip
479  * this if !es->summary, but it's hardly worth the complication.)
480  */
481  INSTR_TIME_SET_CURRENT(starttime);
482 
483  /*
484  * Use a snapshot with an updated command ID to ensure this query sees
485  * results of any previously executed queries.
486  */
489 
490  /*
491  * Normally we discard the query's output, but if explaining CREATE TABLE
492  * AS, we'd better use the appropriate tuple receiver.
493  */
494  if (into)
495  dest = CreateIntoRelDestReceiver(into);
496  else
497  dest = None_Receiver;
498 
499  /* Create a QueryDesc for the query */
500  queryDesc = CreateQueryDesc(plannedstmt, queryString,
502  dest, params, instrument_option);
503 
504  /* Select execution options */
505  if (es->analyze)
506  eflags = 0; /* default run-to-completion flags */
507  else
508  eflags = EXEC_FLAG_EXPLAIN_ONLY;
509  if (into)
510  eflags |= GetIntoRelEFlags(into);
511 
512  /* call ExecutorStart to prepare the plan for execution */
513  ExecutorStart(queryDesc, eflags);
514 
515  /* Execute the plan for statistics if asked for */
516  if (es->analyze)
517  {
518  ScanDirection dir;
519 
520  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
521  if (into && into->skipData)
523  else
524  dir = ForwardScanDirection;
525 
526  /* run the plan */
527  ExecutorRun(queryDesc, dir, 0L);
528 
529  /* run cleanup too */
530  ExecutorFinish(queryDesc);
531 
532  /* We can't run ExecutorEnd 'till we're done printing the stats... */
533  totaltime += elapsed_time(&starttime);
534  }
535 
536  ExplainOpenGroup("Query", NULL, true, es);
537 
538  /* Create textual dump of plan tree */
539  ExplainPrintPlan(es, queryDesc);
540 
541  if (es->summary && planduration)
542  {
543  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
544 
545  if (es->format == EXPLAIN_FORMAT_TEXT)
546  appendStringInfo(es->str, "Planning time: %.3f ms\n",
547  1000.0 * plantime);
548  else
549  ExplainPropertyFloat("Planning Time", 1000.0 * plantime, 3, es);
550  }
551 
552  /* Print info about runtime of triggers */
553  if (es->analyze)
554  ExplainPrintTriggers(es, queryDesc);
555 
556  /*
557  * Close down the query and free resources. Include time for this in the
558  * total execution time (although it should be pretty minimal).
559  */
560  INSTR_TIME_SET_CURRENT(starttime);
561 
562  ExecutorEnd(queryDesc);
563 
564  FreeQueryDesc(queryDesc);
565 
567 
568  /* We need a CCI just in case query expanded to multiple plans */
569  if (es->analyze)
571 
572  totaltime += elapsed_time(&starttime);
573 
574  if (es->summary)
575  {
576  if (es->format == EXPLAIN_FORMAT_TEXT)
577  appendStringInfo(es->str, "Execution time: %.3f ms\n",
578  1000.0 * totaltime);
579  else
580  ExplainPropertyFloat("Execution Time", 1000.0 * totaltime,
581  3, es);
582  }
583 
584  ExplainCloseGroup("Query", NULL, true, es);
585 }
bool summary
Definition: explain.h:37
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:776
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:100
struct timeval instr_time
Definition: instr_time.h:147
void ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ExplainState *es)
Definition: explain.c:3080
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:285
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, int instrument_options)
Definition: pquery.c:66
bool skipData
Definition: primnodes.h:93
DestReceiver * None_Receiver
Definition: dest.c:91
bool analyze
Definition: explain.h:33
static void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3108
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:439
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:391
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:636
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:599
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:764
ScanDirection
Definition: sdir.h:22
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:422
static void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3171
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:379
bool timing
Definition: explain.h:36
#define InvalidSnapshot
Definition: snapshot.h:25
void CommandCounterIncrement(void)
Definition: xact.c:921
CmdType commandType
Definition: plannodes.h:45
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
ExplainFormat format
Definition: explain.h:38
static double elapsed_time(instr_time *starttime)
Definition: explain.c:751
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
bool buffers
Definition: explain.h:35
StringInfo str
Definition: explain.h:30
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
void ExplainOneUtility ( Node utilityStmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params 
)

Definition at line 379 of file explain.c.

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

381 {
382  if (utilityStmt == NULL)
383  return;
384 
385  if (IsA(utilityStmt, CreateTableAsStmt))
386  {
387  /*
388  * We have to rewrite the contained SELECT and then pass it back to
389  * ExplainOneQuery. It's probably not really necessary to copy the
390  * contained parsetree another time, but let's be safe.
391  *
392  * Like ExecCreateTableAs, disallow parallelism in the plan.
393  */
394  CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
395  List *rewritten;
396 
397  rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
398  Assert(list_length(rewritten) == 1);
399  ExplainOneQuery(castNode(Query, linitial(rewritten)),
400  0, ctas->into, es,
401  queryString, params);
402  }
403  else if (IsA(utilityStmt, DeclareCursorStmt))
404  {
405  /*
406  * Likewise for DECLARE CURSOR.
407  *
408  * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
409  * actually run the query. This is different from pre-8.3 behavior
410  * but seems more useful than not running the query. No cursor will
411  * be created, however.
412  */
413  DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
414  List *rewritten;
415 
416  rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
417  Assert(list_length(rewritten) == 1);
418  ExplainOneQuery(castNode(Query, linitial(rewritten)),
419  dcs->options, NULL, es,
420  queryString, params);
421  }
422  else if (IsA(utilityStmt, ExecuteStmt))
423  ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
424  queryString, params);
425  else if (IsA(utilityStmt, NotifyStmt))
426  {
427  if (es->format == EXPLAIN_FORMAT_TEXT)
428  appendStringInfoString(es->str, "NOTIFY\n");
429  else
430  ExplainDummyGroup("Notify", NULL, es);
431  }
432  else
433  {
434  if (es->format == EXPLAIN_FORMAT_TEXT)
436  "Utility statements have no plan structure\n");
437  else
438  ExplainDummyGroup("Utility Statement", NULL, es);
439  }
440 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * QueryRewrite(Query *parsetree)
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:3207
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
#define linitial(l)
Definition: pg_list.h:110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
IntoClause * into
Definition: parsenodes.h:3021
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static int list_length(const List *l)
Definition: pg_list.h:89
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params)
Definition: prepare.c:631
ExplainFormat format
Definition: explain.h:38
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params)
Definition: explain.c:333
Definition: pg_list.h:45
StringInfo str
Definition: explain.h:30
void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 599 of file explain.c.

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

600 {
601  Bitmapset *rels_used = NULL;
602  PlanState *ps;
603 
604  /* Set up ExplainState fields associated with this plan tree */
605  Assert(queryDesc->plannedstmt != NULL);
606  es->pstmt = queryDesc->plannedstmt;
607  es->rtable = queryDesc->plannedstmt->rtable;
608  ExplainPreScanNode(queryDesc->planstate, &rels_used);
611  es->rtable_names);
612  es->printed_subplans = NULL;
613 
614  /*
615  * Sometimes we mark a Gather node as "invisible", which means that it's
616  * not displayed in EXPLAIN output. The purpose of this is to allow
617  * running regression tests with force_parallel_mode=regress to get the
618  * same results as running the same tests with force_parallel_mode=off.
619  */
620  ps = queryDesc->planstate;
621  if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
622  ps = outerPlanState(ps);
623  ExplainNode(ps, NIL, NULL, NULL, es);
624 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Bitmapset * printed_subplans
Definition: explain.h:47
List * deparse_cxt
Definition: explain.h:46
PlannedStmt * pstmt
Definition: explain.h:43
List * rtable_names
Definition: explain.h:45
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:2971
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:833
PlanState * planstate
Definition: execdesc.h:48
#define outerPlanState(node)
Definition: execnodes.h:1090
Plan * plan
Definition: execnodes.h:1047
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
List * rtable
Definition: plannodes.h:63
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:770
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
Definition: ruleutils.c:2896
List * rtable
Definition: explain.h:44
void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 636 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

637 {
638  ResultRelInfo *rInfo;
639  bool show_relname;
640  int numrels = queryDesc->estate->es_num_result_relations;
641  List *targrels = queryDesc->estate->es_trig_target_relations;
642  int nr;
643  ListCell *l;
644 
645  ExplainOpenGroup("Triggers", "Triggers", false, es);
646 
647  show_relname = (numrels > 1 || targrels != NIL);
648  rInfo = queryDesc->estate->es_result_relations;
649  for (nr = 0; nr < numrels; rInfo++, nr++)
650  report_triggers(rInfo, show_relname, es);
651 
652  foreach(l, targrels)
653  {
654  rInfo = (ResultRelInfo *) lfirst(l);
655  report_triggers(rInfo, show_relname, es);
656  }
657 
658  ExplainCloseGroup("Triggers", "Triggers", false, es);
659 }
#define NIL
Definition: pg_list.h:69
EState * estate
Definition: execdesc.h:47
static void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3108
ResultRelInfo * es_result_relations
Definition: execnodes.h:382
static void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3171
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:681
List * es_trig_target_relations
Definition: execnodes.h:387
int es_num_result_relations
Definition: execnodes.h:383
#define lfirst(lc)
Definition: pg_list.h:106
Definition: pg_list.h:45
void ExplainPropertyBool ( const char *  qlabel,
bool  value,
ExplainState es 
)

Definition at line 3093 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode().

3094 {
3095  ExplainProperty(qlabel, value ? "true" : "false", true, es);
3096 }
static struct @76 value
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:2996
void ExplainPropertyFloat ( const char *  qlabel,
double  value,
int  ndigits,
ExplainState es 
)

Definition at line 3080 of file explain.c.

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

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

3082 {
3083  char buf[256];
3084 
3085  snprintf(buf, sizeof(buf), "%.*f", ndigits, value);
3086  ExplainProperty(qlabel, buf, true, es);
3087 }
static struct @76 value
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:2996
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:65
void ExplainPropertyInteger ( const char *  qlabel,
int  value,
ExplainState es 
)

Definition at line 3055 of file explain.c.

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

Referenced by ExplainNode().

3056 {
3057  char buf[32];
3058 
3059  snprintf(buf, sizeof(buf), "%d", value);
3060  ExplainProperty(qlabel, buf, true, es);
3061 }
static struct @76 value
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:2996
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:65
void ExplainPropertyList ( const char *  qlabel,
List data,
ExplainState es 
)

Definition at line 2875 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, X_CLOSING, and X_OPENING.

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

2876 {
2877  ListCell *lc;
2878  bool first = true;
2879 
2880  switch (es->format)
2881  {
2882  case EXPLAIN_FORMAT_TEXT:
2883  appendStringInfoSpaces(es->str, es->indent * 2);
2884  appendStringInfo(es->str, "%s: ", qlabel);
2885  foreach(lc, data)
2886  {
2887  if (!first)
2888  appendStringInfoString(es->str, ", ");
2889  appendStringInfoString(es->str, (const char *) lfirst(lc));
2890  first = false;
2891  }
2892  appendStringInfoChar(es->str, '\n');
2893  break;
2894 
2895  case EXPLAIN_FORMAT_XML:
2896  ExplainXMLTag(qlabel, X_OPENING, es);
2897  foreach(lc, data)
2898  {
2899  char *str;
2900 
2901  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
2902  appendStringInfoString(es->str, "<Item>");
2903  str = escape_xml((const char *) lfirst(lc));
2904  appendStringInfoString(es->str, str);
2905  pfree(str);
2906  appendStringInfoString(es->str, "</Item>\n");
2907  }
2908  ExplainXMLTag(qlabel, X_CLOSING, es);
2909  break;
2910 
2911  case EXPLAIN_FORMAT_JSON:
2913  appendStringInfoSpaces(es->str, es->indent * 2);
2914  escape_json(es->str, qlabel);
2915  appendStringInfoString(es->str, ": [");
2916  foreach(lc, data)
2917  {
2918  if (!first)
2919  appendStringInfoString(es->str, ", ");
2920  escape_json(es->str, (const char *) lfirst(lc));
2921  first = false;
2922  }
2923  appendStringInfoChar(es->str, ']');
2924  break;
2925 
2926  case EXPLAIN_FORMAT_YAML:
2928  appendStringInfo(es->str, "%s: ", qlabel);
2929  foreach(lc, data)
2930  {
2931  appendStringInfoChar(es->str, '\n');
2932  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
2933  appendStringInfoString(es->str, "- ");
2934  escape_yaml(es->str, (const char *) lfirst(lc));
2935  }
2936  break;
2937  }
2938 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2433
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3342
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:992
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3389
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3414
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:219
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3369
#define X_OPENING
Definition: explain.c:51
#define lfirst(lc)
Definition: pg_list.h:106
ExplainFormat format
Definition: explain.h:38
char * escape_xml(const char *str)
Definition: xml.c:2170
StringInfo str
Definition: explain.h:30
void ExplainPropertyListNested ( const char *  qlabel,
List data,
ExplainState es 
)

Definition at line 2945 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().

2946 {
2947  ListCell *lc;
2948  bool first = true;
2949 
2950  switch (es->format)
2951  {
2952  case EXPLAIN_FORMAT_TEXT:
2953  case EXPLAIN_FORMAT_XML:
2954  ExplainPropertyList(qlabel, data, es);
2955  return;
2956 
2957  case EXPLAIN_FORMAT_JSON:
2959  appendStringInfoSpaces(es->str, es->indent * 2);
2960  appendStringInfoChar(es->str, '[');
2961  foreach(lc, data)
2962  {
2963  if (!first)
2964  appendStringInfoString(es->str, ", ");
2965  escape_json(es->str, (const char *) lfirst(lc));
2966  first = false;
2967  }
2968  appendStringInfoChar(es->str, ']');
2969  break;
2970 
2971  case EXPLAIN_FORMAT_YAML:
2973  appendStringInfoString(es->str, "- [");
2974  foreach(lc, data)
2975  {
2976  if (!first)
2977  appendStringInfoString(es->str, ", ");
2978  escape_yaml(es->str, (const char *) lfirst(lc));
2979  first = false;
2980  }
2981  appendStringInfoChar(es->str, ']');
2982  break;
2983  }
2984 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2433
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3389
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3414
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:219
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3369
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:2875
#define lfirst(lc)
Definition: pg_list.h:106
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
void ExplainPropertyLong ( const char *  qlabel,
long  value,
ExplainState es 
)

Definition at line 3067 of file explain.c.

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

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

3068 {
3069  char buf[32];
3070 
3071  snprintf(buf, sizeof(buf), "%ld", value);
3072  ExplainProperty(qlabel, buf, true, es);
3073 }
static struct @76 value
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:2996
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:65
void ExplainPropertyText ( const char *  qlabel,
const char *  value,
ExplainState es 
)

Definition at line 3046 of file explain.c.

References ExplainProperty().

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

3047 {
3048  ExplainProperty(qlabel, value, false, es);
3049 }
static struct @76 value
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:2996
void ExplainQuery ( ParseState pstate,
ExplainStmt stmt,
const char *  queryString,
ParamListInfo  params,
DestReceiver dest 
)

Definition at line 144 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, lnext, DefElem::location, NewExplainState(), NIL, NULL, ExplainStmt::options, parser_errposition(), pfree(), ExplainStmt::query, QueryRewrite(), ExplainState::str, ExplainState::summary, ExplainState::timing, and ExplainState::verbose.

Referenced by standard_ProcessUtility().

146 {
148  TupOutputState *tstate;
149  List *rewritten;
150  ListCell *lc;
151  bool timing_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, "timing") == 0)
167  {
168  timing_set = true;
169  es->timing = defGetBoolean(opt);
170  }
171  else if (strcmp(opt->defname, "format") == 0)
172  {
173  char *p = defGetString(opt);
174 
175  if (strcmp(p, "text") == 0)
177  else if (strcmp(p, "xml") == 0)
179  else if (strcmp(p, "json") == 0)
181  else if (strcmp(p, "yaml") == 0)
183  else
184  ereport(ERROR,
185  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
186  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
187  opt->defname, p),
188  parser_errposition(pstate, opt->location)));
189  }
190  else
191  ereport(ERROR,
192  (errcode(ERRCODE_SYNTAX_ERROR),
193  errmsg("unrecognized EXPLAIN option \"%s\"",
194  opt->defname),
195  parser_errposition(pstate, opt->location)));
196  }
197 
198  if (es->buffers && !es->analyze)
199  ereport(ERROR,
200  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
201  errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
202 
203  /* if the timing was not set explicitly, set default value */
204  es->timing = (timing_set) ? es->timing : es->analyze;
205 
206  /* check that timing is used with EXPLAIN ANALYZE */
207  if (es->timing && !es->analyze)
208  ereport(ERROR,
209  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
210  errmsg("EXPLAIN option TIMING requires ANALYZE")));
211 
212  /* currently, summary option is not exposed to users; just set it */
213  es->summary = es->analyze;
214 
215  /*
216  * Parse analysis was done already, but we still have to run the rule
217  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
218  * came straight from the parser, or suitable locks were acquired by
219  * plancache.c.
220  *
221  * Because the rewriter and planner tend to scribble on the input, we make
222  * a preliminary copy of the source querytree. This prevents problems in
223  * the case that the EXPLAIN is in a portal or plpgsql function and is
224  * executed repeatedly. (See also the same hack in DECLARE CURSOR and
225  * PREPARE.) XXX FIXME someday.
226  */
227  rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
228 
229  /* emit opening boilerplate */
230  ExplainBeginOutput(es);
231 
232  if (rewritten == NIL)
233  {
234  /*
235  * In the case of an INSTEAD NOTHING, tell at least that. But in
236  * non-text format, the output is delimited, so this isn't necessary.
237  */
238  if (es->format == EXPLAIN_FORMAT_TEXT)
239  appendStringInfoString(es->str, "Query rewrites to nothing\n");
240  }
241  else
242  {
243  ListCell *l;
244 
245  /* Explain every plan */
246  foreach(l, rewritten)
247  {
250  queryString, params);
251 
252  /* Separate plans with an appropriate separator */
253  if (lnext(l) != NULL)
255  }
256  }
257 
258  /* emit closing boilerplate */
259  ExplainEndOutput(es);
260  Assert(es->indent == 0);
261 
262  /* output tuples */
263  tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
264  if (es->format == EXPLAIN_FORMAT_TEXT)
265  do_text_output_multiline(tstate, es->str->data);
266  else
267  do_text_output_oneline(tstate, es->str->data);
268  end_tup_output(tstate);
269 
270  pfree(es->str->data);
271 }
#define NIL
Definition: pg_list.h:69
bool summary
Definition: explain.h:37
ExplainState * NewExplainState(void)
Definition: explain.c:277
List * QueryRewrite(Query *parsetree)
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:3313
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
int errcode(int sqlerrcode)
Definition: elog.c:575
List * options
Definition: parsenodes.h:3001
bool costs
Definition: explain.h:34
bool analyze
Definition: explain.h:33
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
Node * query
Definition: parsenodes.h:3000
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:3284
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:992
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:1308
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:3253
#define ERROR
Definition: elog.h:43
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:294
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
int location
Definition: parsenodes.h:678
int indent
Definition: explain.h:40
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
bool timing
Definition: explain.h:36
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
Definition: execTuples.c:1232
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:1278
bool verbose
Definition: explain.h:32
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
ExplainFormat format
Definition: explain.h:38
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:311
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params)
Definition: explain.c:333
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2528
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool buffers
Definition: explain.h:35
char * defname
Definition: parsenodes.h:675
Definition: pg_list.h:45
StringInfo str
Definition: explain.h:30
void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 670 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

671 {
672  if (queryDesc->sourceText)
673  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
674 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:3046
const char * sourceText
Definition: execdesc.h:38
TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 294 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

295 {
296  TupleDesc tupdesc;
297  ListCell *lc;
298  Oid result_type = TEXTOID;
299 
300  /* Check for XML format option */
301  foreach(lc, stmt->options)
302  {
303  DefElem *opt = (DefElem *) lfirst(lc);
304 
305  if (strcmp(opt->defname, "format") == 0)
306  {
307  char *p = defGetString(opt);
308 
309  if (strcmp(p, "xml") == 0)
310  result_type = XMLOID;
311  else if (strcmp(p, "json") == 0)
312  result_type = JSONOID;
313  else
314  result_type = TEXTOID;
315  /* don't "break", as ExplainQuery will use the last value */
316  }
317  }
318 
319  /* Need a tuple descriptor representing a single TEXT or XML column */
320  tupdesc = CreateTemplateTupleDesc(1, false);
321  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
322  result_type, -1, 0);
323  return tupdesc;
324 }
#define TEXTOID
Definition: pg_type.h:324
#define JSONOID
Definition: pg_type.h:356
List * options
Definition: parsenodes.h:3001
unsigned int Oid
Definition: postgres_ext.h:31
char * defGetString(DefElem *def)
Definition: define.c:49
#define XMLOID
Definition: pg_type.h:359
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:493
#define lfirst(lc)
Definition: pg_list.h:106
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
char * defname
Definition: parsenodes.h:675
int16 AttrNumber
Definition: attnum.h:21
void ExplainSeparatePlans ( ExplainState es)

Definition at line 3313 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().

3314 {
3315  switch (es->format)
3316  {
3317  case EXPLAIN_FORMAT_TEXT:
3318  /* add a blank line */
3319  appendStringInfoChar(es->str, '\n');
3320  break;
3321 
3322  case EXPLAIN_FORMAT_XML:
3323  case EXPLAIN_FORMAT_JSON:
3324  case EXPLAIN_FORMAT_YAML:
3325  /* nothing to do */
3326  break;
3327  }
3328 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
ExplainState* NewExplainState ( void  )

Definition at line 277 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

278 {
279  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
280 
281  /* Set default options (most fields can be left as zeroes). */
282  es->costs = true;
283  /* Prepare output buffer. */
284  es->str = makeStringInfo();
285 
286  return es;
287 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
bool costs
Definition: explain.h:34
void * palloc0(Size size)
Definition: mcxt.c:920
StringInfo str
Definition: explain.h:30

Variable Documentation

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

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook

Definition at line 44 of file explain.c.

Referenced by ExplainOneQuery().