PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
explain.h File Reference
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "parser/parse_node.h"
Include dependency graph for explain.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ExplainWorkersState
 
struct  ExplainState
 

Typedefs

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

Enumerations

enum  ExplainSerializeOption { EXPLAIN_SERIALIZE_NONE , EXPLAIN_SERIALIZE_TEXT , EXPLAIN_SERIALIZE_BINARY }
 
enum  ExplainFormat { EXPLAIN_FORMAT_TEXT , EXPLAIN_FORMAT_XML , EXPLAIN_FORMAT_JSON , EXPLAIN_FORMAT_YAML }
 

Functions

void ExplainQuery (ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest)
 
void standard_ExplainOneQuery (Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
ExplainStateNewExplainState (void)
 
TupleDesc ExplainResultDesc (ExplainStmt *stmt)
 
void ExplainOneUtility (Node *utilityStmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
 
void ExplainOnePlan (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters)
 
void ExplainPrintPlan (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintTriggers (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainPrintJITSummary (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainQueryText (ExplainState *es, QueryDesc *queryDesc)
 
void ExplainQueryParameters (ExplainState *es, ParamListInfo params, int maxlen)
 
void ExplainBeginOutput (ExplainState *es)
 
void ExplainEndOutput (ExplainState *es)
 
void ExplainSeparatePlans (ExplainState *es)
 
void ExplainPropertyList (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyListNested (const char *qlabel, List *data, ExplainState *es)
 
void ExplainPropertyText (const char *qlabel, const char *value, ExplainState *es)
 
void ExplainPropertyInteger (const char *qlabel, const char *unit, int64 value, ExplainState *es)
 
void ExplainPropertyUInteger (const char *qlabel, const char *unit, uint64 value, ExplainState *es)
 
void ExplainPropertyFloat (const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
 
void ExplainPropertyBool (const char *qlabel, bool value, ExplainState *es)
 
void ExplainOpenGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 
void ExplainCloseGroup (const char *objtype, const char *labelname, bool labeled, ExplainState *es)
 
DestReceiverCreateExplainSerializeDestReceiver (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 87 of file explain.h.

◆ ExplainFormat

◆ ExplainOneQuery_hook_type

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

Definition at line 77 of file explain.h.

◆ ExplainSerializeOption

◆ ExplainState

typedef struct ExplainState ExplainState

◆ ExplainWorkersState

Enumeration Type Documentation

◆ ExplainFormat

Enumerator
EXPLAIN_FORMAT_TEXT 
EXPLAIN_FORMAT_XML 
EXPLAIN_FORMAT_JSON 
EXPLAIN_FORMAT_YAML 

Definition at line 27 of file explain.h.

28{
ExplainFormat
Definition: explain.h:28
@ EXPLAIN_FORMAT_XML
Definition: explain.h:30
@ EXPLAIN_FORMAT_YAML
Definition: explain.h:32
@ EXPLAIN_FORMAT_TEXT
Definition: explain.h:29
@ EXPLAIN_FORMAT_JSON
Definition: explain.h:31

◆ ExplainSerializeOption

Enumerator
EXPLAIN_SERIALIZE_NONE 
EXPLAIN_SERIALIZE_TEXT 
EXPLAIN_SERIALIZE_BINARY 

Definition at line 20 of file explain.h.

21{
ExplainSerializeOption
Definition: explain.h:21
@ EXPLAIN_SERIALIZE_TEXT
Definition: explain.h:23
@ EXPLAIN_SERIALIZE_NONE
Definition: explain.h:22
@ EXPLAIN_SERIALIZE_BINARY
Definition: explain.h:24

Function Documentation

◆ CreateExplainSerializeDestReceiver()

DestReceiver * CreateExplainSerializeDestReceiver ( ExplainState es)

Definition at line 5883 of file explain.c.

5884{
5886
5888
5894
5895 self->es = es;
5896
5897 return (DestReceiver *) self;
5898}
@ DestExplainSerialize
Definition: dest.h:99
static void serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: explain.c:5817
static void serializeAnalyzeDestroy(DestReceiver *self)
Definition: explain.c:5874
static bool serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self)
Definition: explain.c:5714
static void serializeAnalyzeShutdown(DestReceiver *self)
Definition: explain.c:5853
void * palloc0(Size size)
Definition: mcxt.c:1347
ExplainState * es
Definition: explain.c:5644
DestReceiver pub
Definition: explain.c:5643
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128

References DestExplainSerialize, SerializeDestReceiver::es, _DestReceiver::mydest, palloc0(), SerializeDestReceiver::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, _DestReceiver::rStartup, serializeAnalyzeDestroy(), serializeAnalyzeReceive(), serializeAnalyzeShutdown(), and serializeAnalyzeStartup().

Referenced by CreateDestReceiver(), and ExplainOnePlan().

◆ ExplainBeginOutput()

void ExplainBeginOutput ( ExplainState es)

Definition at line 5450 of file explain.c.

5451{
5452 switch (es->format)
5453 {
5455 /* nothing to do */
5456 break;
5457
5458 case EXPLAIN_FORMAT_XML:
5460 "<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
5461 es->indent++;
5462 break;
5463
5465 /* top-level structure is an array of plans */
5466 appendStringInfoChar(es->str, '[');
5468 es->indent++;
5469 break;
5470
5473 break;
5474 }
5475}
List * lcons_int(int datum, List *list)
Definition: list.c:513
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
List * grouping_stack
Definition: explain.h:62
StringInfo str
Definition: explain.h:46
ExplainFormat format
Definition: explain.h:59
int indent
Definition: explain.h:61

References appendStringInfoChar(), appendStringInfoString(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, lcons_int(), and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

◆ ExplainCloseGroup()

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

Definition at line 5257 of file explain.c.

5259{
5260 switch (es->format)
5261 {
5263 /* nothing to do */
5264 break;
5265
5266 case EXPLAIN_FORMAT_XML:
5267 es->indent--;
5268 ExplainXMLTag(objtype, X_CLOSING, es);
5269 break;
5270
5272 es->indent--;
5273 appendStringInfoChar(es->str, '\n');
5274 appendStringInfoSpaces(es->str, 2 * es->indent);
5275 appendStringInfoChar(es->str, labeled ? '}' : ']');
5277 break;
5278
5280 es->indent--;
5282 break;
5283 }
5284}
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
Definition: explain.c:5539
#define X_CLOSING
Definition: explain.c:62
List * list_delete_first(List *list)
Definition: list.c:943
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:260

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

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

◆ ExplainEndOutput()

void ExplainEndOutput ( ExplainState es)

Definition at line 5481 of file explain.c.

5482{
5483 switch (es->format)
5484 {
5486 /* nothing to do */
5487 break;
5488
5489 case EXPLAIN_FORMAT_XML:
5490 es->indent--;
5491 appendStringInfoString(es->str, "</explain>");
5492 break;
5493
5495 es->indent--;
5496 appendStringInfoString(es->str, "\n]");
5498 break;
5499
5502 break;
5503 }
5504}

References appendStringInfoString(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainState::format, ExplainState::grouping_stack, ExplainState::indent, list_delete_first(), and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

◆ ExplainOnePlan()

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

Definition at line 644 of file explain.c.

649{
651 QueryDesc *queryDesc;
652 instr_time starttime;
653 double totaltime = 0;
654 int eflags;
655 int instrument_option = 0;
656 SerializeMetrics serializeMetrics = {0};
657
658 Assert(plannedstmt->commandType != CMD_UTILITY);
659
660 if (es->analyze && es->timing)
661 instrument_option |= INSTRUMENT_TIMER;
662 else if (es->analyze)
663 instrument_option |= INSTRUMENT_ROWS;
664
665 if (es->buffers)
666 instrument_option |= INSTRUMENT_BUFFERS;
667 if (es->wal)
668 instrument_option |= INSTRUMENT_WAL;
669
670 /*
671 * We always collect timing for the entire statement, even when node-level
672 * timing is off, so we don't look at es->timing here. (We could skip
673 * this if !es->summary, but it's hardly worth the complication.)
674 */
675 INSTR_TIME_SET_CURRENT(starttime);
676
677 /*
678 * Use a snapshot with an updated command ID to ensure this query sees
679 * results of any previously executed queries.
680 */
683
684 /*
685 * We discard the output if we have no use for it. If we're explaining
686 * CREATE TABLE AS, we'd better use the appropriate tuple receiver, while
687 * the SERIALIZE option requires its own tuple receiver. (If you specify
688 * SERIALIZE while explaining CREATE TABLE AS, you'll see zeroes for the
689 * results, which is appropriate since no data would have gone to the
690 * client.)
691 */
692 if (into)
694 else if (es->serialize != EXPLAIN_SERIALIZE_NONE)
696 else
698
699 /* Create a QueryDesc for the query */
700 queryDesc = CreateQueryDesc(plannedstmt, queryString,
702 dest, params, queryEnv, instrument_option);
703
704 /* Select execution options */
705 if (es->analyze)
706 eflags = 0; /* default run-to-completion flags */
707 else
708 eflags = EXEC_FLAG_EXPLAIN_ONLY;
709 if (es->generic)
711 if (into)
712 eflags |= GetIntoRelEFlags(into);
713
714 /* call ExecutorStart to prepare the plan for execution */
715 ExecutorStart(queryDesc, eflags);
716
717 /* Execute the plan for statistics if asked for */
718 if (es->analyze)
719 {
720 ScanDirection dir;
721
722 /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
723 if (into && into->skipData)
725 else
727
728 /* run the plan */
729 ExecutorRun(queryDesc, dir, 0);
730
731 /* run cleanup too */
732 ExecutorFinish(queryDesc);
733
734 /* We can't run ExecutorEnd 'till we're done printing the stats... */
735 totaltime += elapsed_time(&starttime);
736 }
737
738 /* grab serialization metrics before we destroy the DestReceiver */
740 serializeMetrics = GetSerializationMetrics(dest);
741
742 /* call the DestReceiver's destroy method even during explain */
743 dest->rDestroy(dest);
744
745 ExplainOpenGroup("Query", NULL, true, es);
746
747 /* Create textual dump of plan tree */
748 ExplainPrintPlan(es, queryDesc);
749
750 /* Show buffer and/or memory usage in planning */
751 if (peek_buffer_usage(es, bufusage) || mem_counters)
752 {
753 ExplainOpenGroup("Planning", "Planning", true, es);
754
755 if (es->format == EXPLAIN_FORMAT_TEXT)
756 {
758 appendStringInfoString(es->str, "Planning:\n");
759 es->indent++;
760 }
761
762 if (bufusage)
763 show_buffer_usage(es, bufusage);
764
765 if (mem_counters)
766 show_memory_counters(es, mem_counters);
767
768 if (es->format == EXPLAIN_FORMAT_TEXT)
769 es->indent--;
770
771 ExplainCloseGroup("Planning", "Planning", true, es);
772 }
773
774 if (es->summary && planduration)
775 {
776 double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
777
778 ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
779 }
780
781 /* Print info about runtime of triggers */
782 if (es->analyze)
783 ExplainPrintTriggers(es, queryDesc);
784
785 /*
786 * Print info about JITing. Tied to es->costs because we don't want to
787 * display this in regression tests, as it'd cause output differences
788 * depending on build options. Might want to separate that out from COSTS
789 * at a later stage.
790 */
791 if (es->costs)
792 ExplainPrintJITSummary(es, queryDesc);
793
794 /* Print info about serialization of output */
796 ExplainPrintSerialize(es, &serializeMetrics);
797
798 /*
799 * Close down the query and free resources. Include time for this in the
800 * total execution time (although it should be pretty minimal).
801 */
802 INSTR_TIME_SET_CURRENT(starttime);
803
804 ExecutorEnd(queryDesc);
805
806 FreeQueryDesc(queryDesc);
807
809
810 /* We need a CCI just in case query expanded to multiple plans */
811 if (es->analyze)
813
814 totaltime += elapsed_time(&starttime);
815
816 /*
817 * We only report execution time if we actually ran the query (that is,
818 * the user specified ANALYZE), and if summary reporting is enabled (the
819 * user can set SUMMARY OFF to not have the timing information included in
820 * the output). By default, ANALYZE sets SUMMARY to true.
821 */
822 if (es->summary && es->analyze)
823 ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
824 es);
825
826 ExplainCloseGroup("Query", NULL, true, es);
827}
#define Assert(condition)
Definition: c.h:815
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:373
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:438
DestReceiver * None_Receiver
Definition: dest.c:96
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:463
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:403
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:119
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:294
#define EXEC_FLAG_EXPLAIN_GENERIC
Definition: executor.h:66
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:5194
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:4030
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:1024
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
Definition: explain.c:5165
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
Definition: explain.c:5257
static double elapsed_time(instr_time *starttime)
Definition: explain.c:1312
static void ExplainIndentText(ExplainState *es)
Definition: explain.c:5566
static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)
Definition: explain.c:4277
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:904
static void ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)
Definition: explain.c:1148
DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)
Definition: explain.c:5883
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition: explain.c:981
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition: explain.c:4070
static SerializeMetrics GetSerializationMetrics(DestReceiver *dest)
Definition: explain.c:5908
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:188
@ INSTRUMENT_TIMER
Definition: instrument.h:61
@ INSTRUMENT_BUFFERS
Definition: instrument.h:62
@ INSTRUMENT_WAL
Definition: instrument.h:64
@ INSTRUMENT_ROWS
Definition: instrument.h:63
@ CMD_UTILITY
Definition: nodes.h:270
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
ScanDirection
Definition: sdir.h:25
@ NoMovementScanDirection
Definition: sdir.h:27
@ ForwardScanDirection
Definition: sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:672
void PopActiveSnapshot(void)
Definition: snapmgr.c:703
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:728
#define InvalidSnapshot
Definition: snapshot.h:119
bool timing
Definition: explain.h:53
bool analyze
Definition: explain.h:49
bool wal
Definition: explain.h:52
bool generic
Definition: explain.h:57
bool summary
Definition: explain.h:54
ExplainSerializeOption serialize
Definition: explain.h:58
bool costs
Definition: explain.h:50
bool buffers
Definition: explain.h:51
bool skipData
Definition: primnodes.h:170
CmdType commandType
Definition: plannodes.h:52
void CommandCounterIncrement(void)
Definition: xact.c:1099

References ExplainState::analyze, appendStringInfoString(), Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, ExplainState::costs, CreateExplainSerializeDestReceiver(), CreateIntoRelDestReceiver(), CreateQueryDesc(), generate_unaccent_rules::dest, elapsed_time(), EXEC_FLAG_EXPLAIN_GENERIC, EXEC_FLAG_EXPLAIN_ONLY, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), EXPLAIN_FORMAT_TEXT, EXPLAIN_SERIALIZE_NONE, ExplainCloseGroup(), ExplainIndentText(), ExplainOpenGroup(), ExplainPrintJITSummary(), ExplainPrintPlan(), ExplainPrintSerialize(), ExplainPrintTriggers(), ExplainPropertyFloat(), ExplainState::format, ForwardScanDirection, FreeQueryDesc(), ExplainState::generic, GetActiveSnapshot(), GetIntoRelEFlags(), GetSerializationMetrics(), ExplainState::indent, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTRUMENT_BUFFERS, INSTRUMENT_ROWS, INSTRUMENT_TIMER, INSTRUMENT_WAL, InvalidSnapshot, NoMovementScanDirection, None_Receiver, peek_buffer_usage(), PopActiveSnapshot(), PushCopiedSnapshot(), ExplainState::serialize, show_buffer_usage(), show_memory_counters(), IntoClause::skipData, ExplainState::str, ExplainState::summary, ExplainState::timing, UpdateActiveSnapshotCommandId(), and ExplainState::wal.

Referenced by ExplainExecuteQuery(), and standard_ExplainOneQuery().

◆ ExplainOneUtility()

void ExplainOneUtility ( Node utilityStmt,
IntoClause into,
ExplainState es,
ParseState pstate,
ParamListInfo  params 
)

Definition at line 540 of file explain.c.

542{
543 if (utilityStmt == NULL)
544 return;
545
546 if (IsA(utilityStmt, CreateTableAsStmt))
547 {
548 /*
549 * We have to rewrite the contained SELECT and then pass it back to
550 * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case.
551 */
552 CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
553 Query *ctas_query;
554 List *rewritten;
555 JumbleState *jstate = NULL;
556
557 /*
558 * Check if the relation exists or not. This is done at this stage to
559 * avoid query planning or execution.
560 */
561 if (CreateTableAsRelExists(ctas))
562 {
563 if (ctas->objtype == OBJECT_TABLE)
564 ExplainDummyGroup("CREATE TABLE AS", NULL, es);
565 else if (ctas->objtype == OBJECT_MATVIEW)
566 ExplainDummyGroup("CREATE MATERIALIZED VIEW", NULL, es);
567 else
568 elog(ERROR, "unexpected object type: %d",
569 (int) ctas->objtype);
570 return;
571 }
572
573 ctas_query = castNode(Query, copyObject(ctas->query));
574 if (IsQueryIdEnabled())
575 jstate = JumbleQuery(ctas_query);
577 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);
578 rewritten = QueryRewrite(ctas_query);
579 Assert(list_length(rewritten) == 1);
581 CURSOR_OPT_PARALLEL_OK, ctas->into, es,
582 pstate, params);
583 }
584 else if (IsA(utilityStmt, DeclareCursorStmt))
585 {
586 /*
587 * Likewise for DECLARE CURSOR.
588 *
589 * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
590 * actually run the query. This is different from pre-8.3 behavior
591 * but seems more useful than not running the query. No cursor will
592 * be created, however.
593 */
594 DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
595 Query *dcs_query;
596 List *rewritten;
597 JumbleState *jstate = NULL;
598
599 dcs_query = castNode(Query, copyObject(dcs->query));
600 if (IsQueryIdEnabled())
601 jstate = JumbleQuery(dcs_query);
603 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);
604
605 rewritten = QueryRewrite(dcs_query);
606 Assert(list_length(rewritten) == 1);
608 dcs->options, NULL, es,
609 pstate, params);
610 }
611 else if (IsA(utilityStmt, ExecuteStmt))
612 ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
613 pstate, params);
614 else if (IsA(utilityStmt, NotifyStmt))
615 {
616 if (es->format == EXPLAIN_FORMAT_TEXT)
617 appendStringInfoString(es->str, "NOTIFY\n");
618 else
619 ExplainDummyGroup("Notify", NULL, es);
620 }
621 else
622 {
623 if (es->format == EXPLAIN_FORMAT_TEXT)
625 "Utility statements have no plan structure\n");
626 else
627 ExplainDummyGroup("Utility Statement", NULL, es);
628 }
629}
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition: prepare.c:568
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:391
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
Definition: explain.c:5404
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition: explain.c:443
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
@ OBJECT_MATVIEW
Definition: parsenodes.h:2335
@ OBJECT_TABLE
Definition: parsenodes.h:2353
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3364
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:59
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
JumbleState * JumbleQuery(Query *query)
List * QueryRewrite(Query *parsetree)
IntoClause * into
Definition: parsenodes.h:3967
ObjectType objtype
Definition: parsenodes.h:3968
Definition: pg_list.h:54

