PostgreSQL Source Code: src/backend/commands/explain.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15
47
48
49
51
52
54
55
58
59
60
61
62
63#define BYTES_TO_KILOBYTES(b) (((b) + 1023) / 1024)
64
77 const char *relationship, const char *plan_name,
84static void show_qual(List *qual, const char *qlabel,
104 Agg *aggnode, Sort *sortnode,
105 List *context, bool useprefix,
110 int nkeys, int nPresortedKeys, AttrNumber *keycols,
111 Oid *sortOperators, Oid *collations, bool *nullsFirst,
114 Oid sortOperator, Oid collation, bool nullsFirst);
169
170
171
172
173
174
175
176void
179{
184 List *rewritten;
185
186
188
189
193
195 (*post_parse_analyze_hook) (pstate, query, jstate);
196
197
198
199
200
201
202
204
205
207
208 if (rewritten == NIL)
209 {
210
211
212
213
216 }
217 else
218 {
220
221
222 foreach(l, rewritten)
223 {
226 pstate, params);
227
228
229 if (lnext(rewritten, l) != NULL)
231 }
232 }
233
234
237
238
243 else
246
248}
249
250
251
252
253
256{
259 Oid result_type = TEXTOID;
260
261
262 foreach(lc, stmt->options)
263 {
265
266 if (strcmp(opt->defname, "format") == 0)
267 {
269
270 if (strcmp(p, "xml") == 0)
271 result_type = XMLOID;
272 else if (strcmp(p, "json") == 0)
273 result_type = JSONOID;
274 else
275 result_type = TEXTOID;
276
277 }
278 }
279
280
283 result_type, -1, 0);
284 return tupdesc;
285}
286
287
288
289
290
291
292
293static void
297{
298
300 {
302 return;
303 }
304
305
307 (*ExplainOneQuery_hook) (query, cursorOptions, into, es,
309 else
312}
313
314
315
316
317
318void
323{
326 planduration;
328 bufusage;
332
334 {
335
336
337
338
339
340
341
342
344 "explain analyze planner context",
347 }
348
352
353
354 plan = pg_plan_query(query, queryString, cursorOptions, params, es);
355
358
360 {
363 }
364
365
367 {
368 memset(&bufusage, 0, sizeof(BufferUsage));
370 }
371
372
374 &planduration, (es->buffers ? &bufusage : NULL),
375 es->memory ? &mem_counters : NULL);
376}
377
378
379
380
381
382
383
384
385
386
387
388
389
390void
393{
394 if (utilityStmt == NULL)
395 return;
396
398 {
399
400
401
402
404 Query *ctas_query;
405 List *rewritten;
407
408
409
410
411
413 {
418 else
419 elog(ERROR, "unexpected object type: %d",
421 return;
422 }
423
428 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);
433 pstate, params);
434 }
436 {
437
438
439
440
441
442
443
444
446 Query *dcs_query;
447 List *rewritten;
449
454 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);
455
460 pstate, params);
461 }
464 pstate, params);
466 {
469 else
471 }
472 else
473 {
476 "Utility statements have no plan structure\n");
477 else
479 }
480}
481
482
483
484
485
486
487
488
489
490
491
492
493
494void
500{
504 double totaltime = 0;
505 int eflags;
506 int instrument_option = 0;
508
510
515
518 if (es->wal)
520
521
522
523
524
525
527
528
529
530
531
534
535
536
537
538
539
540
541
542
543 if (into)
547 else
549
550
553 dest, params, queryEnv, instrument_option);
554
555
557 eflags = 0;
558 else
562 if (into)
564
565
567
568
570 {
572
573
576 else
578
579
581
582
584
585
587 }
588
589
592
593
595
597
598
600
601
603 {
605
607 {
611 }
612
613 if (bufusage)
615
616 if (mem_counters)
618
621
623 }
624
625 if (es->summary && planduration)
626 {
628
630 }
631
632
635
636
637
638
639
640
641
644
645
648
649
651 (*explain_per_plan_hook) (plannedstmt, into, es, queryString,
652 params, queryEnv);
653
654
655
656
657
659
661
663
665
666
669
671
672
673
674
675
676
677
680 es);
681
683}
684
685
686
687
688
689static void
691{
692 int num;
694
695
697 return;
698
699
701
703 {
705
706 for (int i = 0; i < num; i++)
707 {
708 char *setting;
710
712
714 }
715
717 }
718 else
719 {
721
722
723 if (num <= 0)
724 return;
725
727
728 for (int i = 0; i < num; i++)
729 {
730 char *setting;
732
733 if (i > 0)
735
737
738 if (setting)
740 else
742 }
743
745 }
746}
747
748
749
750
751
752
753
754
755
756
757
758
759void
761{
765
766
776 foreach(lc, es->rtable)
777 {
779
781 {
783 break;
784 }
785 }
786
787
788
789
790
791
792
793
794
795
798 {
801 }
803
804
805
806
807
809
810
811
812
813
814
817 {
820 }
821}
822
823
824
825
826
827
828
829
830
831
832void
834{
836 bool show_relname;
837 List *resultrels;
838 List *routerels;
839 List *targrels;
841
845
847
848 show_relname = (list_length(resultrels) > 1 ||
849 routerels != NIL || targrels != NIL);
850 foreach(l, resultrels)
851 {
854 }
855
856 foreach(l, routerels)
857 {
860 }
861
862 foreach(l, targrels)
863 {
866 }
867
869}
870
871
872
873
874
875void
877{
879
881 return;
882
883
884
885
886
889
890
893
895}
896
897
898
899
900
901static void
903{
905
906
908 return;
909
910
912
917
919
920
922 {
926
928
931 "Inlining", jit_flags & PGJIT_INLINE ? "true" : "false",
932 "Optimization", jit_flags & PGJIT_OPT3 ? "true" : "false",
933 "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",
934 "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");
935
937 {
940 "Timing: %s %.3f ms (%s %.3f ms), %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",
947 }
948
950 }
951 else
952 {
954
961
963 {
965
969 3, es);
972 3, es);
974
977 3, es);
980 3, es);
983 3, es);
986 3, es);
987
989 }
990 }
991
993}
994
995
996
997
998
999static void
1001{
1003
1004
1007 else
1008 {
1011 }
1012
1013 ExplainOpenGroup("Serialization", "Serialization", true, es);
1014
1016 {
1023 else
1027
1029 {
1033 }
1034 }
1035 else
1036 {
1040 3, es);
1046 }
1047
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059void
1061{
1064}
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074void
1076{
1077 char *str;
1078
1079
1080 if (params == NULL || params->numParams <= 0 || maxlen == 0)
1081 return;
1082
1084 if (str && str[0] != '\0')
1086}
1087
1088
1089
1090
1091
1092static void
1094{
1095 int nt;
1096
1098 return;
1100 {
1104 char *conname = NULL;
1105
1106
1108
1109
1110
1111
1112
1113 if (instr->ntuples == 0)
1114 continue;
1115
1117
1121
1122
1123
1124
1125
1126
1128 {
1129 if (es->verbose || conname == NULL)
1131 else
1133 if (conname)
1135 if (show_relname)
1140 else
1142 }
1143 else
1144 {
1146 if (conname)
1151 es);
1153 }
1154
1155 if (conname)
1157
1159 }
1160}
1161
1162
1163static double
1165{
1167
1171}
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182static bool
1184{
1186
1188 {
1189 case T_SeqScan:
1190 case T_SampleScan:
1191 case T_IndexScan:
1192 case T_IndexOnlyScan:
1193 case T_BitmapHeapScan:
1194 case T_TidScan:
1195 case T_TidRangeScan:
1196 case T_SubqueryScan:
1197 case T_FunctionScan:
1198 case T_TableFuncScan:
1199 case T_ValuesScan:
1200 case T_CteScan:
1201 case T_NamedTuplestoreScan:
1202 case T_WorkTableScan:
1204 ((Scan *) plan)->scanrelid);
1205 break;
1206 case T_ForeignScan:
1209 break;
1210 case T_CustomScan:
1213 break;
1214 case T_ModifyTable:
1220
1221 if (plan->targetlist)
1224 break;
1225 case T_Append:
1228 break;
1229 case T_MergeAppend:
1232 break;
1233 case T_Result:
1236 break;
1237 default:
1238 break;
1239 }
1240
1242}
1243
1244
1245
1246
1247
1248
1249
1250static bool
1252{
1253 int child_disabled_nodes;
1254
1255
1256 if (plan->disabled_nodes == 0)
1257 return false;
1258
1259 child_disabled_nodes = 0;
1260
1261
1262
1263
1264
1266 {
1269
1270
1271
1272
1273
1274
1276 {
1278
1280 }
1281 }
1283 {
1286
1287
1288
1289
1290
1291
1293 {
1295
1297 }
1298 }
1300 child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes;
1302 {
1305
1307 {
1309
1311 }
1312 }
1313 else
1314 {
1315
1316
1317
1319 child_disabled_nodes += outerPlan(plan)->disabled_nodes;
1321 child_disabled_nodes += innerPlan(plan)->disabled_nodes;
1322 }
1323
1324
1325
1326
1327
1328 if (plan->disabled_nodes > child_disabled_nodes)
1329 return true;
1330
1331 return false;
1332}
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355static void
1357 const char *relationship, const char *plan_name,
1359{
1361 const char *pname;
1362 const char *sname;
1363 const char *strategy = NULL;
1364 const char *partialmode = NULL;
1365 const char *operation = NULL;
1366 const char *custom_name = NULL;
1368 int save_indent = es->indent;
1369 bool haschildren;
1370 bool isdisabled;
1371
1372
1373
1374
1375
1378 else
1380
1381
1383 {
1384 case T_Result:
1385 pname = sname = "Result";
1386 break;
1387 case T_ProjectSet:
1388 pname = sname = "ProjectSet";
1389 break;
1390 case T_ModifyTable:
1391 sname = "ModifyTable";
1393 {
1395 pname = operation = "Insert";
1396 break;
1398 pname = operation = "Update";
1399 break;
1401 pname = operation = "Delete";
1402 break;
1404 pname = operation = "Merge";
1405 break;
1406 default:
1407 pname = "???";
1408 break;
1409 }
1410 break;
1411 case T_Append:
1412 pname = sname = "Append";
1413 break;
1414 case T_MergeAppend:
1415 pname = sname = "Merge Append";
1416 break;
1417 case T_RecursiveUnion:
1418 pname = sname = "Recursive Union";
1419 break;
1420 case T_BitmapAnd:
1421 pname = sname = "BitmapAnd";
1422 break;
1423 case T_BitmapOr:
1424 pname = sname = "BitmapOr";
1425 break;
1426 case T_NestLoop:
1427 pname = sname = "Nested Loop";
1428 break;
1429 case T_MergeJoin:
1430 pname = "Merge";
1431 sname = "Merge Join";
1432 break;
1433 case T_HashJoin:
1434 pname = "Hash";
1435 sname = "Hash Join";
1436 break;
1437 case T_SeqScan:
1438 pname = sname = "Seq Scan";
1439 break;
1440 case T_SampleScan:
1441 pname = sname = "Sample Scan";
1442 break;
1443 case T_Gather:
1444 pname = sname = "Gather";
1445 break;
1446 case T_GatherMerge:
1447 pname = sname = "Gather Merge";
1448 break;
1449 case T_IndexScan:
1450 pname = sname = "Index Scan";
1451 break;
1452 case T_IndexOnlyScan:
1453 pname = sname = "Index Only Scan";
1454 break;
1455 case T_BitmapIndexScan:
1456 pname = sname = "Bitmap Index Scan";
1457 break;
1458 case T_BitmapHeapScan:
1459 pname = sname = "Bitmap Heap Scan";
1460 break;
1461 case T_TidScan:
1462 pname = sname = "Tid Scan";
1463 break;
1464 case T_TidRangeScan:
1465 pname = sname = "Tid Range Scan";
1466 break;
1467 case T_SubqueryScan:
1468 pname = sname = "Subquery Scan";
1469 break;
1470 case T_FunctionScan:
1471 pname = sname = "Function Scan";
1472 break;
1473 case T_TableFuncScan:
1474 pname = sname = "Table Function Scan";
1475 break;
1476 case T_ValuesScan:
1477 pname = sname = "Values Scan";
1478 break;
1479 case T_CteScan:
1480 pname = sname = "CTE Scan";
1481 break;
1482 case T_NamedTuplestoreScan:
1483 pname = sname = "Named Tuplestore Scan";
1484 break;
1485 case T_WorkTableScan:
1486 pname = sname = "WorkTable Scan";
1487 break;
1488 case T_ForeignScan:
1489 sname = "Foreign Scan";
1491 {
1493 pname = "Foreign Scan";
1494 operation = "Select";
1495 break;
1497 pname = "Foreign Insert";
1498 operation = "Insert";
1499 break;
1501 pname = "Foreign Update";
1502 operation = "Update";
1503 break;
1505 pname = "Foreign Delete";
1506 operation = "Delete";
1507 break;
1508 default:
1509 pname = "???";
1510 break;
1511 }
1512 break;
1513 case T_CustomScan:
1514 sname = "Custom Scan";
1515 custom_name = ((CustomScan *) plan)->methods->CustomName;
1516 if (custom_name)
1517 pname = psprintf("Custom Scan (%s)", custom_name);
1518 else
1519 pname = sname;
1520 break;
1521 case T_Material:
1522 pname = sname = "Materialize";
1523 break;
1524 case T_Memoize:
1525 pname = sname = "Memoize";
1526 break;
1527 case T_Sort:
1528 pname = sname = "Sort";
1529 break;
1530 case T_IncrementalSort:
1531 pname = sname = "Incremental Sort";
1532 break;
1533 case T_Group:
1534 pname = sname = "Group";
1535 break;
1536 case T_Agg:
1537 {
1539
1540 sname = "Aggregate";
1542 {
1544 pname = "Aggregate";
1545 strategy = "Plain";
1546 break;
1548 pname = "GroupAggregate";
1549 strategy = "Sorted";
1550 break;
1552 pname = "HashAggregate";
1553 strategy = "Hashed";
1554 break;
1556 pname = "MixedAggregate";
1557 strategy = "Mixed";
1558 break;
1559 default:
1560 pname = "Aggregate ???";
1561 strategy = "???";
1562 break;
1563 }
1564
1566 {
1567 partialmode = "Partial";
1568 pname = psprintf("%s %s", partialmode, pname);
1569 }
1571 {
1572 partialmode = "Finalize";
1573 pname = psprintf("%s %s", partialmode, pname);
1574 }
1575 else
1576 partialmode = "Simple";
1577 }
1578 break;
1579 case T_WindowAgg:
1580 pname = sname = "WindowAgg";
1581 break;
1582 case T_Unique:
1583 pname = sname = "Unique";
1584 break;
1585 case T_SetOp:
1586 sname = "SetOp";
1587 switch (((SetOp *) plan)->strategy)
1588 {
1590 pname = "SetOp";
1591 strategy = "Sorted";
1592 break;
1594 pname = "HashSetOp";
1595 strategy = "Hashed";
1596 break;
1597 default:
1598 pname = "SetOp ???";
1599 strategy = "???";
1600 break;
1601 }
1602 break;
1603 case T_LockRows:
1604 pname = sname = "LockRows";
1605 break;
1606 case T_Limit:
1607 pname = sname = "Limit";
1608 break;
1609 case T_Hash:
1610 pname = sname = "Hash";
1611 break;
1612 default:
1613 pname = sname = "???";
1614 break;
1615 }
1616
1618 relationship ? NULL : "Plan",
1619 true, es);
1620
1622 {
1623 if (plan_name)
1624 {
1628 }
1630 {
1634 }
1635 if (plan->parallel_aware)
1637 if (plan->async_capable)
1641 }
1642 else
1643 {
1645 if (strategy)
1647 if (partialmode)
1649 if (operation)
1651 if (relationship)
1653 if (plan_name)
1655 if (custom_name)
1659 }
1660
1662 {
1663 case T_SeqScan:
1664 case T_SampleScan:
1665 case T_BitmapHeapScan:
1666 case T_TidScan:
1667 case T_TidRangeScan:
1668 case T_SubqueryScan:
1669 case T_FunctionScan:
1670 case T_TableFuncScan:
1671 case T_ValuesScan:
1672 case T_CteScan:
1673 case T_WorkTableScan:
1675 break;
1676 case T_ForeignScan:
1677 case T_CustomScan:
1678 if (((Scan *) plan)->scanrelid > 0)
1680 break;
1681 case T_IndexScan:
1682 {
1684
1687 es);
1689 }
1690 break;
1691 case T_IndexOnlyScan:
1692 {
1694
1697 es);
1699 }
1700 break;
1701 case T_BitmapIndexScan:
1702 {
1704 const char *indexname =
1706
1710 else
1712 }
1713 break;
1714 case T_ModifyTable:
1716 break;
1717 case T_NestLoop:
1718 case T_MergeJoin:
1719 case T_HashJoin:
1720 {
1721 const char *jointype;
1722
1723 switch (((Join *) plan)->jointype)
1724 {
1726 jointype = "Inner";
1727 break;
1729 jointype = "Left";
1730 break;
1732 jointype = "Full";
1733 break;
1735 jointype = "Right";
1736 break;
1738 jointype = "Semi";
1739 break;
1741 jointype = "Anti";
1742 break;
1744 jointype = "Right Semi";
1745 break;
1747 jointype = "Right Anti";
1748 break;
1749 default:
1750 jointype = "???";
1751 break;
1752 }
1754 {
1755
1756
1757
1758
1763 }
1764 else
1766 }
1767 break;
1768 case T_SetOp:
1769 {
1770 const char *setopcmd;
1771
1773 {
1775 setopcmd = "Intersect";
1776 break;
1778 setopcmd = "Intersect All";
1779 break;
1781 setopcmd = "Except";
1782 break;
1784 setopcmd = "Except All";
1785 break;
1786 default:
1787 setopcmd = "???";
1788 break;
1789 }
1792 else
1794 }
1795 break;
1796 default:
1797 break;
1798 }
1799
1801 {
1803 {
1805 plan->startup_cost, plan->total_cost,
1806 plan->plan_rows, plan->plan_width);
1807 }
1808 else
1809 {
1811 2, es);
1813 2, es);
1815 0, es);
1817 es);
1818 }
1819 }
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1833
1836 {
1838 double startup_ms = 1000.0 * planstate->instrument->startup / nloops;
1839 double total_ms = 1000.0 * planstate->instrument->total / nloops;
1841
1843 {
1845
1848
1850 }
1851 else
1852 {
1854 {
1856 3, es);
1858 3, es);
1859 }
1862 }
1863 }
1865 {
1868 else
1869 {
1871 {
1874 }
1877 }
1878 }
1879
1880
1883
1884
1888
1889
1891 {
1893
1894 for (int n = 0; n < w->num_workers; n++)
1895 {
1897 double nloops = instrument->nloops;
1898 double startup_ms;
1899 double total_ms;
1900 double rows;
1901
1902 if (nloops <= 0)
1903 continue;
1904 startup_ms = 1000.0 * instrument->startup / nloops;
1905 total_ms = 1000.0 * instrument->total / nloops;
1906 rows = instrument->ntuples / nloops;
1907
1909
1911 {
1916
1918 }
1919 else
1920 {
1922 {
1924 startup_ms, 3, es);
1926 total_ms, 3, es);
1927 }
1928
1931 }
1932
1934 }
1935 }
1936
1937
1940
1941
1943 {
1944 case T_NestLoop:
1945 case T_MergeJoin:
1946 case T_HashJoin:
1947
1951 ((Join *) plan)->inner_unique,
1952 es);
1953 break;
1954 default:
1955 break;
1956 }
1957
1958
1960 {
1961 case T_IndexScan:
1963 "Index Cond", planstate, ancestors, es);
1966 planstate, es);
1968 "Order By", planstate, ancestors, es);
1970 if (plan->qual)
1972 planstate, es);
1974 break;
1975 case T_IndexOnlyScan:
1977 "Index Cond", planstate, ancestors, es);
1980 planstate, es);
1982 "Order By", planstate, ancestors, es);
1984 if (plan->qual)
1986 planstate, es);
1991 break;
1992 case T_BitmapIndexScan:
1994 "Index Cond", planstate, ancestors, es);
1996 break;
1997 case T_BitmapHeapScan:
1999 "Recheck Cond", planstate, ancestors, es);
2002 planstate, es);
2004 if (plan->qual)
2006 planstate, es);
2008 break;
2009 case T_SampleScan:
2011 planstate, ancestors, es);
2012
2013
2014 case T_SeqScan:
2015 case T_ValuesScan:
2016 case T_CteScan:
2017 case T_NamedTuplestoreScan:
2018 case T_WorkTableScan:
2019 case T_SubqueryScan:
2021 if (plan->qual)
2023 planstate, es);
2026 break;
2027 case T_Gather:
2028 {
2030
2032 if (plan->qual)
2034 planstate, es);
2037
2039 {
2040 int nworkers;
2041
2042 nworkers = ((GatherState *) planstate)->nworkers_launched;
2044 nworkers, es);
2045 }
2046
2049 }
2050 break;
2051 case T_GatherMerge:
2052 {
2054
2056 if (plan->qual)
2058 planstate, es);
2061
2063 {
2064 int nworkers;
2065
2066 nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
2068 nworkers, es);
2069 }
2070 }
2071 break;
2072 case T_FunctionScan:
2074 {
2077
2079 {
2081
2083 }
2084
2086 "Function Call", planstate, ancestors,
2088 }
2090 if (plan->qual)
2092 planstate, es);
2093 break;
2094 case T_TableFuncScan:
2096 {
2098
2100 "Table Function Call", planstate, ancestors,
2102 }
2104 if (plan->qual)
2106 planstate, es);
2108 planstate), es);
2109 break;
2110 case T_TidScan:
2111 {
2112
2113
2114
2115
2117
2120 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2122 if (plan->qual)
2124 planstate, es);
2125 }
2126 break;
2127 case T_TidRangeScan:
2128 {
2129
2130
2131
2132
2134
2137 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2139 if (plan->qual)
2141 planstate, es);
2142 }
2143 break;
2144 case T_ForeignScan:
2146 if (plan->qual)
2148 planstate, es);
2150 break;
2151 case T_CustomScan:
2152 {
2154
2156 if (plan->qual)
2158 planstate, es);
2161 }
2162 break;
2163 case T_NestLoop:
2165 "Join Filter", planstate, ancestors, es);
2168 planstate, es);
2170 if (plan->qual)
2172 planstate, es);
2173 break;
2174 case T_MergeJoin:
2176 "Merge Cond", planstate, ancestors, es);
2178 "Join Filter", planstate, ancestors, es);
2181 planstate, es);
2183 if (plan->qual)
2185 planstate, es);
2186 break;
2187 case T_HashJoin:
2189 "Hash Cond", planstate, ancestors, es);
2191 "Join Filter", planstate, ancestors, es);
2194 planstate, es);
2196 if (plan->qual)
2198 planstate, es);
2199 break;
2200 case T_Agg:
2204 if (plan->qual)
2206 planstate, es);
2207 break;
2208 case T_WindowAgg:
2211 "Run Condition", planstate, ancestors, es);
2213 if (plan->qual)
2215 planstate, es);
2217 break;
2218 case T_Group:
2221 if (plan->qual)
2223 planstate, es);
2224 break;
2225 case T_Sort:
2228 break;
2229 case T_IncrementalSort:
2231 ancestors, es);
2233 es);
2234 break;
2235 case T_MergeAppend:
2237 ancestors, es);
2238 break;
2239 case T_Result:
2242 "One-Time Filter", planstate, ancestors, es);
2244 if (plan->qual)
2246 planstate, es);
2247 break;
2248 case T_ModifyTable:
2250 es);
2251 break;
2252 case T_Hash:
2254 break;
2255 case T_Material:
2257 break;
2258 case T_Memoize:
2260 es);
2261 break;
2262 case T_RecursiveUnion:
2264 planstate), es);
2265 break;
2266 default:
2267 break;
2268 }
2269
2270
2271
2272
2273
2275 {
2277
2278 if (w)
2279 {
2280 for (int n = 0; n < w->num_workers; n++)
2281 {
2286 }
2287 }
2288 }
2289
2290
2295
2296
2298 {
2300
2301 for (int n = 0; n < w->num_workers; n++)
2302 {
2304 double nloops = instrument->nloops;
2305
2306 if (nloops <= 0)
2307 continue;
2308
2312 if (es->wal)
2315 }
2316 }
2317
2318
2322
2323
2325 (*explain_per_node_hook) (planstate, ancestors, relationship,
2326 plan_name, es);
2327
2328
2329
2330
2331
2332
2333
2334
2335
2337 {
2338 case T_Append:
2341 es);
2342 break;
2343 case T_MergeAppend:
2346 es);
2347 break;
2348 default:
2349 break;
2350 }
2351
2352
2353 haschildren = planstate->initPlan ||
2364 if (haschildren)
2365 {
2367
2368 ancestors = lcons(plan, ancestors);
2369 }
2370
2371
2374
2375
2378 "Outer", NULL, es);
2379
2380
2383 "Inner", NULL, es);
2384
2385
2387 {
2388 case T_Append:
2391 ancestors, es);
2392 break;
2393 case T_MergeAppend:
2396 ancestors, es);
2397 break;
2398 case T_BitmapAnd:
2401 ancestors, es);
2402 break;
2403 case T_BitmapOr:
2406 ancestors, es);
2407 break;
2408 case T_SubqueryScan:
2410 "Subquery", NULL, es);
2411 break;
2412 case T_CustomScan:
2414 ancestors, es);
2415 break;
2416 default:
2417 break;
2418 }
2419
2420
2423
2424
2425 if (haschildren)
2426 {
2429 }
2430
2431
2433 es->indent = save_indent;
2434
2436 relationship ? NULL : "Plan",
2437 true, es);
2438}
2439
2440
2441
2442
2443static void
2445{
2449 bool useprefix;
2451
2452
2453 if (plan->targetlist == NIL)
2454 return;
2455
2457 return;
2458
2460 return;
2462 return;
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2476 return;
2477
2478
2481 ancestors);
2483
2484
2485 foreach(lc, plan->targetlist)
2486 {
2488
2489 result = lappend(result,
2491 useprefix, false));
2492 }
2493
2494
2496}
2497
2498
2499
2500
2501static void
2505{
2507 char *exprstr;
2508
2509
2511 planstate->plan,
2512 ancestors);
2513
2514
2516
2517
2519}
2520
2521
2522
2523
2524static void
2528{
2530
2531
2532 if (qual == NIL)
2533 return;
2534
2535
2537
2538
2539 show_expression(node, qlabel, planstate, ancestors, useprefix, es);
2540}
2541
2542
2543
2544
2545static void
2549{
2550 bool useprefix;
2551
2553 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2554}
2555
2556
2557
2558
2559static void
2563{
2564 bool useprefix;
2565
2567 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2568}
2569
2570
2571
2572
2573static void
2575{
2577
2579 plan->numCols, 0, plan->sortColIdx,
2580 plan->sortOperators, plan->collations,
2581 plan->nullsFirst,
2582 ancestors, es);
2583}
2584
2585
2586
2587
2588static void
2591{
2593
2595 plan->sort.numCols, plan->nPresortedCols,
2596 plan->sort.sortColIdx,
2597 plan->sort.sortOperators, plan->sort.collations,
2598 plan->sort.nullsFirst,
2599 ancestors, es);
2600}
2601
2602
2603
2604
2605static void
2608{
2610
2612 plan->numCols, 0, plan->sortColIdx,
2613 plan->sortOperators, plan->collations,
2614 plan->nullsFirst,
2615 ancestors, es);
2616}
2617
2618
2619
2620
2621static void
2624{
2626
2627 if (plan->numCols > 0 || plan->groupingSets)
2628 {
2629
2630 ancestors = lcons(plan, ancestors);
2631
2632 if (plan->groupingSets)
2634 else
2636 plan->numCols, 0, plan->grpColIdx,
2637 NULL, NULL, NULL,
2638 ancestors, es);
2639
2641 }
2642}
2643
2644static void
2647{
2649 bool useprefix;
2651
2652
2654 planstate->plan,
2655 ancestors);
2657
2658 ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es);
2659
2661 context, useprefix, ancestors, es);
2662
2663 foreach(lc, agg->chain)
2664 {
2667
2669 context, useprefix, ancestors, es);
2670 }
2671
2673}
2674
2675static void
2677 Agg *aggnode, Sort *sortnode,
2680{
2682 char *exprstr;
2685 AttrNumber *keycols = aggnode->grpColIdx;
2686 const char *keyname;
2687 const char *keysetname;
2688
2690 {
2691 keyname = "Hash Key";
2692 keysetname = "Hash Keys";
2693 }
2694 else
2695 {
2696 keyname = "Group Key";
2697 keysetname = "Group Keys";
2698 }
2699
2701
2702 if (sortnode)
2703 {
2705 sortnode->numCols, 0, sortnode->sortColIdx,
2706 sortnode->sortOperators, sortnode->collations,
2707 sortnode->nullsFirst,
2708 ancestors, es);
2711 }
2712
2714
2715 foreach(lc, gsets)
2716 {
2719
2721 {
2725 keyresno);
2726
2727 if (!target)
2728 elog(ERROR, "no tlist entry for key %d", keyresno);
2729
2731 useprefix, true);
2732
2733 result = lappend(result, exprstr);
2734 }
2735
2738 else
2740 }
2741
2743
2746
2748}
2749
2750
2751
2752
2753static void
2756{
2758
2759
2760 ancestors = lcons(plan, ancestors);
2762 plan->numCols, 0, plan->grpColIdx,
2763 NULL, NULL, NULL,
2764 ancestors, es);
2766}
2767
2768
2769
2770
2771
2772
2773static void
2775 int nkeys, int nPresortedKeys, AttrNumber *keycols,
2776 Oid *sortOperators, Oid *collations, bool *nullsFirst,
2778{
2782 List *resultPresorted = NIL;
2784 bool useprefix;
2785 int keyno;
2786
2787 if (nkeys <= 0)
2788 return;
2789
2791
2792
2795 ancestors);
2797
2798 for (keyno = 0; keyno < nkeys; keyno++)
2799 {
2800
2801 AttrNumber keyresno = keycols[keyno];
2803 keyresno);
2804 char *exprstr;
2805
2806 if (!target)
2807 elog(ERROR, "no tlist entry for key %d", keyresno);
2808
2810 useprefix, true);
2813
2814 if (sortOperators != NULL)
2817 sortOperators[keyno],
2818 collations[keyno],
2819 nullsFirst[keyno]);
2820
2822 if (keyno < nPresortedKeys)
2823 resultPresorted = lappend(resultPresorted, exprstr);
2824 }
2825
2827 if (nPresortedKeys > 0)
2829}
2830
2831
2832
2833
2834
2835static void
2837 Oid sortOperator, Oid collation, bool nullsFirst)
2838{
2840 bool reverse = false;
2842
2845
2846
2847
2848
2849
2850
2851
2852
2854 {
2856
2857 if (collname == NULL)
2858 elog(ERROR, "cache lookup failed for collation %u", collation);
2860 }
2861
2862
2863 if (sortOperator == typentry->gt_opr)
2864 {
2866 reverse = true;
2867 }
2868 else if (sortOperator != typentry->lt_opr)
2869 {
2870 char *opname = get_opname(sortOperator);
2871
2872 if (opname == NULL)
2873 elog(ERROR, "cache lookup failed for operator %u", sortOperator);
2875
2877 }
2878
2879
2880 if (nullsFirst && !reverse)
2881 {
2883 }
2884 else if (!nullsFirst && reverse)
2885 {
2887 }
2888}
2889
2890
2891
2892
2893static void
2895{
2898 bool needspace = false;
2899
2902
2903
2904 ancestors = lcons(wagg, ancestors);
2906 {
2910 ancestors, es);
2911 needspace = true;
2912 }
2914 {
2915 if (needspace)
2920 ancestors, es);
2921 needspace = true;
2922 }
2925 {
2927 bool useprefix;
2928 char *framestr;
2929
2930
2932 (Plan *) wagg,
2933 ancestors);
2936 wagg->startOffset,
2937 wagg->endOffset,
2939 useprefix);
2940 if (needspace)
2943 pfree(framestr);
2944 }
2947 pfree(wbuf.data);
2948}
2949
2950
2951
2952
2953
2954
2955
2956static void
2960{
2963 bool useprefix;
2964
2965
2968 ancestors);
2970
2971 for (int keyno = 0; keyno < nkeys; keyno++)
2972 {
2973
2974 AttrNumber keyresno = keycols[keyno];
2976 keyresno);
2977 char *exprstr;
2978
2979 if (!target)
2980 elog(ERROR, "no tlist entry for key %d", keyresno);
2981
2983 useprefix, true);
2984 if (keyno > 0)
2988
2989
2990
2991
2992
2993
2994 }
2995}
2996
2997
2998
2999
3000static void
3002{
3004
3006 {
3009 }
3010 else
3011 {
3014 "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n",
3015 maxStorageType,
3016 maxSpaceUsedKB);
3017 }
3018}
3019
3020
3021
3022
3023static void
3026{
3028 bool useprefix;
3029 char *method_name;
3031 char *repeatable;
3033
3034
3036 planstate->plan,
3037 ancestors);
3039
3040
3042
3043
3044 foreach(lc, tsc->args)
3045 {
3047
3048 params = lappend(params,
3050 useprefix, false));
3051 }
3054 useprefix, false);
3055 else
3056 repeatable = NULL;
3057
3058
3060 {
3061 bool first = true;
3062
3065 foreach(lc, params)
3066 {
3067 if (!first)
3070 first = false;
3071 }
3073 if (repeatable)
3076 }
3077 else
3078 {
3081 if (repeatable)
3083 }
3084}
3085
3086
3087
3088
3089static void
3091{
3093 return;
3094
3096 {
3099 const char *sortMethod;
3100 const char *spaceType;
3101 int64 spaceUsed;
3102
3106 spaceUsed = stats.spaceUsed;
3107
3109 {
3112 sortMethod, spaceType, spaceUsed);
3113 }
3114 else
3115 {
3119 }
3120 }
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3132 {
3133 int n;
3134
3136 {
3138 const char *sortMethod;
3139 const char *spaceType;
3140 int64 spaceUsed;
3141
3144 continue;
3147 spaceUsed = sinstrument->spaceUsed;
3148
3151
3153 {
3157 sortMethod, spaceType, spaceUsed);
3158 }
3159 else
3160 {
3164 }
3165
3168 }
3169 }
3170}
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180static void
3182 const char *groupLabel, bool indent, ExplainState *es)
3183{
3186
3187
3189 {
3191
3192 if (groupInfo->sortMethods & sortMethod)
3193 {
3195
3196 methodNames = lappend(methodNames, unconstify(char *, methodName));
3197 }
3198 }
3199
3201 {
3202 if (indent)
3206
3209 else
3211 foreach(methodCell, methodNames)
3212 {
3216 }
3217
3219 {
3221 const char *spaceTypeName;
3222
3225 spaceTypeName, avgSpace,
3227 }
3228
3230 {
3232
3233 const char *spaceTypeName;
3234
3237 spaceTypeName, avgSpace,
3239 }
3240 }
3241 else
3242 {
3244
3249
3251
3253 {
3255 const char *spaceTypeName;
3257
3260 appendStringInfo(&memoryName, "Sort Space %s", spaceTypeName);
3262
3266
3268 }
3270 {
3272 const char *spaceTypeName;
3274
3277 appendStringInfo(&diskName, "Sort Space %s", spaceTypeName);
3279
3283
3285 }
3286
3288 }
3289}
3290
3291
3292
3293
3294static void
3297{
3300
3302
3304 return;
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315 if (fullsortGroupInfo->groupCount > 0)
3316 {
3319 if (prefixsortGroupInfo->groupCount > 0)
3320 {
3324 }
3327 }
3328
3330 {
3331 int n;
3332 bool indent_first_line;
3333
3335 {
3338
3339
3340
3341
3342
3343
3345
3346
3347
3348
3349
3350
3351
3352 if (fullsortGroupInfo->groupCount == 0)
3353 continue;
3354
3357
3360 indent_first_line, es);
3362 if (prefixsortGroupInfo->groupCount > 0)
3363 {
3367 }
3370
3373 }
3374 }
3375}
3376
3377
3378
3379
3380static void
3382{
3384
3385
3386
3387
3388
3389
3390
3391
3392
3394 memcpy(&hinstrument, hashstate->hinstrument,
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3407 {
3409 int i;
3410
3412 {
3414
3425 }
3426 }
3427
3428 if (hinstrument.nbatch > 0)
3429 {
3431
3433 {
3439 hinstrument.nbatch, es);
3443 spacePeakKb, es);
3444 }
3447 {
3450 "Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: " UINT64_FORMAT "kB\n",
3455 spacePeakKb);
3456 }
3457 else
3458 {
3461 "Buckets: %d Batches: %d Memory Usage: " UINT64_FORMAT "kB\n",
3463 spacePeakKb);
3464 }
3465 }
3466}
3467
3468
3469
3470
3471
3472static void
3474{
3475 char *maxStorageType;
3476 int64 maxSpaceUsed;
3477
3479
3480
3481
3482
3483
3484 if (!es->analyze || tupstore == NULL)
3485 return;
3486
3489}
3490
3491
3492
3493
3494
3495static void
3497{
3498 char *maxStorageType;
3499 int64 maxSpaceUsed;
3500
3502
3503
3504
3505
3506
3507 if (!es->analyze || tupstore == NULL)
3508 return;
3509
3512}
3513
3514
3515
3516
3517
3518static void
3520{
3521 char *maxStorageType;
3522 int64 maxSpaceUsed;
3523
3525
3526 if (!es->analyze || tupstore == NULL)
3527 return;
3528
3531}
3532
3533
3534
3535
3536
3537static void
3539{
3540 char *maxStorageType;
3541 int64 maxSpaceUsed;
3542
3544
3545 if (!es->analyze || tupstore == NULL)
3546 return;
3547
3550}
3551
3552
3553
3554
3555
3556static void
3558{
3559 char *maxStorageType,
3560 *tempStorageType;
3561 int64 maxSpaceUsed,
3562 tempSpaceUsed;
3563
3565 return;
3566
3567
3568
3569
3570
3571
3573 &tempSpaceUsed);
3575 &maxSpaceUsed);
3576
3577 if (tempSpaceUsed > maxSpaceUsed)
3578 maxStorageType = tempStorageType;
3579
3580 maxSpaceUsed += tempSpaceUsed;
3582}
3583
3584
3585
3586
3587static void
3589{
3596 bool useprefix;
3597 int64 memPeakKb;
3598
3600
3601
3602
3603
3604
3606
3607
3610 ancestors);
3611
3613 {
3615
3617
3619 useprefix, false));
3621 }
3622
3625
3627
3629 {
3631 {
3633 appendStringInfo(es->str, "Estimates: capacity=%u distinct keys=%.0f lookups=%.0f hit percent=%.2f%%\n",
3636 }
3637 else
3638 {
3643 }
3644 }
3645
3647 return;
3648
3650 {
3651
3652
3653
3654
3657 else
3659
3661 {
3667 }
3668 else
3669 {
3677 memPeakKb);
3678 }
3679 }
3680
3682 return;
3683
3684
3686 {
3688
3690
3691
3692
3693
3694
3696 continue;
3697
3700
3701
3702
3703
3704
3705
3706
3708
3710 {
3716 memPeakKb);
3717 }
3718 else
3719 {
3729 es);
3730 }
3731
3734 }
3735}
3736
3737
3738
3739
3740static void
3742{
3745
3748 return;
3749
3751 {
3755
3756
3757
3758
3759
3760
3762 {
3768 }
3769 }
3770 else
3771 {
3772 bool gotone = false;
3773
3775 {
3779 gotone = true;
3780 }
3781
3782
3783
3784
3785
3786
3788 {
3789 if (!gotone)
3791 else
3793
3796 gotone = true;
3797
3798
3800 {
3803 }
3804 }
3805
3806 if (gotone)
3808 }
3809
3810
3812 {
3814 {
3816 uint64 hash_disk_used;
3817 int hash_batches_used;
3818
3820
3822 continue;
3826
3829
3831 {
3833
3835 hash_batches_used, memPeakKb);
3836
3837
3838 if (hash_batches_used > 1)
3840 hash_disk_used);
3842 }
3843 else
3844 {
3846 hash_batches_used, es);
3848 es);
3850 }
3851
3854 }
3855 }
3856}
3857
3858
3859
3860
3861
3862static void
3864{
3867 uint64 nsearches = 0;
3868
3870 return;
3871
3872
3874 {
3875 case T_IndexScan:
3876 {
3878
3881 break;
3882 }
3883 case T_IndexOnlyScan:
3884 {
3886
3889 break;
3890 }
3891 case T_BitmapIndexScan:
3892 {
3894
3897 break;
3898 }
3899 default:
3900 break;
3901 }
3902
3903
3904 if (SharedInfo)
3905 {
3907 {
3909
3910 nsearches += winstrument->nsearches;
3911 }
3912 }
3913
3915}
3916
3917
3918
3919
3920static void
3922{
3924 return;
3925
3927 {
3932 }
3933 else
3934 {
3936 {
3944 }
3945 }
3946
3947
3948 if (planstate->pstate != NULL)
3949 {
3951 {
3953
3955 continue;
3956
3959
3961 {
3969 }
3970 else
3971 {
3976 }
3977
3980 }
3981 }
3982}
3983
3984
3985
3986
3987
3988
3989static void
3992{
3993 double nfiltered;
3994 double nloops;
3995
3997 return;
3998
3999 if (which == 2)
4001 else
4004
4005
4007 {
4008 if (nloops > 0)
4010 else
4012 }
4013}
4014
4015
4016
4017
4018static void
4020{
4022
4023
4025 {
4028 }
4029 else
4030 {
4033 }
4034}
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046static const char *
4048{
4049 const char *result;
4050
4052 result = (*explain_get_index_name_hook) (indexId);
4053 else
4054 result = NULL;
4055 if (result == NULL)
4056 {
4057
4059 if (result == NULL)
4060 elog(ERROR, "cache lookup failed for index %u", indexId);
4061 }
4062 return result;
4063}
4064
4065
4066
4067
4068
4069
4070static bool
4072{
4073 bool has_shared;
4074 bool has_local;
4075 bool has_temp;
4076 bool has_shared_timing;
4077 bool has_local_timing;
4078 bool has_temp_timing;
4079
4080 if (usage == NULL)
4081 return false;
4082
4084 return true;
4085
4086 has_shared = (usage->shared_blks_hit > 0 ||
4087 usage->shared_blks_read > 0 ||
4088 usage->shared_blks_dirtied > 0 ||
4089 usage->shared_blks_written > 0);
4090 has_local = (usage->local_blks_hit > 0 ||
4091 usage->local_blks_read > 0 ||
4092 usage->local_blks_dirtied > 0 ||
4093 usage->local_blks_written > 0);
4094 has_temp = (usage->temp_blks_read > 0 ||
4095 usage->temp_blks_written > 0);
4102
4103 return has_shared || has_local || has_temp || has_shared_timing ||
4104 has_local_timing || has_temp_timing;
4105}
4106
4107
4108
4109
4110static void
4112{
4114 {
4115 bool has_shared = (usage->shared_blks_hit > 0 ||
4116 usage->shared_blks_read > 0 ||
4117 usage->shared_blks_dirtied > 0 ||
4118 usage->shared_blks_written > 0);
4119 bool has_local = (usage->local_blks_hit > 0 ||
4120 usage->local_blks_read > 0 ||
4121 usage->local_blks_dirtied > 0 ||
4122 usage->local_blks_written > 0);
4123 bool has_temp = (usage->temp_blks_read > 0 ||
4124 usage->temp_blks_written > 0);
4131
4132
4133 if (has_shared || has_local || has_temp)
4134 {
4137
4138 if (has_shared)
4139 {
4141 if (usage->shared_blks_hit > 0)
4143 usage->shared_blks_hit);
4144 if (usage->shared_blks_read > 0)
4146 usage->shared_blks_read);
4147 if (usage->shared_blks_dirtied > 0)
4149 usage->shared_blks_dirtied);
4150 if (usage->shared_blks_written > 0)
4152 usage->shared_blks_written);
4153 if (has_local || has_temp)
4155 }
4156 if (has_local)
4157 {
4159 if (usage->local_blks_hit > 0)
4161 usage->local_blks_hit);
4162 if (usage->local_blks_read > 0)
4164 usage->local_blks_read);
4165 if (usage->local_blks_dirtied > 0)
4167 usage->local_blks_dirtied);
4168 if (usage->local_blks_written > 0)
4170 usage->local_blks_written);
4171 if (has_temp)
4173 }
4174 if (has_temp)
4175 {
4177 if (usage->temp_blks_read > 0)
4179 usage->temp_blks_read);
4180 if (usage->temp_blks_written > 0)
4182 usage->temp_blks_written);
4183 }
4185 }
4186
4187
4188 if (has_shared_timing || has_local_timing || has_temp_timing)
4189 {
4192
4193 if (has_shared_timing)
4194 {
4202 if (has_local_timing || has_temp_timing)
4204 }
4205 if (has_local_timing)
4206 {
4214 if (has_temp_timing)
4216 }
4217 if (has_temp_timing)
4218 {
4226 }
4228 }
4229 }
4230 else
4231 {
4233 usage->shared_blks_hit, es);
4235 usage->shared_blks_read, es);
4237 usage->shared_blks_dirtied, es);
4239 usage->shared_blks_written, es);
4241 usage->local_blks_hit, es);
4243 usage->local_blks_read, es);
4245 usage->local_blks_dirtied, es);
4247 usage->local_blks_written, es);
4249 usage->temp_blks_read, es);
4251 usage->temp_blks_written, es);
4253 {
4256 3, es);
4259 3, es);
4262 3, es);
4265 3, es);
4268 3, es);
4271 3, es);
4272 }
4273 }
4274}
4275
4276
4277
4278
4279static void
4281{
4283 {
4284
4285 if ((usage->wal_records > 0) || (usage->wal_fpi > 0) ||
4286 (usage->wal_bytes > 0) || (usage->wal_buffers_full > 0) ||
4287 (usage->wal_fpi_bytes > 0))
4288 {
4291
4292 if (usage->wal_records > 0)
4294 usage->wal_records);
4295 if (usage->wal_fpi > 0)
4297 usage->wal_fpi);
4298 if (usage->wal_bytes > 0)
4300 usage->wal_bytes);
4301 if (usage->wal_fpi_bytes > 0)
4303 usage->wal_fpi_bytes);
4304 if (usage->wal_buffers_full > 0)
4306 usage->wal_buffers_full);
4308 }
4309 }
4310 else
4311 {
4313 usage->wal_records, es);
4315 usage->wal_fpi, es);
4317 usage->wal_bytes, es);
4319 usage->wal_fpi_bytes, es);
4321 usage->wal_buffers_full, es);
4322 }
4323}
4324
4325
4326
4327
4328static void
4330{
4334
4336 {
4340 memUsedkB, memAllocatedkB);
4342 }
4343 else
4344 {
4347 }
4348}
4349
4350
4351
4352
4353
4354static void
4357{
4359
4361 {
4365 }
4366 else
4367 {
4368 const char *scandir;
4369
4370 switch (indexorderdir)
4371 {
4373 scandir = "Backward";
4374 break;
4376 scandir = "Forward";
4377 break;
4378 default:
4379 scandir = "???";
4380 break;
4381 }
4384 }
4385}
4386
4387
4388
4389
4390static void
4392{
4394}
4395
4396
4397
4398
4399
4400
4401
4402
4403static void
4405{
4407}
4408
4409
4410
4411
4412static void
4414{
4415 char *objectname = NULL;
4416 char *namespace = NULL;
4417 const char *objecttag = NULL;
4419 char *refname;
4420
4423 if (refname == NULL)
4424 refname = rte->eref->aliasname;
4425
4427 {
4428 case T_SeqScan:
4429 case T_SampleScan:
4430 case T_IndexScan:
4431 case T_IndexOnlyScan:
4432 case T_BitmapHeapScan:
4433 case T_TidScan:
4434 case T_TidRangeScan:
4435 case T_ForeignScan:
4436 case T_CustomScan:
4437 case T_ModifyTable:
4438
4443 objecttag = "Relation Name";
4444 break;
4445 case T_FunctionScan:
4446 {
4448
4449
4451
4452
4453
4454
4455
4456
4457
4459 {
4461
4463 {
4466
4470 }
4471 }
4472 objecttag = "Function Name";
4473 }
4474 break;
4475 case T_TableFuncScan:
4476 {
4478
4480 switch (tablefunc->functype)
4481 {
4483 objectname = "xmltable";
4484 break;
4486 objectname = "json_table";
4487 break;
4488 default:
4489 elog(ERROR, "invalid TableFunc type %d",
4491 }
4492 objecttag = "Table Function Name";
4493 }
4494 break;
4495 case T_ValuesScan:
4497 break;
4498 case T_CteScan:
4499
4501 Assert(!rte->self_reference);
4502 objectname = rte->ctename;
4503 objecttag = "CTE Name";
4504 break;
4505 case T_NamedTuplestoreScan:
4507 objectname = rte->enrname;
4508 objecttag = "Tuplestore Name";
4509 break;
4510 case T_WorkTableScan:
4511
4513 Assert(rte->self_reference);
4514 objectname = rte->ctename;
4515 objecttag = "CTE Name";
4516 break;
4517 default:
4518 break;
4519 }
4520
4522 {
4524 if (namespace != NULL)
4527 else if (objectname != NULL)
4529 if (objectname == NULL || strcmp(refname, objectname) != 0)
4531 }
4532 else
4533 {
4534 if (objecttag != NULL && objectname != NULL)
4536 if (namespace != NULL)
4539 }
4540}
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550static void
4553{
4555 const char *operation;
4556 const char *foperation;
4557 bool labeltargets;
4558 int j;
4561
4563 {
4565 operation = "Insert";
4566 foperation = "Foreign Insert";
4567 break;
4569 operation = "Update";
4570 foperation = "Foreign Update";
4571 break;
4573 operation = "Delete";
4574 foperation = "Foreign Delete";
4575 break;
4577 operation = "Merge";
4578
4579 foperation = "Foreign Merge";
4580 break;
4581 default:
4582 operation = "???";
4583 foperation = "Foreign ???";
4584 break;
4585 }
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596 labeltargets = (mtstate->mt_nrels > 1 ||
4601
4602 if (labeltargets)
4603 ExplainOpenGroup("Target Tables", "Target Tables", false, es);
4604
4606 {
4609
4610 if (labeltargets)
4611 {
4612
4614
4615
4616
4617
4618
4620 {
4623 fdwroutine ? foperation : operation);
4624 }
4625
4626
4629 es);
4630
4632 {
4635 }
4636 }
4637
4638
4640 fdwroutine != NULL &&
4642 {
4644
4646 resultRelInfo,
4647 fdw_private,
4648 j,
4649 es);
4650 }
4651
4652 if (labeltargets)
4653 {
4654
4657
4658
4660 }
4661 }
4662
4663
4665 {
4667
4668 idxNames = lappend(idxNames, indexname);
4669 }
4670
4672 {
4675 "NOTHING" : "UPDATE",
4676 es);
4677
4678
4679
4680
4681
4682 if (idxNames)
4684
4685
4687 {
4689 &mtstate->ps, ancestors, es);
4691 }
4692
4693
4695 {
4696 double total;
4697 double insert_path;
4698 double other_path;
4699
4701
4702
4703 total = outerPlanState(mtstate)->instrument->ntuples;
4705 insert_path = total - other_path;
4706
4708 insert_path, 0, es);
4710 other_path, 0, es);
4711 }
4712 }
4714 {
4715
4717 {
4718 double total;
4719 double insert_path;
4720 double update_path;
4721 double delete_path;
4722 double skipped_path;
4723
4725
4726
4727 total = outerPlanState(mtstate)->instrument->ntuples;
4731 skipped_path = total - insert_path - update_path - delete_path;
4732 Assert(skipped_path >= 0);
4733
4735 {
4736 if (total > 0)
4737 {
4740 if (insert_path > 0)
4742 if (update_path > 0)
4744 if (delete_path > 0)
4746 if (skipped_path > 0)
4749 }
4750 }
4751 else
4752 {
4757 }
4758 }
4759 }
4760
4761 if (labeltargets)
4763}
4764
4765
4766
4767
4768static void
4770{
4772 int nrels = 0;
4773 int rti = -1;
4774 bool found_non_result = false;
4775 char *replacement_type = "???";
4776
4777
4779 return;
4780
4781
4783
4785 {
4787 replacement_type = "Gating";
4788 break;
4790 replacement_type = "Scan";
4791 break;
4793 replacement_type = "Join";
4794 break;
4796
4797 replacement_type = "Aggregate";
4798 break;
4800 replacement_type = "MinMaxAggregate";
4801 break;
4802 }
4803
4804
4805
4806
4807
4810 {
4812 char *refname;
4813
4814
4815
4816
4817
4818
4819
4820
4822 continue;
4823
4824
4825 ++nrels;
4826
4827
4829 if (refname == NULL)
4830 refname = rte->eref->aliasname;
4831 if (buf.len > 0)
4834
4835
4837 found_non_result = true;
4838 }
4839
4840
4841
4842
4843
4844
4845
4846 if (nrels <= 1 && !found_non_result &&
4848 return;
4849
4850
4851 if (buf.len == 0)
4853 else
4854 {
4855 char *s = psprintf("%s on %s", replacement_type, buf.data);
4856
4858 }
4859}
4860
4861
4862
4863
4864
4865
4866
4867
4868static void
4871{
4872 int j;
4873
4874 for (j = 0; j < nplans; j++)
4876 "Member", NULL, es);
4877}
4878
4879
4880
4881
4882
4883
4884
4885
4886static void
4888{
4891 nchildren - nplans, es);
4892}
4893
4894
4895
4896
4897
4898
4899
4900static void
4903{
4905
4906 foreach(lst, plans)
4907 {
4910 char *cooked_plan_name;
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4923 continue;
4926
4927
4928
4929
4930
4931
4932 ancestors = lcons(sp, ancestors);
4933
4934
4935
4936
4937
4938
4943 else
4945
4947 relationship, cooked_plan_name, es);
4948
4950 }
4951}
4952
4953
4954
4955
4956static void
4958{
4960 const char *label =
4962
4965}
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4980{
4982
4989 return wstate;
4990}
4991
4992
4993
4994
4995static void
4997{
4999
5001 Assert(n >= 0 && n < wstate->num_workers);
5002
5003
5005
5007 {
5008
5011
5012
5013
5014
5015
5016
5018
5019
5020
5021
5022
5025
5027 }
5028 else
5029 {
5030
5032
5033
5035 }
5036
5037
5038
5039
5040
5041
5043 {
5045 {
5048 }
5049
5051 }
5052}
5053
5054
5055
5056
5057static void
5059{
5061
5063 Assert(n >= 0 && n < wstate->num_workers);
5065
5066
5067
5068
5069
5071
5072
5073
5074
5075
5076
5077
5079 {
5082
5084 }
5085
5086
5088}
5089
5090
5091
5092
5093static void
5095{
5097
5100 {
5102 {
5103
5107
5109 }
5110 }
5112
5117}
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
int bms_next_member(const Bitmapset *a, int prevbit)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
#define unconstify(underlying_type, expr)
#define OidIsValid(objectId)
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
int GetIntoRelEFlags(IntoClause *intoClause)
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
char * defGetString(DefElem *def)
DestReceiver * None_Receiver
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
const TupleTableSlotOps TTSOpsVirtual
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 outerPlanState(node)
#define innerPlanState(node)
#define EXEC_FLAG_EXPLAIN_GENERIC
#define do_text_output_oneline(tstate, str_to_emit)
#define EXEC_FLAG_EXPLAIN_ONLY
static void show_modifytable_info(ModifyTableState *mtstate, List *ancestors, ExplainState *es)
#define BYTES_TO_KILOBYTES(b)
static void show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es)
static void show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es)
static void show_group_keys(GroupState *gstate, List *ancestors, ExplainState *es)
static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es)
static void show_window_def(WindowAggState *planstate, List *ancestors, ExplainState *es)
static void show_result_replacement_info(Result *result, ExplainState *es)
static void show_agg_keys(AggState *astate, List *ancestors, ExplainState *es)
static void show_hashagg_info(AggState *aggstate, ExplainState *es)
static void show_scan_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, ExplainState *es)
static const char * explain_get_index_name(Oid indexId)
static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir, ExplainState *es)
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)
ExplainOneQuery_hook_type ExplainOneQuery_hook
static void show_instrumentation_count(const char *qlabel, int which, PlanState *planstate, ExplainState *es)
static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
static void show_incremental_sort_group_info(IncrementalSortGroupInfo *groupInfo, const char *groupLabel, bool indent, ExplainState *es)
static void ExplainMemberNodes(PlanState **planstates, int nplans, List *ancestors, ExplainState *es)
static void show_ctescan_info(CteScanState *ctescanstate, ExplainState *es)
explain_get_index_name_hook_type explain_get_index_name_hook
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)
static void show_recursive_union_info(RecursiveUnionState *rstate, ExplainState *es)
void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest)
static void show_incremental_sort_info(IncrementalSortState *incrsortstate, ExplainState *es)
static void show_tablesample(TableSampleClause *tsc, PlanState *planstate, List *ancestors, ExplainState *es)
static void show_upper_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, ExplainState *es)
static void show_sort_info(SortState *sortstate, ExplainState *es)
static void show_window_keys(StringInfo buf, PlanState *planstate, int nkeys, AttrNumber *keycols, List *ancestors, ExplainState *es)
static void ExplainMissingMembers(int nplans, int nchildren, ExplainState *es)
explain_per_node_hook_type explain_per_node_hook
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
static void ExplainFlushWorkersState(ExplainState *es)
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
static void show_hash_info(HashState *hashstate, ExplainState *es)
static void show_sortorder_options(StringInfo buf, Node *sortexpr, Oid sortOperator, Oid collation, bool nullsFirst)
static void show_table_func_scan_info(TableFuncScanState *tscanstate, ExplainState *es)
static void show_indexsearches_info(PlanState *planstate, ExplainState *es)
static void show_expression(Node *node, const char *qlabel, PlanState *planstate, List *ancestors, bool useprefix, ExplainState *es)
static double elapsed_time(instr_time *starttime)
void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc)
explain_per_plan_hook_type explain_per_plan_hook
static bool plan_is_disabled(Plan *plan)
static void show_sort_group_keys(PlanState *planstate, const char *qlabel, int nkeys, int nPresortedKeys, AttrNumber *keycols, Oid *sortOperators, Oid *collations, bool *nullsFirst, List *ancestors, ExplainState *es)
static void show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
static void show_windowagg_info(WindowAggState *winstate, ExplainState *es)
static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)
static void ExplainSubPlans(List *plans, List *ancestors, const char *relationship, ExplainState *es)
static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es)
static void ExplainScanTarget(Scan *plan, ExplainState *es)
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
static void show_merge_append_keys(MergeAppendState *mstate, List *ancestors, ExplainState *es)
static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
void ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen)
static void ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)
static void show_grouping_sets(PlanState *planstate, Agg *agg, List *ancestors, ExplainState *es)
static void ExplainPrintSettings(ExplainState *es)
static void ExplainCloseWorker(int n, ExplainState *es)
static void ExplainOpenWorker(int n, ExplainState *es)
static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
static void show_wal_usage(ExplainState *es, const WalUsage *usage)
static void show_storage_info(char *maxStorageType, int64 maxSpaceUsed, ExplainState *es)
static void show_grouping_set_keys(PlanState *planstate, Agg *aggnode, Sort *sortnode, List *context, bool useprefix, List *ancestors, ExplainState *es)
static void show_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, bool useprefix, ExplainState *es)
static void show_material_info(MaterialState *mstate, ExplainState *es)
static void show_sort_keys(SortState *sortstate, List *ancestors, ExplainState *es)
static ExplainWorkersState * ExplainCreateWorkersState(int num_workers)
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
void standard_ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)
static void show_incremental_sort_keys(IncrementalSortState *incrsortstate, List *ancestors, ExplainState *es)
static void ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es)
const char *(* explain_get_index_name_hook_type)(Oid indexId)
void(* explain_per_plan_hook_type)(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
void(* explain_per_node_hook_type)(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)
void(* ExplainOneQuery_hook_type)(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
SerializeMetrics GetSerializationMetrics(DestReceiver *dest)
DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)
void ExplainPropertyUInteger(const char *qlabel, const char *unit, uint64 value, ExplainState *es)
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
void ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es)
void ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, bool labeled, int depth, ExplainState *es)
void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
void ExplainSeparatePlans(ExplainState *es)
void ExplainEndOutput(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)
void ExplainBeginOutput(ExplainState *es)
void ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es)
void ExplainRestoreGroup(ExplainState *es, int depth, int *state_save)
void ExplainSaveGroup(ExplainState *es, int depth, int *state_save)
void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
ExplainState * NewExplainState(void)
void ParseExplainOptionList(ExplainState *es, List *options, ParseState *pstate)
@ EXPLAIN_SERIALIZE_BINARY
#define palloc_object(type)
char * GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
struct config_generic ** get_explain_guc_options(int *num)
Assert(PointerIsAligned(start, uint64))
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_ADD(x, y)
#define INSTR_TIME_IS_ZERO(t)
#define INSTR_TIME_GET_DOUBLE(t)
#define INSTR_TIME_SUBTRACT(x, y)
#define INSTR_TIME_GET_MILLISEC(t)
#define INSTR_TIME_SET_ZERO(t)
void InstrEndLoop(Instrumentation *instr)
BufferUsage pgBufferUsage
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
if(TABLE==NULL||TABLE_index==NULL)
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
List * lappend(List *list, void *datum)
List * list_delete_first(List *list)
List * lcons(void *datum, List *list)
char * get_rel_name(Oid relid)
char * get_opname(Oid opno)
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Oid get_rel_namespace(Oid relid)
Oid get_typcollation(Oid typid)
char * get_collation_name(Oid colloid)
char * get_namespace_name_or_temp(Oid nspid)
char * get_constraint_name(Oid conoid)
char * get_func_name(Oid funcid)
Oid get_func_namespace(Oid funcid)
Expr * make_orclause(List *orclauses)
Expr * make_ands_explicit(List *andclauses)
Expr * make_andclause(List *andclauses)
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
Oid exprType(const Node *expr)
#define planstate_tree_walker(ps, w, c)
#define DO_AGGSPLIT_SKIPFINAL(as)
#define IsA(nodeptr, _type_)
#define DO_AGGSPLIT_COMBINE(as)
#define castNode(_type_, nodeptr)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define CURSOR_OPT_PARALLEL_OK
#define FRAMEOPTION_NONDEFAULT
post_parse_analyze_hook_type post_parse_analyze_hook
#define rt_fetch(rangetable_index, rangetable)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
#define foreach_current_index(var_or_cell)
static void * list_nth(const List *list, int n)
static ListCell * lnext(const List *l, const ListCell *c)
static char buf[DEFAULT_XLOG_SEG_SIZE]
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
void FreeQueryDesc(QueryDesc *qdesc)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
char * psprintf(const char *fmt,...)
@ COMPUTE_QUERY_ID_REGRESS
static bool IsQueryIdEnabled(void)
JumbleState * JumbleQuery(Query *query)
static const struct fns functions
#define RelationGetRelationName(relation)
List * QueryRewrite(Query *parsetree)
List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
List * set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
const char * quote_identifier(const char *ident)
List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
char * get_window_frame_options_for_explain(int frameOptions, Node *startOffset, Node *endOffset, List *dpcontext, bool forceprefix)
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
#define ScanDirectionIsBackward(direction)
@ NoMovementScanDirection
void UpdateActiveSnapshotCommandId(void)
void PopActiveSnapshot(void)
void PushCopiedSnapshot(Snapshot snapshot)
Snapshot GetActiveSnapshot(void)
void resetStringInfo(StringInfo str)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoSpaces(StringInfo str, int count)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
int hash_planned_partitions
SharedAggInfo * shared_info
ParallelBitmapHeapState * pstate
BitmapHeapScanInstrumentation stats
SharedBitmapHeapInstrumentation * sinstrument
SharedIndexScanInstrumentation * biss_SharedInfo
IndexScanInstrumentation biss_Instrument
Tuplestorestate * cte_table
struct CteScanState * leader
void(* ExplainCustomScan)(CustomScanState *node, List *ancestors, ExplainState *es)
const struct CustomExecMethods * methods
List * es_tuple_routing_result_relations
struct JitContext * es_jit
struct JitInstrumentation * es_jit_worker_instr
Bitmapset * es_unpruned_relids
List * es_trig_target_relations
List * es_opened_result_relations
Bitmapset * printed_subplans
ExplainWorkersState * workers_state
ExplainSerializeOption serialize
ExplainForeignScan_function ExplainForeignScan
ExplainForeignModify_function ExplainForeignModify
ExplainDirectModify_function ExplainDirectModify
struct FdwRoutine * fdwroutine
SharedHashInfo * shared_info
HashInstrumentation * hinstrument
int64 totalMemorySpaceUsed
IncrementalSortGroupInfo prefixsortGroupInfo
IncrementalSortGroupInfo fullsortGroupInfo
SharedIncrementalSortInfo * shared_info
IncrementalSortInfo incsort_info
SharedIndexScanInstrumentation * ioss_SharedInfo
IndexScanInstrumentation ioss_Instrument
ScanDirection indexorderdir
IndexScanInstrumentation iss_Instrument
SharedIndexScanInstrumentation * iss_SharedInfo
ScanDirection indexorderdir
instr_time generation_counter
instr_time optimization_counter
instr_time deform_counter
instr_time emission_counter
instr_time inlining_counter
Tuplestorestate * tuplestorestate
SharedMemoizeInfo * shared_info
MemoizeInstrumentation stats
Cardinality est_unique_keys
ResultRelInfo * resultRelInfo
OnConflictAction onConflictAction
QueryEnvironment * p_queryEnv
const char * p_sourcetext
struct SharedJitInstrumentation * worker_jit_instrument
Instrumentation * instrument
WorkerInstrumentation * worker_instrument
PlannedStmt * plannedstmt
Tuplestorestate * working_table
Tuplestorestate * intermediate_table
Instrumentation * ri_TrigInstrument
TriggerDesc * ri_TrigDesc
struct FdwRoutine * ri_FdwRoutine
bool ri_usesFdwDirectModify
SharedSortInfo * shared_info
Tuplestorestate * tupstore
TuplesortMethod sortMethod
TuplesortSpaceType spaceType
Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER]
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void tuplesort_get_stats(Tuplesortstate *state, TuplesortInstrumentation *stats)
const char * tuplesort_space_type_name(TuplesortSpaceType t)
const char * tuplesort_method_name(TuplesortMethod m)
#define NUM_TUPLESORTMETHODS
@ SORT_TYPE_STILL_IN_PROGRESS
void tuplestore_get_stats(Tuplestorestate *state, char **max_storage_type, int64 *max_space)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
static void usage(const char *progname)
Datum bit(PG_FUNCTION_ARGS)
void CommandCounterIncrement(void)