PostgreSQL Source Code git master
Loading...
Searching...
No Matches
explain.h File Reference
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.

Typedefs

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 void(* explain_per_plan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
typedef void(* explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
 
typedef const char *(* explain_get_index_name_hook_type) (Oid indexId)
 

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

Variables

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
 
PGDLLIMPORT explain_per_plan_hook_type explain_per_plan_hook
 
PGDLLIMPORT explain_per_node_hook_type explain_per_node_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 50 of file explain.h.

◆ explain_per_node_hook_type

typedef void(* explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)

Definition at line 42 of file explain.h.

◆ explain_per_plan_hook_type

typedef void(* explain_per_plan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)

Definition at line 33 of file explain.h.

◆ 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 23 of file explain.h.

◆ ExplainState

Definition at line 20 of file explain.h.

Function Documentation

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

Definition at line 500 of file explain.c.

505{
507 QueryDesc *queryDesc;
508 instr_time starttime;
509 double totaltime = 0;
510 int eflags;
511 int instrument_option = 0;
513
514 Assert(plannedstmt->commandType != CMD_UTILITY);
515
516 if (es->analyze && es->timing)
518 else if (es->analyze)
520
521 if (es->buffers)
523 if (es->wal)
525 if (es->io)
527
528 /*
529 * We always collect timing for the entire statement, even when node-level
530 * timing is off, so we don't look at es->timing here. (We could skip
531 * this if !es->summary, but it's hardly worth the complication.)
532 */
533 INSTR_TIME_SET_CURRENT(starttime);
534
535 /*
536 * Use a snapshot with an updated command ID to ensure this query sees
537 * results of any previously executed queries.
538 */
541
542 /*
543 * We discard the output if we have no use for it. If we're explaining
544 * CREATE TABLE AS, we'd better use the appropriate tuple receiver, while
545 * the SERIALIZE option requires its own tuple receiver. (If you specify
546 * SERIALIZE while explaining CREATE TABLE AS, you'll see zeroes for the
547 * results, which is appropriate since no data would have gone to the
548 * client.)
549 */
550 if (into)
552 else if (es->serialize != EXPLAIN_SERIALIZE_NONE)
554 else
556
557 /* Create a QueryDesc for the query */
558 queryDesc = CreateQueryDesc(plannedstmt, queryString,
560 dest, params, queryEnv, instrument_option);
561
562 /* Select execution options */
563 if (es->analyze)
564 eflags = 0; /* default run-to-completion flags */
565 else
566 eflags = EXEC_FLAG_EXPLAIN_ONLY;
567 if (es->generic)
569 if (into)
570 eflags |= GetIntoRelEFlags(into);
571
572 /* call ExecutorStart to prepare the plan for execution */
573 ExecutorStart(queryDesc, eflags);
574
575 /* Execute the plan for statistics if asked for */
576 if (es->analyze)
577 {
578 ScanDirection dir;
579
580 /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */
581 if (into && into->skipData)
583 else
585
586 /* run the plan */
587 ExecutorRun(queryDesc, dir, 0);
588
589 /* run cleanup too */
590 ExecutorFinish(queryDesc);
591
592 /* We can't run ExecutorEnd 'till we're done printing the stats... */
593 totaltime += elapsed_time(&starttime);
594 }
595
596 /* grab serialization metrics before we destroy the DestReceiver */
599
600 /* call the DestReceiver's destroy method even during explain */
601 dest->rDestroy(dest);
602
603 ExplainOpenGroup("Query", NULL, true, es);
604
605 /* Create textual dump of plan tree */
606 ExplainPrintPlan(es, queryDesc);
607
608 /* Show buffer and/or memory usage in planning */
609 if (peek_buffer_usage(es, bufusage) || mem_counters)
610 {
611 ExplainOpenGroup("Planning", "Planning", true, es);
612
613 if (es->format == EXPLAIN_FORMAT_TEXT)
614 {
616 appendStringInfoString(es->str, "Planning:\n");
617 es->indent++;
618 }
619
620 if (bufusage)
621 show_buffer_usage(es, bufusage);
622
623 if (mem_counters)
625
626 if (es->format == EXPLAIN_FORMAT_TEXT)
627 es->indent--;
628
629 ExplainCloseGroup("Planning", "Planning", true, es);
630 }
631
632 if (es->summary && planduration)
633 {
635
636 ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
637 }
638
639 /* Print info about runtime of triggers */
640 if (es->analyze)
641 ExplainPrintTriggers(es, queryDesc);
642
643 /*
644 * Print info about JITing. Tied to es->costs because we don't want to
645 * display this in regression tests, as it'd cause output differences
646 * depending on build options. Might want to separate that out from COSTS
647 * at a later stage.
648 */
649 if (es->costs)
650 ExplainPrintJITSummary(es, queryDesc);
651
652 /* Print info about serialization of output */
655
656 /* Allow plugins to print additional information */
658 (*explain_per_plan_hook) (plannedstmt, into, es, queryString,
659 params, queryEnv);
660
661 /*
662 * Close down the query and free resources. Include time for this in the
663 * total execution time (although it should be pretty minimal).
664 */
665 INSTR_TIME_SET_CURRENT(starttime);
666
667 ExecutorEnd(queryDesc);
668
669 FreeQueryDesc(queryDesc);
670
672
673 /* We need a CCI just in case query expanded to multiple plans */
674 if (es->analyze)
676
677 totaltime += elapsed_time(&starttime);
678
679 /*
680 * We only report execution time if we actually ran the query (that is,
681 * the user specified ANALYZE), and if summary reporting is enabled (the
682 * user can set SUMMARY OFF to not have the timing information included in
683 * the output). By default, ANALYZE sets SUMMARY to true.
684 */
685 if (es->summary && es->analyze)
686 ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
687 es);
688
689 ExplainCloseGroup("Query", NULL, true, es);
690}
#define Assert(condition)
Definition c.h:943
int GetIntoRelEFlags(IntoClause *intoClause)
Definition createas.c:375
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition createas.c:440
DestReceiver * None_Receiver
Definition dest.c:96
void ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:477
void ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:417
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition execMain.c:124
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:308
#define EXEC_FLAG_EXPLAIN_GENERIC
Definition executor.h:68
#define EXEC_FLAG_EXPLAIN_ONLY
Definition executor.h:67
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition explain.c:4252
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:883
static double elapsed_time(instr_time *starttime)
Definition explain.c:1171
explain_per_plan_hook_type explain_per_plan_hook
Definition explain.c:58
static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)
Definition explain.c:4510
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:767
static void ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)
Definition explain.c:1007
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:840
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)
Definition explain.c:4292
SerializeMetrics GetSerializationMetrics(DestReceiver *dest)
Definition explain_dr.c:300
DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)
Definition explain_dr.c:275
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
void ExplainIndentText(ExplainState *es)
void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)
void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
@ EXPLAIN_SERIALIZE_NONE
@ EXPLAIN_FORMAT_TEXT
#define INSTR_TIME_SET_CURRENT(t)
Definition instr_time.h:426
#define INSTR_TIME_GET_DOUBLE(t)
Definition instr_time.h:448
@ INSTRUMENT_TIMER
Definition instrument.h:63
@ INSTRUMENT_IO
Definition instrument.h:67
@ INSTRUMENT_BUFFERS
Definition instrument.h:64
@ INSTRUMENT_WAL
Definition instrument.h:66
@ INSTRUMENT_ROWS
Definition instrument.h:65
@ CMD_UTILITY
Definition nodes.h:280
void FreeQueryDesc(QueryDesc *qdesc)
Definition pquery.c:107
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition pquery.c:68
static int fb(int x)
ScanDirection
Definition sdir.h:25
@ NoMovementScanDirection
Definition sdir.h:27
@ ForwardScanDirection
Definition sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition snapmgr.c:744
void PopActiveSnapshot(void)
Definition snapmgr.c:775
void PushCopiedSnapshot(Snapshot snapshot)
Definition snapmgr.c:732
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
#define InvalidSnapshot
Definition snapshot.h:119
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
StringInfo str
ExplainFormat format
ExplainSerializeOption serialize
bool skipData
Definition primnodes.h:172
CmdType commandType
Definition plannodes.h:66
void CommandCounterIncrement(void)
Definition xact.c:1130