References appendStringInfoString(), Assert, castNode, copyObject, CreateTableAsRelExists(), CURSOR_OPT_PARALLEL_OK, elog, ERROR, EXPLAIN_FORMAT_TEXT, ExplainDummyGroup(), ExplainExecuteQuery(), ExplainOneQuery(), ExplainState::format, CreateTableAsStmt::into, IsA, IsQueryIdEnabled(), JumbleQuery(), linitial_node, list_length(), OBJECT_MATVIEW, OBJECT_TABLE, CreateTableAsStmt::objtype, DeclareCursorStmt::options, post_parse_analyze_hook, DeclareCursorStmt::query, CreateTableAsStmt::query, QueryRewrite(), and ExplainState::str.

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

◆ ExplainOpenGroup()

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

Definition at line 5194 of file explain.c.

5196{
5197 switch (es->format)
5198 {
5200 /* nothing to do */
5201 break;
5202
5203 case EXPLAIN_FORMAT_XML:
5204 ExplainXMLTag(objtype, X_OPENING, es);
5205 es->indent++;
5206 break;
5207
5210 appendStringInfoSpaces(es->str, 2 * es->indent);
5211 if (labelname)
5212 {
5213 escape_json(es->str, labelname);
5214 appendStringInfoString(es->str, ": ");
5215 }
5216 appendStringInfoChar(es->str, labeled ? '{' : '[');
5217
5218 /*
5219 * In JSON format, the grouping_stack is an integer list. 0 means
5220 * we've emitted nothing at this grouping level, 1 means we've
5221 * emitted something (and so the next item needs a comma). See
5222 * ExplainJSONLineEnding().
5223 */
5225 es->indent++;
5226 break;
5227
5229
5230 /*
5231 * In YAML format, the grouping stack is an integer list. 0 means
5232 * we've emitted nothing at this grouping level AND this grouping
5233 * level is unlabeled and must be marked with "- ". See
5234 * ExplainYAMLLineStarting().
5235 */
5237 if (labelname)
5238 {
5239 appendStringInfo(es->str, "%s: ", labelname);
5241 }
5242 else
5243 {
5244 appendStringInfoString(es->str, "- ");
5246 }
5247 es->indent++;
5248 break;
5249 }
5250}
#define X_OPENING
Definition: explain.c:61
static void ExplainYAMLLineStarting(ExplainState *es)
Definition: explain.c:5601
static void ExplainJSONLineEnding(ExplainState *es)
Definition: explain.c:5581
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1602
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145

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

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

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 1024 of file explain.c.

