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{

3183 List *methodNames = NIL;

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 {

4908 if (es->str->len == 0)

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)