References ExplainState::analyze, appendStringInfoString(), Assert, ExplainState::buffers, CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, ExplainState::costs, CreateExplainSerializeDestReceiver(), CreateIntoRelDestReceiver(), CreateQueryDesc(), elapsed_time(), EXEC_FLAG_EXPLAIN_GENERIC, EXEC_FLAG_EXPLAIN_ONLY, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), EXPLAIN_FORMAT_TEXT, explain_per_plan_hook, EXPLAIN_SERIALIZE_NONE, ExplainCloseGroup(), ExplainIndentText(), ExplainOpenGroup(), ExplainPrintJITSummary(), ExplainPrintPlan(), ExplainPrintSerialize(), ExplainPrintTriggers(), ExplainPropertyFloat(), fb(), ExplainState::format, ForwardScanDirection, FreeQueryDesc(), ExplainState::generic, GetActiveSnapshot(), GetIntoRelEFlags(), GetSerializationMetrics(), ExplainState::indent, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTRUMENT_BUFFERS, INSTRUMENT_IO, INSTRUMENT_ROWS, INSTRUMENT_TIMER, INSTRUMENT_WAL, InvalidSnapshot, ExplainState::io, 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 
)
extern

Definition at line 396 of file explain.c.

398{
399 if (utilityStmt == NULL)
400 return;
401
402 if (IsA(utilityStmt, CreateTableAsStmt))
403 {
404 /*
405 * We have to rewrite the contained SELECT and then pass it back to
406 * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case.
407 */
408 CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
412
413 /*
414 * Check if the relation exists or not. This is done at this stage to
415 * avoid query planning or execution.
416 */
418 {
419 if (ctas->objtype == OBJECT_TABLE)
420 ExplainDummyGroup("CREATE TABLE AS", NULL, es);
421 else if (ctas->objtype == OBJECT_MATVIEW)
422 ExplainDummyGroup("CREATE MATERIALIZED VIEW", NULL, es);
423 else
424 elog(ERROR, "unexpected object type: %d",
425 (int) ctas->objtype);
426 return;
427 }
428
430 if (IsQueryIdEnabled())
433 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);
437 CURSOR_OPT_PARALLEL_OK, ctas->into, es,
438 pstate, params);
439 }
440 else if (IsA(utilityStmt, DeclareCursorStmt))
441 {
442 /*
443 * Likewise for DECLARE CURSOR.
444 *
445 * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
446 * actually run the query. This is different from pre-8.3 behavior
447 * but seems more useful than not running the query. No cursor will
448 * be created, however.
449 */
450 DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
454
456 if (IsQueryIdEnabled())
459 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);
460
464 dcs->options, NULL, es,
465 pstate, params);
466 }
467 else if (IsA(utilityStmt, ExecuteStmt))
468 ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es,
469 pstate, params);
470 else if (IsA(utilityStmt, NotifyStmt))
471 {
472 if (es->format == EXPLAIN_FORMAT_TEXT)
473 appendStringInfoString(es->str, "NOTIFY\n");
474 else
475 ExplainDummyGroup("Notify", NULL, es);
476 }
477 else
478 {
479 if (es->format == EXPLAIN_FORMAT_TEXT)
481 "Utility statements have no plan structure\n");
482 else
483 ExplainDummyGroup("Utility Statement", NULL, es);
484 }
485}
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition prepare.c:573
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition createas.c:393
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition explain.c:299
void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define copyObject(obj)
Definition nodes.h:232
#define castNode(_type_, nodeptr)
Definition nodes.h:182
@ OBJECT_MATVIEW
@ OBJECT_TABLE
#define CURSOR_OPT_PARALLEL_OK
post_parse_analyze_hook_type post_parse_analyze_hook
Definition analyze.c:74
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)
JumbleState * JumbleQuery(Query *query)
List * QueryRewrite(Query *parsetree)
Definition pg_list.h:54

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