1025{
1026 JitInstrumentation ji = {0};
1027
1028 if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
1029 return;
1030
1031 /*
1032 * Work with a copy instead of modifying the leader state, since this
1033 * function may be called twice
1034 */
1035 if (queryDesc->estate->es_jit)
1036 InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
1037
1038 /* If this process has done JIT in parallel workers, merge stats */
1039 if (queryDesc->estate->es_jit_worker_instr)
1040 InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
1041
1042 ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
1043}
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition: explain.c:1050
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:182
#define PGJIT_PERFORM
Definition: jit.h:20
struct JitContext * es_jit
Definition: execnodes.h:745
struct JitInstrumentation * es_jit_worker_instr
Definition: execnodes.h:746
int es_jit_flags
Definition: execnodes.h:744
JitInstrumentation instr
Definition: jit.h:62
EState * estate
Definition: execdesc.h:48

References EState::es_jit, EState::es_jit_flags, EState::es_jit_worker_instr, QueryDesc::estate, ExplainPrintJIT(), JitContext::instr, InstrJitAgg(), and PGJIT_PERFORM.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 904 of file explain.c.

905{
906 Bitmapset *rels_used = NULL;
907 PlanState *ps;
908 ListCell *lc;
909
910 /* Set up ExplainState fields associated with this plan tree */
911 Assert(queryDesc->plannedstmt != NULL);
912 es->pstmt = queryDesc->plannedstmt;
913 es->rtable = queryDesc->plannedstmt->rtable;
914 ExplainPreScanNode(queryDesc->planstate, &rels_used);
917 es->rtable_names);
918 es->printed_subplans = NULL;
919 es->rtable_size = list_length(es->rtable);
920 foreach(lc, es->rtable)
921 {
923
924 if (rte->rtekind == RTE_GROUP)
925 {
926 es->rtable_size--;
927 break;
928 }
929 }
930
931 /*
932 * Sometimes we mark a Gather node as "invisible", which means that it's
933 * not to be displayed in EXPLAIN output. The purpose of this is to allow
934 * running regression tests with debug_parallel_query=regress to get the
935 * same results as running the same tests with debug_parallel_query=off.
936 * Such marking is currently only supported on a Gather at the top of the
937 * plan. We skip that node, and we must also hide per-worker detail data
938 * further down in the plan tree.
939 */
940 ps = queryDesc->planstate;
941 if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
942 {
944 es->hide_workers = true;
945 }
946 ExplainNode(ps, NIL, NULL, NULL, es);
947
948 /*
949 * If requested, include information about GUC parameters with values that
950 * don't match the built-in defaults.
951 */
953
954 /*
955 * COMPUTE_QUERY_ID_REGRESS means COMPUTE_QUERY_ID_AUTO, but we don't show
956 * the queryid in any of the EXPLAIN plans to keep stable the results
957 * generated by regression test suites.
958 */
959 if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) &&
961 {
962 /*
963 * Output the queryid as an int64 rather than a uint64 so we match
964 * what would be seen in the BIGINT pg_stat_statements.queryid column.
965 */
966 ExplainPropertyInteger("Query Identifier", NULL, (int64)
967 queryDesc->plannedstmt->queryId, es);
968 }
969}
int64_t int64
Definition: c.h:485
#define UINT64CONST(x)
Definition: c.h:503
#define outerPlanState(node)
Definition: execnodes.h:1237
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition: explain.c:1496
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition: explain.c:1331
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:5138
static void ExplainPrintSettings(ExplainState *es)
Definition: explain.c:834
struct parser_state ps
@ RTE_GROUP
Definition: parsenodes.h:1037
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
@ COMPUTE_QUERY_ID_REGRESS
Definition: queryjumble.h:59
int compute_query_id
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition: ruleutils.c:3750
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition: ruleutils.c:3852
bool verbose
Definition: explain.h:48
int rtable_size
Definition: explain.h:70
Bitmapset * printed_subplans
Definition: explain.h:68
bool hide_workers
Definition: explain.h:69
List * rtable_names
Definition: explain.h:66
List * rtable
Definition: explain.h:65
PlannedStmt * pstmt
Definition: explain.h:64
List * deparse_cxt
Definition: explain.h:67
List * rtable
Definition: plannodes.h:72
uint64 queryId
Definition: plannodes.h:54
PlannedStmt * plannedstmt
Definition: execdesc.h:37
PlanState * planstate
Definition: execdesc.h:49
RTEKind rtekind
Definition: parsenodes.h:1056

