63#define X_CLOSE_IMMEDIATE 2
64#define X_NOWHITESPACE 4
70#define BYTES_TO_KILOBYTES(b) (((b) + 1023) / 1024)
84 const char *relationship,
const char *plan_name,
112 List *context,
bool useprefix,
117 int nkeys,
int nPresortedKeys,
AttrNumber *keycols,
118 Oid *sortOperators,
Oid *collations,
bool *nullsFirst,
121 Oid sortOperator,
Oid collation,
bool nullsFirst);
200 bool timing_set =
false;
201 bool buffers_set =
false;
202 bool summary_set =
false;
205 foreach(lc,
stmt->options)
209 if (strcmp(opt->
defname,
"analyze") == 0)
211 else if (strcmp(opt->
defname,
"verbose") == 0)
213 else if (strcmp(opt->
defname,
"costs") == 0)
215 else if (strcmp(opt->
defname,
"buffers") == 0)
220 else if (strcmp(opt->
defname,
"wal") == 0)
222 else if (strcmp(opt->
defname,
"settings") == 0)
224 else if (strcmp(opt->
defname,
"generic_plan") == 0)
226 else if (strcmp(opt->
defname,
"timing") == 0)
231 else if (strcmp(opt->
defname,
"summary") == 0)
236 else if (strcmp(opt->
defname,
"memory") == 0)
238 else if (strcmp(opt->
defname,
"serialize") == 0)
244 if (strcmp(p,
"off") == 0 || strcmp(p,
"none") == 0)
246 else if (strcmp(p,
"text") == 0)
248 else if (strcmp(p,
"binary") == 0)
252 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
253 errmsg(
"unrecognized value for EXPLAIN option \"%s\": \"%s\"",
263 else if (strcmp(opt->
defname,
"format") == 0)
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)
277 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
278 errmsg(
"unrecognized value for EXPLAIN option \"%s\": \"%s\"",
284 (
errcode(ERRCODE_SYNTAX_ERROR),
285 errmsg(
"unrecognized EXPLAIN option \"%s\"",
293 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
294 errmsg(
"EXPLAIN option %s requires ANALYZE",
"WAL")));
305 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306 errmsg(
"EXPLAIN option %s requires ANALYZE",
"TIMING")));
311 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
312 errmsg(
"EXPLAIN option %s requires ANALYZE",
"SERIALIZE")));
317 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
318 errmsg(
"EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together")));
328 (*post_parse_analyze_hook) (pstate, query, jstate);
341 if (rewritten ==
NIL)
355 foreach(l, rewritten)
362 if (
lnext(rewritten, l) != NULL)
408 Oid result_type = TEXTOID;
411 foreach(lc,
stmt->options)
415 if (strcmp(opt->
defname,
"format") == 0)
419 if (strcmp(p,
"xml") == 0)
420 result_type = XMLOID;
421 else if (strcmp(p,
"json") == 0)
422 result_type = JSONOID;
424 result_type = TEXTOID;
456 (*ExplainOneQuery_hook) (query, cursorOptions, into, es,
493 "explain analyze planner context",
523 &planduration, (es->
buffers ? &bufusage : NULL),
524 es->
memory ? &mem_counters : NULL);
543 if (utilityStmt == NULL)
568 elog(
ERROR,
"unexpected object type: %d",
577 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);
603 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);
625 "Utility statements have no plan structure\n");
653 double totaltime = 0;
655 int instrument_option = 0;
702 dest, params, queryEnv, instrument_option);
774 if (es->
summary && planduration)
850 for (
int i = 0;
i < num;
i++)
872 for (
int i = 0;
i < num;
i++)
997 routerels !=
NIL || targrels !=
NIL);
998 foreach(l, resultrels)
1004 foreach(l, routerels)
1010 foreach(l, targrels)
1079 "Inlining", jit_flags &
PGJIT_INLINE ?
"true" :
"false",
1080 "Optimization", jit_flags &
PGJIT_OPT3 ?
"true" :
"false",
1081 "Expressions", jit_flags &
PGJIT_EXPR ?
"true" :
"false",
1082 "Deforming", jit_flags &
PGJIT_DEFORM ?
"true" :
"false");
1088 "Timing: %s %.3f ms (%s %.3f ms), %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",
1228 if (params == NULL || params->
numParams <= 0 || maxlen == 0)
1232 if (
str &&
str[0] !=
'\0')
1252 char *conname = NULL;
1277 if (es->
verbose || conname == NULL)
1340 case T_IndexOnlyScan:
1341 case T_BitmapHeapScan:
1343 case T_TidRangeScan:
1344 case T_SubqueryScan:
1345 case T_FunctionScan:
1346 case T_TableFuncScan:
1349 case T_NamedTuplestoreScan:
1350 case T_WorkTableScan:
1393 int child_disabled_nodes;
1396 if (
plan->disabled_nodes == 0)
1399 child_disabled_nodes = 0;
1468 if (
plan->disabled_nodes > child_disabled_nodes)
1497 const char *relationship,
const char *plan_name,
1503 const char *strategy = NULL;
1504 const char *partialmode = NULL;
1505 const char *operation = NULL;
1506 const char *custom_name = NULL;
1508 int save_indent = es->
indent;
1525 pname = sname =
"Result";
1528 pname = sname =
"ProjectSet";
1531 sname =
"ModifyTable";
1535 pname = operation =
"Insert";
1538 pname = operation =
"Update";
1541 pname = operation =
"Delete";
1544 pname = operation =
"Merge";
1552 pname = sname =
"Append";
1555 pname = sname =
"Merge Append";
1557 case T_RecursiveUnion:
1558 pname = sname =
"Recursive Union";
1561 pname = sname =
"BitmapAnd";
1564 pname = sname =
"BitmapOr";
1567 pname = sname =
"Nested Loop";
1571 sname =
"Merge Join";
1575 sname =
"Hash Join";
1578 pname = sname =
"Seq Scan";
1581 pname = sname =
"Sample Scan";
1584 pname = sname =
"Gather";
1587 pname = sname =
"Gather Merge";
1590 pname = sname =
"Index Scan";
1592 case T_IndexOnlyScan:
1593 pname = sname =
"Index Only Scan";
1595 case T_BitmapIndexScan:
1596 pname = sname =
"Bitmap Index Scan";
1598 case T_BitmapHeapScan:
1599 pname = sname =
"Bitmap Heap Scan";
1602 pname = sname =
"Tid Scan";
1604 case T_TidRangeScan:
1605 pname = sname =
"Tid Range Scan";
1607 case T_SubqueryScan:
1608 pname = sname =
"Subquery Scan";
1610 case T_FunctionScan:
1611 pname = sname =
"Function Scan";
1613 case T_TableFuncScan:
1614 pname = sname =
"Table Function Scan";
1617 pname = sname =
"Values Scan";
1620 pname = sname =
"CTE Scan";
1622 case T_NamedTuplestoreScan:
1623 pname = sname =
"Named Tuplestore Scan";
1625 case T_WorkTableScan:
1626 pname = sname =
"WorkTable Scan";
1629 sname =
"Foreign Scan";
1633 pname =
"Foreign Scan";
1634 operation =
"Select";
1637 pname =
"Foreign Insert";
1638 operation =
"Insert";
1641 pname =
"Foreign Update";
1642 operation =
"Update";
1645 pname =
"Foreign Delete";
1646 operation =
"Delete";
1654 sname =
"Custom Scan";
1657 pname =
psprintf(
"Custom Scan (%s)", custom_name);
1662 pname = sname =
"Materialize";
1665 pname = sname =
"Memoize";
1668 pname = sname =
"Sort";
1670 case T_IncrementalSort:
1671 pname = sname =
"Incremental Sort";
1674 pname = sname =
"Group";
1680 sname =
"Aggregate";
1684 pname =
"Aggregate";
1688 pname =
"GroupAggregate";
1689 strategy =
"Sorted";
1692 pname =
"HashAggregate";
1693 strategy =
"Hashed";
1696 pname =
"MixedAggregate";
1700 pname =
"Aggregate ???";
1707 partialmode =
"Partial";
1708 pname =
psprintf(
"%s %s", partialmode, pname);
1712 partialmode =
"Finalize";
1713 pname =
psprintf(
"%s %s", partialmode, pname);
1716 partialmode =
"Simple";
1720 pname = sname =
"WindowAgg";
1723 pname = sname =
"Unique";
1731 strategy =
"Sorted";
1734 pname =
"HashSetOp";
1735 strategy =
"Hashed";
1738 pname =
"SetOp ???";
1744 pname = sname =
"LockRows";
1747 pname = sname =
"Limit";
1750 pname = sname =
"Hash";
1753 pname = sname =
"???";
1758 relationship ? NULL :
"Plan",
1775 if (
plan->parallel_aware)
1777 if (
plan->async_capable)
1805 case T_BitmapHeapScan:
1807 case T_TidRangeScan:
1808 case T_SubqueryScan:
1809 case T_FunctionScan:
1810 case T_TableFuncScan:
1813 case T_WorkTableScan:
1818 if (((
Scan *)
plan)->scanrelid > 0)
1831 case T_IndexOnlyScan:
1841 case T_BitmapIndexScan:
1844 const char *indexname =
1861 const char *jointype;
1884 jointype =
"Right Semi";
1887 jointype =
"Right Anti";
1910 const char *setopcmd;
1915 setopcmd =
"Intersect";
1918 setopcmd =
"Intersect All";
1921 setopcmd =
"Except";
1924 setopcmd =
"Except All";
1945 plan->startup_cost,
plan->total_cost,
1946 plan->plan_rows,
plan->plan_width);
1986 " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
1987 startup_ms, total_ms, rows, nloops);
1990 " (actual rows=%.0f loops=%.0f)",
2039 double nloops = instrument->
nloops;
2046 startup_ms = 1000.0 * instrument->
startup / nloops;
2047 total_ms = 1000.0 * instrument->
total / nloops;
2048 rows = instrument->
ntuples / nloops;
2057 "actual time=%.3f..%.3f rows=%.0f loops=%.0f\n",
2058 startup_ms, total_ms, rows, nloops);
2061 "actual rows=%.0f loops=%.0f\n",
2107 "Index Cond", planstate, ancestors, es);
2112 "Order By", planstate, ancestors, es);
2118 case T_IndexOnlyScan:
2120 "Index Cond", planstate, ancestors, es);
2125 "Order By", planstate, ancestors, es);
2134 case T_BitmapIndexScan:
2136 "Index Cond", planstate, ancestors, es);
2138 case T_BitmapHeapScan:
2140 "Recheck Cond", planstate, ancestors, es);
2152 planstate, ancestors, es);
2158 case T_NamedTuplestoreScan:
2159 case T_WorkTableScan:
2160 case T_SubqueryScan:
2183 nworkers = ((
GatherState *) planstate)->nworkers_launched;
2213 case T_FunctionScan:
2227 "Function Call", planstate, ancestors,
2235 case T_TableFuncScan:
2241 "Table Function Call", planstate, ancestors,
2268 case T_TidRangeScan:
2306 "Join Filter", planstate, ancestors, es);
2317 "Merge Cond", planstate, ancestors, es);
2319 "Join Filter", planstate, ancestors, es);
2330 "Hash Cond", planstate, ancestors, es);
2332 "Join Filter", planstate, ancestors, es);
2355 "Run Condition", planstate, ancestors, es);
2369 case T_IncrementalSort:
2381 "One-Time Filter", planstate, ancestors, es);
2401 case T_RecursiveUnion:
2443 double nloops = instrument->
nloops;
2487 haschildren = planstate->
initPlan ||
2542 case T_SubqueryScan:
2544 "Subquery", NULL, es);
2567 es->
indent = save_indent;
2570 relationship ? NULL :
"Plan",
2619 foreach(lc,
plan->targetlist)
2687 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2701 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2713 plan->numCols, 0,
plan->sortColIdx,
2714 plan->sortOperators,
plan->collations,
2729 plan->sort.numCols,
plan->nPresortedCols,
2730 plan->sort.sortColIdx,
2731 plan->sort.sortOperators,
plan->sort.collations,
2732 plan->sort.nullsFirst,
2746 plan->numCols, 0,
plan->sortColIdx,
2747 plan->sortOperators,
plan->collations,
2766 if (
plan->groupingSets)
2795 context, useprefix, ancestors, es);
2797 foreach(lc, agg->
chain)
2803 context, useprefix, ancestors, es);
2820 const char *keyname;
2821 const char *keysetname;
2825 keyname =
"Hash Key";
2826 keysetname =
"Hash Keys";
2830 keyname =
"Group Key";
2831 keysetname =
"Group Keys";
2839 sortnode->
numCols, 0, sortnode->sortColIdx,
2840 sortnode->sortOperators, sortnode->collations,
2841 sortnode->nullsFirst,
2862 elog(
ERROR,
"no tlist entry for key %d", keyresno);
2867 result =
lappend(result, exprstr);
2909 int nkeys,
int nPresortedKeys,
AttrNumber *keycols,
2910 Oid *sortOperators,
Oid *collations,
bool *nullsFirst,
2932 for (keyno = 0; keyno < nkeys; keyno++)
2941 elog(
ERROR,
"no tlist entry for key %d", keyresno);
2948 if (sortOperators != NULL)
2951 sortOperators[keyno],
2956 if (keyno < nPresortedKeys)
2957 resultPresorted =
lappend(resultPresorted, exprstr);
2961 if (nPresortedKeys > 0)
2971 Oid sortOperator,
Oid collation,
bool nullsFirst)
2974 bool reverse =
false;
2991 if (collname == NULL)
2992 elog(
ERROR,
"cache lookup failed for collation %u", collation);
2997 if (sortOperator == typentry->
gt_opr)
3002 else if (sortOperator != typentry->
lt_opr)
3007 elog(
ERROR,
"cache lookup failed for operator %u", sortOperator);
3014 if (nullsFirst && !reverse)
3018 else if (!nullsFirst && reverse)
3071 foreach(lc, tsc->
args)
3126 const char *sortMethod;
3127 const char *spaceType;
3133 spaceUsed = stats.spaceUsed;
3139 sortMethod, spaceType, spaceUsed);
3165 const char *sortMethod;
3166 const char *spaceType;
3184 sortMethod, spaceType, spaceUsed);
3238 foreach(methodCell, methodNames)
3248 const char *spaceTypeName;
3252 spaceTypeName, avgSpace,
3260 const char *spaceTypeName;
3264 spaceTypeName, avgSpace,
3282 const char *spaceTypeName;
3299 const char *spaceTypeName;
3359 bool indent_first_line;
3387 indent_first_line, es);
3455 if (hinstrument.
nbatch > 0)
3477 "Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: " UINT64_FORMAT "kB\n",
3488 "Buckets: %d Batches: %d Memory Usage: " UINT64_FORMAT "kB\n",
3502 char *maxStorageType;
3511 if (!es->
analyze || tupstore == NULL)
3525 char *maxStorageType;
3534 if (!es->
analyze || tupstore == NULL)
3548 char *maxStorageType;
3553 if (!es->
analyze || tupstore == NULL)
3567 char *maxStorageType;
3572 if (!es->
analyze || tupstore == NULL)
3586 char *maxStorageType,
3604 if (tempSpaceUsed > maxSpaceUsed)
3605 maxStorageType = tempStorageType;
3607 maxSpaceUsed += tempSpaceUsed;
3790 bool gotone =
false;
3835 int hash_batches_used;
3853 hash_batches_used, memPeakKb);
3856 if (hash_batches_used > 1)
3864 hash_batches_used, es);
3907 if (planstate->
pstate != NULL)
4011 result = (*explain_get_index_name_hook) (indexId);
4019 elog(
ERROR,
"cache lookup failed for index %u", indexId);
4035 bool has_shared_timing;
4036 bool has_local_timing;
4037 bool has_temp_timing;
4045 has_shared = (
usage->shared_blks_hit > 0 ||
4046 usage->shared_blks_read > 0 ||
4047 usage->shared_blks_dirtied > 0 ||
4048 usage->shared_blks_written > 0);
4049 has_local = (
usage->local_blks_hit > 0 ||
4050 usage->local_blks_read > 0 ||
4051 usage->local_blks_dirtied > 0 ||
4052 usage->local_blks_written > 0);
4053 has_temp = (
usage->temp_blks_read > 0 ||
4054 usage->temp_blks_written > 0);
4062 return has_shared || has_local || has_temp || has_shared_timing ||
4063 has_local_timing || has_temp_timing;
4074 bool has_shared = (
usage->shared_blks_hit > 0 ||
4075 usage->shared_blks_read > 0 ||
4076 usage->shared_blks_dirtied > 0 ||
4077 usage->shared_blks_written > 0);
4078 bool has_local = (
usage->local_blks_hit > 0 ||
4079 usage->local_blks_read > 0 ||
4080 usage->local_blks_dirtied > 0 ||
4081 usage->local_blks_written > 0);
4082 bool has_temp = (
usage->temp_blks_read > 0 ||
4083 usage->temp_blks_written > 0);
4092 if (has_shared || has_local || has_temp)
4100 if (
usage->shared_blks_hit > 0)
4102 (
long long)
usage->shared_blks_hit);
4103 if (
usage->shared_blks_read > 0)
4105 (
long long)
usage->shared_blks_read);
4106 if (
usage->shared_blks_dirtied > 0)
4108 (
long long)
usage->shared_blks_dirtied);
4109 if (
usage->shared_blks_written > 0)
4111 (
long long)
usage->shared_blks_written);
4112 if (has_local || has_temp)
4118 if (
usage->local_blks_hit > 0)
4120 (
long long)
usage->local_blks_hit);
4121 if (
usage->local_blks_read > 0)
4123 (
long long)
usage->local_blks_read);
4124 if (
usage->local_blks_dirtied > 0)
4126 (
long long)
usage->local_blks_dirtied);
4127 if (
usage->local_blks_written > 0)
4129 (
long long)
usage->local_blks_written);
4136 if (
usage->temp_blks_read > 0)
4138 (
long long)
usage->temp_blks_read);
4139 if (
usage->temp_blks_written > 0)
4141 (
long long)
usage->temp_blks_written);
4147 if (has_shared_timing || has_local_timing || has_temp_timing)
4152 if (has_shared_timing)
4161 if (has_local_timing || has_temp_timing)
4164 if (has_local_timing)
4173 if (has_temp_timing)
4176 if (has_temp_timing)
4192 usage->shared_blks_hit, es);
4194 usage->shared_blks_read, es);
4196 usage->shared_blks_dirtied, es);
4198 usage->shared_blks_written, es);
4200 usage->local_blks_hit, es);
4202 usage->local_blks_read, es);
4204 usage->local_blks_dirtied, es);
4206 usage->local_blks_written, es);
4208 usage->temp_blks_read, es);
4210 usage->temp_blks_written, es);
4244 if ((
usage->wal_records > 0) || (
usage->wal_fpi > 0) ||
4245 (
usage->wal_bytes > 0))
4250 if (
usage->wal_records > 0)
4252 (
long long)
usage->wal_records);
4253 if (
usage->wal_fpi > 0)
4255 (
long long)
usage->wal_fpi);
4256 if (
usage->wal_bytes > 0)
4265 usage->wal_records, es);
4267 usage->wal_fpi, es);
4269 usage->wal_bytes, es);
4288 memUsedkB, memAllocatedkB);
4316 const char *scandir;
4318 switch (indexorderdir)
4321 scandir =
"Backward";
4324 scandir =
"Forward";
4363 char *objectname = NULL;
4364 char *
namespace = NULL;
4365 const char *objecttag = NULL;
4371 if (refname == NULL)
4372 refname = rte->eref->aliasname;
4379 case T_IndexOnlyScan:
4380 case T_BitmapHeapScan:
4382 case T_TidRangeScan:
4391 objecttag =
"Relation Name";
4393 case T_FunctionScan:
4420 objecttag =
"Function Name";
4423 case T_TableFuncScan:
4431 objectname =
"xmltable";
4434 objectname =
"json_table";
4437 elog(
ERROR,
"invalid TableFunc type %d",
4440 objecttag =
"Table Function Name";
4449 Assert(!rte->self_reference);
4450 objectname = rte->ctename;
4451 objecttag =
"CTE Name";
4453 case T_NamedTuplestoreScan:
4455 objectname = rte->enrname;
4456 objecttag =
"Tuplestore Name";
4458 case T_WorkTableScan:
4461 Assert(rte->self_reference);
4462 objectname = rte->ctename;
4463 objecttag =
"CTE Name";
4472 if (
namespace != NULL)
4475 else if (objectname != NULL)
4477 if (objectname == NULL || strcmp(refname, objectname) != 0)
4482 if (objecttag != NULL && objectname != NULL)
4484 if (
namespace != NULL)
4503 const char *operation;
4504 const char *foperation;
4513 operation =
"Insert";
4514 foperation =
"Foreign Insert";
4517 operation =
"Update";
4518 foperation =
"Foreign Update";
4521 operation =
"Delete";
4522 foperation =
"Foreign Delete";
4525 operation =
"Merge";
4527 foperation =
"Foreign Merge";
4531 foperation =
"Foreign ???";
4536 labeltargets = (mtstate->
mt_nrels > 1 ||
4561 fdwroutine ? foperation : operation);
4578 fdwroutine != NULL &&
4606 idxNames =
lappend(idxNames, indexname);
4613 "NOTHING" :
"UPDATE",
4627 &mtstate->
ps, ancestors, es);
4643 insert_path = total - other_path;
4646 insert_path, 0, es);
4660 double skipped_path;
4669 skipped_path = total - insert_path - update_path - delete_path;
4670 Assert(skipped_path >= 0);
4678 if (insert_path > 0)
4680 if (update_path > 0)
4682 if (delete_path > 0)
4684 if (skipped_path > 0)
4716 for (
j = 0;
j < nplans;
j++)
4718 "Member", NULL, es);
4733 nchildren - nplans, es);
4773 ancestors =
lcons(sp, ancestors);
4830 Assert(n >= 0 && n < wstate->num_workers);
4892 Assert(n >= 0 && n < wstate->num_workers);