Referenced by ExplainExecuteQuery(), and ExplainOneQuery().

◆ ExplainPrintJITSummary()

void ExplainPrintJITSummary ( ExplainState es,
QueryDesc queryDesc 
)
extern

Definition at line 883 of file explain.c.

884{
886
887 if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
888 return;
889
890 /*
891 * Work with a copy instead of modifying the leader state, since this
892 * function may be called twice
893 */
894 if (queryDesc->estate->es_jit)
895 InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
896
897 /* If this process has done JIT in parallel workers, merge stats */
898 if (queryDesc->estate->es_jit_worker_instr)
900
901 ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji);
902}
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
Definition explain.c:909
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition jit.c:183
#define PGJIT_PERFORM
Definition jit.h:20
struct JitContext * es_jit
Definition execnodes.h:800
struct JitInstrumentation * es_jit_worker_instr
Definition execnodes.h:801
int es_jit_flags
Definition execnodes.h:799
JitInstrumentation instr
Definition jit.h:62
EState * estate
Definition execdesc.h:50

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

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintPlan()

void ExplainPrintPlan ( ExplainState es,
QueryDesc queryDesc 
)
extern

Definition at line 767 of file explain.c.

768{
770 PlanState *ps;
771 ListCell *lc;
772
773 /* Set up ExplainState fields associated with this plan tree */
774 Assert(queryDesc->plannedstmt != NULL);
775 es->pstmt = queryDesc->plannedstmt;
776 es->rtable = queryDesc->plannedstmt->rtable;
780 es->rtable_names);
782 es->rtable_size = list_length(es->rtable);
783 foreach(lc, es->rtable)
784 {
786
787 if (rte->rtekind == RTE_GROUP)
788 {
789 es->rtable_size--;
790 break;
791 }
792 }
793
794 /*
795 * Sometimes we mark a Gather node as "invisible", which means that it's
796 * not to be displayed in EXPLAIN output. The purpose of this is to allow
797 * running regression tests with debug_parallel_query=regress to get the
798 * same results as running the same tests with debug_parallel_query=off.
799 * Such marking is currently only supported on a Gather at the top of the
800 * plan. We skip that node, and we must also hide per-worker detail data
801 * further down in the plan tree.
802 */
803 ps = queryDesc->planstate;
804 if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible)
805 {
807 es->hide_workers = true;
808 }
809 ExplainNode(ps, NIL, NULL, NULL, es);
810
811 /*
812 * If requested, include information about GUC parameters with values that
813 * don't match the built-in defaults.
814 */
816
817 /*
818 * COMPUTE_QUERY_ID_REGRESS means COMPUTE_QUERY_ID_AUTO, but we don't show
819 * the queryid in any of the EXPLAIN plans to keep stable the results
820 * generated by regression test suites.
821 */
822 if (es->verbose && queryDesc->plannedstmt->queryId != INT64CONST(0) &&
824 {
825 ExplainPropertyInteger("Query Identifier", NULL,
826 queryDesc->plannedstmt->queryId, es);
827 }
828}
#define INT64CONST(x)
Definition c.h:630
#define outerPlanState(node)
Definition execnodes.h:1299
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
Definition explain.c:1363
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
Definition explain.c:1190
static void ExplainPrintSettings(ExplainState *es)
Definition explain.c:697
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
struct parser_state ps
@ RTE_GROUP
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define NIL
Definition pg_list.h:68
@ COMPUTE_QUERY_ID_REGRESS
Definition queryjumble.h:86
int compute_query_id
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
Definition ruleutils.c:4115
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
Definition ruleutils.c:4217
Bitmapset * printed_subplans
List * rtable_names
PlannedStmt * pstmt
List * deparse_cxt
int64 queryId
Definition plannodes.h:69
List * rtable
Definition plannodes.h:107
PlannedStmt * plannedstmt
Definition execdesc.h:37
PlanState * planstate
Definition execdesc.h:51