References Assert, compute_query_id, COMPUTE_QUERY_ID_REGRESS, deparse_context_for_plan_tree(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), ExplainPropertyInteger(), ExplainState::hide_workers, IsA, lfirst_node, list_length(), NIL, outerPlanState, QueryDesc::plannedstmt, QueryDesc::planstate, ExplainState::printed_subplans, ps, ExplainState::pstmt, PlannedStmt::queryId, ExplainState::rtable, PlannedStmt::rtable, ExplainState::rtable_names, ExplainState::rtable_size, RTE_GROUP, RangeTblEntry::rtekind, select_rtable_names_for_explain(), UINT64CONST, and ExplainState::verbose.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 981 of file explain.c.

982{
983 ResultRelInfo *rInfo;
984 bool show_relname;
985 List *resultrels;
986 List *routerels;
987 List *targrels;
988 ListCell *l;
989
990 resultrels = queryDesc->estate->es_opened_result_relations;
991 routerels = queryDesc->estate->es_tuple_routing_result_relations;
992 targrels = queryDesc->estate->es_trig_target_relations;
993
994 ExplainOpenGroup("Triggers", "Triggers", false, es);
995
996 show_relname = (list_length(resultrels) > 1 ||
997 routerels != NIL || targrels != NIL);
998 foreach(l, resultrels)
999 {
1000 rInfo = (ResultRelInfo *) lfirst(l);
1001 report_triggers(rInfo, show_relname, es);
1002 }
1003
1004 foreach(l, routerels)
1005 {
1006 rInfo = (ResultRelInfo *) lfirst(l);
1007 report_triggers(rInfo, show_relname, es);
1008 }
1009
1010 foreach(l, targrels)
1011 {
1012 rInfo = (ResultRelInfo *) lfirst(l);
1013 report_triggers(rInfo, show_relname, es);
1014 }
1015
1016 ExplainCloseGroup("Triggers", "Triggers", false, es);
1017}
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition: explain.c:1241
#define lfirst(lc)
Definition: pg_list.h:172
List * es_tuple_routing_result_relations
Definition: execnodes.h:679
List * es_trig_target_relations
Definition: execnodes.h:682
List * es_opened_result_relations
Definition: execnodes.h:669

