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

◆ explain_get_index_name_hook_type

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

Definition at line 60 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)

Definition at line 51 of file explain.h.

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

3483 {
3484  switch (es->format)
3485  {
3486  case EXPLAIN_FORMAT_TEXT:
3487  /* nothing to do */
3488  break;
3489 
3490  case EXPLAIN_FORMAT_XML:
3492  "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
3493  es->indent++;
3494  break;
3495 
3496  case EXPLAIN_FORMAT_JSON:
3497  /* top-level structure is an array of plans */
3498  appendStringInfoChar(es->str, '[');
3499  es->grouping_stack = lcons_int(0, es->grouping_stack);
3500  es->indent++;
3501  break;
3502 
3503  case EXPLAIN_FORMAT_YAML:
3504  es->grouping_stack = lcons_int(0, es->grouping_stack);
3505  break;
3506  }
3507 }
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

◆ ExplainCloseGroup()

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

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

3402 {
3403  switch (es->format)
3404  {
3405  case EXPLAIN_FORMAT_TEXT:
3406  /* nothing to do */
3407  break;
3408 
3409  case EXPLAIN_FORMAT_XML:
3410  es->indent--;
3411  ExplainXMLTag(objtype, X_CLOSING, es);
3412  break;
3413 
3414  case EXPLAIN_FORMAT_JSON:
3415  es->indent--;
3416  appendStringInfoChar(es->str, '\n');
3417  appendStringInfoSpaces(es->str, 2 * es->indent);
3418  appendStringInfoChar(es->str, labeled ? '}' : ']');
3420  break;
3421 
3422  case EXPLAIN_FORMAT_YAML:
3423  es->indent--;
3425  break;
3426  }
3427 }
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3571
#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

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

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

3514 {
3515  switch (es->format)
3516  {
3517  case EXPLAIN_FORMAT_TEXT:
3518  /* nothing to do */
3519  break;
3520 
3521  case EXPLAIN_FORMAT_XML:
3522  es->indent--;
3523  appendStringInfoString(es->str, "</explain>");
3524  break;
3525 
3526  case EXPLAIN_FORMAT_JSON:
3527  es->indent--;
3528  appendStringInfoString(es->str, "\n]");
3530  break;
3531 
3532  case EXPLAIN_FORMAT_YAML:
3534  break;
3535  }
3536 }
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

◆ ExplainOnePlan()

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

Definition at line 462 of file explain.c.

References ExplainState::analyze, appendStringInfo(), Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, CreateIntoRelDestReceiver(), CreateQueryDesc(), generate_unaccent_rules::dest, 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().

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

◆ ExplainOneUtility()

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

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

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

◆ ExplainOpenGroup()

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

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