References Assert, compute_query_id, COMPUTE_QUERY_ID_REGRESS, deparse_context_for_plan_tree(), ExplainState::deparse_cxt, ExplainNode(), ExplainPreScanNode(), ExplainPrintSettings(), ExplainPropertyInteger(), fb(), ExplainState::hide_workers, INT64CONST, 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, select_rtable_names_for_explain(), and ExplainState::verbose.

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainPrintTriggers()

void ExplainPrintTriggers ( ExplainState es,
QueryDesc queryDesc 
)
extern

Definition at line 840 of file explain.c.

841{
843 bool show_relname;
846 List *targrels;
847 ListCell *l;
848
852
853 ExplainOpenGroup("Triggers", "Triggers", false, es);
854
856 routerels != NIL || targrels != NIL);
857 foreach(l, resultrels)
858 {
859 rInfo = (ResultRelInfo *) lfirst(l);
861 }
862
863 foreach(l, routerels)
864 {
865 rInfo = (ResultRelInfo *) lfirst(l);
867 }
868
869 foreach(l, targrels)
870 {
871 rInfo = (ResultRelInfo *) lfirst(l);
873 }
874
875 ExplainCloseGroup("Triggers", "Triggers", false, es);
876}
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
Definition explain.c:1100
#define lfirst(lc)
Definition pg_list.h:172
List * es_tuple_routing_result_relations
Definition execnodes.h:734
List * es_trig_target_relations
Definition execnodes.h:737
List * es_opened_result_relations
Definition execnodes.h:724

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