References EState::es_opened_result_relations, EState::es_trig_target_relations, EState::es_tuple_routing_result_relations, QueryDesc::estate, ExplainCloseGroup(), ExplainOpenGroup(), lfirst, list_length(), NIL, and report_triggers().

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPropertyBool()

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

Definition at line 5179 of file explain.c.

5180{
5181 ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
5182}
static void ExplainProperty(const char *qlabel, const char *unit, const char *value, bool numeric, ExplainState *es)
Definition: explain.c:5076
static struct @162 value

References ExplainProperty(), and value.

Referenced by ExplainNode(), and ExplainPrintJIT().

◆ ExplainPropertyFloat()

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

Definition at line 5165 of file explain.c.

5167{
5168 char *buf;
5169
5170 buf = psprintf("%.*f", ndigits, value);
5171 ExplainProperty(qlabel, unit, buf, true, es);
5172 pfree(buf);
5173}
void pfree(void *pointer)
Definition: mcxt.c:1521
static char * buf
Definition: pg_test_fsync.c:72
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43

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

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

◆ ExplainPropertyInteger()

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

◆ ExplainPropertyList()

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

Definition at line 4953 of file explain.c.

4954{
4955 ListCell *lc;
4956 bool first = true;
4957
4958 switch (es->format)
4959 {
4962 appendStringInfo(es->str, "%s: ", qlabel);
4963 foreach(lc, data)
4964 {
4965 if (!first)
4966 appendStringInfoString(es->str, ", ");
4967 appendStringInfoString(es->str, (const char *) lfirst(lc));
4968 first = false;
4969 }
4970 appendStringInfoChar(es->str, '\n');
4971 break;
4972
4973 case EXPLAIN_FORMAT_XML:
4974 ExplainXMLTag(qlabel, X_OPENING, es);
4975 foreach(lc, data)
4976 {
4977 char *str;
4978
4979 appendStringInfoSpaces(es->str, es->indent * 2 + 2);
4980 appendStringInfoString(es->str, "<Item>");
4981 str = escape_xml((const char *) lfirst(lc));
4983 pfree(str);
4984 appendStringInfoString(es->str, "</Item>\n");
4985 }
4986 ExplainXMLTag(qlabel, X_CLOSING, es);
4987 break;
4988
4991 appendStringInfoSpaces(es->str, es->indent * 2);
4992 escape_json(es->str, qlabel);
4993 appendStringInfoString(es->str, ": [");
4994 foreach(lc, data)
4995 {
4996 if (!first)
4997 appendStringInfoString(es->str, ", ");
4998 escape_json(es->str, (const char *) lfirst(lc));
4999 first = false;
5000 }
5001 appendStringInfoChar(es->str, ']');
5002 break;
5003
5006 appendStringInfo(es->str, "%s: ", qlabel);
5007 foreach(lc, data)
5008 {
5009 appendStringInfoChar(es->str, '\n');
5010 appendStringInfoSpaces(es->str, es->indent * 2 + 2);
5011 appendStringInfoString(es->str, "- ");
5012 escape_yaml(es->str, (const char *) lfirst(lc));
5013 }
5014 break;
5015 }
5016}
static void escape_yaml(StringInfo buf, const char *str)
Definition: explain.c:5626
const char * str
const void * data
char * escape_xml(const char *str)
Definition: xml.c:2695

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

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