3339 {
3340  switch (es->format)
3341  {
3342  case EXPLAIN_FORMAT_TEXT:
3343  /* nothing to do */
3344  break;
3345 
3346  case EXPLAIN_FORMAT_XML:
3347  ExplainXMLTag(objtype, X_OPENING, es);
3348  es->indent++;
3349  break;
3350 
3351  case EXPLAIN_FORMAT_JSON:
3353  appendStringInfoSpaces(es->str, 2 * es->indent);
3354  if (labelname)
3355  {
3356  escape_json(es->str, labelname);
3357  appendStringInfoString(es->str, ": ");
3358  }
3359  appendStringInfoChar(es->str, labeled ? '{' : '[');
3360 
3361  /*
3362  * In JSON format, the grouping_stack is an integer list. 0 means
3363  * we've emitted nothing at this grouping level, 1 means we've
3364  * emitted something (and so the next item needs a comma). See
3365  * ExplainJSONLineEnding().
3366  */
3367  es->grouping_stack = lcons_int(0, es->grouping_stack);
3368  es->indent++;
3369  break;
3370 
3371  case EXPLAIN_FORMAT_YAML:
3372 
3373  /*
3374  * In YAML format, the grouping stack is an integer list. 0 means
3375  * we've emitted nothing at this grouping level AND this grouping
3376  * level is unlabelled and must be marked with "- ". See
3377  * ExplainYAMLLineStarting().
3378  */
3380  if (labelname)
3381  {
3382  appendStringInfo(es->str, "%s: ", labelname);
3383  es->grouping_stack = lcons_int(1, es->grouping_stack);
3384  }
3385  else
3386  {
3387  appendStringInfoString(es->str, "- ");
3388  es->grouping_stack = lcons_int(0, es->grouping_stack);
3389  }
3390  es->indent++;
3391  break;
3392  }
3393 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2397
List * lcons_int(int datum, List *list)
Definition: list.c:277
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3571
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:3618
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:3598
#define X_OPENING
Definition: explain.c:51
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

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

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

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

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

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

◆ ExplainPropertyBool()

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

Definition at line 3322 of file explain.c.

References ExplainProperty().

Referenced by ExplainNode().

3323 {
3324  ExplainProperty(qlabel, value ? "true" : "false", true, es);
3325 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3225
static struct @121 value

◆ ExplainPropertyFloat()

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

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

3311 {
3312  char buf[256];
3313 
3314  snprintf(buf, sizeof(buf), "%.*f", ndigits, value);
3315  ExplainProperty(qlabel, buf, true, es);
3316 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3225
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

◆ ExplainPropertyInteger()

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

Definition at line 3284 of file explain.c.

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

Referenced by ExplainNode(), and show_sort_info().

3285 {
3286  char buf[32];
3287 
3288  snprintf(buf, sizeof(buf), "%d", value);
3289  ExplainProperty(qlabel, buf, true, es);
3290 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3225
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

◆ ExplainPropertyList()

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

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

3105 {
3106  ListCell *lc;
3107  bool first = true;
3108 
3109  switch (es->format)
3110  {
3111  case EXPLAIN_FORMAT_TEXT:
3112  appendStringInfoSpaces(es->str, es->indent * 2);
3113  appendStringInfo(es->str, "%s: ", qlabel);
3114  foreach(lc, data)
3115  {
3116  if (!first)
3117  appendStringInfoString(es->str, ", ");
3118  appendStringInfoString(es->str, (const char *) lfirst(lc));
3119  first = false;
3120  }
3121  appendStringInfoChar(es->str, '\n');
3122  break;
3123 
3124  case EXPLAIN_FORMAT_XML:
3125  ExplainXMLTag(qlabel, X_OPENING, es);
3126  foreach(lc, data)
3127  {
3128  char *str;
3129 
3130  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3131  appendStringInfoString(es->str, "<Item>");
3132  str = escape_xml((const char *) lfirst(lc));
3133  appendStringInfoString(es->str, str);
3134  pfree(str);
3135  appendStringInfoString(es->str, "</Item>\n");
3136  }
3137  ExplainXMLTag(qlabel, X_CLOSING, es);
3138  break;
3139 
3140  case EXPLAIN_FORMAT_JSON:
3142  appendStringInfoSpaces(es->str, es->indent * 2);
3143  escape_json(es->str, qlabel);
3144  appendStringInfoString(es->str, ": [");
3145  foreach(lc, data)
3146  {
3147  if (!first)
3148  appendStringInfoString(es->str, ", ");
3149  escape_json(es->str, (const char *) lfirst(lc));
3150  first = false;
3151  }
3152  appendStringInfoChar(es->str, ']');
3153  break;
3154 
3155  case EXPLAIN_FORMAT_YAML:
3157  appendStringInfo(es->str, "%s: ", qlabel);
3158  foreach(lc, data)
3159  {
3160  appendStringInfoChar(es->str, '\n');
3161  appendStringInfoSpaces(es->str, es->indent * 2 + 2);
3162  appendStringInfoString(es->str, "- ");
3163  escape_yaml(es->str, (const char *) lfirst(lc));
3164  }
3165  break;
3166  }
3167 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2397
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:3571
#define X_CLOSING
Definition: explain.c:52
void pfree(void *pointer)
Definition: mcxt.c:936
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:3618
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:3643
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3598
#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

◆ ExplainPropertyListNested()

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

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

3175 {
3176  ListCell *lc;
3177  bool first = true;
3178 
3179  switch (es->format)
3180  {
3181  case EXPLAIN_FORMAT_TEXT:
3182  case EXPLAIN_FORMAT_XML:
3183  ExplainPropertyList(qlabel, data, es);
3184  return;
3185 
3186  case EXPLAIN_FORMAT_JSON:
3188  appendStringInfoSpaces(es->str, es->indent * 2);
3189  appendStringInfoChar(es->str, '[');
3190  foreach(lc, data)
3191  {
3192  if (!first)
3193  appendStringInfoString(es->str, ", ");
3194  escape_json(es->str, (const char *) lfirst(lc));
3195  first = false;
3196  }
3197  appendStringInfoChar(es->str, ']');
3198  break;
3199 
3200  case EXPLAIN_FORMAT_YAML:
3202  appendStringInfoString(es->str, "- [");
3203  foreach(lc, data)
3204  {
3205  if (!first)
3206  appendStringInfoString(es->str, ", ");
3207  escape_yaml(es->str, (const char *) lfirst(lc));
3208  first = false;
3209  }
3210  appendStringInfoChar(es->str, ']');
3211  break;
3212  }
3213 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2397
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:3618
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:3643
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:3598
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:3104
#define lfirst(lc)
Definition: pg_list.h:106
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ ExplainPropertyLong()

void ExplainPropertyLong ( const char *  qlabel,
long  value,
ExplainState es 
)

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

3297 {
3298  char buf[32];
3299 
3300  snprintf(buf, sizeof(buf), "%ld", value);
3301  ExplainProperty(qlabel, buf, true, es);
3302 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3225
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

◆ ExplainPropertyText()

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

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

3276 {
3277  ExplainProperty(qlabel, value, false, es);
3278 }
static void ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:3225
static struct @121 value

◆ 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::str, ExplainState::summary, ExplainState::timing, 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, "timing") == 0)
167  {
168  timing_set = true;
169  es->timing = defGetBoolean(opt);
170  }
171  else if (strcmp(opt->defname, "summary") == 0)
172  {
173  summary_set = true;
174  es->summary = defGetBoolean(opt);
175  }
176  else if (strcmp(opt->defname, "format") == 0)
177  {
178  char *p = defGetString(opt);
179 
180  if (strcmp(p, "text") == 0)
182  else if (strcmp(p, "xml") == 0)
184  else if (strcmp(p, "json") == 0)
186  else if (strcmp(p, "yaml") == 0)
188  else
189  ereport(ERROR,
190  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
191  errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
192  opt->defname, p),
193  parser_errposition(pstate, opt->location)));
194  }
195  else
196  ereport(ERROR,
197  (errcode(ERRCODE_SYNTAX_ERROR),
198  errmsg("unrecognized EXPLAIN option \"%s\"",
199  opt->defname),
200  parser_errposition(pstate, opt->location)));
201  }
202 
203  if (es->buffers && !es->analyze)
204  ereport(ERROR,
205  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
206  errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
207 
208  /* if the timing was not set explicitly, set default value */
209  es->timing = (timing_set) ? es->timing : es->analyze;
210 
211  /* check that timing is used with EXPLAIN ANALYZE */
212  if (es->timing && !es->analyze)
213  ereport(ERROR,
214  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
215  errmsg("EXPLAIN option TIMING requires ANALYZE")));
216 
217  /* if the summary was not set explicitly, set default value */
218  es->summary = (summary_set) ? es->summary : es->analyze;
219 
220  /*
221  * Parse analysis was done already, but we still have to run the rule
222  * rewriter. We do not do AcquireRewriteLocks: we assume the query either
223  * came straight from the parser, or suitable locks were acquired by
224  * plancache.c.
225  *
226  * Because the rewriter and planner tend to scribble on the input, we make
227  * a preliminary copy of the source querytree. This prevents problems in
228  * the case that the EXPLAIN is in a portal or plpgsql function and is
229  * executed repeatedly. (See also the same hack in DECLARE CURSOR and
230  * PREPARE.) XXX FIXME someday.
231  */
232  rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
233 
234  /* emit opening boilerplate */
235  ExplainBeginOutput(es);
236 
237  if (rewritten == NIL)
238  {
239  /*
240  * In the case of an INSTEAD NOTHING, tell at least that. But in
241  * non-text format, the output is delimited, so this isn't necessary.
242  */
243  if (es->format == EXPLAIN_FORMAT_TEXT)
244  appendStringInfoString(es->str, "Query rewrites to nothing\n");
245  }
246  else
247  {
248  ListCell *l;
249 
250  /* Explain every plan */
251  foreach(l, rewritten)
252  {
254  CURSOR_OPT_PARALLEL_OK, NULL, es,
255  queryString, params, queryEnv);
256 
257  /* Separate plans with an appropriate separator */
258  if (lnext(l) != NULL)
260  }
261  }
262 
263  /* emit closing boilerplate */
264  ExplainEndOutput(es);
265  Assert(es->indent == 0);
266 
267  /* output tuples */
268  tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
269  if (es->format == EXPLAIN_FORMAT_TEXT)
270  do_text_output_multiline(tstate, es->str->data);
271  else
272  do_text_output_oneline(tstate, es->str->data);
273  end_tup_output(tstate);
274 
275  pfree(es->str->data);
276 }
#define NIL
Definition: pg_list.h:69
bool summary
Definition: explain.h:37
ExplainState * NewExplainState(void)
Definition: explain.c:282
List * QueryRewrite(Query *parsetree)
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:3542
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
int errcode(int sqlerrcode)
Definition: elog.c:575
List * options
Definition: parsenodes.h:3158
bool costs
Definition: explain.h:34
bool analyze
Definition: explain.h:33
Node * query
Definition: parsenodes.h:3157
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:3513
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:936
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:1311
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:3482
#define ERROR
Definition: elog.h:43
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:299
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:338
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:680
#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:441
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2650
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:625
Definition: pg_list.h:45
StringInfo str
Definition: explain.h:30

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 696 of file explain.c.

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

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

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 299 of file explain.c.

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

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

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

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

3543 {
3544  switch (es->format)
3545  {
3546  case EXPLAIN_FORMAT_TEXT:
3547  /* add a blank line */
3548  appendStringInfoChar(es->str, '\n');
3549  break;
3550 
3551  case EXPLAIN_FORMAT_XML:
3552  case EXPLAIN_FORMAT_JSON:
3553  case EXPLAIN_FORMAT_YAML:
3554  /* nothing to do */
3555  break;
3556  }
3557 }
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
ExplainFormat format
Definition: explain.h:38
StringInfo str
Definition: explain.h:30

◆ NewExplainState()

ExplainState* NewExplainState ( void  )

Definition at line 282 of file explain.c.

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

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