Referenced by explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainQuery()

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

Definition at line 181 of file explain.c.

183{
187 Query *query;
189
190 /* Configure the ExplainState based on the provided options */
191 ParseExplainOptionList(es, stmt->options, pstate);
192
193 /* Extract the query and, if enabled, jumble it */
194 query = castNode(Query, stmt->query);
195 if (IsQueryIdEnabled())
196 jstate = JumbleQuery(query);
197
199 (*post_parse_analyze_hook) (pstate, query, jstate);
200
201 /*
202 * Parse analysis was done already, but we still have to run the rule
203 * rewriter. We do not do AcquireRewriteLocks: we assume the query either
204 * came straight from the parser, or suitable locks were acquired by
205 * plancache.c.
206 */
208
209 /* emit opening boilerplate */
211
212 if (rewritten == NIL)
213 {
214 /*
215 * In the case of an INSTEAD NOTHING, tell at least that. But in
216 * non-text format, the output is delimited, so this isn't necessary.
217 */
218 if (es->format == EXPLAIN_FORMAT_TEXT)
219 appendStringInfoString(es->str, "Query rewrites to nothing\n");
220 }
221 else
222 {
223 ListCell *l;
224
225 /* Explain every plan */
226 foreach(l, rewritten)
227 {
230 pstate, params);
231
232 /* Separate plans with an appropriate separator */
233 if (lnext(rewritten, l) != NULL)
235 }
236 }
237
238 /* emit closing boilerplate */
240 Assert(es->indent == 0);
241
242 /* output tuples */
245 if (es->format == EXPLAIN_FORMAT_TEXT)
247 else
250
251 pfree(es->str->data);
252}
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
void end_tup_output(TupOutputState *tstate)
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
#define do_text_output_oneline(tstate, str_to_emit)
Definition executor.h:639
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition explain.c:259
void ExplainSeparatePlans(ExplainState *es)
void ExplainEndOutput(ExplainState *es)
void ExplainBeginOutput(ExplainState *es)
ExplainState * NewExplainState(void)
void ParseExplainOptionList(ExplainState *es, List *options, ParseState *pstate)
#define stmt
void pfree(void *pointer)
Definition mcxt.c:1616
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:375

References appendStringInfoString(), Assert, begin_tup_output_tupdesc(), castNode, CURSOR_OPT_PARALLEL_OK, StringInfoData::data, do_text_output_multiline(), do_text_output_oneline, end_tup_output(), EXPLAIN_FORMAT_TEXT, ExplainBeginOutput(), ExplainEndOutput(), ExplainOneQuery(), ExplainResultDesc(), ExplainSeparatePlans(), fb(), ExplainState::format, ExplainState::indent, IsQueryIdEnabled(), JumbleQuery(), lfirst_node, lnext(), NewExplainState(), NIL, ParseExplainOptionList(), pfree(), post_parse_analyze_hook, QueryRewrite(), stmt, ExplainState::str, and TTSOpsVirtual.

Referenced by standard_ProcessUtility().

◆ ExplainQueryParameters()

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

Definition at line 1082 of file explain.c.

1083{
1084 char *str;
1085
1086 /* This check is consistent with errdetail_params() */
1087 if (params == NULL || params->numParams <= 0 || maxlen == 0)
1088 return;
1089
1090 str = BuildParamLogString(params, NULL, maxlen);
1091 if (str && str[0] != '\0')
1092 ExplainPropertyText("Query Parameters", str, es);
1093}
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
const char * str
char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)
Definition params.c:333

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

