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);
168
169
170
171
172
173
174
175void
178{
183 List *rewritten;
184
185
187
188
192
194 (*post_parse_analyze_hook) (pstate, query, jstate);
195
196
197
198
199
200
201
203
204
206
207 if (rewritten == NIL)
208 {
209
210
211
212
215 }
216 else
217 {
219
220
221 foreach(l, rewritten)
222 {
225 pstate, params);
226
227
228 if (lnext(rewritten, l) != NULL)
230 }
231 }
232
233
236
237
242 else
245
247}
248
249
250
251
252
255{
258 Oid result_type = TEXTOID;
259
260
261 foreach(lc, stmt->options)
262 {
264
265 if (strcmp(opt->defname, "format") == 0)
266 {
268
269 if (strcmp(p, "xml") == 0)
270 result_type = XMLOID;
271 else if (strcmp(p, "json") == 0)
272 result_type = JSONOID;
273 else
274 result_type = TEXTOID;
275
276 }
277 }
278
279
282 result_type, -1, 0);
283 return tupdesc;
284}
285
286
287
288
289
290
291
292static void
296{
297
299 {
301 return;
302 }
303
304
306 (*ExplainOneQuery_hook) (query, cursorOptions, into, es,
308 else
311}
312
313
314
315
316
317void
322{
325 planduration;
327 bufusage;
331
333 {
334
335
336
337
338
339
340
341
343 "explain analyze planner context",
346 }
347
351
352
354
357
359 {
362 }
363
364
366 {
367 memset(&bufusage, 0, sizeof(BufferUsage));
369 }
370
371
373 queryEnv,
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
502{
506 double totaltime = 0;
507 int eflags;
508 int instrument_option = 0;
510
512
517
520 if (es->wal)
522
523
524
525
526
527
529
530
531
532
533
536
537
538
539
540
541
542
543
544
545 if (into)
549 else
551
552
553 queryDesc = CreateQueryDesc(plannedstmt, cplan, queryString,
555 dest, params, queryEnv, instrument_option);
556
557
559 eflags = 0;
560 else
564 if (into)
566
567
568 if (queryDesc->cplan)
569 {
572 }
573 else
574 {
576 elog(ERROR, "ExecutorStart() failed unexpectedly");
577 }
578
579
581 {
583
584
587 else
589
590
592
593
595
596
598 }
599
600
603
604
606
608
609
611
612
614 {
616
618 {
622 }
623
624 if (bufusage)
626
627 if (mem_counters)
629
632
634 }
635
636 if (es->summary && planduration)
637 {
639
641 }
642
643
646
647
648
649
650
651
652
655
656
659
660
662 (*explain_per_plan_hook) (plannedstmt, into, es, queryString,
663 params, queryEnv);
664
665
666
667
668
670
672
674
676
677
680
682
683
684
685
686
687
688
691 es);
692
694}
695
696
697
698
699
700static void
702{
703 int num;
705
706
708 return;
709
710
712
714 {
716
717 for (int i = 0; i < num; i++)
718 {
719 char *setting;
721
723
725 }
726
728 }
729 else
730 {
732
733
734 if (num <= 0)
735 return;
736
738
739 for (int i = 0; i < num; i++)
740 {
741 char *setting;
743
744 if (i > 0)
746
748
749 if (setting)
751 else
753 }
754
756 }
757}
758
759
760
761
762
763
764
765
766
767
768
769
770void
772{
776
777
787 foreach(lc, es->rtable)
788 {
790
792 {
794 break;
795 }
796 }
797
798
799
800
801
802
803
804
805
806
809 {
812 }
814
815
816
817
818
820
821
822
823
824
825
828 {
829
830
831
832
835 }
836}
837
838
839
840
841
842
843
844
845
846
847void
849{
851 bool show_relname;
852 List *resultrels;
853 List *routerels;
854 List *targrels;
856
860
862
863 show_relname = (list_length(resultrels) > 1 ||
864 routerels != NIL || targrels != NIL);
865 foreach(l, resultrels)
866 {
869 }
870
871 foreach(l, routerels)
872 {
875 }
876
877 foreach(l, targrels)
878 {
881 }
882
884}
885
886
887
888
889
890void
892{
894
896 return;
897
898
899
900
901
904
905
908
910}
911
912
913
914
915
916static void
918{
920
921
923 return;
924
925
927
932
934
935
937 {
941
943
946 "Inlining", jit_flags & PGJIT_INLINE ? "true" : "false",
947 "Optimization", jit_flags & PGJIT_OPT3 ? "true" : "false",
948 "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",
949 "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");
950
952 {
955 "Timing: %s %.3f ms (%s %.3f ms), %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",
962 }
963
965 }
966 else
967 {
969
976
978 {
980
984 3, es);
987 3, es);
989
992 3, es);
995 3, es);
998 3, es);
1001 3, es);
1002
1004 }
1005 }
1006
1008}
1009
1010
1011
1012
1013
1014static void
1016{
1018
1019
1022 else
1023 {
1026 }
1027
1028 ExplainOpenGroup("Serialization", "Serialization", true, es);
1029
1031 {
1038 else
1042
1044 {
1048 }
1049 }
1050 else
1051 {
1055 3, es);
1061 }
1062
1064}
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074void
1076{
1079}
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089void
1091{
1092 char *str;
1093
1094
1095 if (params == NULL || params->numParams <= 0 || maxlen == 0)
1096 return;
1097
1099 if (str && str[0] != '\0')
1101}
1102
1103
1104
1105
1106
1107static void
1109{
1110 int nt;
1111
1113 return;
1115 {
1119 char *conname = NULL;
1120
1121
1123
1124
1125
1126
1127
1128 if (instr->ntuples == 0)
1129 continue;
1130
1132
1136
1137
1138
1139
1140
1141
1143 {
1144 if (es->verbose || conname == NULL)
1146 else
1148 if (conname)
1150 if (show_relname)
1155 else
1157 }
1158 else
1159 {
1161 if (conname)
1166 es);
1168 }
1169
1170 if (conname)
1172
1174 }
1175}
1176
1177
1178static double
1180{
1182
1186}
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197static bool
1199{
1201
1203 {
1204 case T_SeqScan:
1205 case T_SampleScan:
1206 case T_IndexScan:
1207 case T_IndexOnlyScan:
1208 case T_BitmapHeapScan:
1209 case T_TidScan:
1210 case T_TidRangeScan:
1211 case T_SubqueryScan:
1212 case T_FunctionScan:
1213 case T_TableFuncScan:
1214 case T_ValuesScan:
1215 case T_CteScan:
1216 case T_NamedTuplestoreScan:
1217 case T_WorkTableScan:
1219 ((Scan *) plan)->scanrelid);
1220 break;
1221 case T_ForeignScan:
1224 break;
1225 case T_CustomScan:
1228 break;
1229 case T_ModifyTable:
1235 break;
1236 case T_Append:
1239 break;
1240 case T_MergeAppend:
1243 break;
1244 default:
1245 break;
1246 }
1247
1249}
1250
1251
1252
1253
1254
1255
1256
1257static bool
1259{
1260 int child_disabled_nodes;
1261
1262
1263 if (plan->disabled_nodes == 0)
1264 return false;
1265
1266 child_disabled_nodes = 0;
1267
1268
1269
1270
1271
1273 {
1276
1277
1278
1279
1280
1281
1283 {
1285
1287 }
1288 }
1290 {
1293
1294
1295
1296
1297
1298
1300 {
1302
1304 }
1305 }
1307 child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes;
1309 {
1312
1314 {
1316
1318 }
1319 }
1320 else
1321 {
1322
1323
1324
1326 child_disabled_nodes += outerPlan(plan)->disabled_nodes;
1328 child_disabled_nodes += innerPlan(plan)->disabled_nodes;
1329 }
1330
1331
1332
1333
1334
1335 if (plan->disabled_nodes > child_disabled_nodes)
1336 return true;
1337
1338 return false;
1339}
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362static void
1364 const char *relationship, const char *plan_name,
1366{
1368 const char *pname;
1369 const char *sname;
1370 const char *strategy = NULL;
1371 const char *partialmode = NULL;
1372 const char *operation = NULL;
1373 const char *custom_name = NULL;
1375 int save_indent = es->indent;
1376 bool haschildren;
1377 bool isdisabled;
1378
1379
1380
1381
1382
1385 else
1387
1388
1390 {
1391 case T_Result:
1392 pname = sname = "Result";
1393 break;
1394 case T_ProjectSet:
1395 pname = sname = "ProjectSet";
1396 break;
1397 case T_ModifyTable:
1398 sname = "ModifyTable";
1400 {
1402 pname = operation = "Insert";
1403 break;
1405 pname = operation = "Update";
1406 break;
1408 pname = operation = "Delete";
1409 break;
1411 pname = operation = "Merge";
1412 break;
1413 default:
1414 pname = "???";
1415 break;
1416 }
1417 break;
1418 case T_Append:
1419 pname = sname = "Append";
1420 break;
1421 case T_MergeAppend:
1422 pname = sname = "Merge Append";
1423 break;
1424 case T_RecursiveUnion:
1425 pname = sname = "Recursive Union";
1426 break;
1427 case T_BitmapAnd:
1428 pname = sname = "BitmapAnd";
1429 break;
1430 case T_BitmapOr:
1431 pname = sname = "BitmapOr";
1432 break;
1433 case T_NestLoop:
1434 pname = sname = "Nested Loop";
1435 break;
1436 case T_MergeJoin:
1437 pname = "Merge";
1438 sname = "Merge Join";
1439 break;
1440 case T_HashJoin:
1441 pname = "Hash";
1442 sname = "Hash Join";
1443 break;
1444 case T_SeqScan:
1445 pname = sname = "Seq Scan";
1446 break;
1447 case T_SampleScan:
1448 pname = sname = "Sample Scan";
1449 break;
1450 case T_Gather:
1451 pname = sname = "Gather";
1452 break;
1453 case T_GatherMerge:
1454 pname = sname = "Gather Merge";
1455 break;
1456 case T_IndexScan:
1457 pname = sname = "Index Scan";
1458 break;
1459 case T_IndexOnlyScan:
1460 pname = sname = "Index Only Scan";
1461 break;
1462 case T_BitmapIndexScan:
1463 pname = sname = "Bitmap Index Scan";
1464 break;
1465 case T_BitmapHeapScan:
1466 pname = sname = "Bitmap Heap Scan";
1467 break;
1468 case T_TidScan:
1469 pname = sname = "Tid Scan";
1470 break;
1471 case T_TidRangeScan:
1472 pname = sname = "Tid Range Scan";
1473 break;
1474 case T_SubqueryScan:
1475 pname = sname = "Subquery Scan";
1476 break;
1477 case T_FunctionScan:
1478 pname = sname = "Function Scan";
1479 break;
1480 case T_TableFuncScan:
1481 pname = sname = "Table Function Scan";
1482 break;
1483 case T_ValuesScan:
1484 pname = sname = "Values Scan";
1485 break;
1486 case T_CteScan:
1487 pname = sname = "CTE Scan";
1488 break;
1489 case T_NamedTuplestoreScan:
1490 pname = sname = "Named Tuplestore Scan";
1491 break;
1492 case T_WorkTableScan:
1493 pname = sname = "WorkTable Scan";
1494 break;
1495 case T_ForeignScan:
1496 sname = "Foreign Scan";
1498 {
1500 pname = "Foreign Scan";
1501 operation = "Select";
1502 break;
1504 pname = "Foreign Insert";
1505 operation = "Insert";
1506 break;
1508 pname = "Foreign Update";
1509 operation = "Update";
1510 break;
1512 pname = "Foreign Delete";
1513 operation = "Delete";
1514 break;
1515 default:
1516 pname = "???";
1517 break;
1518 }
1519 break;
1520 case T_CustomScan:
1521 sname = "Custom Scan";
1522 custom_name = ((CustomScan *) plan)->methods->CustomName;
1523 if (custom_name)
1524 pname = psprintf("Custom Scan (%s)", custom_name);
1525 else
1526 pname = sname;
1527 break;
1528 case T_Material:
1529 pname = sname = "Materialize";
1530 break;
1531 case T_Memoize:
1532 pname = sname = "Memoize";
1533 break;
1534 case T_Sort:
1535 pname = sname = "Sort";
1536 break;
1537 case T_IncrementalSort:
1538 pname = sname = "Incremental Sort";
1539 break;
1540 case T_Group:
1541 pname = sname = "Group";
1542 break;
1543 case T_Agg:
1544 {
1546
1547 sname = "Aggregate";
1549 {
1551 pname = "Aggregate";
1552 strategy = "Plain";
1553 break;
1555 pname = "GroupAggregate";
1556 strategy = "Sorted";
1557 break;
1559 pname = "HashAggregate";
1560 strategy = "Hashed";
1561 break;
1563 pname = "MixedAggregate";
1564 strategy = "Mixed";
1565 break;
1566 default:
1567 pname = "Aggregate ???";
1568 strategy = "???";
1569 break;
1570 }
1571
1573 {
1574 partialmode = "Partial";
1575 pname = psprintf("%s %s", partialmode, pname);
1576 }
1578 {
1579 partialmode = "Finalize";
1580 pname = psprintf("%s %s", partialmode, pname);
1581 }
1582 else
1583 partialmode = "Simple";
1584 }
1585 break;
1586 case T_WindowAgg:
1587 pname = sname = "WindowAgg";
1588 break;
1589 case T_Unique:
1590 pname = sname = "Unique";
1591 break;
1592 case T_SetOp:
1593 sname = "SetOp";
1594 switch (((SetOp *) plan)->strategy)
1595 {
1597 pname = "SetOp";
1598 strategy = "Sorted";
1599 break;
1601 pname = "HashSetOp";
1602 strategy = "Hashed";
1603 break;
1604 default:
1605 pname = "SetOp ???";
1606 strategy = "???";
1607 break;
1608 }
1609 break;
1610 case T_LockRows:
1611 pname = sname = "LockRows";
1612 break;
1613 case T_Limit:
1614 pname = sname = "Limit";
1615 break;
1616 case T_Hash:
1617 pname = sname = "Hash";
1618 break;
1619 default:
1620 pname = sname = "???";
1621 break;
1622 }
1623
1625 relationship ? NULL : "Plan",
1626 true, es);
1627
1629 {
1630 if (plan_name)
1631 {
1635 }
1637 {
1641 }
1642 if (plan->parallel_aware)
1644 if (plan->async_capable)
1648 }
1649 else
1650 {
1652 if (strategy)
1654 if (partialmode)
1656 if (operation)
1658 if (relationship)
1660 if (plan_name)
1662 if (custom_name)
1666 }
1667
1669 {
1670 case T_SeqScan:
1671 case T_SampleScan:
1672 case T_BitmapHeapScan:
1673 case T_TidScan:
1674 case T_TidRangeScan:
1675 case T_SubqueryScan:
1676 case T_FunctionScan:
1677 case T_TableFuncScan:
1678 case T_ValuesScan:
1679 case T_CteScan:
1680 case T_WorkTableScan:
1682 break;
1683 case T_ForeignScan:
1684 case T_CustomScan:
1685 if (((Scan *) plan)->scanrelid > 0)
1687 break;
1688 case T_IndexScan:
1689 {
1691
1694 es);
1696 }
1697 break;
1698 case T_IndexOnlyScan:
1699 {
1701
1704 es);
1706 }
1707 break;
1708 case T_BitmapIndexScan:
1709 {
1711 const char *indexname =
1713
1717 else
1719 }
1720 break;
1721 case T_ModifyTable:
1723 break;
1724 case T_NestLoop:
1725 case T_MergeJoin:
1726 case T_HashJoin:
1727 {
1728 const char *jointype;
1729
1730 switch (((Join *) plan)->jointype)
1731 {
1733 jointype = "Inner";
1734 break;
1736 jointype = "Left";
1737 break;
1739 jointype = "Full";
1740 break;
1742 jointype = "Right";
1743 break;
1745 jointype = "Semi";
1746 break;
1748 jointype = "Anti";
1749 break;
1751 jointype = "Right Semi";
1752 break;
1754 jointype = "Right Anti";
1755 break;
1756 default:
1757 jointype = "???";
1758 break;
1759 }
1761 {
1762
1763
1764
1765
1770 }
1771 else
1773 }
1774 break;
1775 case T_SetOp:
1776 {
1777 const char *setopcmd;
1778
1780 {
1782 setopcmd = "Intersect";
1783 break;
1785 setopcmd = "Intersect All";
1786 break;
1788 setopcmd = "Except";
1789 break;
1791 setopcmd = "Except All";
1792 break;
1793 default:
1794 setopcmd = "???";
1795 break;
1796 }
1799 else
1801 }
1802 break;
1803 default:
1804 break;
1805 }
1806
1808 {
1810 {
1812 plan->startup_cost, plan->total_cost,
1813 plan->plan_rows, plan->plan_width);
1814 }
1815 else
1816 {
1818 2, es);
1820 2, es);
1822 0, es);
1824 es);
1825 }
1826 }
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1840
1843 {
1845 double startup_ms = 1000.0 * planstate->instrument->startup / nloops;
1846 double total_ms = 1000.0 * planstate->instrument->total / nloops;
1848
1850 {
1852
1855
1857 }
1858 else
1859 {
1861 {
1863 3, es);
1865 3, es);
1866 }
1869 }
1870 }
1872 {
1875 else
1876 {
1878 {
1881 }
1884 }
1885 }
1886
1887
1890
1891
1895
1896
1898 {
1900
1901 for (int n = 0; n < w->num_workers; n++)
1902 {
1904 double nloops = instrument->nloops;
1905 double startup_ms;
1906 double total_ms;
1907 double rows;
1908
1909 if (nloops <= 0)
1910 continue;
1911 startup_ms = 1000.0 * instrument->startup / nloops;
1912 total_ms = 1000.0 * instrument->total / nloops;
1913 rows = instrument->ntuples / nloops;
1914
1916
1918 {
1923
1925 }
1926 else
1927 {
1929 {
1931 startup_ms, 3, es);
1933 total_ms, 3, es);
1934 }
1935
1938 }
1939
1941 }
1942 }
1943
1944
1947
1948
1950 {
1951 case T_NestLoop:
1952 case T_MergeJoin:
1953 case T_HashJoin:
1954
1958 ((Join *) plan)->inner_unique,
1959 es);
1960 break;
1961 default:
1962 break;
1963 }
1964
1965
1967 {
1968 case T_IndexScan:
1970 "Index Cond", planstate, ancestors, es);
1973 planstate, es);
1975 "Order By", planstate, ancestors, es);
1977 if (plan->qual)
1979 planstate, es);
1981 break;
1982 case T_IndexOnlyScan:
1984 "Index Cond", planstate, ancestors, es);
1987 planstate, es);
1989 "Order By", planstate, ancestors, es);
1991 if (plan->qual)
1993 planstate, es);
1998 break;
1999 case T_BitmapIndexScan:
2001 "Index Cond", planstate, ancestors, es);
2003 break;
2004 case T_BitmapHeapScan:
2006 "Recheck Cond", planstate, ancestors, es);
2009 planstate, es);
2011 if (plan->qual)
2013 planstate, es);
2015 break;
2016 case T_SampleScan:
2018 planstate, ancestors, es);
2019
2020
2021 case T_SeqScan:
2022 case T_ValuesScan:
2023 case T_CteScan:
2024 case T_NamedTuplestoreScan:
2025 case T_WorkTableScan:
2026 case T_SubqueryScan:
2028 if (plan->qual)
2030 planstate, es);
2033 break;
2034 case T_Gather:
2035 {
2037
2039 if (plan->qual)
2041 planstate, es);
2044
2046 {
2047 int nworkers;
2048
2049 nworkers = ((GatherState *) planstate)->nworkers_launched;
2051 nworkers, es);
2052 }
2053
2056 }
2057 break;
2058 case T_GatherMerge:
2059 {
2061
2063 if (plan->qual)
2065 planstate, es);
2068
2070 {
2071 int nworkers;
2072
2073 nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
2075 nworkers, es);
2076 }
2077 }
2078 break;
2079 case T_FunctionScan:
2081 {
2084
2086 {
2088
2090 }
2091
2093 "Function Call", planstate, ancestors,
2095 }
2097 if (plan->qual)
2099 planstate, es);
2100 break;
2101 case T_TableFuncScan:
2103 {
2105
2107 "Table Function Call", planstate, ancestors,
2109 }
2111 if (plan->qual)
2113 planstate, es);
2115 planstate), es);
2116 break;
2117 case T_TidScan:
2118 {
2119
2120
2121
2122
2124
2127 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2129 if (plan->qual)
2131 planstate, es);
2132 }
2133 break;
2134 case T_TidRangeScan:
2135 {
2136
2137
2138
2139
2141
2144 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2146 if (plan->qual)
2148 planstate, es);
2149 }
2150 break;
2151 case T_ForeignScan:
2153 if (plan->qual)
2155 planstate, es);
2157 break;
2158 case T_CustomScan:
2159 {
2161
2163 if (plan->qual)
2165 planstate, es);
2168 }
2169 break;
2170 case T_NestLoop:
2172 "Join Filter", planstate, ancestors, es);
2175 planstate, es);
2177 if (plan->qual)
2179 planstate, es);
2180 break;
2181 case T_MergeJoin:
2183 "Merge Cond", planstate, ancestors, es);
2185 "Join Filter", planstate, ancestors, es);
2188 planstate, es);
2190 if (plan->qual)
2192 planstate, es);
2193 break;
2194 case T_HashJoin:
2196 "Hash Cond", planstate, ancestors, es);
2198 "Join Filter", planstate, ancestors, es);
2201 planstate, es);
2203 if (plan->qual)
2205 planstate, es);
2206 break;
2207 case T_Agg:
2211 if (plan->qual)
2213 planstate, es);
2214 break;
2215 case T_WindowAgg:
2218 "Run Condition", planstate, ancestors, es);
2220 if (plan->qual)
2222 planstate, es);
2224 break;
2225 case T_Group:
2228 if (plan->qual)
2230 planstate, es);
2231 break;
2232 case T_Sort:
2235 break;
2236 case T_IncrementalSort:
2238 ancestors, es);
2240 es);
2241 break;
2242 case T_MergeAppend:
2244 ancestors, es);
2245 break;
2246 case T_Result:
2248 "One-Time Filter", planstate, ancestors, es);
2250 if (plan->qual)
2252 planstate, es);
2253 break;
2254 case T_ModifyTable:
2256 es);
2257 break;
2258 case T_Hash:
2260 break;
2261 case T_Material:
2263 break;
2264 case T_Memoize:
2266 es);
2267 break;
2268 case T_RecursiveUnion:
2270 planstate), es);
2271 break;
2272 default:
2273 break;
2274 }
2275
2276
2277
2278
2279
2281 {
2283
2284 if (w)
2285 {
2286 for (int n = 0; n < w->num_workers; n++)
2287 {
2292 }
2293 }
2294 }
2295
2296
2301
2302
2304 {
2306
2307 for (int n = 0; n < w->num_workers; n++)
2308 {
2310 double nloops = instrument->nloops;
2311
2312 if (nloops <= 0)
2313 continue;
2314
2318 if (es->wal)
2321 }
2322 }
2323
2324
2328
2329
2331 (*explain_per_node_hook) (planstate, ancestors, relationship,
2332 plan_name, es);
2333
2334
2335
2336
2337
2338
2339
2340
2341
2343 {
2344 case T_Append:
2347 es);
2348 break;
2349 case T_MergeAppend:
2352 es);
2353 break;
2354 default:
2355 break;
2356 }
2357
2358
2359 haschildren = planstate->initPlan ||
2370 if (haschildren)
2371 {
2373
2374 ancestors = lcons(plan, ancestors);
2375 }
2376
2377
2380
2381
2384 "Outer", NULL, es);
2385
2386
2389 "Inner", NULL, es);
2390
2391
2393 {
2394 case T_Append:
2397 ancestors, es);
2398 break;
2399 case T_MergeAppend:
2402 ancestors, es);
2403 break;
2404 case T_BitmapAnd:
2407 ancestors, es);
2408 break;
2409 case T_BitmapOr:
2412 ancestors, es);
2413 break;
2414 case T_SubqueryScan:
2416 "Subquery", NULL, es);
2417 break;
2418 case T_CustomScan:
2420 ancestors, es);
2421 break;
2422 default:
2423 break;
2424 }
2425
2426
2429
2430
2431 if (haschildren)
2432 {
2435 }
2436
2437
2439 es->indent = save_indent;
2440
2442 relationship ? NULL : "Plan",
2443 true, es);
2444}
2445
2446
2447
2448
2449static void
2451{
2455 bool useprefix;
2457
2458
2459 if (plan->targetlist == NIL)
2460 return;
2461
2463 return;
2464
2466 return;
2468 return;
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2482 return;
2483
2484
2487 ancestors);
2489
2490
2491 foreach(lc, plan->targetlist)
2492 {
2494
2495 result = lappend(result,
2497 useprefix, false));
2498 }
2499
2500
2502}
2503
2504
2505
2506
2507static void
2511{
2513 char *exprstr;
2514
2515
2517 planstate->plan,
2518 ancestors);
2519
2520
2522
2523
2525}
2526
2527
2528
2529
2530static void
2534{
2536
2537
2538 if (qual == NIL)
2539 return;
2540
2541
2543
2544
2545 show_expression(node, qlabel, planstate, ancestors, useprefix, es);
2546}
2547
2548
2549
2550
2551static void
2555{
2556 bool useprefix;
2557
2559 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2560}
2561
2562
2563
2564
2565static void
2569{
2570 bool useprefix;
2571
2573 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2574}
2575
2576
2577
2578
2579static void
2581{
2583
2585 plan->numCols, 0, plan->sortColIdx,
2586 plan->sortOperators, plan->collations,
2587 plan->nullsFirst,
2588 ancestors, es);
2589}
2590
2591
2592
2593
2594static void
2597{
2599
2601 plan->sort.numCols, plan->nPresortedCols,
2602 plan->sort.sortColIdx,
2603 plan->sort.sortOperators, plan->sort.collations,
2604 plan->sort.nullsFirst,
2605 ancestors, es);
2606}
2607
2608
2609
2610
2611static void
2614{
2616
2618 plan->numCols, 0, plan->sortColIdx,
2619 plan->sortOperators, plan->collations,
2620 plan->nullsFirst,
2621 ancestors, es);
2622}
2623
2624
2625
2626
2627static void
2630{
2632
2633 if (plan->numCols > 0 || plan->groupingSets)
2634 {
2635
2636 ancestors = lcons(plan, ancestors);
2637
2638 if (plan->groupingSets)
2640 else
2642 plan->numCols, 0, plan->grpColIdx,
2643 NULL, NULL, NULL,
2644 ancestors, es);
2645
2647 }
2648}
2649
2650static void
2653{
2655 bool useprefix;
2657
2658
2660 planstate->plan,
2661 ancestors);
2663
2664 ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es);
2665
2667 context, useprefix, ancestors, es);
2668
2669 foreach(lc, agg->chain)
2670 {
2673
2675 context, useprefix, ancestors, es);
2676 }
2677
2679}
2680
2681static void
2683 Agg *aggnode, Sort *sortnode,
2686{
2688 char *exprstr;
2691 AttrNumber *keycols = aggnode->grpColIdx;
2692 const char *keyname;
2693 const char *keysetname;
2694
2696 {
2697 keyname = "Hash Key";
2698 keysetname = "Hash Keys";
2699 }
2700 else
2701 {
2702 keyname = "Group Key";
2703 keysetname = "Group Keys";
2704 }
2705
2707
2708 if (sortnode)
2709 {
2711 sortnode->numCols, 0, sortnode->sortColIdx,
2712 sortnode->sortOperators, sortnode->collations,
2713 sortnode->nullsFirst,
2714 ancestors, es);
2717 }
2718
2720
2721 foreach(lc, gsets)
2722 {
2725
2727 {
2731 keyresno);
2732
2733 if (!target)
2734 elog(ERROR, "no tlist entry for key %d", keyresno);
2735
2737 useprefix, true);
2738
2739 result = lappend(result, exprstr);
2740 }
2741
2744 else
2746 }
2747
2749
2752
2754}
2755
2756
2757
2758
2759static void
2762{
2764
2765
2766 ancestors = lcons(plan, ancestors);
2768 plan->numCols, 0, plan->grpColIdx,
2769 NULL, NULL, NULL,
2770 ancestors, es);
2772}
2773
2774
2775
2776
2777
2778
2779static void
2781 int nkeys, int nPresortedKeys, AttrNumber *keycols,
2782 Oid *sortOperators, Oid *collations, bool *nullsFirst,
2784{
2788 List *resultPresorted = NIL;
2790 bool useprefix;
2791 int keyno;
2792
2793 if (nkeys <= 0)
2794 return;
2795
2797
2798
2801 ancestors);
2803
2804 for (keyno = 0; keyno < nkeys; keyno++)
2805 {
2806
2807 AttrNumber keyresno = keycols[keyno];
2809 keyresno);
2810 char *exprstr;
2811
2812 if (!target)
2813 elog(ERROR, "no tlist entry for key %d", keyresno);
2814
2816 useprefix, true);
2819
2820 if (sortOperators != NULL)
2823 sortOperators[keyno],
2824 collations[keyno],
2825 nullsFirst[keyno]);
2826
2828 if (keyno < nPresortedKeys)
2829 resultPresorted = lappend(resultPresorted, exprstr);
2830 }
2831
2833 if (nPresortedKeys > 0)
2835}
2836
2837
2838
2839
2840
2841static void
2843 Oid sortOperator, Oid collation, bool nullsFirst)
2844{
2846 bool reverse = false;
2848
2851
2852
2853
2854
2855
2856
2857
2858
2860 {
2862
2863 if (collname == NULL)
2864 elog(ERROR, "cache lookup failed for collation %u", collation);
2866 }
2867
2868
2869 if (sortOperator == typentry->gt_opr)
2870 {
2872 reverse = true;
2873 }
2874 else if (sortOperator != typentry->lt_opr)
2875 {
2876 char *opname = get_opname(sortOperator);
2877
2878 if (opname == NULL)
2879 elog(ERROR, "cache lookup failed for operator %u", sortOperator);
2881
2883 }
2884
2885
2886 if (nullsFirst && !reverse)
2887 {
2889 }
2890 else if (!nullsFirst && reverse)
2891 {
2893 }
2894}
2895
2896
2897
2898
2899static void
2901{
2904 bool needspace = false;
2905
2908
2909
2910 ancestors = lcons(wagg, ancestors);
2912 {
2916 ancestors, es);
2917 needspace = true;
2918 }
2920 {
2921 if (needspace)
2926 ancestors, es);
2927 needspace = true;
2928 }
2931 {
2933 bool useprefix;
2934 char *framestr;
2935
2936
2938 (Plan *) wagg,
2939 ancestors);
2942 wagg->startOffset,
2943 wagg->endOffset,
2945 useprefix);
2946 if (needspace)
2949 pfree(framestr);
2950 }
2953 pfree(wbuf.data);
2954}
2955
2956
2957
2958
2959
2960
2961
2962static void
2966{
2969 bool useprefix;
2970
2971
2974 ancestors);
2976
2977 for (int keyno = 0; keyno < nkeys; keyno++)
2978 {
2979
2980 AttrNumber keyresno = keycols[keyno];
2982 keyresno);
2983 char *exprstr;
2984
2985 if (!target)
2986 elog(ERROR, "no tlist entry for key %d", keyresno);
2987
2989 useprefix, true);
2990 if (keyno > 0)
2994
2995
2996
2997
2998
2999
3000 }
3001}
3002
3003
3004
3005
3006static void
3008{
3010
3012 {
3015 }
3016 else
3017 {
3020 "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n",
3021 maxStorageType,
3022 maxSpaceUsedKB);
3023 }
3024}
3025
3026
3027
3028
3029static void
3032{
3034 bool useprefix;
3035 char *method_name;
3037 char *repeatable;
3039
3040
3042 planstate->plan,
3043 ancestors);
3045
3046
3048
3049
3050 foreach(lc, tsc->args)
3051 {
3053
3054 params = lappend(params,
3056 useprefix, false));
3057 }
3060 useprefix, false);
3061 else
3062 repeatable = NULL;
3063
3064
3066 {
3067 bool first = true;
3068
3071 foreach(lc, params)
3072 {
3073 if (!first)
3076 first = false;
3077 }
3079 if (repeatable)
3082 }
3083 else
3084 {
3087 if (repeatable)
3089 }
3090}
3091
3092
3093
3094
3095static void
3097{
3099 return;
3100
3102 {
3105 const char *sortMethod;
3106 const char *spaceType;
3107 int64 spaceUsed;
3108
3112 spaceUsed = stats.spaceUsed;
3113
3115 {
3118 sortMethod, spaceType, spaceUsed);
3119 }
3120 else
3121 {
3125 }
3126 }
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3138 {
3139 int n;
3140
3142 {
3144 const char *sortMethod;
3145 const char *spaceType;
3146 int64 spaceUsed;
3147
3150 continue;
3153 spaceUsed = sinstrument->spaceUsed;
3154
3157
3159 {
3163 sortMethod, spaceType, spaceUsed);
3164 }
3165 else
3166 {
3170 }
3171
3174 }
3175 }
3176}
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186static void
3188 const char *groupLabel, bool indent, ExplainState *es)
3189{
3192
3193
3195 {
3197
3198 if (groupInfo->sortMethods & sortMethod)
3199 {
3201
3202 methodNames = lappend(methodNames, unconstify(char *, methodName));
3203 }
3204 }
3205
3207 {
3208 if (indent)
3212
3215 else
3217 foreach(methodCell, methodNames)
3218 {
3222 }
3223
3225 {
3227 const char *spaceTypeName;
3228
3231 spaceTypeName, avgSpace,
3233 }
3234
3236 {
3238
3239 const char *spaceTypeName;
3240
3243 spaceTypeName, avgSpace,
3245 }
3246 }
3247 else
3248 {
3250
3255
3257
3259 {
3261 const char *spaceTypeName;
3263
3266 appendStringInfo(&memoryName, "Sort Space %s", spaceTypeName);
3268
3272
3274 }
3276 {
3278 const char *spaceTypeName;
3280
3283 appendStringInfo(&diskName, "Sort Space %s", spaceTypeName);
3285
3289
3291 }
3292
3294 }
3295}
3296
3297
3298
3299
3300static void
3303{
3306
3308
3310 return;
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321 if (fullsortGroupInfo->groupCount > 0)
3322 {
3325 if (prefixsortGroupInfo->groupCount > 0)
3326 {
3330 }
3333 }
3334
3336 {
3337 int n;
3338 bool indent_first_line;
3339
3341 {
3344
3345
3346
3347
3348
3349
3351
3352
3353
3354
3355
3356
3357
3358 if (fullsortGroupInfo->groupCount == 0)
3359 continue;
3360
3363
3366 indent_first_line, es);
3368 if (prefixsortGroupInfo->groupCount > 0)
3369 {
3373 }
3376
3379 }
3380 }
3381}
3382
3383
3384
3385
3386static void
3388{
3390
3391
3392
3393
3394
3395
3396
3397
3398
3400 memcpy(&hinstrument, hashstate->hinstrument,
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3413 {
3415 int i;
3416
3418 {
3420
3431 }
3432 }
3433
3434 if (hinstrument.nbatch > 0)
3435 {
3437
3439 {
3445 hinstrument.nbatch, es);
3449 spacePeakKb, es);
3450 }
3453 {
3456 "Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: " UINT64_FORMAT "kB\n",
3461 spacePeakKb);
3462 }
3463 else
3464 {
3467 "Buckets: %d Batches: %d Memory Usage: " UINT64_FORMAT "kB\n",
3469 spacePeakKb);
3470 }
3471 }
3472}
3473
3474
3475
3476
3477
3478static void
3480{
3481 char *maxStorageType;
3482 int64 maxSpaceUsed;
3483
3485
3486
3487
3488
3489
3490 if (!es->analyze || tupstore == NULL)
3491 return;
3492
3495}
3496
3497
3498
3499
3500
3501static void
3503{
3504 char *maxStorageType;
3505 int64 maxSpaceUsed;
3506
3508
3509
3510
3511
3512
3513 if (!es->analyze || tupstore == NULL)
3514 return;
3515
3518}
3519
3520
3521
3522
3523
3524static void
3526{
3527 char *maxStorageType;
3528 int64 maxSpaceUsed;
3529
3531
3532 if (!es->analyze || tupstore == NULL)
3533 return;
3534
3537}
3538
3539
3540
3541
3542
3543static void
3545{
3546 char *maxStorageType;
3547 int64 maxSpaceUsed;
3548
3550
3551 if (!es->analyze || tupstore == NULL)
3552 return;
3553
3556}
3557
3558
3559
3560
3561
3562static void
3564{
3565 char *maxStorageType,
3566 *tempStorageType;
3567 int64 maxSpaceUsed,
3568 tempSpaceUsed;
3569
3571 return;
3572
3573
3574
3575
3576
3577
3579 &tempSpaceUsed);
3581 &maxSpaceUsed);
3582
3583 if (tempSpaceUsed > maxSpaceUsed)
3584 maxStorageType = tempStorageType;
3585
3586 maxSpaceUsed += tempSpaceUsed;
3588}
3589
3590
3591
3592
3593static void
3595{
3601 bool useprefix;
3602 int64 memPeakKb;
3603
3605
3606
3607
3608
3609
3611
3612
3615 ancestors);
3616
3617 foreach(lc, ((Memoize *) plan)->param_exprs)
3618 {
3620
3622
3624 useprefix, false));
3626 }
3627
3630
3632
3634 return;
3635
3637 {
3638
3639
3640
3641
3644 else
3646
3648 {
3654 }
3655 else
3656 {
3664 memPeakKb);
3665 }
3666 }
3667
3669 return;
3670
3671
3673 {
3675
3677
3678
3679
3680
3681
3683 continue;
3684
3687
3688
3689
3690
3691
3692
3693
3695
3697 {
3703 memPeakKb);
3704 }
3705 else
3706 {
3716 es);
3717 }
3718
3721 }
3722}
3723
3724
3725
3726
3727static void
3729{
3732
3735 return;
3736
3738 {
3742
3743
3744
3745
3746
3747
3749 {
3755 }
3756 }
3757 else
3758 {
3759 bool gotone = false;
3760
3762 {
3766 gotone = true;
3767 }
3768
3769
3770
3771
3772
3773
3775 {
3776 if (!gotone)
3778 else
3780
3783 gotone = true;
3784
3785
3787 {
3790 }
3791 }
3792
3793 if (gotone)
3795 }
3796
3797
3799 {
3801 {
3803 uint64 hash_disk_used;
3804 int hash_batches_used;
3805
3807
3809 continue;
3813
3816
3818 {
3820
3822 hash_batches_used, memPeakKb);
3823
3824
3825 if (hash_batches_used > 1)
3827 hash_disk_used);
3829 }
3830 else
3831 {
3833 hash_batches_used, es);
3835 es);
3837 }
3838
3841 }
3842 }
3843}
3844
3845
3846
3847
3848
3849static void
3851{
3854 uint64 nsearches = 0;
3855
3857 return;
3858
3859
3861 {
3862 case T_IndexScan:
3863 {
3865
3868 break;
3869 }
3870 case T_IndexOnlyScan:
3871 {
3873
3876 break;
3877 }
3878 case T_BitmapIndexScan:
3879 {
3881
3884 break;
3885 }
3886 default:
3887 break;
3888 }
3889
3890
3891 if (SharedInfo)
3892 {
3894 {
3896
3897 nsearches += winstrument->nsearches;
3898 }
3899 }
3900
3902}
3903
3904
3905
3906
3907static void
3909{
3911 return;
3912
3914 {
3919 }
3920 else
3921 {
3923 {
3931 }
3932 }
3933
3934
3935 if (planstate->pstate != NULL)
3936 {
3938 {
3940
3942 continue;
3943
3946
3948 {
3956 }
3957 else
3958 {
3963 }
3964
3967 }
3968 }
3969}
3970
3971
3972
3973
3974
3975
3976static void
3979{
3980 double nfiltered;
3981 double nloops;
3982
3984 return;
3985
3986 if (which == 2)
3988 else
3991
3992
3994 {
3995 if (nloops > 0)
3997 else
3999 }
4000}
4001
4002
4003
4004
4005static void
4007{
4009
4010
4012 {
4015 }
4016 else
4017 {
4020 }
4021}
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033static const char *
4035{
4036 const char *result;
4037
4039 result = (*explain_get_index_name_hook) (indexId);
4040 else
4041 result = NULL;
4042 if (result == NULL)
4043 {
4044
4046 if (result == NULL)
4047 elog(ERROR, "cache lookup failed for index %u", indexId);
4048 }
4049 return result;
4050}
4051
4052
4053
4054
4055
4056
4057static bool
4059{
4060 bool has_shared;
4061 bool has_local;
4062 bool has_temp;
4063 bool has_shared_timing;
4064 bool has_local_timing;
4065 bool has_temp_timing;
4066
4067 if (usage == NULL)
4068 return false;
4069
4071 return true;
4072
4073 has_shared = (usage->shared_blks_hit > 0 ||
4074 usage->shared_blks_read > 0 ||
4075 usage->shared_blks_dirtied > 0 ||
4076 usage->shared_blks_written > 0);
4077 has_local = (usage->local_blks_hit > 0 ||
4078 usage->local_blks_read > 0 ||
4079 usage->local_blks_dirtied > 0 ||
4080 usage->local_blks_written > 0);
4081 has_temp = (usage->temp_blks_read > 0 ||
4082 usage->temp_blks_written > 0);
4089
4090 return has_shared || has_local || has_temp || has_shared_timing ||
4091 has_local_timing || has_temp_timing;
4092}
4093
4094
4095
4096
4097static void
4099{
4101 {
4102 bool has_shared = (usage->shared_blks_hit > 0 ||
4103 usage->shared_blks_read > 0 ||
4104 usage->shared_blks_dirtied > 0 ||
4105 usage->shared_blks_written > 0);
4106 bool has_local = (usage->local_blks_hit > 0 ||
4107 usage->local_blks_read > 0 ||
4108 usage->local_blks_dirtied > 0 ||
4109 usage->local_blks_written > 0);
4110 bool has_temp = (usage->temp_blks_read > 0 ||
4111 usage->temp_blks_written > 0);
4118
4119
4120 if (has_shared || has_local || has_temp)
4121 {
4124
4125 if (has_shared)
4126 {
4128 if (usage->shared_blks_hit > 0)
4130 usage->shared_blks_hit);
4131 if (usage->shared_blks_read > 0)
4133 usage->shared_blks_read);
4134 if (usage->shared_blks_dirtied > 0)
4136 usage->shared_blks_dirtied);
4137 if (usage->shared_blks_written > 0)
4139 usage->shared_blks_written);
4140 if (has_local || has_temp)
4142 }
4143 if (has_local)
4144 {
4146 if (usage->local_blks_hit > 0)
4148 usage->local_blks_hit);
4149 if (usage->local_blks_read > 0)
4151 usage->local_blks_read);
4152 if (usage->local_blks_dirtied > 0)
4154 usage->local_blks_dirtied);
4155 if (usage->local_blks_written > 0)
4157 usage->local_blks_written);
4158 if (has_temp)
4160 }
4161 if (has_temp)
4162 {
4164 if (usage->temp_blks_read > 0)
4166 usage->temp_blks_read);
4167 if (usage->temp_blks_written > 0)
4169 usage->temp_blks_written);
4170 }
4172 }
4173
4174
4175 if (has_shared_timing || has_local_timing || has_temp_timing)
4176 {
4179
4180 if (has_shared_timing)
4181 {
4189 if (has_local_timing || has_temp_timing)
4191 }
4192 if (has_local_timing)
4193 {
4201 if (has_temp_timing)
4203 }
4204 if (has_temp_timing)
4205 {
4213 }
4215 }
4216 }
4217 else
4218 {
4220 usage->shared_blks_hit, es);
4222 usage->shared_blks_read, es);
4224 usage->shared_blks_dirtied, es);
4226 usage->shared_blks_written, es);
4228 usage->local_blks_hit, es);
4230 usage->local_blks_read, es);
4232 usage->local_blks_dirtied, es);
4234 usage->local_blks_written, es);
4236 usage->temp_blks_read, es);
4238 usage->temp_blks_written, es);
4240 {
4243 3, es);
4246 3, es);
4249 3, es);
4252 3, es);
4255 3, es);
4258 3, es);
4259 }
4260 }
4261}
4262
4263
4264
4265
4266static void
4268{
4270 {
4271
4272 if ((usage->wal_records > 0) || (usage->wal_fpi > 0) ||
4273 (usage->wal_bytes > 0) || (usage->wal_buffers_full > 0))
4274 {
4277
4278 if (usage->wal_records > 0)
4280 usage->wal_records);
4281 if (usage->wal_fpi > 0)
4283 usage->wal_fpi);
4284 if (usage->wal_bytes > 0)
4286 usage->wal_bytes);
4287 if (usage->wal_buffers_full > 0)
4289 usage->wal_buffers_full);
4291 }
4292 }
4293 else
4294 {
4296 usage->wal_records, es);
4298 usage->wal_fpi, es);
4300 usage->wal_bytes, es);
4302 usage->wal_buffers_full, es);
4303 }
4304}
4305
4306
4307
4308
4309static void
4311{
4315
4317 {
4321 memUsedkB, memAllocatedkB);
4323 }
4324 else
4325 {
4328 }
4329}
4330
4331
4332
4333
4334
4335static void
4338{
4340
4342 {
4346 }
4347 else
4348 {
4349 const char *scandir;
4350
4351 switch (indexorderdir)
4352 {
4354 scandir = "Backward";
4355 break;
4357 scandir = "Forward";
4358 break;
4359 default:
4360 scandir = "???";
4361 break;
4362 }
4365 }
4366}
4367
4368
4369
4370
4371static void
4373{
4375}
4376
4377
4378
4379
4380
4381
4382
4383
4384static void
4386{
4388}
4389
4390
4391
4392
4393static void
4395{
4396 char *objectname = NULL;
4397 char *namespace = NULL;
4398 const char *objecttag = NULL;
4400 char *refname;
4401
4404 if (refname == NULL)
4405 refname = rte->eref->aliasname;
4406
4408 {
4409 case T_SeqScan:
4410 case T_SampleScan:
4411 case T_IndexScan:
4412 case T_IndexOnlyScan:
4413 case T_BitmapHeapScan:
4414 case T_TidScan:
4415 case T_TidRangeScan:
4416 case T_ForeignScan:
4417 case T_CustomScan:
4418 case T_ModifyTable:
4419
4424 objecttag = "Relation Name";
4425 break;
4426 case T_FunctionScan:
4427 {
4429
4430
4432
4433
4434
4435
4436
4437
4438
4440 {
4442
4444 {
4447
4451 }
4452 }
4453 objecttag = "Function Name";
4454 }
4455 break;
4456 case T_TableFuncScan:
4457 {
4459
4461 switch (tablefunc->functype)
4462 {
4464 objectname = "xmltable";
4465 break;
4467 objectname = "json_table";
4468 break;
4469 default:
4470 elog(ERROR, "invalid TableFunc type %d",
4472 }
4473 objecttag = "Table Function Name";
4474 }
4475 break;
4476 case T_ValuesScan:
4478 break;
4479 case T_CteScan:
4480
4482 Assert(!rte->self_reference);
4483 objectname = rte->ctename;
4484 objecttag = "CTE Name";
4485 break;
4486 case T_NamedTuplestoreScan:
4488 objectname = rte->enrname;
4489 objecttag = "Tuplestore Name";
4490 break;
4491 case T_WorkTableScan:
4492
4494 Assert(rte->self_reference);
4495 objectname = rte->ctename;
4496 objecttag = "CTE Name";
4497 break;
4498 default:
4499 break;
4500 }
4501
4503 {
4505 if (namespace != NULL)
4508 else if (objectname != NULL)
4510 if (objectname == NULL || strcmp(refname, objectname) != 0)
4512 }
4513 else
4514 {
4515 if (objecttag != NULL && objectname != NULL)
4517 if (namespace != NULL)
4520 }
4521}
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531static void
4534{
4536 const char *operation;
4537 const char *foperation;
4538 bool labeltargets;
4539 int j;
4542
4544 {
4546 operation = "Insert";
4547 foperation = "Foreign Insert";
4548 break;
4550 operation = "Update";
4551 foperation = "Foreign Update";
4552 break;
4554 operation = "Delete";
4555 foperation = "Foreign Delete";
4556 break;
4558 operation = "Merge";
4559
4560 foperation = "Foreign Merge";
4561 break;
4562 default:
4563 operation = "???";
4564 foperation = "Foreign ???";
4565 break;
4566 }
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577 labeltargets = (mtstate->mt_nrels > 1 ||
4582
4583 if (labeltargets)
4584 ExplainOpenGroup("Target Tables", "Target Tables", false, es);
4585
4587 {
4590
4591 if (labeltargets)
4592 {
4593
4595
4596
4597
4598
4599
4601 {
4604 fdwroutine ? foperation : operation);
4605 }
4606
4607
4610 es);
4611
4613 {
4616 }
4617 }
4618
4619
4621 fdwroutine != NULL &&
4623 {
4625
4627 resultRelInfo,
4628 fdw_private,
4629 j,
4630 es);
4631 }
4632
4633 if (labeltargets)
4634 {
4635
4638
4639
4641 }
4642 }
4643
4644
4646 {
4648
4649 idxNames = lappend(idxNames, indexname);
4650 }
4651
4653 {
4656 "NOTHING" : "UPDATE",
4657 es);
4658
4659
4660
4661
4662
4663 if (idxNames)
4665
4666
4668 {
4670 &mtstate->ps, ancestors, es);
4672 }
4673
4674
4676 {
4677 double total;
4678 double insert_path;
4679 double other_path;
4680
4682
4683
4684 total = outerPlanState(mtstate)->instrument->ntuples;
4686 insert_path = total - other_path;
4687
4689 insert_path, 0, es);
4691 other_path, 0, es);
4692 }
4693 }
4695 {
4696
4698 {
4699 double total;
4700 double insert_path;
4701 double update_path;
4702 double delete_path;
4703 double skipped_path;
4704
4706
4707
4708 total = outerPlanState(mtstate)->instrument->ntuples;
4712 skipped_path = total - insert_path - update_path - delete_path;
4713 Assert(skipped_path >= 0);
4714
4716 {
4717 if (total > 0)
4718 {
4721 if (insert_path > 0)
4723 if (update_path > 0)
4725 if (delete_path > 0)
4727 if (skipped_path > 0)
4730 }
4731 }
4732 else
4733 {
4738 }
4739 }
4740 }
4741
4742 if (labeltargets)
4744}
4745
4746
4747
4748
4749
4750
4751
4752
4753static void
4756{
4757 int j;
4758
4759 for (j = 0; j < nplans; j++)
4761 "Member", NULL, es);
4762}
4763
4764
4765
4766
4767
4768
4769
4770
4771static void
4773{
4776 nchildren - nplans, es);
4777}
4778
4779
4780
4781
4782
4783
4784
4785static void
4788{
4790
4791 foreach(lst, plans)
4792 {
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4807 continue;
4810
4811
4812
4813
4814
4815
4816 ancestors = lcons(sp, ancestors);
4817
4819 relationship, sp->plan_name, es);
4820
4822 }
4823}
4824
4825
4826
4827
4828static void
4830{
4832 const char *label =
4834
4837}
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4852{
4854
4861 return wstate;
4862}
4863
4864
4865
4866
4867static void
4869{
4871
4873 Assert(n >= 0 && n < wstate->num_workers);
4874
4875
4877
4879 {
4880
4883
4884
4885
4886
4887
4888
4890
4891
4892
4893
4894
4897
4899 }
4900 else
4901 {
4902
4904
4905
4907 }
4908
4909
4910
4911
4912
4913
4915 {
4917 {
4920 }
4921
4923 }
4924}
4925
4926
4927
4928
4929static void
4931{
4933
4935 Assert(n >= 0 && n < wstate->num_workers);
4937
4938
4939
4940
4941
4943
4944
4945
4946
4947
4948
4949
4951 {
4954
4956 }
4957
4958
4960}
4961
4962
4963
4964
4965static void
4967{
4969
4972 {
4974 {
4975
4979
4981 }
4982 }
4984
4989}
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
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
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorStartCachedPlan(QueryDesc *queryDesc, int eflags, CachedPlanSource *plansource, int query_index)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
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_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)
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)
void ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, CachedPlanSource *plansource, int query_index, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters)
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, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
void(* ExplainOneQuery_hook_type)(Query *query, int cursorOptions, IntoClause *into, struct 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, struct ExplainState *es)
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
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)
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
void FreeQueryDesc(QueryDesc *qdesc)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, 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
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
struct PlanState * planstate
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)