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 &planduration, (es->buffers ? &bufusage : NULL),
374 es->memory ? &mem_counters : NULL);
375}
376
377
378
379
380
381
382
383
384
385
386
387
388
389void
392{
393 if (utilityStmt == NULL)
394 return;
395
397 {
398
399
400
401
403 Query *ctas_query;
404 List *rewritten;
406
407
408
409
410
412 {
417 else
418 elog(ERROR, "unexpected object type: %d",
420 return;
421 }
422
427 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);
432 pstate, params);
433 }
435 {
436
437
438
439
440
441
442
443
445 Query *dcs_query;
446 List *rewritten;
448
453 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);
454
459 pstate, params);
460 }
463 pstate, params);
465 {
468 else
470 }
471 else
472 {
475 "Utility statements have no plan structure\n");
476 else
478 }
479}
480
481
482
483
484
485
486
487
488
489
490
491
492
493void
499{
503 double totaltime = 0;
504 int eflags;
505 int instrument_option = 0;
507
509
514
517 if (es->wal)
519
520
521
522
523
524
526
527
528
529
530
533
534
535
536
537
538
539
540
541
542 if (into)
546 else
548
549
552 dest, params, queryEnv, instrument_option);
553
554
556 eflags = 0;
557 else
561 if (into)
563
564
566
567
569 {
571
572
575 else
577
578
580
581
583
584
586 }
587
588
591
592
594
596
597
599
600
602 {
604
606 {
610 }
611
612 if (bufusage)
614
615 if (mem_counters)
617
620
622 }
623
624 if (es->summary && planduration)
625 {
627
629 }
630
631
634
635
636
637
638
639
640
643
644
647
648
650 (*explain_per_plan_hook) (plannedstmt, into, es, queryString,
651 params, queryEnv);
652
653
654
655
656
658
660
662
664
665
668
670
671
672
673
674
675
676
679 es);
680
682}
683
684
685
686
687
688static void
690{
691 int num;
693
694
696 return;
697
698
700
702 {
704
705 for (int i = 0; i < num; i++)
706 {
707 char *setting;
709
711
713 }
714
716 }
717 else
718 {
720
721
722 if (num <= 0)
723 return;
724
726
727 for (int i = 0; i < num; i++)
728 {
729 char *setting;
731
732 if (i > 0)
734
736
737 if (setting)
739 else
741 }
742
744 }
745}
746
747
748
749
750
751
752
753
754
755
756
757
758void
760{
764
765
775 foreach(lc, es->rtable)
776 {
778
780 {
782 break;
783 }
784 }
785
786
787
788
789
790
791
792
793
794
797 {
800 }
802
803
804
805
806
808
809
810
811
812
813
816 {
817
818
819
820
823 }
824}
825
826
827
828
829
830
831
832
833
834
835void
837{
839 bool show_relname;
840 List *resultrels;
841 List *routerels;
842 List *targrels;
844
848
850
851 show_relname = (list_length(resultrels) > 1 ||
852 routerels != NIL || targrels != NIL);
853 foreach(l, resultrels)
854 {
857 }
858
859 foreach(l, routerels)
860 {
863 }
864
865 foreach(l, targrels)
866 {
869 }
870
872}
873
874
875
876
877
878void
880{
882
884 return;
885
886
887
888
889
892
893
896
898}
899
900
901
902
903
904static void
906{
908
909
911 return;
912
913
915
920
922
923
925 {
929
931
934 "Inlining", jit_flags & PGJIT_INLINE ? "true" : "false",
935 "Optimization", jit_flags & PGJIT_OPT3 ? "true" : "false",
936 "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",
937 "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");
938
940 {
943 "Timing: %s %.3f ms (%s %.3f ms), %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",
950 }
951
953 }
954 else
955 {
957
964
966 {
968
972 3, es);
975 3, es);
977
980 3, es);
983 3, es);
986 3, es);
989 3, es);
990
992 }
993 }
994
996}
997
998
999
1000
1001
1002static void
1004{
1006
1007
1010 else
1011 {
1014 }
1015
1016 ExplainOpenGroup("Serialization", "Serialization", true, es);
1017
1019 {
1026 else
1030
1032 {
1036 }
1037 }
1038 else
1039 {
1043 3, es);
1049 }
1050
1052}
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062void
1064{
1067}
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077void
1079{
1080 char *str;
1081
1082
1083 if (params == NULL || params->numParams <= 0 || maxlen == 0)
1084 return;
1085
1087 if (str && str[0] != '\0')
1089}
1090
1091
1092
1093
1094
1095static void
1097{
1098 int nt;
1099
1101 return;
1103 {
1107 char *conname = NULL;
1108
1109
1111
1112
1113
1114
1115
1116 if (instr->ntuples == 0)
1117 continue;
1118
1120
1124
1125
1126
1127
1128
1129
1131 {
1132 if (es->verbose || conname == NULL)
1134 else
1136 if (conname)
1138 if (show_relname)
1143 else
1145 }
1146 else
1147 {
1149 if (conname)
1154 es);
1156 }
1157
1158 if (conname)
1160
1162 }
1163}
1164
1165
1166static double
1168{
1170
1174}
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185static bool
1187{
1189
1191 {
1192 case T_SeqScan:
1193 case T_SampleScan:
1194 case T_IndexScan:
1195 case T_IndexOnlyScan:
1196 case T_BitmapHeapScan:
1197 case T_TidScan:
1198 case T_TidRangeScan:
1199 case T_SubqueryScan:
1200 case T_FunctionScan:
1201 case T_TableFuncScan:
1202 case T_ValuesScan:
1203 case T_CteScan:
1204 case T_NamedTuplestoreScan:
1205 case T_WorkTableScan:
1207 ((Scan *) plan)->scanrelid);
1208 break;
1209 case T_ForeignScan:
1212 break;
1213 case T_CustomScan:
1216 break;
1217 case T_ModifyTable:
1223
1224 if (plan->targetlist)
1227 break;
1228 case T_Append:
1231 break;
1232 case T_MergeAppend:
1235 break;
1236 default:
1237 break;
1238 }
1239
1241}
1242
1243
1244
1245
1246
1247
1248
1249static bool
1251{
1252 int child_disabled_nodes;
1253
1254
1255 if (plan->disabled_nodes == 0)
1256 return false;
1257
1258 child_disabled_nodes = 0;
1259
1260
1261
1262
1263
1265 {
1268
1269
1270
1271
1272
1273
1275 {
1277
1279 }
1280 }
1282 {
1285
1286
1287
1288
1289
1290
1292 {
1294
1296 }
1297 }
1299 child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes;
1301 {
1304
1306 {
1308
1310 }
1311 }
1312 else
1313 {
1314
1315
1316
1318 child_disabled_nodes += outerPlan(plan)->disabled_nodes;
1320 child_disabled_nodes += innerPlan(plan)->disabled_nodes;
1321 }
1322
1323
1324
1325
1326
1327 if (plan->disabled_nodes > child_disabled_nodes)
1328 return true;
1329
1330 return false;
1331}
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354static void
1356 const char *relationship, const char *plan_name,
1358{
1360 const char *pname;
1361 const char *sname;
1362 const char *strategy = NULL;
1363 const char *partialmode = NULL;
1364 const char *operation = NULL;
1365 const char *custom_name = NULL;
1367 int save_indent = es->indent;
1368 bool haschildren;
1369 bool isdisabled;
1370
1371
1372
1373
1374
1377 else
1379
1380
1382 {
1383 case T_Result:
1384 pname = sname = "Result";
1385 break;
1386 case T_ProjectSet:
1387 pname = sname = "ProjectSet";
1388 break;
1389 case T_ModifyTable:
1390 sname = "ModifyTable";
1392 {
1394 pname = operation = "Insert";
1395 break;
1397 pname = operation = "Update";
1398 break;
1400 pname = operation = "Delete";
1401 break;
1403 pname = operation = "Merge";
1404 break;
1405 default:
1406 pname = "???";
1407 break;
1408 }
1409 break;
1410 case T_Append:
1411 pname = sname = "Append";
1412 break;
1413 case T_MergeAppend:
1414 pname = sname = "Merge Append";
1415 break;
1416 case T_RecursiveUnion:
1417 pname = sname = "Recursive Union";
1418 break;
1419 case T_BitmapAnd:
1420 pname = sname = "BitmapAnd";
1421 break;
1422 case T_BitmapOr:
1423 pname = sname = "BitmapOr";
1424 break;
1425 case T_NestLoop:
1426 pname = sname = "Nested Loop";
1427 break;
1428 case T_MergeJoin:
1429 pname = "Merge";
1430 sname = "Merge Join";
1431 break;
1432 case T_HashJoin:
1433 pname = "Hash";
1434 sname = "Hash Join";
1435 break;
1436 case T_SeqScan:
1437 pname = sname = "Seq Scan";
1438 break;
1439 case T_SampleScan:
1440 pname = sname = "Sample Scan";
1441 break;
1442 case T_Gather:
1443 pname = sname = "Gather";
1444 break;
1445 case T_GatherMerge:
1446 pname = sname = "Gather Merge";
1447 break;
1448 case T_IndexScan:
1449 pname = sname = "Index Scan";
1450 break;
1451 case T_IndexOnlyScan:
1452 pname = sname = "Index Only Scan";
1453 break;
1454 case T_BitmapIndexScan:
1455 pname = sname = "Bitmap Index Scan";
1456 break;
1457 case T_BitmapHeapScan:
1458 pname = sname = "Bitmap Heap Scan";
1459 break;
1460 case T_TidScan:
1461 pname = sname = "Tid Scan";
1462 break;
1463 case T_TidRangeScan:
1464 pname = sname = "Tid Range Scan";
1465 break;
1466 case T_SubqueryScan:
1467 pname = sname = "Subquery Scan";
1468 break;
1469 case T_FunctionScan:
1470 pname = sname = "Function Scan";
1471 break;
1472 case T_TableFuncScan:
1473 pname = sname = "Table Function Scan";
1474 break;
1475 case T_ValuesScan:
1476 pname = sname = "Values Scan";
1477 break;
1478 case T_CteScan:
1479 pname = sname = "CTE Scan";
1480 break;
1481 case T_NamedTuplestoreScan:
1482 pname = sname = "Named Tuplestore Scan";
1483 break;
1484 case T_WorkTableScan:
1485 pname = sname = "WorkTable Scan";
1486 break;
1487 case T_ForeignScan:
1488 sname = "Foreign Scan";
1490 {
1492 pname = "Foreign Scan";
1493 operation = "Select";
1494 break;
1496 pname = "Foreign Insert";
1497 operation = "Insert";
1498 break;
1500 pname = "Foreign Update";
1501 operation = "Update";
1502 break;
1504 pname = "Foreign Delete";
1505 operation = "Delete";
1506 break;
1507 default:
1508 pname = "???";
1509 break;
1510 }
1511 break;
1512 case T_CustomScan:
1513 sname = "Custom Scan";
1514 custom_name = ((CustomScan *) plan)->methods->CustomName;
1515 if (custom_name)
1516 pname = psprintf("Custom Scan (%s)", custom_name);
1517 else
1518 pname = sname;
1519 break;
1520 case T_Material:
1521 pname = sname = "Materialize";
1522 break;
1523 case T_Memoize:
1524 pname = sname = "Memoize";
1525 break;
1526 case T_Sort:
1527 pname = sname = "Sort";
1528 break;
1529 case T_IncrementalSort:
1530 pname = sname = "Incremental Sort";
1531 break;
1532 case T_Group:
1533 pname = sname = "Group";
1534 break;
1535 case T_Agg:
1536 {
1538
1539 sname = "Aggregate";
1541 {
1543 pname = "Aggregate";
1544 strategy = "Plain";
1545 break;
1547 pname = "GroupAggregate";
1548 strategy = "Sorted";
1549 break;
1551 pname = "HashAggregate";
1552 strategy = "Hashed";
1553 break;
1555 pname = "MixedAggregate";
1556 strategy = "Mixed";
1557 break;
1558 default:
1559 pname = "Aggregate ???";
1560 strategy = "???";
1561 break;
1562 }
1563
1565 {
1566 partialmode = "Partial";
1567 pname = psprintf("%s %s", partialmode, pname);
1568 }
1570 {
1571 partialmode = "Finalize";
1572 pname = psprintf("%s %s", partialmode, pname);
1573 }
1574 else
1575 partialmode = "Simple";
1576 }
1577 break;
1578 case T_WindowAgg:
1579 pname = sname = "WindowAgg";
1580 break;
1581 case T_Unique:
1582 pname = sname = "Unique";
1583 break;
1584 case T_SetOp:
1585 sname = "SetOp";
1586 switch (((SetOp *) plan)->strategy)
1587 {
1589 pname = "SetOp";
1590 strategy = "Sorted";
1591 break;
1593 pname = "HashSetOp";
1594 strategy = "Hashed";
1595 break;
1596 default:
1597 pname = "SetOp ???";
1598 strategy = "???";
1599 break;
1600 }
1601 break;
1602 case T_LockRows:
1603 pname = sname = "LockRows";
1604 break;
1605 case T_Limit:
1606 pname = sname = "Limit";
1607 break;
1608 case T_Hash:
1609 pname = sname = "Hash";
1610 break;
1611 default:
1612 pname = sname = "???";
1613 break;
1614 }
1615
1617 relationship ? NULL : "Plan",
1618 true, es);
1619
1621 {
1622 if (plan_name)
1623 {
1627 }
1629 {
1633 }
1634 if (plan->parallel_aware)
1636 if (plan->async_capable)
1640 }
1641 else
1642 {
1644 if (strategy)
1646 if (partialmode)
1648 if (operation)
1650 if (relationship)
1652 if (plan_name)
1654 if (custom_name)
1658 }
1659
1661 {
1662 case T_SeqScan:
1663 case T_SampleScan:
1664 case T_BitmapHeapScan:
1665 case T_TidScan:
1666 case T_TidRangeScan:
1667 case T_SubqueryScan:
1668 case T_FunctionScan:
1669 case T_TableFuncScan:
1670 case T_ValuesScan:
1671 case T_CteScan:
1672 case T_WorkTableScan:
1674 break;
1675 case T_ForeignScan:
1676 case T_CustomScan:
1677 if (((Scan *) plan)->scanrelid > 0)
1679 break;
1680 case T_IndexScan:
1681 {
1683
1686 es);
1688 }
1689 break;
1690 case T_IndexOnlyScan:
1691 {
1693
1696 es);
1698 }
1699 break;
1700 case T_BitmapIndexScan:
1701 {
1703 const char *indexname =
1705
1709 else
1711 }
1712 break;
1713 case T_ModifyTable:
1715 break;
1716 case T_NestLoop:
1717 case T_MergeJoin:
1718 case T_HashJoin:
1719 {
1720 const char *jointype;
1721
1722 switch (((Join *) plan)->jointype)
1723 {
1725 jointype = "Inner";
1726 break;
1728 jointype = "Left";
1729 break;
1731 jointype = "Full";
1732 break;
1734 jointype = "Right";
1735 break;
1737 jointype = "Semi";
1738 break;
1740 jointype = "Anti";
1741 break;
1743 jointype = "Right Semi";
1744 break;
1746 jointype = "Right Anti";
1747 break;
1748 default:
1749 jointype = "???";
1750 break;
1751 }
1753 {
1754
1755
1756
1757
1762 }
1763 else
1765 }
1766 break;
1767 case T_SetOp:
1768 {
1769 const char *setopcmd;
1770
1772 {
1774 setopcmd = "Intersect";
1775 break;
1777 setopcmd = "Intersect All";
1778 break;
1780 setopcmd = "Except";
1781 break;
1783 setopcmd = "Except All";
1784 break;
1785 default:
1786 setopcmd = "???";
1787 break;
1788 }
1791 else
1793 }
1794 break;
1795 default:
1796 break;
1797 }
1798
1800 {
1802 {
1804 plan->startup_cost, plan->total_cost,
1805 plan->plan_rows, plan->plan_width);
1806 }
1807 else
1808 {
1810 2, es);
1812 2, es);
1814 0, es);
1816 es);
1817 }
1818 }
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1832
1835 {
1837 double startup_ms = 1000.0 * planstate->instrument->startup / nloops;
1838 double total_ms = 1000.0 * planstate->instrument->total / nloops;
1840
1842 {
1844
1847
1849 }
1850 else
1851 {
1853 {
1855 3, es);
1857 3, es);
1858 }
1861 }
1862 }
1864 {
1867 else
1868 {
1870 {
1873 }
1876 }
1877 }
1878
1879
1882
1883
1887
1888
1890 {
1892
1893 for (int n = 0; n < w->num_workers; n++)
1894 {
1896 double nloops = instrument->nloops;
1897 double startup_ms;
1898 double total_ms;
1899 double rows;
1900
1901 if (nloops <= 0)
1902 continue;
1903 startup_ms = 1000.0 * instrument->startup / nloops;
1904 total_ms = 1000.0 * instrument->total / nloops;
1905 rows = instrument->ntuples / nloops;
1906
1908
1910 {
1915
1917 }
1918 else
1919 {
1921 {
1923 startup_ms, 3, es);
1925 total_ms, 3, es);
1926 }
1927
1930 }
1931
1933 }
1934 }
1935
1936
1939
1940
1942 {
1943 case T_NestLoop:
1944 case T_MergeJoin:
1945 case T_HashJoin:
1946
1950 ((Join *) plan)->inner_unique,
1951 es);
1952 break;
1953 default:
1954 break;
1955 }
1956
1957
1959 {
1960 case T_IndexScan:
1962 "Index Cond", planstate, ancestors, es);
1965 planstate, es);
1967 "Order By", planstate, ancestors, es);
1969 if (plan->qual)
1971 planstate, es);
1973 break;
1974 case T_IndexOnlyScan:
1976 "Index Cond", planstate, ancestors, es);
1979 planstate, es);
1981 "Order By", planstate, ancestors, es);
1983 if (plan->qual)
1985 planstate, es);
1990 break;
1991 case T_BitmapIndexScan:
1993 "Index Cond", planstate, ancestors, es);
1995 break;
1996 case T_BitmapHeapScan:
1998 "Recheck Cond", planstate, ancestors, es);
2001 planstate, es);
2003 if (plan->qual)
2005 planstate, es);
2007 break;
2008 case T_SampleScan:
2010 planstate, ancestors, es);
2011
2012
2013 case T_SeqScan:
2014 case T_ValuesScan:
2015 case T_CteScan:
2016 case T_NamedTuplestoreScan:
2017 case T_WorkTableScan:
2018 case T_SubqueryScan:
2020 if (plan->qual)
2022 planstate, es);
2025 break;
2026 case T_Gather:
2027 {
2029
2031 if (plan->qual)
2033 planstate, es);
2036
2038 {
2039 int nworkers;
2040
2041 nworkers = ((GatherState *) planstate)->nworkers_launched;
2043 nworkers, es);
2044 }
2045
2048 }
2049 break;
2050 case T_GatherMerge:
2051 {
2053
2055 if (plan->qual)
2057 planstate, es);
2060
2062 {
2063 int nworkers;
2064
2065 nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
2067 nworkers, es);
2068 }
2069 }
2070 break;
2071 case T_FunctionScan:
2073 {
2076
2078 {
2080
2082 }
2083
2085 "Function Call", planstate, ancestors,
2087 }
2089 if (plan->qual)
2091 planstate, es);
2092 break;
2093 case T_TableFuncScan:
2095 {
2097
2099 "Table Function Call", planstate, ancestors,
2101 }
2103 if (plan->qual)
2105 planstate, es);
2107 planstate), es);
2108 break;
2109 case T_TidScan:
2110 {
2111
2112
2113
2114
2116
2119 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2121 if (plan->qual)
2123 planstate, es);
2124 }
2125 break;
2126 case T_TidRangeScan:
2127 {
2128
2129
2130
2131
2133
2136 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);
2138 if (plan->qual)
2140 planstate, es);
2141 }
2142 break;
2143 case T_ForeignScan:
2145 if (plan->qual)
2147 planstate, es);
2149 break;
2150 case T_CustomScan:
2151 {
2153
2155 if (plan->qual)
2157 planstate, es);
2160 }
2161 break;
2162 case T_NestLoop:
2164 "Join Filter", planstate, ancestors, es);
2167 planstate, es);
2169 if (plan->qual)
2171 planstate, es);
2172 break;
2173 case T_MergeJoin:
2175 "Merge Cond", planstate, ancestors, es);
2177 "Join Filter", planstate, ancestors, es);
2180 planstate, es);
2182 if (plan->qual)
2184 planstate, es);
2185 break;
2186 case T_HashJoin:
2188 "Hash Cond", planstate, ancestors, es);
2190 "Join Filter", planstate, ancestors, es);
2193 planstate, es);
2195 if (plan->qual)
2197 planstate, es);
2198 break;
2199 case T_Agg:
2203 if (plan->qual)
2205 planstate, es);
2206 break;
2207 case T_WindowAgg:
2210 "Run Condition", planstate, ancestors, es);
2212 if (plan->qual)
2214 planstate, es);
2216 break;
2217 case T_Group:
2220 if (plan->qual)
2222 planstate, es);
2223 break;
2224 case T_Sort:
2227 break;
2228 case T_IncrementalSort:
2230 ancestors, es);
2232 es);
2233 break;
2234 case T_MergeAppend:
2236 ancestors, es);
2237 break;
2238 case T_Result:
2240 "One-Time Filter", planstate, ancestors, es);
2242 if (plan->qual)
2244 planstate, es);
2245 break;
2246 case T_ModifyTable:
2248 es);
2249 break;
2250 case T_Hash:
2252 break;
2253 case T_Material:
2255 break;
2256 case T_Memoize:
2258 es);
2259 break;
2260 case T_RecursiveUnion:
2262 planstate), es);
2263 break;
2264 default:
2265 break;
2266 }
2267
2268
2269
2270
2271
2273 {
2275
2276 if (w)
2277 {
2278 for (int n = 0; n < w->num_workers; n++)
2279 {
2284 }
2285 }
2286 }
2287
2288
2293
2294
2296 {
2298
2299 for (int n = 0; n < w->num_workers; n++)
2300 {
2302 double nloops = instrument->nloops;
2303
2304 if (nloops <= 0)
2305 continue;
2306
2310 if (es->wal)
2313 }
2314 }
2315
2316
2320
2321
2323 (*explain_per_node_hook) (planstate, ancestors, relationship,
2324 plan_name, es);
2325
2326
2327
2328
2329
2330
2331
2332
2333
2335 {
2336 case T_Append:
2339 es);
2340 break;
2341 case T_MergeAppend:
2344 es);
2345 break;
2346 default:
2347 break;
2348 }
2349
2350
2351 haschildren = planstate->initPlan ||
2362 if (haschildren)
2363 {
2365
2366 ancestors = lcons(plan, ancestors);
2367 }
2368
2369
2372
2373
2376 "Outer", NULL, es);
2377
2378
2381 "Inner", NULL, es);
2382
2383
2385 {
2386 case T_Append:
2389 ancestors, es);
2390 break;
2391 case T_MergeAppend:
2394 ancestors, es);
2395 break;
2396 case T_BitmapAnd:
2399 ancestors, es);
2400 break;
2401 case T_BitmapOr:
2404 ancestors, es);
2405 break;
2406 case T_SubqueryScan:
2408 "Subquery", NULL, es);
2409 break;
2410 case T_CustomScan:
2412 ancestors, es);
2413 break;
2414 default:
2415 break;
2416 }
2417
2418
2421
2422
2423 if (haschildren)
2424 {
2427 }
2428
2429
2431 es->indent = save_indent;
2432
2434 relationship ? NULL : "Plan",
2435 true, es);
2436}
2437
2438
2439
2440
2441static void
2443{
2447 bool useprefix;
2449
2450
2451 if (plan->targetlist == NIL)
2452 return;
2453
2455 return;
2456
2458 return;
2460 return;
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2474 return;
2475
2476
2479 ancestors);
2481
2482
2483 foreach(lc, plan->targetlist)
2484 {
2486
2487 result = lappend(result,
2489 useprefix, false));
2490 }
2491
2492
2494}
2495
2496
2497
2498
2499static void
2503{
2505 char *exprstr;
2506
2507
2509 planstate->plan,
2510 ancestors);
2511
2512
2514
2515
2517}
2518
2519
2520
2521
2522static void
2526{
2528
2529
2530 if (qual == NIL)
2531 return;
2532
2533
2535
2536
2537 show_expression(node, qlabel, planstate, ancestors, useprefix, es);
2538}
2539
2540
2541
2542
2543static void
2547{
2548 bool useprefix;
2549
2551 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2552}
2553
2554
2555
2556
2557static void
2561{
2562 bool useprefix;
2563
2565 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);
2566}
2567
2568
2569
2570
2571static void
2573{
2575
2577 plan->numCols, 0, plan->sortColIdx,
2578 plan->sortOperators, plan->collations,
2579 plan->nullsFirst,
2580 ancestors, es);
2581}
2582
2583
2584
2585
2586static void
2589{
2591
2593 plan->sort.numCols, plan->nPresortedCols,
2594 plan->sort.sortColIdx,
2595 plan->sort.sortOperators, plan->sort.collations,
2596 plan->sort.nullsFirst,
2597 ancestors, es);
2598}
2599
2600
2601
2602
2603static void
2606{
2608
2610 plan->numCols, 0, plan->sortColIdx,
2611 plan->sortOperators, plan->collations,
2612 plan->nullsFirst,
2613 ancestors, es);
2614}
2615
2616
2617
2618
2619static void
2622{
2624
2625 if (plan->numCols > 0 || plan->groupingSets)
2626 {
2627
2628 ancestors = lcons(plan, ancestors);
2629
2630 if (plan->groupingSets)
2632 else
2634 plan->numCols, 0, plan->grpColIdx,
2635 NULL, NULL, NULL,
2636 ancestors, es);
2637
2639 }
2640}
2641
2642static void
2645{
2647 bool useprefix;
2649
2650
2652 planstate->plan,
2653 ancestors);
2655
2656 ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es);
2657
2659 context, useprefix, ancestors, es);
2660
2661 foreach(lc, agg->chain)
2662 {
2665
2667 context, useprefix, ancestors, es);
2668 }
2669
2671}
2672
2673static void
2675 Agg *aggnode, Sort *sortnode,
2678{
2680 char *exprstr;
2683 AttrNumber *keycols = aggnode->grpColIdx;
2684 const char *keyname;
2685 const char *keysetname;
2686
2688 {
2689 keyname = "Hash Key";
2690 keysetname = "Hash Keys";
2691 }
2692 else
2693 {
2694 keyname = "Group Key";
2695 keysetname = "Group Keys";
2696 }
2697
2699
2700 if (sortnode)
2701 {
2703 sortnode->numCols, 0, sortnode->sortColIdx,
2704 sortnode->sortOperators, sortnode->collations,
2705 sortnode->nullsFirst,
2706 ancestors, es);
2709 }
2710
2712
2713 foreach(lc, gsets)
2714 {
2717
2719 {
2723 keyresno);
2724
2725 if (!target)
2726 elog(ERROR, "no tlist entry for key %d", keyresno);
2727
2729 useprefix, true);
2730
2731 result = lappend(result, exprstr);
2732 }
2733
2736 else
2738 }
2739
2741
2744
2746}
2747
2748
2749
2750
2751static void
2754{
2756
2757
2758 ancestors = lcons(plan, ancestors);
2760 plan->numCols, 0, plan->grpColIdx,
2761 NULL, NULL, NULL,
2762 ancestors, es);
2764}
2765
2766
2767
2768
2769
2770
2771static void
2773 int nkeys, int nPresortedKeys, AttrNumber *keycols,
2774 Oid *sortOperators, Oid *collations, bool *nullsFirst,
2776{
2780 List *resultPresorted = NIL;
2782 bool useprefix;
2783 int keyno;
2784
2785 if (nkeys <= 0)
2786 return;
2787
2789
2790
2793 ancestors);
2795
2796 for (keyno = 0; keyno < nkeys; keyno++)
2797 {
2798
2799 AttrNumber keyresno = keycols[keyno];
2801 keyresno);
2802 char *exprstr;
2803
2804 if (!target)
2805 elog(ERROR, "no tlist entry for key %d", keyresno);
2806
2808 useprefix, true);
2811
2812 if (sortOperators != NULL)
2815 sortOperators[keyno],
2816 collations[keyno],
2817 nullsFirst[keyno]);
2818
2820 if (keyno < nPresortedKeys)
2821 resultPresorted = lappend(resultPresorted, exprstr);
2822 }
2823
2825 if (nPresortedKeys > 0)
2827}
2828
2829
2830
2831
2832
2833static void
2835 Oid sortOperator, Oid collation, bool nullsFirst)
2836{
2838 bool reverse = false;
2840
2843
2844
2845
2846
2847
2848
2849
2850
2852 {
2854
2855 if (collname == NULL)
2856 elog(ERROR, "cache lookup failed for collation %u", collation);
2858 }
2859
2860
2861 if (sortOperator == typentry->gt_opr)
2862 {
2864 reverse = true;
2865 }
2866 else if (sortOperator != typentry->lt_opr)
2867 {
2868 char *opname = get_opname(sortOperator);
2869
2870 if (opname == NULL)
2871 elog(ERROR, "cache lookup failed for operator %u", sortOperator);
2873
2875 }
2876
2877
2878 if (nullsFirst && !reverse)
2879 {
2881 }
2882 else if (!nullsFirst && reverse)
2883 {
2885 }
2886}
2887
2888
2889
2890
2891static void
2893{
2896 bool needspace = false;
2897
2900
2901
2902 ancestors = lcons(wagg, ancestors);
2904 {
2908 ancestors, es);
2909 needspace = true;
2910 }
2912 {
2913 if (needspace)
2918 ancestors, es);
2919 needspace = true;
2920 }
2923 {
2925 bool useprefix;
2926 char *framestr;
2927
2928
2930 (Plan *) wagg,
2931 ancestors);
2934 wagg->startOffset,
2935 wagg->endOffset,
2937 useprefix);
2938 if (needspace)
2941 pfree(framestr);
2942 }
2945 pfree(wbuf.data);
2946}
2947
2948
2949
2950
2951
2952
2953
2954static void
2958{
2961 bool useprefix;
2962
2963
2966 ancestors);
2968
2969 for (int keyno = 0; keyno < nkeys; keyno++)
2970 {
2971
2972 AttrNumber keyresno = keycols[keyno];
2974 keyresno);
2975 char *exprstr;
2976
2977 if (!target)
2978 elog(ERROR, "no tlist entry for key %d", keyresno);
2979
2981 useprefix, true);
2982 if (keyno > 0)
2986
2987
2988
2989
2990
2991
2992 }
2993}
2994
2995
2996
2997
2998static void
3000{
3002
3004 {
3007 }
3008 else
3009 {
3012 "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n",
3013 maxStorageType,
3014 maxSpaceUsedKB);
3015 }
3016}
3017
3018
3019
3020
3021static void
3024{
3026 bool useprefix;
3027 char *method_name;
3029 char *repeatable;
3031
3032
3034 planstate->plan,
3035 ancestors);
3037
3038
3040
3041
3042 foreach(lc, tsc->args)
3043 {
3045
3046 params = lappend(params,
3048 useprefix, false));
3049 }
3052 useprefix, false);
3053 else
3054 repeatable = NULL;
3055
3056
3058 {
3059 bool first = true;
3060
3063 foreach(lc, params)
3064 {
3065 if (!first)
3068 first = false;
3069 }
3071 if (repeatable)
3074 }
3075 else
3076 {
3079 if (repeatable)
3081 }
3082}
3083
3084
3085
3086
3087static void
3089{
3091 return;
3092
3094 {
3097 const char *sortMethod;
3098 const char *spaceType;
3099 int64 spaceUsed;
3100
3104 spaceUsed = stats.spaceUsed;
3105
3107 {
3110 sortMethod, spaceType, spaceUsed);
3111 }
3112 else
3113 {
3117 }
3118 }
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3130 {
3131 int n;
3132
3134 {
3136 const char *sortMethod;
3137 const char *spaceType;
3138 int64 spaceUsed;
3139
3142 continue;
3145 spaceUsed = sinstrument->spaceUsed;
3146
3149
3151 {
3155 sortMethod, spaceType, spaceUsed);
3156 }
3157 else
3158 {
3162 }
3163
3166 }
3167 }
3168}
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178static void
3180 const char *groupLabel, bool indent, ExplainState *es)
3181{
3184
3185
3187 {
3189
3190 if (groupInfo->sortMethods & sortMethod)
3191 {
3193
3194 methodNames = lappend(methodNames, unconstify(char *, methodName));
3195 }
3196 }
3197
3199 {
3200 if (indent)
3204
3207 else
3209 foreach(methodCell, methodNames)
3210 {
3214 }
3215
3217 {
3219 const char *spaceTypeName;
3220
3223 spaceTypeName, avgSpace,
3225 }
3226
3228 {
3230
3231 const char *spaceTypeName;
3232
3235 spaceTypeName, avgSpace,
3237 }
3238 }
3239 else
3240 {
3242
3247
3249
3251 {
3253 const char *spaceTypeName;
3255
3258 appendStringInfo(&memoryName, "Sort Space %s", spaceTypeName);
3260
3264
3266 }
3268 {
3270 const char *spaceTypeName;
3272
3275 appendStringInfo(&diskName, "Sort Space %s", spaceTypeName);
3277
3281
3283 }
3284
3286 }
3287}
3288
3289
3290
3291
3292static void
3295{
3298
3300
3302 return;
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313 if (fullsortGroupInfo->groupCount > 0)
3314 {
3317 if (prefixsortGroupInfo->groupCount > 0)
3318 {
3322 }
3325 }
3326
3328 {
3329 int n;
3330 bool indent_first_line;
3331
3333 {
3336
3337
3338
3339
3340
3341
3343
3344
3345
3346
3347
3348
3349
3350 if (fullsortGroupInfo->groupCount == 0)
3351 continue;
3352
3355
3358 indent_first_line, es);
3360 if (prefixsortGroupInfo->groupCount > 0)
3361 {
3365 }
3368
3371 }
3372 }
3373}
3374
3375
3376
3377
3378static void
3380{
3382
3383
3384
3385
3386
3387
3388
3389
3390
3392 memcpy(&hinstrument, hashstate->hinstrument,
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3405 {
3407 int i;
3408
3410 {
3412
3423 }
3424 }
3425
3426 if (hinstrument.nbatch > 0)
3427 {
3429
3431 {
3437 hinstrument.nbatch, es);
3441 spacePeakKb, es);
3442 }
3445 {
3448 "Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: " UINT64_FORMAT "kB\n",
3453 spacePeakKb);
3454 }
3455 else
3456 {
3459 "Buckets: %d Batches: %d Memory Usage: " UINT64_FORMAT "kB\n",
3461 spacePeakKb);
3462 }
3463 }
3464}
3465
3466
3467
3468
3469
3470static void
3472{
3473 char *maxStorageType;
3474 int64 maxSpaceUsed;
3475
3477
3478
3479
3480
3481
3482 if (!es->analyze || tupstore == NULL)
3483 return;
3484
3487}
3488
3489
3490
3491
3492
3493static void
3495{
3496 char *maxStorageType;
3497 int64 maxSpaceUsed;
3498
3500
3501
3502
3503
3504
3505 if (!es->analyze || tupstore == NULL)
3506 return;
3507
3510}
3511
3512
3513
3514
3515
3516static void
3518{
3519 char *maxStorageType;
3520 int64 maxSpaceUsed;
3521
3523
3524 if (!es->analyze || tupstore == NULL)
3525 return;
3526
3529}
3530
3531
3532
3533
3534
3535static void
3537{
3538 char *maxStorageType;
3539 int64 maxSpaceUsed;
3540
3542
3543 if (!es->analyze || tupstore == NULL)
3544 return;
3545
3548}
3549
3550
3551
3552
3553
3554static void
3556{
3557 char *maxStorageType,
3558 *tempStorageType;
3559 int64 maxSpaceUsed,
3560 tempSpaceUsed;
3561
3563 return;
3564
3565
3566
3567
3568
3569
3571 &tempSpaceUsed);
3573 &maxSpaceUsed);
3574
3575 if (tempSpaceUsed > maxSpaceUsed)
3576 maxStorageType = tempStorageType;
3577
3578 maxSpaceUsed += tempSpaceUsed;
3580}
3581
3582
3583
3584
3585static void
3587{
3593 bool useprefix;
3594 int64 memPeakKb;
3595
3597
3598
3599
3600
3601
3603
3604
3607 ancestors);
3608
3609 foreach(lc, ((Memoize *) plan)->param_exprs)
3610 {
3612
3614
3616 useprefix, false));
3618 }
3619
3622
3624
3626 return;
3627
3629 {
3630
3631
3632
3633
3636 else
3638
3640 {
3646 }
3647 else
3648 {
3656 memPeakKb);
3657 }
3658 }
3659
3661 return;
3662
3663
3665 {
3667
3669
3670
3671
3672
3673
3675 continue;
3676
3679
3680
3681
3682
3683
3684
3685
3687
3689 {
3695 memPeakKb);
3696 }
3697 else
3698 {
3708 es);
3709 }
3710
3713 }
3714}
3715
3716
3717
3718
3719static void
3721{
3724
3727 return;
3728
3730 {
3734
3735
3736
3737
3738
3739
3741 {
3747 }
3748 }
3749 else
3750 {
3751 bool gotone = false;
3752
3754 {
3758 gotone = true;
3759 }
3760
3761
3762
3763
3764
3765
3767 {
3768 if (!gotone)
3770 else
3772
3775 gotone = true;
3776
3777
3779 {
3782 }
3783 }
3784
3785 if (gotone)
3787 }
3788
3789
3791 {
3793 {
3795 uint64 hash_disk_used;
3796 int hash_batches_used;
3797
3799
3801 continue;
3805
3808
3810 {
3812
3814 hash_batches_used, memPeakKb);
3815
3816
3817 if (hash_batches_used > 1)
3819 hash_disk_used);
3821 }
3822 else
3823 {
3825 hash_batches_used, es);
3827 es);
3829 }
3830
3833 }
3834 }
3835}
3836
3837
3838
3839
3840
3841static void
3843{
3846 uint64 nsearches = 0;
3847
3849 return;
3850
3851
3853 {
3854 case T_IndexScan:
3855 {
3857
3860 break;
3861 }
3862 case T_IndexOnlyScan:
3863 {
3865
3868 break;
3869 }
3870 case T_BitmapIndexScan:
3871 {
3873
3876 break;
3877 }
3878 default:
3879 break;
3880 }
3881
3882
3883 if (SharedInfo)
3884 {
3886 {
3888
3889 nsearches += winstrument->nsearches;
3890 }
3891 }
3892
3894}
3895
3896
3897
3898
3899static void
3901{
3903 return;
3904
3906 {
3911 }
3912 else
3913 {
3915 {
3923 }
3924 }
3925
3926
3927 if (planstate->pstate != NULL)
3928 {
3930 {
3932
3934 continue;
3935
3938
3940 {
3948 }
3949 else
3950 {
3955 }
3956
3959 }
3960 }
3961}
3962
3963
3964
3965
3966
3967
3968static void
3971{
3972 double nfiltered;
3973 double nloops;
3974
3976 return;
3977
3978 if (which == 2)
3980 else
3983
3984
3986 {
3987 if (nloops > 0)
3989 else
3991 }
3992}
3993
3994
3995
3996
3997static void
3999{
4001
4002
4004 {
4007 }
4008 else
4009 {
4012 }
4013}
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025static const char *
4027{
4028 const char *result;
4029
4031 result = (*explain_get_index_name_hook) (indexId);
4032 else
4033 result = NULL;
4034 if (result == NULL)
4035 {
4036
4038 if (result == NULL)
4039 elog(ERROR, "cache lookup failed for index %u", indexId);
4040 }
4041 return result;
4042}
4043
4044
4045
4046
4047
4048
4049static bool
4051{
4052 bool has_shared;
4053 bool has_local;
4054 bool has_temp;
4055 bool has_shared_timing;
4056 bool has_local_timing;
4057 bool has_temp_timing;
4058
4059 if (usage == NULL)
4060 return false;
4061
4063 return true;
4064
4065 has_shared = (usage->shared_blks_hit > 0 ||
4066 usage->shared_blks_read > 0 ||
4067 usage->shared_blks_dirtied > 0 ||
4068 usage->shared_blks_written > 0);
4069 has_local = (usage->local_blks_hit > 0 ||
4070 usage->local_blks_read > 0 ||
4071 usage->local_blks_dirtied > 0 ||
4072 usage->local_blks_written > 0);
4073 has_temp = (usage->temp_blks_read > 0 ||
4074 usage->temp_blks_written > 0);
4081
4082 return has_shared || has_local || has_temp || has_shared_timing ||
4083 has_local_timing || has_temp_timing;
4084}
4085
4086
4087
4088
4089static void
4091{
4093 {
4094 bool has_shared = (usage->shared_blks_hit > 0 ||
4095 usage->shared_blks_read > 0 ||
4096 usage->shared_blks_dirtied > 0 ||
4097 usage->shared_blks_written > 0);
4098 bool has_local = (usage->local_blks_hit > 0 ||
4099 usage->local_blks_read > 0 ||
4100 usage->local_blks_dirtied > 0 ||
4101 usage->local_blks_written > 0);
4102 bool has_temp = (usage->temp_blks_read > 0 ||
4103 usage->temp_blks_written > 0);
4110
4111
4112 if (has_shared || has_local || has_temp)
4113 {
4116
4117 if (has_shared)
4118 {
4120 if (usage->shared_blks_hit > 0)
4122 usage->shared_blks_hit);
4123 if (usage->shared_blks_read > 0)
4125 usage->shared_blks_read);
4126 if (usage->shared_blks_dirtied > 0)
4128 usage->shared_blks_dirtied);
4129 if (usage->shared_blks_written > 0)
4131 usage->shared_blks_written);
4132 if (has_local || has_temp)
4134 }
4135 if (has_local)
4136 {
4138 if (usage->local_blks_hit > 0)
4140 usage->local_blks_hit);
4141 if (usage->local_blks_read > 0)
4143 usage->local_blks_read);
4144 if (usage->local_blks_dirtied > 0)
4146 usage->local_blks_dirtied);
4147 if (usage->local_blks_written > 0)
4149 usage->local_blks_written);
4150 if (has_temp)
4152 }
4153 if (has_temp)
4154 {
4156 if (usage->temp_blks_read > 0)
4158 usage->temp_blks_read);
4159 if (usage->temp_blks_written > 0)
4161 usage->temp_blks_written);
4162 }
4164 }
4165
4166
4167 if (has_shared_timing || has_local_timing || has_temp_timing)
4168 {
4171
4172 if (has_shared_timing)
4173 {
4181 if (has_local_timing || has_temp_timing)
4183 }
4184 if (has_local_timing)
4185 {
4193 if (has_temp_timing)
4195 }
4196 if (has_temp_timing)
4197 {
4205 }
4207 }
4208 }
4209 else
4210 {
4212 usage->shared_blks_hit, es);
4214 usage->shared_blks_read, es);
4216 usage->shared_blks_dirtied, es);
4218 usage->shared_blks_written, es);
4220 usage->local_blks_hit, es);
4222 usage->local_blks_read, es);
4224 usage->local_blks_dirtied, es);
4226 usage->local_blks_written, es);
4228 usage->temp_blks_read, es);
4230 usage->temp_blks_written, es);
4232 {
4235 3, es);
4238 3, es);
4241 3, es);
4244 3, es);
4247 3, es);
4250 3, es);
4251 }
4252 }
4253}
4254
4255
4256
4257
4258static void
4260{
4262 {
4263
4264 if ((usage->wal_records > 0) || (usage->wal_fpi > 0) ||
4265 (usage->wal_bytes > 0) || (usage->wal_buffers_full > 0))
4266 {
4269
4270 if (usage->wal_records > 0)
4272 usage->wal_records);
4273 if (usage->wal_fpi > 0)
4275 usage->wal_fpi);
4276 if (usage->wal_bytes > 0)
4278 usage->wal_bytes);
4279 if (usage->wal_buffers_full > 0)
4281 usage->wal_buffers_full);
4283 }
4284 }
4285 else
4286 {
4288 usage->wal_records, es);
4290 usage->wal_fpi, es);
4292 usage->wal_bytes, es);
4294 usage->wal_buffers_full, es);
4295 }
4296}
4297
4298
4299
4300
4301static void
4303{
4307
4309 {
4313 memUsedkB, memAllocatedkB);
4315 }
4316 else
4317 {
4320 }
4321}
4322
4323
4324
4325
4326
4327static void
4330{
4332
4334 {
4338 }
4339 else
4340 {
4341 const char *scandir;
4342
4343 switch (indexorderdir)
4344 {
4346 scandir = "Backward";
4347 break;
4349 scandir = "Forward";
4350 break;
4351 default:
4352 scandir = "???";
4353 break;
4354 }
4357 }
4358}
4359
4360
4361
4362
4363static void
4365{
4367}
4368
4369
4370
4371
4372
4373
4374
4375
4376static void
4378{
4380}
4381
4382
4383
4384
4385static void
4387{
4388 char *objectname = NULL;
4389 char *namespace = NULL;
4390 const char *objecttag = NULL;
4392 char *refname;
4393
4396 if (refname == NULL)
4397 refname = rte->eref->aliasname;
4398
4400 {
4401 case T_SeqScan:
4402 case T_SampleScan:
4403 case T_IndexScan:
4404 case T_IndexOnlyScan:
4405 case T_BitmapHeapScan:
4406 case T_TidScan:
4407 case T_TidRangeScan:
4408 case T_ForeignScan:
4409 case T_CustomScan:
4410 case T_ModifyTable:
4411
4416 objecttag = "Relation Name";
4417 break;
4418 case T_FunctionScan:
4419 {
4421
4422
4424
4425
4426
4427
4428
4429
4430
4432 {
4434
4436 {
4439
4443 }
4444 }
4445 objecttag = "Function Name";
4446 }
4447 break;
4448 case T_TableFuncScan:
4449 {
4451
4453 switch (tablefunc->functype)
4454 {
4456 objectname = "xmltable";
4457 break;
4459 objectname = "json_table";
4460 break;
4461 default:
4462 elog(ERROR, "invalid TableFunc type %d",
4464 }
4465 objecttag = "Table Function Name";
4466 }
4467 break;
4468 case T_ValuesScan:
4470 break;
4471 case T_CteScan:
4472
4474 Assert(!rte->self_reference);
4475 objectname = rte->ctename;
4476 objecttag = "CTE Name";
4477 break;
4478 case T_NamedTuplestoreScan:
4480 objectname = rte->enrname;
4481 objecttag = "Tuplestore Name";
4482 break;
4483 case T_WorkTableScan:
4484
4486 Assert(rte->self_reference);
4487 objectname = rte->ctename;
4488 objecttag = "CTE Name";
4489 break;
4490 default:
4491 break;
4492 }
4493
4495 {
4497 if (namespace != NULL)
4500 else if (objectname != NULL)
4502 if (objectname == NULL || strcmp(refname, objectname) != 0)
4504 }
4505 else
4506 {
4507 if (objecttag != NULL && objectname != NULL)
4509 if (namespace != NULL)
4512 }
4513}
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523static void
4526{
4528 const char *operation;
4529 const char *foperation;
4530 bool labeltargets;
4531 int j;
4534
4536 {
4538 operation = "Insert";
4539 foperation = "Foreign Insert";
4540 break;
4542 operation = "Update";
4543 foperation = "Foreign Update";
4544 break;
4546 operation = "Delete";
4547 foperation = "Foreign Delete";
4548 break;
4550 operation = "Merge";
4551
4552 foperation = "Foreign Merge";
4553 break;
4554 default:
4555 operation = "???";
4556 foperation = "Foreign ???";
4557 break;
4558 }
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569 labeltargets = (mtstate->mt_nrels > 1 ||
4574
4575 if (labeltargets)
4576 ExplainOpenGroup("Target Tables", "Target Tables", false, es);
4577
4579 {
4582
4583 if (labeltargets)
4584 {
4585
4587
4588
4589
4590
4591
4593 {
4596 fdwroutine ? foperation : operation);
4597 }
4598
4599
4602 es);
4603
4605 {
4608 }
4609 }
4610
4611
4613 fdwroutine != NULL &&
4615 {
4617
4619 resultRelInfo,
4620 fdw_private,
4621 j,
4622 es);
4623 }
4624
4625 if (labeltargets)
4626 {
4627
4630
4631
4633 }
4634 }
4635
4636
4638 {
4640
4641 idxNames = lappend(idxNames, indexname);
4642 }
4643
4645 {
4648 "NOTHING" : "UPDATE",
4649 es);
4650
4651
4652
4653
4654
4655 if (idxNames)
4657
4658
4660 {
4662 &mtstate->ps, ancestors, es);
4664 }
4665
4666
4668 {
4669 double total;
4670 double insert_path;
4671 double other_path;
4672
4674
4675
4676 total = outerPlanState(mtstate)->instrument->ntuples;
4678 insert_path = total - other_path;
4679
4681 insert_path, 0, es);
4683 other_path, 0, es);
4684 }
4685 }
4687 {
4688
4690 {
4691 double total;
4692 double insert_path;
4693 double update_path;
4694 double delete_path;
4695 double skipped_path;
4696
4698
4699
4700 total = outerPlanState(mtstate)->instrument->ntuples;
4704 skipped_path = total - insert_path - update_path - delete_path;
4705 Assert(skipped_path >= 0);
4706
4708 {
4709 if (total > 0)
4710 {
4713 if (insert_path > 0)
4715 if (update_path > 0)
4717 if (delete_path > 0)
4719 if (skipped_path > 0)
4722 }
4723 }
4724 else
4725 {
4730 }
4731 }
4732 }
4733
4734 if (labeltargets)
4736}
4737
4738
4739
4740
4741
4742
4743
4744
4745static void
4748{
4749 int j;
4750
4751 for (j = 0; j < nplans; j++)
4753 "Member", NULL, es);
4754}
4755
4756
4757
4758
4759
4760
4761
4762
4763static void
4765{
4768 nchildren - nplans, es);
4769}
4770
4771
4772
4773
4774
4775
4776
4777static void
4780{
4782
4783 foreach(lst, plans)
4784 {
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4799 continue;
4802
4803
4804
4805
4806
4807
4808 ancestors = lcons(sp, ancestors);
4809
4811 relationship, sp->plan_name, es);
4812
4814 }
4815}
4816
4817
4818
4819
4820static void
4822{
4824 const char *label =
4826
4829}
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4844{
4846
4853 return wstate;
4854}
4855
4856
4857
4858
4859static void
4861{
4863
4865 Assert(n >= 0 && n < wstate->num_workers);
4866
4867
4869
4871 {
4872
4875
4876
4877
4878
4879
4880
4882
4883
4884
4885
4886
4889
4891 }
4892 else
4893 {
4894
4896
4897
4899 }
4900
4901
4902
4903
4904
4905
4907 {
4909 {
4912 }
4913
4915 }
4916}
4917
4918
4919
4920
4921static void
4923{
4925
4927 Assert(n >= 0 && n < wstate->num_workers);
4929
4930
4931
4932
4933
4935
4936
4937
4938
4939
4940
4941
4943 {
4946
4948 }
4949
4950
4952}
4953
4954
4955
4956
4957static void
4959{
4961
4964 {
4966 {
4967
4971
4973 }
4974 }
4976
4981}
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
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_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, 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, 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)