Referenced by explain_ExecutorEnd().

◆ ExplainQueryText()

void ExplainQueryText ( ExplainState es,
QueryDesc queryDesc 
)
extern

Definition at line 1067 of file explain.c.

1068{
1069 if (queryDesc->sourceText)
1070 ExplainPropertyText("Query Text", queryDesc->sourceText, es);
1071}
const char * sourceText
Definition execdesc.h:38

References ExplainPropertyText(), and QueryDesc::sourceText.

Referenced by explain_ExecutorEnd().

◆ ExplainResultDesc()

TupleDesc ExplainResultDesc ( ExplainStmt stmt)
extern

Definition at line 259 of file explain.c.

260{
261 TupleDesc tupdesc;
262 ListCell *lc;
263 Oid result_type = TEXTOID;
264
265 /* Check for XML format option */
266 foreach(lc, stmt->options)
267 {
268 DefElem *opt = (DefElem *) lfirst(lc);
269
270 if (strcmp(opt->defname, "format") == 0)
271 {
272 char *p = defGetString(opt);
273
274 if (strcmp(p, "xml") == 0)
275 result_type = XMLOID;
276 else if (strcmp(p, "json") == 0)
277 result_type = JSONOID;
278 else
279 result_type = TEXTOID;
280 /* don't "break", as ExplainQuery will use the last value */
281 }
282 }
283
284 /* Need a tuple descriptor representing a single TEXT or XML column */
285 tupdesc = CreateTemplateTupleDesc(1);
286 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
287 result_type, -1, 0);
288 TupleDescFinalize(tupdesc);
289 return tupdesc;
290}
int16 AttrNumber
Definition attnum.h:21
char * defGetString(DefElem *def)
Definition define.c:34
unsigned int Oid
char * defname
Definition parsenodes.h:860
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:900

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

Referenced by ExplainQuery(), and UtilityTupleDescriptor().

◆ standard_ExplainOneQuery()

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

Definition at line 324 of file explain.c.

328{
332 BufferUsage bufusage_start,
333 bufusage;
337
338 if (es->memory)
339 {
340 /*
341 * Create a new memory context to measure planner's memory consumption
342 * accurately. Note that if the planner were to be modified to use a
343 * different memory context type, here we would be changing that to
344 * AllocSet, which might be undesirable. However, we don't have a way
345 * to create a context of the same type as another, so we pray and
346 * hope that this is OK.
347 */
349 "explain analyze planner context",
352 }
353
354 if (es->buffers)
355 bufusage_start = pgBufferUsage;
357
358 /* plan the query */
359 plan = pg_plan_query(query, queryString, cursorOptions, params, es);
360
363
364 if (es->memory)
365 {
368 }
369
370 /* calc differences of buffer counters. */
371 if (es->buffers)
372 {
373 memset(&bufusage, 0, sizeof(BufferUsage));
374 BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
375 }
376
377 /* run it (if needed) and produce output */
378 ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
379 &planduration, (es->buffers ? &bufusage : NULL),
380 es->memory ? &mem_counters : NULL);
381}
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:500
#define INSTR_TIME_SUBTRACT(x, y)
Definition instr_time.h:436
BufferUsage pgBufferUsage
Definition instrument.c:25
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition instrument.c:327
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition mcxt.c:835
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#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:164
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
Definition postgres.c:898

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ExplainState::buffers, BufferUsageAccumDiff(), CurrentMemoryContext, ExplainOnePlan(), fb(), 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 55 of file explain.c.

Referenced by explain_get_index_name().

◆ explain_per_node_hook

PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook
extern

Definition at line 59 of file explain.c.

Referenced by _PG_init(), and ExplainNode().

◆ explain_per_plan_hook

PGDLLIMPORT explain_per_plan_hook_type explain_per_plan_hook
extern

Definition at line 58 of file explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and ExplainOnePlan().

◆ ExplainOneQuery_hook

PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook
extern

Definition at line 52 of file explain.c.

Referenced by ExplainOneQuery().