◆ ExplainPropertyListNested()

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

Definition at line 5023 of file explain.c.

5024{
5025 ListCell *lc;
5026 bool first = true;
5027
5028 switch (es->format)
5029 {
5031 case EXPLAIN_FORMAT_XML:
5032 ExplainPropertyList(qlabel, data, es);
5033 return;
5034
5037 appendStringInfoSpaces(es->str, es->indent * 2);
5038 appendStringInfoChar(es->str, '[');
5039 foreach(lc, data)
5040 {
5041 if (!first)
5042 appendStringInfoString(es->str, ", ");
5043 escape_json(es->str, (const char *) lfirst(lc));
5044 first = false;
5045 }
5046 appendStringInfoChar(es->str, ']');
5047 break;
5048
5051 appendStringInfoString(es->str, "- [");
5052 foreach(lc, data)
5053 {
5054 if (!first)
5055 appendStringInfoString(es->str, ", ");
5056 escape_yaml(es->str, (const char *) lfirst(lc));
5057 first = false;
5058 }
5059 appendStringInfoChar(es->str, ']');
5060 break;
5061 }
5062}
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
Definition: explain.c:4953

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), data, escape_json(), escape_yaml(), EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, ExplainJSONLineEnding(), ExplainPropertyList(), ExplainYAMLLineStarting(), ExplainState::format, ExplainState::indent, lfirst, and ExplainState::str.

Referenced by show_grouping_set_keys().

◆ ExplainPropertyText()

◆ ExplainPropertyUInteger()

void ExplainPropertyUInteger ( const char *  qlabel,
const char *  unit,
uint64  value,
ExplainState es 
)

Definition at line 5151 of file explain.c.

5153{
5154 char buf[32];
5155
5156 snprintf(buf, sizeof(buf), UINT64_FORMAT, value);
5157 ExplainProperty(qlabel, unit, buf, true, es);
5158}
#define UINT64_FORMAT
Definition: c.h:507

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

Referenced by ExplainPrintSerialize(), show_hash_info(), show_tidbitmap_info(), and show_wal_usage().

◆ ExplainQuery()

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

Definition at line 191 of file explain.c.

