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, 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 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)
 
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

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

3421 {
3422  switch (es->format)
3423  {
3424  case EXPLAIN_FORMAT_TEXT:
3425  /* nothing to do */
3426  break;
3427 
3428  case EXPLAIN_FORMAT_XML:
3430  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
3431  es->indent++;
3432  break;
3433 
3434  case EXPLAIN_FORMAT_JSON:
3435  /* top-level structure is an array of plans */
3436  appendStringInfoChar(es->str, '[');
3437  es->grouping_stack = lcons_int(0, es->grouping_stack);
3438  es->indent++;
3439  break;
3440 
3441  case EXPLAIN_FORMAT_YAML:
3442  es->grouping_stack = lcons_int(0, es->grouping_stack);
3443  break;
3444  }
3445 }
List * lcons_int(int datum, List *list)
Definition: list.c:277
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
void ExplainCloseGroup ( const char *  objtype,
const char *  labelname,
bool  labeled,
ExplainState es 
)

Definition at line 3338 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(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3340 {
3341  switch (es->format)
3342  {
3343  case EXPLAIN_FORMAT_TEXT:
3344  /* nothing to do */
3345  break;
3346 
3347  case EXPLAIN_FORMAT_XML:
3348  es->indent--;
3349  ExplainXMLTag(objtype, X_CLOSING, es);
3350  break;
3351 
3352  case EXPLAIN_FORMAT_JSON:
3353  es->indent--;
3354  appendStringInfoChar(es->str, '\n');
3355  appendStringInfoSpaces(es->str, 2 * es->indent);
3356  appendStringInfoChar(es->str, labeled ? '}' : ']');
3358  break;
3359 
3360  case EXPLAIN_FORMAT_YAML:
3361  es->indent--;
3363  break;
3364  }
3365 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3509
#define X_CLOSING
Definition: explain.c:52
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
List * list_delete_first(List *list)
Definition: list.c:666
void ExplainEndOutput ( ExplainState es)

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

3452 {
3453  switch (es->format)
3454  {
3455  case EXPLAIN_FORMAT_TEXT:
3456  /* nothing to do */
3457  break;
3458 
3459  case EXPLAIN_FORMAT_XML:
3460  es->indent--;
3461  appendStringInfoString(es->str, "</explain>");
3462  break;
3463 
3464  case EXPLAIN_FORMAT_JSON:
3465  es->indent--;
3466  appendStringInfoString(es->str, "\n]");
3468  break;
3469 
3470  case EXPLAIN_FORMAT_YAML:
3472  break;
3473  }
3474 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
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,
QueryEnvironment queryEnv,
const instr_time planduration 
)

Definition at line 461 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, PopActiveSnapshot(), PushCopiedSnapshot(), IntoClause::skipData, ExplainState::str, ExplainState::summary, ExplainState::timing, and UpdateActiveSnapshotCommandId().

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

464 {
465  DestReceiver *dest;
466  QueryDesc *queryDesc;
467  instr_time starttime;
468  double totaltime = 0;
469  int eflags;
470  int instrument_option = 0;
471 
472  Assert(plannedstmt->commandType != CMD_UTILITY);
473 
474  if (es->analyze && es->timing)
475  instrument_option |= INSTRUMENT_TIMER;
476  else if (es->analyze)
477  instrument_option |= INSTRUMENT_ROWS;
478 
479  if (es->buffers)
480  instrument_option |= INSTRUMENT_BUFFERS;
481 
482  /*
483  * We always collect timing for the entire statement, even when node-level
484  * timing is off, so we don't look at es->timing here. (We could skip
485  * this if !es->summary, but it's hardly worth the complication.)
486  */
487  INSTR_TIME_SET_CURRENT(starttime);
488 
489  /*
490  * Use a snapshot with an updated command ID to ensure this query sees
491  * results of any previously executed queries.
492  */
495 
496  /*
497  * Normally we discard the query's output, but if explaining CREATE TABLE
498  * AS, we'd better use the appropriate tuple receiver.
499  */
500  if (into)
501  dest = CreateIntoRelDestReceiver(into);
502  else
503  dest = None_Receiver;
504 
505  /* Create a QueryDesc for the query */
506  queryDesc = CreateQueryDesc(plannedstmt, queryString,
508  dest, params, queryEnv, instrument_option);
509 
510  /* Select execution options */
511  if (es->analyze)
512  eflags = 0; /* default run-to-completion flags */
513  else
514  eflags = EXEC_FLAG_EXPLAIN_ONLY;
515  if (into)
516  eflags |= GetIntoRelEFlags(into);
517 
518  /* call ExecutorStart to prepare the plan for execution */
519  ExecutorStart(queryDesc, eflags);
520 
521  /* Execute the plan for statistics if asked for */
522  if (es->analyze)
523  {
524  ScanDirection dir;
525 
526  /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
527  if (into && into->skipData)
529  else
530  dir = ForwardScanDirection;
531 
532  /* run the plan */
533  ExecutorRun(queryDesc, dir, 0L, true);
534 
535  /* run cleanup too */
536  ExecutorFinish(queryDesc);
537 
538  /* We can't run ExecutorEnd 'till we're done printing the stats... */
539  totaltime += elapsed_time(&starttime);
540  }
541 
542  ExplainOpenGroup("Query", NULL, true, es);
543 
544  /* Create textual dump of plan tree */
545  ExplainPrintPlan(es, queryDesc);
546 
547  if (es->summary && planduration)
548  {
549  double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
550 
551  if (es->format == EXPLAIN_FORMAT_TEXT)
552  appendStringInfo(es->str, "Planning time: %.3f ms\n",
553  1000.0 * plantime);
554  else
555  ExplainPropertyFloat("Planning Time", 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  * Close down the query and free resources. Include time for this in the
564  * total execution time (although it should be pretty minimal).
565  */
566  INSTR_TIME_SET_CURRENT(starttime);
567 
568  ExecutorEnd(queryDesc);
569 
570  FreeQueryDesc(queryDesc);
571 
573 
574  /* We need a CCI just in case query expanded to multiple plans */
575  if (es->analyze)
577 
578  totaltime += elapsed_time(&starttime);
579 
580  /*
581  * We only report execution time if we actually ran the query (that is,
582  * the user specified ANALYZE), and if summary reporting is enabled (the
583  * user can set SUMMARY OFF to not have the timing information included in
584  * the output). By default, ANALYZE sets SUMMARY to true.
585  */
586  if (es->summary && es->analyze)
587  {
588  if (es->format == EXPLAIN_FORMAT_TEXT)
589  appendStringInfo(es->str, "Execution time: %.3f ms\n",
590  1000.0 * totaltime);
591  else
592  ExplainPropertyFloat("Execution Time", 1000.0 * totaltime,
593  3, es);
594  }
595 
596  ExplainCloseGroup("Query", NULL, true, es);
597 }
bool summary
Definition: explain.h:37
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:781
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
struct timeval instr_time
Definition: instr_time.h:147
void ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ExplainState *es)
Definition: explain.c:3247
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:147
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
bool skipData
Definition: primnodes.h:115
DestReceiver * None_Receiver
Definition: dest.c:91
bool analyze
Definition: explain.h:33
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:461
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:392
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:648
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:611
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:299
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:769
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:423
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:401
bool timing
Definition: explain.h:36
#define InvalidSnapshot
Definition: snapshot.h:25
void CommandCounterIncrement(void)
Definition: xact.c:915
CmdType commandType
Definition: plannodes.h:45
#define Assert(condition)
Definition: c.h:681
ExplainFormat format
Definition: explain.h:38
static double elapsed_time(instr_time *starttime)
Definition: explain.c:776
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
bool buffers
Definition: explain.h:35
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3338
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3275
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,
QueryEnvironment queryEnv 
)

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

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

Definition at line 3275 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(), ExplainPrintTriggers(), report_triggers(), show_grouping_set_keys(), show_grouping_sets(), show_modifytable_info(), and show_sort_info().

3277 {
3278  switch (es->format)
3279  {
3280  case EXPLAIN_FORMAT_TEXT:
3281  /* nothing to do */
3282  break;
3283 
3284  case EXPLAIN_FORMAT_XML:
3285  ExplainXMLTag(objtype, X_OPENING, es);
3286  es->indent++;
3287  break;
3288 
3289  case EXPLAIN_FORMAT_JSON:
3291  appendStringInfoSpaces(es->str, 2 * es->indent);
3292  if (labelname)
3293  {
3294  escape_json(es->str, labelname);
3295  appendStringInfoString(es->str, ": ");
3296  }
3297  appendStringInfoChar(es->str, labeled ? '{' : '[');
3298 
3299  /*
3300  * In JSON format, the grouping_stack is an integer list. 0 means
3301  * we've emitted nothing at this grouping level, 1 means we've
3302  * emitted something (and so the next item needs a comma). See
3303  * ExplainJSONLineEnding().
3304  */
3305  es->grouping_stack = lcons_int(0, es->grouping_stack);
3306  es->indent++;
3307  break;
3308 
3309  case EXPLAIN_FORMAT_YAML:
3310 
3311  /*
3312  * In YAML format, the grouping stack is an integer list. 0 means
3313  * we've emitted nothing at this grouping level AND this grouping
3314  * level is unlabelled and must be marked with "- ". See
3315  * ExplainYAMLLineStarting().
3316  */
3318  if (labelname)
3319  {
3320  appendStringInfo(es->str, "%s: ", labelname);
3321  es->grouping_stack = lcons_int(1, es->grouping_stack);
3322  }
3323  else
3324  {
3325  appendStringInfoString(es->str, "- ");
3326  es->grouping_stack = lcons_int(0, es->grouping_stack);
3327  }
3328  es->indent++;
3329  break;
3330  }
3331 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2433
List * lcons_int(int datum, List *list)
Definition: list.c:277
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3509
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3556
List * grouping_stack
Definition: explain.h:41
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3536
#define X_OPENING
Definition: explain.c:51
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 611 of file explain.c.

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

612 {
613  Bitmapset *rels_used = NULL;
614  PlanState *ps;
615 
616  /* Set up ExplainState fields associated with this plan tree */
617  Assert(queryDesc->plannedstmt != NULL);
618  es->pstmt = queryDesc->plannedstmt;
619  es->rtable = queryDesc->plannedstmt->rtable;
620  ExplainPreScanNode(queryDesc->planstate, &rels_used);
623  es->rtable_names);
624  es->printed_subplans = NULL;
625 
626  /*
627  * Sometimes we mark a Gather node as "invisible", which means that it's
628  * not displayed in EXPLAIN output. The purpose of this is to allow
629  * running regression tests with force_parallel_mode=regress to get the
630  * same results as running the same tests with force_parallel_mode=off.
631  */
632  ps = queryDesc->planstate;
633  if (IsA(ps, GatherState) &&((Gather *) ps->plan)->invisible)
634  ps = outerPlanState(ps);
635  ExplainNode(ps, NIL, NULL, NULL, es);
636 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
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:3161
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:860
PlanState * planstate
Definition: execdesc.h:49
#define outerPlanState(node)
Definition: execnodes.h:893
Plan * plan
Definition: execnodes.h:847
#define Assert(condition)
Definition: c.h:681
List * rtable
Definition: plannodes.h:63
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:795
PlannedStmt * plannedstmt
Definition: execdesc.h:37
List * deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
Definition: ruleutils.c:3086
List * rtable
Definition: explain.h:44
void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 648 of file explain.c.

References EState::es_leaf_result_relations, 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, QueryDesc::estate, ExplainCloseGroup(), ExplainOpenGroup(), lfirst, NIL, and report_triggers().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

649 {
650  ResultRelInfo *rInfo;
651  bool show_relname;
652  int numrels = queryDesc->estate->es_num_result_relations;
653  int numrootrels = queryDesc->estate->es_num_root_result_relations;
654  List *leafrels = queryDesc->estate->es_leaf_result_relations;
655  List *targrels = queryDesc->estate->es_trig_target_relations;
656  int nr;
657  ListCell *l;
658 
659  ExplainOpenGroup("Triggers", "Triggers", false, es);
660 
661  show_relname = (numrels > 1 || numrootrels > 0 ||
662  leafrels != NIL || targrels != NIL);
663  rInfo = queryDesc->estate->es_result_relations;
664  for (nr = 0; nr < numrels; rInfo++, nr++)
665  report_triggers(rInfo, show_relname, es);
666 
667  rInfo = queryDesc->estate->es_root_result_relations;
668  for (nr = 0; nr < numrootrels; rInfo++, nr++)
669  report_triggers(rInfo, show_relname, es);
670 
671  foreach(l, leafrels)
672  {
673  rInfo = (ResultRelInfo *) lfirst(l);
674  report_triggers(rInfo, show_relname, es);
675  }
676 
677  foreach(l, targrels)
678  {
679  rInfo = (ResultRelInfo *) lfirst(l);
680  report_triggers(rInfo, show_relname, es);
681  }
682 
683  ExplainCloseGroup("Triggers", "Triggers", false, es);
684 }
#define NIL
Definition: pg_list.h:69
EState * estate
Definition: execdesc.h:48
ResultRelInfo * es_result_relations
Definition: execnodes.h:441
List * es_leaf_result_relations
Definition: execnodes.h:456
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:706
int es_num_root_result_relations
Definition: execnodes.h:453
List * es_trig_target_relations
Definition: execnodes.h:459
int es_num_result_relations
Definition: execnodes.h:442
#define lfirst(lc)
Definition: pg_list.h:106
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:452
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3338
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:3275
Definition: pg_list.h:45
void ExplainPropertyBool ( const char *  qlabel,
bool  value,
ExplainState es 
)

Definition at line 3260 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode().

3261 {
3262  ExplainProperty(qlabel, value ? "true" : "false", true, es);
3263 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3163
static struct @121 value
void ExplainPropertyFloat ( const char *  qlabel,
double  value,
int  ndigits,
ExplainState es 
)

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

3249 {
3250  char buf[256];
3251 
3252  snprintf(buf, sizeof(buf), "%.*f", ndigits, value);
3253  ExplainProperty(qlabel, buf, true, es);
3254 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3163
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static struct @121 value
static char * buf
Definition: pg_test_fsync.c:67
void ExplainPropertyInteger ( const char *  qlabel,
int  value,
ExplainState es 
)

Definition at line 3222 of file explain.c.

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

Referenced by ExplainNode(), and show_sort_info().

3223 {
3224  char buf[32];
3225 
3226  snprintf(buf, sizeof(buf), "%d", value);
3227  ExplainProperty(qlabel, buf, true, es);
3228 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3163
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static struct @121 value
static char * buf
Definition: pg_test_fsync.c:67
void ExplainPropertyList ( const char *  qlabel,
List data,
ExplainState es 
)

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

3043 {
3044  ListCell *lc;
3045  bool first = true;
3046 
3047  switch (es->format)
3048  {
3049  case EXPLAIN_FORMAT_TEXT:
3050  appendStringInfoSpaces(es->str, es->indent * 2);
3051  appendStringInfo(es->str, "%s: ", qlabel);
3052  foreach(lc, data)
3053  {
3054  if (!first)
3055  appendStringInfoString(es->str, ", ");
3056  appendStringInfoString(es->str, (const char *) lfirst(lc));
3057  first = false;
3058  }
3059  appendStringInfoChar(es->str, '\n');
3060  break;
3061 
3062  case EXPLAIN_FORMAT_XML:
3063  ExplainXMLTag(qlabel, X_OPENING, es);
3064  foreach(lc, data)
3065  {
3066  char *str;
3067 
3068  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3069  appendStringInfoString(es->str, "<Item>");
3070  str = escape_xml((const char *) lfirst(lc));
3071  appendStringInfoString(es->str, str);
3072  pfree(str);
3073  appendStringInfoString(es->str, "</Item>\n");
3074  }
3075  ExplainXMLTag(qlabel, X_CLOSING, es);
3076  break;
3077 
3078  case EXPLAIN_FORMAT_JSON:
3080  appendStringInfoSpaces(es->str, es->indent * 2);
3081  escape_json(es->str, qlabel);
3082  appendStringInfoString(es->str, ": [");
3083  foreach(lc, data)
3084  {
3085  if (!first)
3086  appendStringInfoString(es->str, ", ");
3087  escape_json(es->str, (const char *) lfirst(lc));
3088  first = false;
3089  }
3090  appendStringInfoChar(es->str, ']');
3091  break;
3092 
3093  case EXPLAIN_FORMAT_YAML:
3095  appendStringInfo(es->str, "%s: ", qlabel);
3096  foreach(lc, data)
3097  {
3098  appendStringInfoChar(es->str, '\n');
3099  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3100  appendStringInfoString(es->str, "- ");
3101  escape_yaml(es->str, (const char *) lfirst(lc));
3102  }
3103  break;
3104  }
3105 }
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:3509
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:949
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3556
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3581
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3536
#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:2232
StringInfo str
Definition: explain.h:30
void ExplainPropertyListNested ( const char *  qlabel,
List data,
ExplainState es 
)

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

3113 {
3114  ListCell *lc;
3115  bool first = true;
3116 
3117  switch (es->format)
3118  {
3119  case EXPLAIN_FORMAT_TEXT:
3120  case EXPLAIN_FORMAT_XML:
3121  ExplainPropertyList(qlabel, data, es);
3122  return;
3123 
3124  case EXPLAIN_FORMAT_JSON:
3126  appendStringInfoSpaces(es->str, es->indent * 2);
3127  appendStringInfoChar(es->str, '[');
3128  foreach(lc, data)
3129  {
3130  if (!first)
3131  appendStringInfoString(es->str, ", ");
3132  escape_json(es->str, (const char *) lfirst(lc));
3133  first = false;
3134  }
3135  appendStringInfoChar(es->str, ']');
3136  break;
3137 
3138  case EXPLAIN_FORMAT_YAML:
3140  appendStringInfoString(es->str, "- [");
3141  foreach(lc, data)
3142  {
3143  if (!first)
3144  appendStringInfoString(es->str, ", ");
3145  escape_yaml(es->str, (const char *) lfirst(lc));
3146  first = false;
3147  }
3148  appendStringInfoChar(es->str, ']');
3149  break;
3150  }
3151 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2433
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3556
int indent
Definition: explain.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:3581
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3536
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:3042
#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 3234 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().

3235 {
3236  char buf[32];
3237 
3238  snprintf(buf, sizeof(buf), "%ld", value);
3239  ExplainProperty(qlabel, buf, true, es);
3240 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3163
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static struct @121 value
static char * buf
Definition: pg_test_fsync.c:67
void ExplainPropertyText ( const char *  qlabel,
const char *  value,
ExplainState es 
)

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

3214 {
3215  ExplainProperty(qlabel, value, false, es);
3216 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3163
static struct @121 value
void ExplainQuery ( ParseState pstate,
ExplainStmt stmt,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv,
DestReceiver dest 
)

Definition at line 141 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::str, ExplainState::summary, ExplainState::timing, and ExplainState::verbose.

Referenced by standard_ProcessUtility().

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

Definition at line 695 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

696 {
697  if (queryDesc->sourceText)
698  ExplainPropertyText("Query Text", queryDesc->sourceText, es);
699 }
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:3213
const char * sourceText
Definition: execdesc.h:38
TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 298 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

299 {
300  TupleDesc tupdesc;
301  ListCell *lc;
302  Oid result_type = TEXTOID;
303 
304  /* Check for XML format option */
305  foreach(lc, stmt->options)
306  {
307  DefElem *opt = (DefElem *) lfirst(lc);
308 
309  if (strcmp(opt->defname, "format") == 0)
310  {
311  char *p = defGetString(opt);
312 
313  if (strcmp(p, "xml") == 0)
314  result_type = XMLOID;
315  else if (strcmp(p, "json") == 0)
316  result_type = JSONOID;
317  else
318  result_type = TEXTOID;
319  /* don't "break", as ExplainQuery will use the last value */
320  }
321  }
322 
323  /* Need a tuple descriptor representing a single TEXT or XML column */
324  tupdesc = CreateTemplateTupleDesc(1, false);
325  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
326  result_type, -1, 0);
327  return tupdesc;
328 }
#define TEXTOID
Definition: pg_type.h:324
#define JSONOID
Definition: pg_type.h:356
List * options
Definition: parsenodes.h:3135
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:505
#define lfirst(lc)
Definition: pg_list.h:106
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
char * defname
Definition: parsenodes.h:719
int16 AttrNumber
Definition: attnum.h:21
void ExplainSeparatePlans ( ExplainState es)

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

3481 {
3482  switch (es->format)
3483  {
3484  case EXPLAIN_FORMAT_TEXT:
3485  /* add a blank line */
3486  appendStringInfoChar(es->str, '\n');
3487  break;
3488 
3489  case EXPLAIN_FORMAT_XML:
3490  case EXPLAIN_FORMAT_JSON:
3491  case EXPLAIN_FORMAT_YAML:
3492  /* nothing to do */
3493  break;
3494  }
3495 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30
ExplainState* NewExplainState ( void  )

Definition at line 281 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

282 {
283  ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
284 
285  /* Set default options (most fields can be left as zeroes). */
286  es->costs = true;
287  /* Prepare output buffer. */
288  es->str = makeStringInfo();
289 
290  return es;
291 }
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
bool costs
Definition: explain.h:34
void * palloc0(Size size)
Definition: mcxt.c:877
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().