193{
195 TupOutputState *tstate;
196 JumbleState *jstate = NULL;
197 Query *query;
198 List *rewritten;
199 ListCell *lc;
200 bool timing_set = false;
201 bool buffers_set = false;
202 bool summary_set = false;
203
204 /* Parse options list. */
205 foreach(lc, stmt->options)
206 {
207 DefElem *opt = (DefElem *) lfirst(lc);
208
209 if (strcmp(opt->defname, "analyze") == 0)
210 es->analyze = defGetBoolean(opt);
211 else if (strcmp(opt->defname, "verbose") == 0)
212 es->verbose = defGetBoolean(opt);
213 else if (strcmp(opt->defname, "costs") == 0)
214 es->costs = defGetBoolean(opt);
215 else if (strcmp(opt->defname, "buffers") == 0)
216 {
217 buffers_set = true;
218 es->buffers = defGetBoolean(opt);
219 }
220 else if (strcmp(opt->defname, "wal") == 0)
221 es->wal = defGetBoolean(opt);
222 else if (strcmp(opt->defname, "settings") == 0)
223 es->settings = defGetBoolean(opt);
224 else if (strcmp(opt->defname, "generic_plan") == 0)
225 es->generic = defGetBoolean(opt);
226 else if (strcmp(opt->defname, "timing") == 0)
227 {
228 timing_set = true;
229 es->timing = defGetBoolean(opt);
230 }
231 else if (strcmp(opt->defname, "summary") == 0)
232 {
233 summary_set = true;
234 es->summary = defGetBoolean(opt);
235 }
236 else if (strcmp(opt->defname, "memory") == 0)
237 es->memory = defGetBoolean(opt);
238 else if (strcmp(opt->defname, "serialize") == 0)
239 {
240 if (opt->arg)
241 {
242 char *p = defGetString(opt);
243
244 if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0)
246 else if (strcmp(p, "text") == 0)
248 else if (strcmp(p, "binary") == 0)
250 else
252 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
253 errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
254 opt->defname, p),
255 parser_errposition(pstate, opt->location)));
256 }
257 else
258 {
259 /* SERIALIZE without an argument is taken as 'text' */
261 }
262 }
263 else if (strcmp(opt->defname, "format") == 0)
264 {
265 char *p = defGetString(opt);
266
267 if (strcmp(p, "text") == 0)
269 else if (strcmp(p, "xml") == 0)
271 else if (strcmp(p, "json") == 0)
273 else if (strcmp(p, "yaml") == 0)
275 else
277 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
278 errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
279 opt->defname, p),
280 parser_errposition(pstate, opt->location)));
281 }
282 else
284 (errcode(ERRCODE_SYNTAX_ERROR),
285 errmsg("unrecognized EXPLAIN option \"%s\"",
286 opt->defname),
287 parser_errposition(pstate, opt->location)));
288 }
289
290 /* check that WAL is used with EXPLAIN ANALYZE */
291 if (es->wal && !es->analyze)
293 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
294 errmsg("EXPLAIN option %s requires ANALYZE", "WAL")));
295
296 /* if the timing was not set explicitly, set default value */
297 es->timing = (timing_set) ? es->timing : es->analyze;
298
299 /* if the buffers was not set explicitly, set default value */
300 es->buffers = (buffers_set) ? es->buffers : es->analyze;
301
302 /* check that timing is used with EXPLAIN ANALYZE */
303 if (es->timing && !es->analyze)
305 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306 errmsg("EXPLAIN option %s requires ANALYZE", "TIMING")));
307
308 /* check that serialize is used with EXPLAIN ANALYZE */
309 if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze)
311 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
312 errmsg("EXPLAIN option %s requires ANALYZE", "SERIALIZE")));
313
314 /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */
315 if (es->generic && es->analyze)
317 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
318 errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together")));
319
320 /* if the summary was not set explicitly, set default value */
321 es->summary = (summary_set) ? es->summary : es->analyze;
322
323 query = castNode(Query, stmt->query);
324 if (IsQueryIdEnabled())
325 jstate = JumbleQuery(query);
326
328 (*post_parse_analyze_hook) (pstate, query, jstate);
329
330 /*
331 * Parse analysis was done already, but we still have to run the rule
332 * rewriter. We do not do AcquireRewriteLocks: we assume the query either
333 * came straight from the parser, or suitable locks were acquired by
334 * plancache.c.
335 */
336 rewritten = QueryRewrite(castNode(Query, stmt->query));
337
338 /* emit opening boilerplate */
340
341 if (rewritten == NIL)
342 {
343 /*
344 * In the case of an INSTEAD NOTHING, tell at least that. But in
345 * non-text format, the output is delimited, so this isn't necessary.
346 */
347 if (es->format == EXPLAIN_FORMAT_TEXT)
348 appendStringInfoString(es->str, "Query rewrites to nothing\n");
349 }
350 else
351 {
352 ListCell *l;
353
354 /* Explain every plan */
355 foreach(l, rewritten)
356 {
358 CURSOR_OPT_PARALLEL_OK, NULL, es,
359 pstate, params);
360
361 /* Separate plans with an appropriate separator */
362 if (lnext(rewritten, l) != NULL)
364 }
365 }
366
367 /* emit closing boilerplate */
369 Assert(es->indent == 0);
370
371 /* output tuples */
374 if (es->format == EXPLAIN_FORMAT_TEXT)
375 do_text_output_multiline(tstate, es->str->data);
376 else
377 do_text_output_oneline(tstate, es->str->data);
378 end_tup_output(tstate);
379
380 pfree(es->str->data);
381}
char * defGetString(DefElem *def)
Definition: define.c:35
bool defGetBoolean(DefElem *def)
Definition: define.c:94
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2520
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2490
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2442
#define do_text_output_oneline(tstate, str_to_emit)
Definition: executor.h:535
ExplainState * NewExplainState(void)
Definition: explain.c:387
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:5510
void ExplainEndOutput(ExplainState *es)
Definition: explain.c:5481
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:404
void ExplainBeginOutput(ExplainState *es)
Definition: explain.c:5450
#define stmt
Definition: indent_codes.h:59
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
char * defname
Definition: parsenodes.h:826
ParseLoc location
Definition: parsenodes.h:830
Node * arg
Definition: parsenodes.h:827
bool settings
Definition: explain.h:56
bool memory
Definition: explain.h:55

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

Referenced by standard_ProcessUtility().

◆ ExplainQueryParameters()

void ExplainQueryParameters ( ExplainState es,
ParamListInfo  params,
int  maxlen 
)

Definition at line 1223 of file explain.c.

1224{
1225 char *str;
1226
1227 /* This check is consistent with errdetail_params() */
1228 if (params == NULL || params->numParams <= 0 || maxlen == 0)
1229 return;
1230
1231 str = BuildParamLogString(params, NULL, maxlen);
1232 if (str && str[0] != '\0')
1233 ExplainPropertyText("Query Parameters", str, es);
1234}
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:5129
char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)
Definition: params.c:335

References BuildParamLogString(), ExplainPropertyText(), ParamListInfoData::numParams, and str.

Referenced by explain_ExecutorEnd().

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)

Definition at line 1208 of file explain.c.

1209{
1210 if (queryDesc->sourceText)
1211 ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1212}
const char * sourceText
Definition: execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)

Definition at line 404 of file explain.c.

405{
406 TupleDesc tupdesc;
407 ListCell *lc;
408 Oid result_type = TEXTOID;
409
410 /* Check for XML format option */
411 foreach(lc, stmt->options)
412 {
413 DefElem *opt = (DefElem *) lfirst(lc);
414
415 if (strcmp(opt->defname, "format") == 0)
416 {
417 char *p = defGetString(opt);
418
419 if (strcmp(p, "xml") == 0)
420 result_type = XMLOID;
421 else if (strcmp(p, "json") == 0)
422 result_type = JSONOID;
423 else
424 result_type = TEXTOID;
425 /* don't "break", as ExplainQuery will use the last value */
426 }
427 }
428
429 /* Need a tuple descriptor representing a single TEXT or XML column */
430 tupdesc = CreateTemplateTupleDesc(1);
431 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
432 result_type, -1, 0);
433 return tupdesc;
434}
int16 AttrNumber
Definition: attnum.h:21
unsigned int Oid
Definition: postgres_ext.h:32
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:164
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:798

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

◆ ExplainSeparatePlans()

void ExplainSeparatePlans ( ExplainState es)

Definition at line 5510 of file explain.c.

5511{
5512 switch (es->format)
5513 {
5515 /* add a blank line */
5516 appendStringInfoChar(es->str, '\n');
5517 break;
5518
5519 case EXPLAIN_FORMAT_XML:
5522 /* nothing to do */
5523 break;
5524 }
5525}

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

Referenced by ExplainExecuteQuery(), and ExplainQuery().

◆ NewExplainState()

ExplainState * NewExplainState ( void  )

Definition at line 387 of file explain.c.

388{
390
391 /* Set default options (most fields can be left as zeroes). */
392 es->costs = true;
393 /* Prepare output buffer. */
394 es->str = makeStringInfo();
395
396 return es;
397}
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72

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

Referenced by explain_ExecutorEnd(), and ExplainQuery().

◆ standard_ExplainOneQuery()

void standard_ExplainOneQuery ( Query query,
int  cursorOptions,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv 
)

Definition at line 468 of file explain.c.

472{
474 instr_time planstart,
475 planduration;
476 BufferUsage bufusage_start,
477 bufusage;
478 MemoryContextCounters mem_counters;
479 MemoryContext planner_ctx = NULL;
480 MemoryContext saved_ctx = NULL;
481
482 if (es->memory)
483 {
484 /*
485 * Create a new memory context to measure planner's memory consumption
486 * accurately. Note that if the planner were to be modified to use a
487 * different memory context type, here we would be changing that to
488 * AllocSet, which might be undesirable. However, we don't have a way
489 * to create a context of the same type as another, so we pray and
490 * hope that this is OK.
491 */
493 "explain analyze planner context",
495 saved_ctx = MemoryContextSwitchTo(planner_ctx);
496 }
497
498 if (es->buffers)
499 bufusage_start = pgBufferUsage;
500 INSTR_TIME_SET_CURRENT(planstart);
501
502 /* plan the query */
503 plan = pg_plan_query(query, queryString, cursorOptions, params);
504
505 INSTR_TIME_SET_CURRENT(planduration);
506 INSTR_TIME_SUBTRACT(planduration, planstart);
507
508 if (es->memory)
509 {
510 MemoryContextSwitchTo(saved_ctx);
511 MemoryContextMemConsumed(planner_ctx, &mem_counters);
512 }
513
514 /* calc differences of buffer counters. */
515 if (es->buffers)
516 {
517 memset(&bufusage, 0, sizeof(BufferUsage));
518 BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
519 }
520
521 /* run it (if needed) and produce output */
522 ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
523 &planduration, (es->buffers ? &bufusage : NULL),
524 es->memory ? &mem_counters : NULL);
525}
void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters)
Definition: explain.c:644
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:181
BufferUsage pgBufferUsage
Definition: instrument.c:20
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition: instrument.c:248
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition: mcxt.c:786
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define plan(x)
Definition: pg_regress.c:161
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:881

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ExplainState::buffers, BufferUsageAccumDiff(), CurrentMemoryContext, ExplainOnePlan(), INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, ExplainState::memory, MemoryContextMemConsumed(), MemoryContextSwitchTo(), pg_plan_query(), pgBufferUsage, and plan.

Referenced by ExplainOneQuery().

Variable Documentation

◆ explain_get_index_name_hook

PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook
extern

Definition at line 49 of file explain.c.

Referenced by explain_get_index_name().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 46 of file explain.c.

Referenced by ExplainOneQuery().