PostgreSQL Source Code: src/backend/commands/explain.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15

47

48

49

51

52

54

55

58

59

60

61

62

63#define BYTES_TO_KILOBYTES(b) (((b) + 1023) / 1024)

64

77 const char *relationship, const char *plan_name,

84static void show_qual(List *qual, const char *qlabel,

104 Agg *aggnode, Sort *sortnode,

105 List *context, bool useprefix,

110 int nkeys, int nPresortedKeys, AttrNumber *keycols,

111 Oid *sortOperators, Oid *collations, bool *nullsFirst,

114 Oid sortOperator, Oid collation, bool nullsFirst);

168

169

170

171

172

173

174

175void

178{

183 List *rewritten;

184

185

187

188

192

194 (*post_parse_analyze_hook) (pstate, query, jstate);

195

196

197

198

199

200

201

203

204

206

207 if (rewritten == NIL)

208 {

209

210

211

212

215 }

216 else

217 {

219

220

221 foreach(l, rewritten)

222 {

225 pstate, params);

226

227

228 if (lnext(rewritten, l) != NULL)

230 }

231 }

232

233

236

237

242 else

245

247}

248

249

250

251

252

255{

258 Oid result_type = TEXTOID;

259

260

261 foreach(lc, stmt->options)

262 {

264

265 if (strcmp(opt->defname, "format") == 0)

266 {

268

269 if (strcmp(p, "xml") == 0)

270 result_type = XMLOID;

271 else if (strcmp(p, "json") == 0)

272 result_type = JSONOID;

273 else

274 result_type = TEXTOID;

275

276 }

277 }

278

279

282 result_type, -1, 0);

283 return tupdesc;

284}

285

286

287

288

289

290

291

292static void

296{

297

299 {

301 return;

302 }

303

304

306 (*ExplainOneQuery_hook) (query, cursorOptions, into, es,

308 else

311}

312

313

314

315

316

317void

322{

325 planduration;

327 bufusage;

331

333 {

334

335

336

337

338

339

340

341

343 "explain analyze planner context",

346 }

347

351

352

354

357

359 {

362 }

363

364

366 {

367 memset(&bufusage, 0, sizeof(BufferUsage));

369 }

370

371

373 queryEnv,

374 &planduration, (es->buffers ? &bufusage : NULL),

375 es->memory ? &mem_counters : NULL);

376}

377

378

379

380

381

382

383

384

385

386

387

388

389

390void

393{

394 if (utilityStmt == NULL)

395 return;

396

398 {

399

400

401

402

404 Query *ctas_query;

405 List *rewritten;

407

408

409

410

411

413 {

418 else

419 elog(ERROR, "unexpected object type: %d",

421 return;

422 }

423

428 (*post_parse_analyze_hook) (pstate, ctas_query, jstate);

433 pstate, params);

434 }

436 {

437

438

439

440

441

442

443

444

446 Query *dcs_query;

447 List *rewritten;

449

454 (*post_parse_analyze_hook) (pstate, dcs_query, jstate);

455

460 pstate, params);

461 }

464 pstate, params);

466 {

469 else

471 }

472 else

473 {

476 "Utility statements have no plan structure\n");

477 else

479 }

480}

481

482

483

484

485

486

487

488

489

490

491

492

493

494void

502{

506 double totaltime = 0;

507 int eflags;

508 int instrument_option = 0;

510

512

517

520 if (es->wal)

522

523

524

525

526

527

529

530

531

532

533

536

537

538

539

540

541

542

543

544

545 if (into)

549 else

551

552

553 queryDesc = CreateQueryDesc(plannedstmt, cplan, queryString,

555 dest, params, queryEnv, instrument_option);

556

557

559 eflags = 0;

560 else

564 if (into)

566

567

568 if (queryDesc->cplan)

569 {

572 }

573 else

574 {

576 elog(ERROR, "ExecutorStart() failed unexpectedly");

577 }

578

579

581 {

583

584

587 else

589

590

592

593

595

596

598 }

599

600

603

604

606

608

609

611

612

614 {

616

618 {

622 }

623

624 if (bufusage)

626

627 if (mem_counters)

629

632

634 }

635

636 if (es->summary && planduration)

637 {

639

641 }

642

643

646

647

648

649

650

651

652

655

656

659

660

662 (*explain_per_plan_hook) (plannedstmt, into, es, queryString,

663 params, queryEnv);

664

665

666

667

668

670

672

674

676

677

680

682

683

684

685

686

687

688

691 es);

692

694}

695

696

697

698

699

700static void

702{

703 int num;

705

706

708 return;

709

710

712

714 {

716

717 for (int i = 0; i < num; i++)

718 {

719 char *setting;

721

723

725 }

726

728 }

729 else

730 {

732

733

734 if (num <= 0)

735 return;

736

738

739 for (int i = 0; i < num; i++)

740 {

741 char *setting;

743

744 if (i > 0)

746

748

749 if (setting)

751 else

753 }

754

756 }

757}

758

759

760

761

762

763

764

765

766

767

768

769

770void

772{

776

777

787 foreach(lc, es->rtable)

788 {

790

792 {

794 break;

795 }

796 }

797

798

799

800

801

802

803

804

805

806

809 {

812 }

814

815

816

817

818

820

821

822

823

824

825

828 {

829

830

831

832

835 }

836}

837

838

839

840

841

842

843

844

845

846

847void

849{

851 bool show_relname;

852 List *resultrels;

853 List *routerels;

854 List *targrels;

856

860

862

863 show_relname = (list_length(resultrels) > 1 ||

864 routerels != NIL || targrels != NIL);

865 foreach(l, resultrels)

866 {

869 }

870

871 foreach(l, routerels)

872 {

875 }

876

877 foreach(l, targrels)

878 {

881 }

882

884}

885

886

887

888

889

890void

892{

894

896 return;

897

898

899

900

901

904

905

908

910}

911

912

913

914

915

916static void

918{

920

921

923 return;

924

925

927

932

934

935

937 {

941

943

946 "Inlining", jit_flags & PGJIT_INLINE ? "true" : "false",

947 "Optimization", jit_flags & PGJIT_OPT3 ? "true" : "false",

948 "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",

949 "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");

950

952 {

955 "Timing: %s %.3f ms (%s %.3f ms), %s %.3f ms, %s %.3f ms, %s %.3f ms, %s %.3f ms\n",

962 }

963

965 }

966 else

967 {

969

976

978 {

980

984 3, es);

987 3, es);

989

992 3, es);

995 3, es);

998 3, es);

1001 3, es);

1002

1004 }

1005 }

1006

1008}

1009

1010

1011

1012

1013

1014static void

1016{

1018

1019

1022 else

1023 {

1026 }

1027

1028 ExplainOpenGroup("Serialization", "Serialization", true, es);

1029

1031 {

1038 else

1042

1044 {

1048 }

1049 }

1050 else

1051 {

1055 3, es);

1061 }

1062

1064}

1065

1066

1067

1068

1069

1070

1071

1072

1073

1074void

1076{

1079}

1080

1081

1082

1083

1084

1085

1086

1087

1088

1089void

1091{

1092 char *str;

1093

1094

1095 if (params == NULL || params->numParams <= 0 || maxlen == 0)

1096 return;

1097

1099 if (str && str[0] != '\0')

1101}

1102

1103

1104

1105

1106

1107static void

1109{

1110 int nt;

1111

1113 return;

1115 {

1119 char *conname = NULL;

1120

1121

1123

1124

1125

1126

1127

1128 if (instr->ntuples == 0)

1129 continue;

1130

1132

1136

1137

1138

1139

1140

1141

1143 {

1144 if (es->verbose || conname == NULL)

1146 else

1148 if (conname)

1150 if (show_relname)

1155 else

1157 }

1158 else

1159 {

1161 if (conname)

1166 es);

1168 }

1169

1170 if (conname)

1172

1174 }

1175}

1176

1177

1178static double

1180{

1182

1186}

1187

1188

1189

1190

1191

1192

1193

1194

1195

1196

1197static bool

1199{

1201

1203 {

1204 case T_SeqScan:

1205 case T_SampleScan:

1206 case T_IndexScan:

1207 case T_IndexOnlyScan:

1208 case T_BitmapHeapScan:

1209 case T_TidScan:

1210 case T_TidRangeScan:

1211 case T_SubqueryScan:

1212 case T_FunctionScan:

1213 case T_TableFuncScan:

1214 case T_ValuesScan:

1215 case T_CteScan:

1216 case T_NamedTuplestoreScan:

1217 case T_WorkTableScan:

1219 ((Scan *) plan)->scanrelid);

1220 break;

1221 case T_ForeignScan:

1224 break;

1225 case T_CustomScan:

1228 break;

1229 case T_ModifyTable:

1235 break;

1236 case T_Append:

1239 break;

1240 case T_MergeAppend:

1243 break;

1244 default:

1245 break;

1246 }

1247

1249}

1250

1251

1252

1253

1254

1255

1256

1257static bool

1259{

1260 int child_disabled_nodes;

1261

1262

1263 if (plan->disabled_nodes == 0)

1264 return false;

1265

1266 child_disabled_nodes = 0;

1267

1268

1269

1270

1271

1273 {

1276

1277

1278

1279

1280

1281

1283 {

1285

1287 }

1288 }

1290 {

1293

1294

1295

1296

1297

1298

1300 {

1302

1304 }

1305 }

1307 child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes;

1309 {

1312

1314 {

1316

1318 }

1319 }

1320 else

1321 {

1322

1323

1324

1326 child_disabled_nodes += outerPlan(plan)->disabled_nodes;

1328 child_disabled_nodes += innerPlan(plan)->disabled_nodes;

1329 }

1330

1331

1332

1333

1334

1335 if (plan->disabled_nodes > child_disabled_nodes)

1336 return true;

1337

1338 return false;

1339}

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

1359

1360

1361

1362static void

1364 const char *relationship, const char *plan_name,

1366{

1368 const char *pname;

1369 const char *sname;

1370 const char *strategy = NULL;

1371 const char *partialmode = NULL;

1372 const char *operation = NULL;

1373 const char *custom_name = NULL;

1375 int save_indent = es->indent;

1376 bool haschildren;

1377 bool isdisabled;

1378

1379

1380

1381

1382

1385 else

1387

1388

1390 {

1391 case T_Result:

1392 pname = sname = "Result";

1393 break;

1394 case T_ProjectSet:

1395 pname = sname = "ProjectSet";

1396 break;

1397 case T_ModifyTable:

1398 sname = "ModifyTable";

1400 {

1402 pname = operation = "Insert";

1403 break;

1405 pname = operation = "Update";

1406 break;

1408 pname = operation = "Delete";

1409 break;

1411 pname = operation = "Merge";

1412 break;

1413 default:

1414 pname = "???";

1415 break;

1416 }

1417 break;

1418 case T_Append:

1419 pname = sname = "Append";

1420 break;

1421 case T_MergeAppend:

1422 pname = sname = "Merge Append";

1423 break;

1424 case T_RecursiveUnion:

1425 pname = sname = "Recursive Union";

1426 break;

1427 case T_BitmapAnd:

1428 pname = sname = "BitmapAnd";

1429 break;

1430 case T_BitmapOr:

1431 pname = sname = "BitmapOr";

1432 break;

1433 case T_NestLoop:

1434 pname = sname = "Nested Loop";

1435 break;

1436 case T_MergeJoin:

1437 pname = "Merge";

1438 sname = "Merge Join";

1439 break;

1440 case T_HashJoin:

1441 pname = "Hash";

1442 sname = "Hash Join";

1443 break;

1444 case T_SeqScan:

1445 pname = sname = "Seq Scan";

1446 break;

1447 case T_SampleScan:

1448 pname = sname = "Sample Scan";

1449 break;

1450 case T_Gather:

1451 pname = sname = "Gather";

1452 break;

1453 case T_GatherMerge:

1454 pname = sname = "Gather Merge";

1455 break;

1456 case T_IndexScan:

1457 pname = sname = "Index Scan";

1458 break;

1459 case T_IndexOnlyScan:

1460 pname = sname = "Index Only Scan";

1461 break;

1462 case T_BitmapIndexScan:

1463 pname = sname = "Bitmap Index Scan";

1464 break;

1465 case T_BitmapHeapScan:

1466 pname = sname = "Bitmap Heap Scan";

1467 break;

1468 case T_TidScan:

1469 pname = sname = "Tid Scan";

1470 break;

1471 case T_TidRangeScan:

1472 pname = sname = "Tid Range Scan";

1473 break;

1474 case T_SubqueryScan:

1475 pname = sname = "Subquery Scan";

1476 break;

1477 case T_FunctionScan:

1478 pname = sname = "Function Scan";

1479 break;

1480 case T_TableFuncScan:

1481 pname = sname = "Table Function Scan";

1482 break;

1483 case T_ValuesScan:

1484 pname = sname = "Values Scan";

1485 break;

1486 case T_CteScan:

1487 pname = sname = "CTE Scan";

1488 break;

1489 case T_NamedTuplestoreScan:

1490 pname = sname = "Named Tuplestore Scan";

1491 break;

1492 case T_WorkTableScan:

1493 pname = sname = "WorkTable Scan";

1494 break;

1495 case T_ForeignScan:

1496 sname = "Foreign Scan";

1498 {

1500 pname = "Foreign Scan";

1501 operation = "Select";

1502 break;

1504 pname = "Foreign Insert";

1505 operation = "Insert";

1506 break;

1508 pname = "Foreign Update";

1509 operation = "Update";

1510 break;

1512 pname = "Foreign Delete";

1513 operation = "Delete";

1514 break;

1515 default:

1516 pname = "???";

1517 break;

1518 }

1519 break;

1520 case T_CustomScan:

1521 sname = "Custom Scan";

1522 custom_name = ((CustomScan *) plan)->methods->CustomName;

1523 if (custom_name)

1524 pname = psprintf("Custom Scan (%s)", custom_name);

1525 else

1526 pname = sname;

1527 break;

1528 case T_Material:

1529 pname = sname = "Materialize";

1530 break;

1531 case T_Memoize:

1532 pname = sname = "Memoize";

1533 break;

1534 case T_Sort:

1535 pname = sname = "Sort";

1536 break;

1537 case T_IncrementalSort:

1538 pname = sname = "Incremental Sort";

1539 break;

1540 case T_Group:

1541 pname = sname = "Group";

1542 break;

1543 case T_Agg:

1544 {

1546

1547 sname = "Aggregate";

1549 {

1551 pname = "Aggregate";

1552 strategy = "Plain";

1553 break;

1555 pname = "GroupAggregate";

1556 strategy = "Sorted";

1557 break;

1559 pname = "HashAggregate";

1560 strategy = "Hashed";

1561 break;

1563 pname = "MixedAggregate";

1564 strategy = "Mixed";

1565 break;

1566 default:

1567 pname = "Aggregate ???";

1568 strategy = "???";

1569 break;

1570 }

1571

1573 {

1574 partialmode = "Partial";

1575 pname = psprintf("%s %s", partialmode, pname);

1576 }

1578 {

1579 partialmode = "Finalize";

1580 pname = psprintf("%s %s", partialmode, pname);

1581 }

1582 else

1583 partialmode = "Simple";

1584 }

1585 break;

1586 case T_WindowAgg:

1587 pname = sname = "WindowAgg";

1588 break;

1589 case T_Unique:

1590 pname = sname = "Unique";

1591 break;

1592 case T_SetOp:

1593 sname = "SetOp";

1594 switch (((SetOp *) plan)->strategy)

1595 {

1597 pname = "SetOp";

1598 strategy = "Sorted";

1599 break;

1601 pname = "HashSetOp";

1602 strategy = "Hashed";

1603 break;

1604 default:

1605 pname = "SetOp ???";

1606 strategy = "???";

1607 break;

1608 }

1609 break;

1610 case T_LockRows:

1611 pname = sname = "LockRows";

1612 break;

1613 case T_Limit:

1614 pname = sname = "Limit";

1615 break;

1616 case T_Hash:

1617 pname = sname = "Hash";

1618 break;

1619 default:

1620 pname = sname = "???";

1621 break;

1622 }

1623

1625 relationship ? NULL : "Plan",

1626 true, es);

1627

1629 {

1630 if (plan_name)

1631 {

1635 }

1637 {

1641 }

1642 if (plan->parallel_aware)

1644 if (plan->async_capable)

1648 }

1649 else

1650 {

1652 if (strategy)

1654 if (partialmode)

1656 if (operation)

1658 if (relationship)

1660 if (plan_name)

1662 if (custom_name)

1666 }

1667

1669 {

1670 case T_SeqScan:

1671 case T_SampleScan:

1672 case T_BitmapHeapScan:

1673 case T_TidScan:

1674 case T_TidRangeScan:

1675 case T_SubqueryScan:

1676 case T_FunctionScan:

1677 case T_TableFuncScan:

1678 case T_ValuesScan:

1679 case T_CteScan:

1680 case T_WorkTableScan:

1682 break;

1683 case T_ForeignScan:

1684 case T_CustomScan:

1685 if (((Scan *) plan)->scanrelid > 0)

1687 break;

1688 case T_IndexScan:

1689 {

1691

1694 es);

1696 }

1697 break;

1698 case T_IndexOnlyScan:

1699 {

1701

1704 es);

1706 }

1707 break;

1708 case T_BitmapIndexScan:

1709 {

1711 const char *indexname =

1713

1717 else

1719 }

1720 break;

1721 case T_ModifyTable:

1723 break;

1724 case T_NestLoop:

1725 case T_MergeJoin:

1726 case T_HashJoin:

1727 {

1728 const char *jointype;

1729

1730 switch (((Join *) plan)->jointype)

1731 {

1733 jointype = "Inner";

1734 break;

1736 jointype = "Left";

1737 break;

1739 jointype = "Full";

1740 break;

1742 jointype = "Right";

1743 break;

1745 jointype = "Semi";

1746 break;

1748 jointype = "Anti";

1749 break;

1751 jointype = "Right Semi";

1752 break;

1754 jointype = "Right Anti";

1755 break;

1756 default:

1757 jointype = "???";

1758 break;

1759 }

1761 {

1762

1763

1764

1765

1770 }

1771 else

1773 }

1774 break;

1775 case T_SetOp:

1776 {

1777 const char *setopcmd;

1778

1780 {

1782 setopcmd = "Intersect";

1783 break;

1785 setopcmd = "Intersect All";

1786 break;

1788 setopcmd = "Except";

1789 break;

1791 setopcmd = "Except All";

1792 break;

1793 default:

1794 setopcmd = "???";

1795 break;

1796 }

1799 else

1801 }

1802 break;

1803 default:

1804 break;

1805 }

1806

1808 {

1810 {

1812 plan->startup_cost, plan->total_cost,

1813 plan->plan_rows, plan->plan_width);

1814 }

1815 else

1816 {

1818 2, es);

1820 2, es);

1822 0, es);

1824 es);

1825 }

1826 }

1827

1828

1829

1830

1831

1832

1833

1834

1835

1836

1837

1840

1843 {

1845 double startup_ms = 1000.0 * planstate->instrument->startup / nloops;

1846 double total_ms = 1000.0 * planstate->instrument->total / nloops;

1848

1850 {

1852

1855

1857 }

1858 else

1859 {

1861 {

1863 3, es);

1865 3, es);

1866 }

1869 }

1870 }

1872 {

1875 else

1876 {

1878 {

1881 }

1884 }

1885 }

1886

1887

1890

1891

1895

1896

1898 {

1900

1901 for (int n = 0; n < w->num_workers; n++)

1902 {

1904 double nloops = instrument->nloops;

1905 double startup_ms;

1906 double total_ms;

1907 double rows;

1908

1909 if (nloops <= 0)

1910 continue;

1911 startup_ms = 1000.0 * instrument->startup / nloops;

1912 total_ms = 1000.0 * instrument->total / nloops;

1913 rows = instrument->ntuples / nloops;

1914

1916

1918 {

1923

1925 }

1926 else

1927 {

1929 {

1931 startup_ms, 3, es);

1933 total_ms, 3, es);

1934 }

1935

1938 }

1939

1941 }

1942 }

1943

1944

1947

1948

1950 {

1951 case T_NestLoop:

1952 case T_MergeJoin:

1953 case T_HashJoin:

1954

1958 ((Join *) plan)->inner_unique,

1959 es);

1960 break;

1961 default:

1962 break;

1963 }

1964

1965

1967 {

1968 case T_IndexScan:

1970 "Index Cond", planstate, ancestors, es);

1973 planstate, es);

1975 "Order By", planstate, ancestors, es);

1977 if (plan->qual)

1979 planstate, es);

1981 break;

1982 case T_IndexOnlyScan:

1984 "Index Cond", planstate, ancestors, es);

1987 planstate, es);

1989 "Order By", planstate, ancestors, es);

1991 if (plan->qual)

1993 planstate, es);

1998 break;

1999 case T_BitmapIndexScan:

2001 "Index Cond", planstate, ancestors, es);

2003 break;

2004 case T_BitmapHeapScan:

2006 "Recheck Cond", planstate, ancestors, es);

2009 planstate, es);

2011 if (plan->qual)

2013 planstate, es);

2015 break;

2016 case T_SampleScan:

2018 planstate, ancestors, es);

2019

2020

2021 case T_SeqScan:

2022 case T_ValuesScan:

2023 case T_CteScan:

2024 case T_NamedTuplestoreScan:

2025 case T_WorkTableScan:

2026 case T_SubqueryScan:

2028 if (plan->qual)

2030 planstate, es);

2033 break;

2034 case T_Gather:

2035 {

2037

2039 if (plan->qual)

2041 planstate, es);

2044

2046 {

2047 int nworkers;

2048

2049 nworkers = ((GatherState *) planstate)->nworkers_launched;

2051 nworkers, es);

2052 }

2053

2056 }

2057 break;

2058 case T_GatherMerge:

2059 {

2061

2063 if (plan->qual)

2065 planstate, es);

2068

2070 {

2071 int nworkers;

2072

2073 nworkers = ((GatherMergeState *) planstate)->nworkers_launched;

2075 nworkers, es);

2076 }

2077 }

2078 break;

2079 case T_FunctionScan:

2081 {

2084

2086 {

2088

2090 }

2091

2093 "Function Call", planstate, ancestors,

2095 }

2097 if (plan->qual)

2099 planstate, es);

2100 break;

2101 case T_TableFuncScan:

2103 {

2105

2107 "Table Function Call", planstate, ancestors,

2109 }

2111 if (plan->qual)

2113 planstate, es);

2115 planstate), es);

2116 break;

2117 case T_TidScan:

2118 {

2119

2120

2121

2122

2124

2127 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);

2129 if (plan->qual)

2131 planstate, es);

2132 }

2133 break;

2134 case T_TidRangeScan:

2135 {

2136

2137

2138

2139

2141

2144 show_scan_qual(tidquals, "TID Cond", planstate, ancestors, es);

2146 if (plan->qual)

2148 planstate, es);

2149 }

2150 break;

2151 case T_ForeignScan:

2153 if (plan->qual)

2155 planstate, es);

2157 break;

2158 case T_CustomScan:

2159 {

2161

2163 if (plan->qual)

2165 planstate, es);

2168 }

2169 break;

2170 case T_NestLoop:

2172 "Join Filter", planstate, ancestors, es);

2175 planstate, es);

2177 if (plan->qual)

2179 planstate, es);

2180 break;

2181 case T_MergeJoin:

2183 "Merge Cond", planstate, ancestors, es);

2185 "Join Filter", planstate, ancestors, es);

2188 planstate, es);

2190 if (plan->qual)

2192 planstate, es);

2193 break;

2194 case T_HashJoin:

2196 "Hash Cond", planstate, ancestors, es);

2198 "Join Filter", planstate, ancestors, es);

2201 planstate, es);

2203 if (plan->qual)

2205 planstate, es);

2206 break;

2207 case T_Agg:

2211 if (plan->qual)

2213 planstate, es);

2214 break;

2215 case T_WindowAgg:

2218 "Run Condition", planstate, ancestors, es);

2220 if (plan->qual)

2222 planstate, es);

2224 break;

2225 case T_Group:

2228 if (plan->qual)

2230 planstate, es);

2231 break;

2232 case T_Sort:

2235 break;

2236 case T_IncrementalSort:

2238 ancestors, es);

2240 es);

2241 break;

2242 case T_MergeAppend:

2244 ancestors, es);

2245 break;

2246 case T_Result:

2248 "One-Time Filter", planstate, ancestors, es);

2250 if (plan->qual)

2252 planstate, es);

2253 break;

2254 case T_ModifyTable:

2256 es);

2257 break;

2258 case T_Hash:

2260 break;

2261 case T_Material:

2263 break;

2264 case T_Memoize:

2266 es);

2267 break;

2268 case T_RecursiveUnion:

2270 planstate), es);

2271 break;

2272 default:

2273 break;

2274 }

2275

2276

2277

2278

2279

2281 {

2283

2284 if (w)

2285 {

2286 for (int n = 0; n < w->num_workers; n++)

2287 {

2292 }

2293 }

2294 }

2295

2296

2301

2302

2304 {

2306

2307 for (int n = 0; n < w->num_workers; n++)

2308 {

2310 double nloops = instrument->nloops;

2311

2312 if (nloops <= 0)

2313 continue;

2314

2318 if (es->wal)

2321 }

2322 }

2323

2324

2328

2329

2331 (*explain_per_node_hook) (planstate, ancestors, relationship,

2332 plan_name, es);

2333

2334

2335

2336

2337

2338

2339

2340

2341

2343 {

2344 case T_Append:

2347 es);

2348 break;

2349 case T_MergeAppend:

2352 es);

2353 break;

2354 default:

2355 break;

2356 }

2357

2358

2359 haschildren = planstate->initPlan ||

2370 if (haschildren)

2371 {

2373

2374 ancestors = lcons(plan, ancestors);

2375 }

2376

2377

2380

2381

2384 "Outer", NULL, es);

2385

2386

2389 "Inner", NULL, es);

2390

2391

2393 {

2394 case T_Append:

2397 ancestors, es);

2398 break;

2399 case T_MergeAppend:

2402 ancestors, es);

2403 break;

2404 case T_BitmapAnd:

2407 ancestors, es);

2408 break;

2409 case T_BitmapOr:

2412 ancestors, es);

2413 break;

2414 case T_SubqueryScan:

2416 "Subquery", NULL, es);

2417 break;

2418 case T_CustomScan:

2420 ancestors, es);

2421 break;

2422 default:

2423 break;

2424 }

2425

2426

2429

2430

2431 if (haschildren)

2432 {

2435 }

2436

2437

2439 es->indent = save_indent;

2440

2442 relationship ? NULL : "Plan",

2443 true, es);

2444}

2445

2446

2447

2448

2449static void

2451{

2455 bool useprefix;

2457

2458

2459 if (plan->targetlist == NIL)

2460 return;

2461

2463 return;

2464

2466 return;

2468 return;

2469

2470

2471

2472

2473

2474

2475

2476

2477

2478

2479

2482 return;

2483

2484

2487 ancestors);

2489

2490

2491 foreach(lc, plan->targetlist)

2492 {

2494

2495 result = lappend(result,

2497 useprefix, false));

2498 }

2499

2500

2502}

2503

2504

2505

2506

2507static void

2511{

2513 char *exprstr;

2514

2515

2517 planstate->plan,

2518 ancestors);

2519

2520

2522

2523

2525}

2526

2527

2528

2529

2530static void

2534{

2536

2537

2538 if (qual == NIL)

2539 return;

2540

2541

2543

2544

2545 show_expression(node, qlabel, planstate, ancestors, useprefix, es);

2546}

2547

2548

2549

2550

2551static void

2555{

2556 bool useprefix;

2557

2559 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);

2560}

2561

2562

2563

2564

2565static void

2569{

2570 bool useprefix;

2571

2573 show_qual(qual, qlabel, planstate, ancestors, useprefix, es);

2574}

2575

2576

2577

2578

2579static void

2581{

2583

2585 plan->numCols, 0, plan->sortColIdx,

2586 plan->sortOperators, plan->collations,

2587 plan->nullsFirst,

2588 ancestors, es);

2589}

2590

2591

2592

2593

2594static void

2597{

2599

2601 plan->sort.numCols, plan->nPresortedCols,

2602 plan->sort.sortColIdx,

2603 plan->sort.sortOperators, plan->sort.collations,

2604 plan->sort.nullsFirst,

2605 ancestors, es);

2606}

2607

2608

2609

2610

2611static void

2614{

2616

2618 plan->numCols, 0, plan->sortColIdx,

2619 plan->sortOperators, plan->collations,

2620 plan->nullsFirst,

2621 ancestors, es);

2622}

2623

2624

2625

2626

2627static void

2630{

2632

2633 if (plan->numCols > 0 || plan->groupingSets)

2634 {

2635

2636 ancestors = lcons(plan, ancestors);

2637

2638 if (plan->groupingSets)

2640 else

2642 plan->numCols, 0, plan->grpColIdx,

2643 NULL, NULL, NULL,

2644 ancestors, es);

2645

2647 }

2648}

2649

2650static void

2653{

2655 bool useprefix;

2657

2658

2660 planstate->plan,

2661 ancestors);

2663

2664 ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es);

2665

2667 context, useprefix, ancestors, es);

2668

2669 foreach(lc, agg->chain)

2670 {

2673

2675 context, useprefix, ancestors, es);

2676 }

2677

2679}

2680

2681static void

2683 Agg *aggnode, Sort *sortnode,

2686{

2688 char *exprstr;

2691 AttrNumber *keycols = aggnode->grpColIdx;

2692 const char *keyname;

2693 const char *keysetname;

2694

2696 {

2697 keyname = "Hash Key";

2698 keysetname = "Hash Keys";

2699 }

2700 else

2701 {

2702 keyname = "Group Key";

2703 keysetname = "Group Keys";

2704 }

2705

2707

2708 if (sortnode)

2709 {

2711 sortnode->numCols, 0, sortnode->sortColIdx,

2712 sortnode->sortOperators, sortnode->collations,

2713 sortnode->nullsFirst,

2714 ancestors, es);

2717 }

2718

2720

2721 foreach(lc, gsets)

2722 {

2725

2727 {

2731 keyresno);

2732

2733 if (!target)

2734 elog(ERROR, "no tlist entry for key %d", keyresno);

2735

2737 useprefix, true);

2738

2739 result = lappend(result, exprstr);

2740 }

2741

2744 else

2746 }

2747

2749

2752

2754}

2755

2756

2757

2758

2759static void

2762{

2764

2765

2766 ancestors = lcons(plan, ancestors);

2768 plan->numCols, 0, plan->grpColIdx,

2769 NULL, NULL, NULL,

2770 ancestors, es);

2772}

2773

2774

2775

2776

2777

2778

2779static void

2781 int nkeys, int nPresortedKeys, AttrNumber *keycols,

2782 Oid *sortOperators, Oid *collations, bool *nullsFirst,

2784{

2788 List *resultPresorted = NIL;

2790 bool useprefix;

2791 int keyno;

2792

2793 if (nkeys <= 0)

2794 return;

2795

2797

2798

2801 ancestors);

2803

2804 for (keyno = 0; keyno < nkeys; keyno++)

2805 {

2806

2807 AttrNumber keyresno = keycols[keyno];

2809 keyresno);

2810 char *exprstr;

2811

2812 if (!target)

2813 elog(ERROR, "no tlist entry for key %d", keyresno);

2814

2816 useprefix, true);

2819

2820 if (sortOperators != NULL)

2823 sortOperators[keyno],

2824 collations[keyno],

2825 nullsFirst[keyno]);

2826

2828 if (keyno < nPresortedKeys)

2829 resultPresorted = lappend(resultPresorted, exprstr);

2830 }

2831

2833 if (nPresortedKeys > 0)

2835}

2836

2837

2838

2839

2840

2841static void

2843 Oid sortOperator, Oid collation, bool nullsFirst)

2844{

2846 bool reverse = false;

2848

2851

2852

2853

2854

2855

2856

2857

2858

2860 {

2862

2863 if (collname == NULL)

2864 elog(ERROR, "cache lookup failed for collation %u", collation);

2866 }

2867

2868

2869 if (sortOperator == typentry->gt_opr)

2870 {

2872 reverse = true;

2873 }

2874 else if (sortOperator != typentry->lt_opr)

2875 {

2876 char *opname = get_opname(sortOperator);

2877

2878 if (opname == NULL)

2879 elog(ERROR, "cache lookup failed for operator %u", sortOperator);

2881

2883 }

2884

2885

2886 if (nullsFirst && !reverse)

2887 {

2889 }

2890 else if (!nullsFirst && reverse)

2891 {

2893 }

2894}

2895

2896

2897

2898

2899static void

2901{

2904 bool needspace = false;

2905

2908

2909

2910 ancestors = lcons(wagg, ancestors);

2912 {

2916 ancestors, es);

2917 needspace = true;

2918 }

2920 {

2921 if (needspace)

2926 ancestors, es);

2927 needspace = true;

2928 }

2931 {

2933 bool useprefix;

2934 char *framestr;

2935

2936

2938 (Plan *) wagg,

2939 ancestors);

2942 wagg->startOffset,

2943 wagg->endOffset,

2945 useprefix);

2946 if (needspace)

2949 pfree(framestr);

2950 }

2953 pfree(wbuf.data);

2954}

2955

2956

2957

2958

2959

2960

2961

2962static void

2966{

2969 bool useprefix;

2970

2971

2974 ancestors);

2976

2977 for (int keyno = 0; keyno < nkeys; keyno++)

2978 {

2979

2980 AttrNumber keyresno = keycols[keyno];

2982 keyresno);

2983 char *exprstr;

2984

2985 if (!target)

2986 elog(ERROR, "no tlist entry for key %d", keyresno);

2987

2989 useprefix, true);

2990 if (keyno > 0)

2994

2995

2996

2997

2998

2999

3000 }

3001}

3002

3003

3004

3005

3006static void

3008{

3010

3012 {

3015 }

3016 else

3017 {

3020 "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n",

3021 maxStorageType,

3022 maxSpaceUsedKB);

3023 }

3024}

3025

3026

3027

3028

3029static void

3032{

3034 bool useprefix;

3035 char *method_name;

3037 char *repeatable;

3039

3040

3042 planstate->plan,

3043 ancestors);

3045

3046

3048

3049

3050 foreach(lc, tsc->args)

3051 {

3053

3054 params = lappend(params,

3056 useprefix, false));

3057 }

3060 useprefix, false);

3061 else

3062 repeatable = NULL;

3063

3064

3066 {

3067 bool first = true;

3068

3071 foreach(lc, params)

3072 {

3073 if (!first)

3076 first = false;

3077 }

3079 if (repeatable)

3082 }

3083 else

3084 {

3087 if (repeatable)

3089 }

3090}

3091

3092

3093

3094

3095static void

3097{

3099 return;

3100

3102 {

3105 const char *sortMethod;

3106 const char *spaceType;

3107 int64 spaceUsed;

3108

3112 spaceUsed = stats.spaceUsed;

3113

3115 {

3118 sortMethod, spaceType, spaceUsed);

3119 }

3120 else

3121 {

3125 }

3126 }

3127

3128

3129

3130

3131

3132

3133

3134

3135

3136

3138 {

3139 int n;

3140

3142 {

3144 const char *sortMethod;

3145 const char *spaceType;

3146 int64 spaceUsed;

3147

3150 continue;

3153 spaceUsed = sinstrument->spaceUsed;

3154

3157

3159 {

3163 sortMethod, spaceType, spaceUsed);

3164 }

3165 else

3166 {

3170 }

3171

3174 }

3175 }

3176}

3177

3178

3179

3180

3181

3182

3183

3184

3185

3186static void

3188 const char *groupLabel, bool indent, ExplainState *es)

3189{

3191 List *methodNames = NIL;

3192

3193

3195 {

3197

3198 if (groupInfo->sortMethods & sortMethod)

3199 {

3201

3202 methodNames = lappend(methodNames, unconstify(char *, methodName));

3203 }

3204 }

3205

3207 {

3208 if (indent)

3212

3215 else

3217 foreach(methodCell, methodNames)

3218 {

3222 }

3223

3225 {

3227 const char *spaceTypeName;

3228

3231 spaceTypeName, avgSpace,

3233 }

3234

3236 {

3238

3239 const char *spaceTypeName;

3240

3243 spaceTypeName, avgSpace,

3245 }

3246 }

3247 else

3248 {

3250

3255

3257

3259 {

3261 const char *spaceTypeName;

3263

3266 appendStringInfo(&memoryName, "Sort Space %s", spaceTypeName);

3268

3272

3274 }

3276 {

3278 const char *spaceTypeName;

3280

3283 appendStringInfo(&diskName, "Sort Space %s", spaceTypeName);

3285

3289

3291 }

3292

3294 }

3295}

3296

3297

3298

3299

3300static void

3303{

3306

3308

3310 return;

3311

3312

3313

3314

3315

3316

3317

3318

3319

3320

3321 if (fullsortGroupInfo->groupCount > 0)

3322 {

3325 if (prefixsortGroupInfo->groupCount > 0)

3326 {

3330 }

3333 }

3334

3336 {

3337 int n;

3338 bool indent_first_line;

3339

3341 {

3344

3345

3346

3347

3348

3349

3351

3352

3353

3354

3355

3356

3357

3358 if (fullsortGroupInfo->groupCount == 0)

3359 continue;

3360

3363

3366 indent_first_line, es);

3368 if (prefixsortGroupInfo->groupCount > 0)

3369 {

3373 }

3376

3379 }

3380 }

3381}

3382

3383

3384

3385

3386static void

3388{

3390

3391

3392

3393

3394

3395

3396

3397

3398

3400 memcpy(&hinstrument, hashstate->hinstrument,

3402

3403

3404

3405

3406

3407

3408

3409

3410

3411

3413 {

3415 int i;

3416

3418 {

3420

3431 }

3432 }

3433

3434 if (hinstrument.nbatch > 0)

3435 {

3437

3439 {

3445 hinstrument.nbatch, es);

3449 spacePeakKb, es);

3450 }

3453 {

3456 "Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: " UINT64_FORMAT "kB\n",

3461 spacePeakKb);

3462 }

3463 else

3464 {

3467 "Buckets: %d Batches: %d Memory Usage: " UINT64_FORMAT "kB\n",

3469 spacePeakKb);

3470 }

3471 }

3472}

3473

3474

3475

3476

3477

3478static void

3480{

3481 char *maxStorageType;

3482 int64 maxSpaceUsed;

3483

3485

3486

3487

3488

3489

3490 if (!es->analyze || tupstore == NULL)

3491 return;

3492

3495}

3496

3497

3498

3499

3500

3501static void

3503{

3504 char *maxStorageType;

3505 int64 maxSpaceUsed;

3506

3508

3509

3510

3511

3512

3513 if (!es->analyze || tupstore == NULL)

3514 return;

3515

3518}

3519

3520

3521

3522

3523

3524static void

3526{

3527 char *maxStorageType;

3528 int64 maxSpaceUsed;

3529

3531

3532 if (!es->analyze || tupstore == NULL)

3533 return;

3534

3537}

3538

3539

3540

3541

3542

3543static void

3545{

3546 char *maxStorageType;

3547 int64 maxSpaceUsed;

3548

3550

3551 if (!es->analyze || tupstore == NULL)

3552 return;

3553

3556}

3557

3558

3559

3560

3561

3562static void

3564{

3565 char *maxStorageType,

3566 *tempStorageType;

3567 int64 maxSpaceUsed,

3568 tempSpaceUsed;

3569

3571 return;

3572

3573

3574

3575

3576

3577

3579 &tempSpaceUsed);

3581 &maxSpaceUsed);

3582

3583 if (tempSpaceUsed > maxSpaceUsed)

3584 maxStorageType = tempStorageType;

3585

3586 maxSpaceUsed += tempSpaceUsed;

3588}

3589

3590

3591

3592

3593static void

3595{

3601 bool useprefix;

3602 int64 memPeakKb;

3603

3605

3606

3607

3608

3609

3611

3612

3615 ancestors);

3616

3617 foreach(lc, ((Memoize *) plan)->param_exprs)

3618 {

3620

3622

3624 useprefix, false));

3626 }

3627

3630

3632

3634 return;

3635

3637 {

3638

3639

3640

3641

3644 else

3646

3648 {

3654 }

3655 else

3656 {

3664 memPeakKb);

3665 }

3666 }

3667

3669 return;

3670

3671

3673 {

3675

3677

3678

3679

3680

3681

3683 continue;

3684

3687

3688

3689

3690

3691

3692

3693

3695

3697 {

3703 memPeakKb);

3704 }

3705 else

3706 {

3716 es);

3717 }

3718

3721 }

3722}

3723

3724

3725

3726

3727static void

3729{

3732

3735 return;

3736

3738 {

3742

3743

3744

3745

3746

3747

3749 {

3755 }

3756 }

3757 else

3758 {

3759 bool gotone = false;

3760

3762 {

3766 gotone = true;

3767 }

3768

3769

3770

3771

3772

3773

3775 {

3776 if (!gotone)

3778 else

3780

3783 gotone = true;

3784

3785

3787 {

3790 }

3791 }

3792

3793 if (gotone)

3795 }

3796

3797

3799 {

3801 {

3803 uint64 hash_disk_used;

3804 int hash_batches_used;

3805

3807

3809 continue;

3813

3816

3818 {

3820

3822 hash_batches_used, memPeakKb);

3823

3824

3825 if (hash_batches_used > 1)

3827 hash_disk_used);

3829 }

3830 else

3831 {

3833 hash_batches_used, es);

3835 es);

3837 }

3838

3841 }

3842 }

3843}

3844

3845

3846

3847

3848

3849static void

3851{

3854 uint64 nsearches = 0;

3855

3857 return;

3858

3859

3861 {

3862 case T_IndexScan:

3863 {

3865

3868 break;

3869 }

3870 case T_IndexOnlyScan:

3871 {

3873

3876 break;

3877 }

3878 case T_BitmapIndexScan:

3879 {

3881

3884 break;

3885 }

3886 default:

3887 break;

3888 }

3889

3890

3891 if (SharedInfo)

3892 {

3894 {

3896

3897 nsearches += winstrument->nsearches;

3898 }

3899 }

3900

3902}

3903

3904

3905

3906

3907static void

3909{

3911 return;

3912

3914 {

3919 }

3920 else

3921 {

3923 {

3931 }

3932 }

3933

3934

3935 if (planstate->pstate != NULL)

3936 {

3938 {

3940

3942 continue;

3943

3946

3948 {

3956 }

3957 else

3958 {

3963 }

3964

3967 }

3968 }

3969}

3970

3971

3972

3973

3974

3975

3976static void

3979{

3980 double nfiltered;

3981 double nloops;

3982

3984 return;

3985

3986 if (which == 2)

3988 else

3991

3992

3994 {

3995 if (nloops > 0)

3997 else

3999 }

4000}

4001

4002

4003

4004

4005static void

4007{

4009

4010

4012 {

4015 }

4016 else

4017 {

4020 }

4021}

4022

4023

4024

4025

4026

4027

4028

4029

4030

4031

4032

4033static const char *

4035{

4036 const char *result;

4037

4039 result = (*explain_get_index_name_hook) (indexId);

4040 else

4041 result = NULL;

4042 if (result == NULL)

4043 {

4044

4046 if (result == NULL)

4047 elog(ERROR, "cache lookup failed for index %u", indexId);

4048 }

4049 return result;

4050}

4051

4052

4053

4054

4055

4056

4057static bool

4059{

4060 bool has_shared;

4061 bool has_local;

4062 bool has_temp;

4063 bool has_shared_timing;

4064 bool has_local_timing;

4065 bool has_temp_timing;

4066

4067 if (usage == NULL)

4068 return false;

4069

4071 return true;

4072

4073 has_shared = (usage->shared_blks_hit > 0 ||

4074 usage->shared_blks_read > 0 ||

4075 usage->shared_blks_dirtied > 0 ||

4076 usage->shared_blks_written > 0);

4077 has_local = (usage->local_blks_hit > 0 ||

4078 usage->local_blks_read > 0 ||

4079 usage->local_blks_dirtied > 0 ||

4080 usage->local_blks_written > 0);

4081 has_temp = (usage->temp_blks_read > 0 ||

4082 usage->temp_blks_written > 0);

4089

4090 return has_shared || has_local || has_temp || has_shared_timing ||

4091 has_local_timing || has_temp_timing;

4092}

4093

4094

4095

4096

4097static void

4099{

4101 {

4102 bool has_shared = (usage->shared_blks_hit > 0 ||

4103 usage->shared_blks_read > 0 ||

4104 usage->shared_blks_dirtied > 0 ||

4105 usage->shared_blks_written > 0);

4106 bool has_local = (usage->local_blks_hit > 0 ||

4107 usage->local_blks_read > 0 ||

4108 usage->local_blks_dirtied > 0 ||

4109 usage->local_blks_written > 0);

4110 bool has_temp = (usage->temp_blks_read > 0 ||

4111 usage->temp_blks_written > 0);

4118

4119

4120 if (has_shared || has_local || has_temp)

4121 {

4124

4125 if (has_shared)

4126 {

4128 if (usage->shared_blks_hit > 0)

4130 usage->shared_blks_hit);

4131 if (usage->shared_blks_read > 0)

4133 usage->shared_blks_read);

4134 if (usage->shared_blks_dirtied > 0)

4136 usage->shared_blks_dirtied);

4137 if (usage->shared_blks_written > 0)

4139 usage->shared_blks_written);

4140 if (has_local || has_temp)

4142 }

4143 if (has_local)

4144 {

4146 if (usage->local_blks_hit > 0)

4148 usage->local_blks_hit);

4149 if (usage->local_blks_read > 0)

4151 usage->local_blks_read);

4152 if (usage->local_blks_dirtied > 0)

4154 usage->local_blks_dirtied);

4155 if (usage->local_blks_written > 0)

4157 usage->local_blks_written);

4158 if (has_temp)

4160 }

4161 if (has_temp)

4162 {

4164 if (usage->temp_blks_read > 0)

4166 usage->temp_blks_read);

4167 if (usage->temp_blks_written > 0)

4169 usage->temp_blks_written);

4170 }

4172 }

4173

4174

4175 if (has_shared_timing || has_local_timing || has_temp_timing)

4176 {

4179

4180 if (has_shared_timing)

4181 {

4189 if (has_local_timing || has_temp_timing)

4191 }

4192 if (has_local_timing)

4193 {

4201 if (has_temp_timing)

4203 }

4204 if (has_temp_timing)

4205 {

4213 }

4215 }

4216 }

4217 else

4218 {

4220 usage->shared_blks_hit, es);

4222 usage->shared_blks_read, es);

4224 usage->shared_blks_dirtied, es);

4226 usage->shared_blks_written, es);

4228 usage->local_blks_hit, es);

4230 usage->local_blks_read, es);

4232 usage->local_blks_dirtied, es);

4234 usage->local_blks_written, es);

4236 usage->temp_blks_read, es);

4238 usage->temp_blks_written, es);

4240 {

4243 3, es);

4246 3, es);

4249 3, es);

4252 3, es);

4255 3, es);

4258 3, es);

4259 }

4260 }

4261}

4262

4263

4264

4265

4266static void

4268{

4270 {

4271

4272 if ((usage->wal_records > 0) || (usage->wal_fpi > 0) ||

4273 (usage->wal_bytes > 0) || (usage->wal_buffers_full > 0))

4274 {

4277

4278 if (usage->wal_records > 0)

4280 usage->wal_records);

4281 if (usage->wal_fpi > 0)

4283 usage->wal_fpi);

4284 if (usage->wal_bytes > 0)

4286 usage->wal_bytes);

4287 if (usage->wal_buffers_full > 0)

4289 usage->wal_buffers_full);

4291 }

4292 }

4293 else

4294 {

4296 usage->wal_records, es);

4298 usage->wal_fpi, es);

4300 usage->wal_bytes, es);

4302 usage->wal_buffers_full, es);

4303 }

4304}

4305

4306

4307

4308

4309static void

4311{

4315

4317 {

4321 memUsedkB, memAllocatedkB);

4323 }

4324 else

4325 {

4328 }

4329}

4330

4331

4332

4333

4334

4335static void

4338{

4340

4342 {

4346 }

4347 else

4348 {

4349 const char *scandir;

4350

4351 switch (indexorderdir)

4352 {

4354 scandir = "Backward";

4355 break;

4357 scandir = "Forward";

4358 break;

4359 default:

4360 scandir = "???";

4361 break;

4362 }

4365 }

4366}

4367

4368

4369

4370

4371static void

4373{

4375}

4376

4377

4378

4379

4380

4381

4382

4383

4384static void

4386{

4388}

4389

4390

4391

4392

4393static void

4395{

4396 char *objectname = NULL;

4397 char *namespace = NULL;

4398 const char *objecttag = NULL;

4400 char *refname;

4401

4404 if (refname == NULL)

4405 refname = rte->eref->aliasname;

4406

4408 {

4409 case T_SeqScan:

4410 case T_SampleScan:

4411 case T_IndexScan:

4412 case T_IndexOnlyScan:

4413 case T_BitmapHeapScan:

4414 case T_TidScan:

4415 case T_TidRangeScan:

4416 case T_ForeignScan:

4417 case T_CustomScan:

4418 case T_ModifyTable:

4419

4424 objecttag = "Relation Name";

4425 break;

4426 case T_FunctionScan:

4427 {

4429

4430

4432

4433

4434

4435

4436

4437

4438

4440 {

4442

4444 {

4447

4451 }

4452 }

4453 objecttag = "Function Name";

4454 }

4455 break;

4456 case T_TableFuncScan:

4457 {

4459

4461 switch (tablefunc->functype)

4462 {

4464 objectname = "xmltable";

4465 break;

4467 objectname = "json_table";

4468 break;

4469 default:

4470 elog(ERROR, "invalid TableFunc type %d",

4472 }

4473 objecttag = "Table Function Name";

4474 }

4475 break;

4476 case T_ValuesScan:

4478 break;

4479 case T_CteScan:

4480

4482 Assert(!rte->self_reference);

4483 objectname = rte->ctename;

4484 objecttag = "CTE Name";

4485 break;

4486 case T_NamedTuplestoreScan:

4488 objectname = rte->enrname;

4489 objecttag = "Tuplestore Name";

4490 break;

4491 case T_WorkTableScan:

4492

4494 Assert(rte->self_reference);

4495 objectname = rte->ctename;

4496 objecttag = "CTE Name";

4497 break;

4498 default:

4499 break;

4500 }

4501

4503 {

4505 if (namespace != NULL)

4508 else if (objectname != NULL)

4510 if (objectname == NULL || strcmp(refname, objectname) != 0)

4512 }

4513 else

4514 {

4515 if (objecttag != NULL && objectname != NULL)

4517 if (namespace != NULL)

4520 }

4521}

4522

4523

4524

4525

4526

4527

4528

4529

4530

4531static void

4534{

4536 const char *operation;

4537 const char *foperation;

4538 bool labeltargets;

4539 int j;

4542

4544 {

4546 operation = "Insert";

4547 foperation = "Foreign Insert";

4548 break;

4550 operation = "Update";

4551 foperation = "Foreign Update";

4552 break;

4554 operation = "Delete";

4555 foperation = "Foreign Delete";

4556 break;

4558 operation = "Merge";

4559

4560 foperation = "Foreign Merge";

4561 break;

4562 default:

4563 operation = "???";

4564 foperation = "Foreign ???";

4565 break;

4566 }

4567

4568

4569

4570

4571

4572

4573

4574

4575

4576

4577 labeltargets = (mtstate->mt_nrels > 1 ||

4582

4583 if (labeltargets)

4584 ExplainOpenGroup("Target Tables", "Target Tables", false, es);

4585

4587 {

4590

4591 if (labeltargets)

4592 {

4593

4595

4596

4597

4598

4599

4601 {

4604 fdwroutine ? foperation : operation);

4605 }

4606

4607

4610 es);

4611

4613 {

4616 }

4617 }

4618

4619

4621 fdwroutine != NULL &&

4623 {

4625

4627 resultRelInfo,

4628 fdw_private,

4629 j,

4630 es);

4631 }

4632

4633 if (labeltargets)

4634 {

4635

4638

4639

4641 }

4642 }

4643

4644

4646 {

4648

4649 idxNames = lappend(idxNames, indexname);

4650 }

4651

4653 {

4656 "NOTHING" : "UPDATE",

4657 es);

4658

4659

4660

4661

4662

4663 if (idxNames)

4665

4666

4668 {

4670 &mtstate->ps, ancestors, es);

4672 }

4673

4674

4676 {

4677 double total;

4678 double insert_path;

4679 double other_path;

4680

4682

4683

4684 total = outerPlanState(mtstate)->instrument->ntuples;

4686 insert_path = total - other_path;

4687

4689 insert_path, 0, es);

4691 other_path, 0, es);

4692 }

4693 }

4695 {

4696

4698 {

4699 double total;

4700 double insert_path;

4701 double update_path;

4702 double delete_path;

4703 double skipped_path;

4704

4706

4707

4708 total = outerPlanState(mtstate)->instrument->ntuples;

4712 skipped_path = total - insert_path - update_path - delete_path;

4713 Assert(skipped_path >= 0);

4714

4716 {

4717 if (total > 0)

4718 {

4721 if (insert_path > 0)

4723 if (update_path > 0)

4725 if (delete_path > 0)

4727 if (skipped_path > 0)

4730 }

4731 }

4732 else

4733 {

4738 }

4739 }

4740 }

4741

4742 if (labeltargets)

4744}

4745

4746

4747

4748

4749

4750

4751

4752

4753static void

4756{

4757 int j;

4758

4759 for (j = 0; j < nplans; j++)

4761 "Member", NULL, es);

4762}

4763

4764

4765

4766

4767

4768

4769

4770

4771static void

4773{

4776 nchildren - nplans, es);

4777}

4778

4779

4780

4781

4782

4783

4784

4785static void

4788{

4790

4791 foreach(lst, plans)

4792 {

4795

4796

4797

4798

4799

4800

4801

4802

4803

4804

4805

4807 continue;

4810

4811

4812

4813

4814

4815

4816 ancestors = lcons(sp, ancestors);

4817

4819 relationship, sp->plan_name, es);

4820

4822 }

4823}

4824

4825

4826

4827

4828static void

4830{

4832 const char *label =

4834

4837}

4838

4839

4840

4841

4842

4843

4844

4845

4846

4847

4848

4849

4852{

4854

4861 return wstate;

4862}

4863

4864

4865

4866

4867static void

4869{

4871

4873 Assert(n >= 0 && n < wstate->num_workers);

4874

4875

4877

4879 {

4880

4883

4884

4885

4886

4887

4888

4890

4891

4892

4893

4894

4897

4899 }

4900 else

4901 {

4902

4904

4905

4907 }

4908

4909

4910

4911

4912

4913

4915 {

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

4917 {

4920 }

4921

4923 }

4924}

4925

4926

4927

4928

4929static void

4931{

4933

4935 Assert(n >= 0 && n < wstate->num_workers);

4937

4938

4939

4940

4941

4943

4944

4945

4946

4947

4948

4949

4951 {

4954

4956 }

4957

4958

4960}

4961

4962

4963

4964

4965static void

4967{

4969

4972 {

4974 {

4975

4979

4981 }

4982 }

4984

4989}

void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)

bool bms_is_member(int x, const Bitmapset *a)

Bitmapset * bms_add_member(Bitmapset *a, int x)

Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)

#define unconstify(underlying_type, expr)

#define OidIsValid(objectId)

bool CreateTableAsRelExists(CreateTableAsStmt *ctas)

int GetIntoRelEFlags(IntoClause *intoClause)

DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)

char * defGetString(DefElem *def)

DestReceiver * None_Receiver

bool ExecutorStart(QueryDesc *queryDesc, int eflags)

void ExecutorStartCachedPlan(QueryDesc *queryDesc, int eflags, CachedPlanSource *plansource, int query_index)

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)

const TupleTableSlotOps TTSOpsVirtual

void end_tup_output(TupOutputState *tstate)

void do_text_output_multiline(TupOutputState *tstate, const char *txt)

TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)

#define outerPlanState(node)

#define innerPlanState(node)

#define EXEC_FLAG_EXPLAIN_GENERIC

#define do_text_output_oneline(tstate, str_to_emit)

#define EXEC_FLAG_EXPLAIN_ONLY

static void show_modifytable_info(ModifyTableState *mtstate, List *ancestors, ExplainState *es)

#define BYTES_TO_KILOBYTES(b)

static void show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es)

static void show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es)

static void show_group_keys(GroupState *gstate, List *ancestors, ExplainState *es)

static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es)

static void show_window_def(WindowAggState *planstate, List *ancestors, ExplainState *es)

static void show_agg_keys(AggState *astate, List *ancestors, ExplainState *es)

static void show_hashagg_info(AggState *aggstate, ExplainState *es)

static void show_scan_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, ExplainState *es)

static const char * explain_get_index_name(Oid indexId)

static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir, ExplainState *es)

ExplainOneQuery_hook_type ExplainOneQuery_hook

static void show_instrumentation_count(const char *qlabel, int which, PlanState *planstate, ExplainState *es)

static void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es)

static void show_incremental_sort_group_info(IncrementalSortGroupInfo *groupInfo, const char *groupLabel, bool indent, ExplainState *es)

void ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, CachedPlanSource *plansource, int query_index, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters)

static void ExplainMemberNodes(PlanState **planstates, int nplans, List *ancestors, ExplainState *es)

static void show_ctescan_info(CteScanState *ctescanstate, ExplainState *es)

explain_get_index_name_hook_type explain_get_index_name_hook

static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)

static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji)

static void show_recursive_union_info(RecursiveUnionState *rstate, ExplainState *es)

void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest)

static void show_incremental_sort_info(IncrementalSortState *incrsortstate, ExplainState *es)

static void show_tablesample(TableSampleClause *tsc, PlanState *planstate, List *ancestors, ExplainState *es)

static void show_upper_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, ExplainState *es)

static void show_sort_info(SortState *sortstate, ExplainState *es)

static void show_window_keys(StringInfo buf, PlanState *planstate, int nkeys, AttrNumber *keycols, List *ancestors, ExplainState *es)

static void ExplainMissingMembers(int nplans, int nchildren, ExplainState *es)

explain_per_node_hook_type explain_per_node_hook

TupleDesc ExplainResultDesc(ExplainStmt *stmt)

static void ExplainFlushWorkersState(ExplainState *es)

static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage)

void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)

static void show_hash_info(HashState *hashstate, ExplainState *es)

static void show_sortorder_options(StringInfo buf, Node *sortexpr, Oid sortOperator, Oid collation, bool nullsFirst)

static void show_table_func_scan_info(TableFuncScanState *tscanstate, ExplainState *es)

static void show_indexsearches_info(PlanState *planstate, ExplainState *es)

static void show_expression(Node *node, const char *qlabel, PlanState *planstate, List *ancestors, bool useprefix, ExplainState *es)

static double elapsed_time(instr_time *starttime)

void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc)

explain_per_plan_hook_type explain_per_plan_hook

static bool plan_is_disabled(Plan *plan)

static void show_sort_group_keys(PlanState *planstate, const char *qlabel, int nkeys, int nPresortedKeys, AttrNumber *keycols, Oid *sortOperators, Oid *collations, bool *nullsFirst, List *ancestors, ExplainState *es)

static void show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)

static void show_windowagg_info(WindowAggState *winstate, ExplainState *es)

static void show_memory_counters(ExplainState *es, const MemoryContextCounters *mem_counters)

static void ExplainSubPlans(List *plans, List *ancestors, const char *relationship, ExplainState *es)

static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es)

static void ExplainScanTarget(Scan *plan, ExplainState *es)

void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)

static void show_merge_append_keys(MergeAppendState *mstate, List *ancestors, ExplainState *es)

static void report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)

void ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen)

static void ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)

static void show_grouping_sets(PlanState *planstate, Agg *agg, List *ancestors, ExplainState *es)

static void ExplainPrintSettings(ExplainState *es)

static void ExplainCloseWorker(int n, ExplainState *es)

static void ExplainOpenWorker(int n, ExplainState *es)

static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)

static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)

void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)

static void show_wal_usage(ExplainState *es, const WalUsage *usage)

static void show_storage_info(char *maxStorageType, int64 maxSpaceUsed, ExplainState *es)

static void show_grouping_set_keys(PlanState *planstate, Agg *aggnode, Sort *sortnode, List *context, bool useprefix, List *ancestors, ExplainState *es)

static void show_qual(List *qual, const char *qlabel, PlanState *planstate, List *ancestors, bool useprefix, ExplainState *es)

static void show_material_info(MaterialState *mstate, ExplainState *es)

static void show_sort_keys(SortState *sortstate, List *ancestors, ExplainState *es)

static ExplainWorkersState * ExplainCreateWorkersState(int num_workers)

void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)

void standard_ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)

static void show_buffer_usage(ExplainState *es, const BufferUsage *usage)

static void show_incremental_sort_keys(IncrementalSortState *incrsortstate, List *ancestors, ExplainState *es)

static void ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es)

const char *(* explain_get_index_name_hook_type)(Oid indexId)

void(* explain_per_plan_hook_type)(PlannedStmt *plannedstmt, IntoClause *into, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)

void(* ExplainOneQuery_hook_type)(Query *query, int cursorOptions, IntoClause *into, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)

void(* explain_per_node_hook_type)(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, struct ExplainState *es)

SerializeMetrics GetSerializationMetrics(DestReceiver *dest)

DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)

void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)

void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)

void ExplainPropertyUInteger(const char *qlabel, const char *unit, uint64 value, ExplainState *es)

void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)

void ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es)

void ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, bool labeled, int depth, ExplainState *es)

void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)

void ExplainSeparatePlans(ExplainState *es)

void ExplainEndOutput(ExplainState *es)

void ExplainIndentText(ExplainState *es)

void ExplainPropertyFloat(const char *qlabel, const char *unit, double value, int ndigits, ExplainState *es)

void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es)

void ExplainBeginOutput(ExplainState *es)

void ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es)

void ExplainRestoreGroup(ExplainState *es, int depth, int *state_save)

void ExplainSaveGroup(ExplainState *es, int depth, int *state_save)

void ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)

ExplainState * NewExplainState(void)

void ParseExplainOptionList(ExplainState *es, List *options, ParseState *pstate)

@ EXPLAIN_SERIALIZE_BINARY

char * GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)

struct config_generic ** get_explain_guc_options(int *num)

Assert(PointerIsAligned(start, uint64))

#define INSTR_TIME_SET_CURRENT(t)

#define INSTR_TIME_ADD(x, y)

#define INSTR_TIME_IS_ZERO(t)

#define INSTR_TIME_GET_DOUBLE(t)

#define INSTR_TIME_SUBTRACT(x, y)

#define INSTR_TIME_GET_MILLISEC(t)

#define INSTR_TIME_SET_ZERO(t)

void InstrEndLoop(Instrumentation *instr)

BufferUsage pgBufferUsage

void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)

if(TABLE==NULL||TABLE_index==NULL)

void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)

List * lappend(List *list, void *datum)

List * list_delete_first(List *list)

List * lcons(void *datum, List *list)

char * get_rel_name(Oid relid)

char * get_opname(Oid opno)

Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)

Oid get_rel_namespace(Oid relid)

Oid get_typcollation(Oid typid)

char * get_collation_name(Oid colloid)

char * get_namespace_name_or_temp(Oid nspid)

char * get_constraint_name(Oid conoid)

char * get_func_name(Oid funcid)

Oid get_func_namespace(Oid funcid)

Expr * make_orclause(List *orclauses)

Expr * make_ands_explicit(List *andclauses)

Expr * make_andclause(List *andclauses)

void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)

char * pstrdup(const char *in)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext CurrentMemoryContext

#define AllocSetContextCreate

#define ALLOCSET_DEFAULT_SIZES

Oid exprType(const Node *expr)

#define planstate_tree_walker(ps, w, c)

#define DO_AGGSPLIT_SKIPFINAL(as)

#define IsA(nodeptr, _type_)

#define DO_AGGSPLIT_COMBINE(as)

#define castNode(_type_, nodeptr)

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

char * BuildParamLogString(ParamListInfo params, char **knownTextValues, int maxlen)

TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)

#define CURSOR_OPT_PARALLEL_OK

#define FRAMEOPTION_NONDEFAULT

post_parse_analyze_hook_type post_parse_analyze_hook

#define rt_fetch(rangetable_index, rangetable)

#define lfirst_node(type, lc)

static int list_length(const List *l)

#define linitial_node(type, l)

#define foreach_current_index(var_or_cell)

static void * list_nth(const List *list, int n)

static ListCell * lnext(const List *l, const ListCell *c)

PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)

void FreeQueryDesc(QueryDesc *qdesc)

QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)

char * psprintf(const char *fmt,...)

@ COMPUTE_QUERY_ID_REGRESS

static bool IsQueryIdEnabled(void)

JumbleState * JumbleQuery(Query *query)

static const struct fns functions

#define RelationGetRelationName(relation)

List * QueryRewrite(Query *parsetree)

List * deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)

List * set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)

const char * quote_identifier(const char *ident)

List * select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)

char * get_window_frame_options_for_explain(int frameOptions, Node *startOffset, Node *endOffset, List *dpcontext, bool forceprefix)

char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)

#define ScanDirectionIsBackward(direction)

@ NoMovementScanDirection

void UpdateActiveSnapshotCommandId(void)

void PopActiveSnapshot(void)

void PushCopiedSnapshot(Snapshot snapshot)

Snapshot GetActiveSnapshot(void)

void resetStringInfo(StringInfo str)

void appendStringInfo(StringInfo str, const char *fmt,...)

void appendStringInfoSpaces(StringInfo str, int count)

void appendStringInfoString(StringInfo str, const char *s)

void appendStringInfoChar(StringInfo str, char ch)

void initStringInfo(StringInfo str)

int hash_planned_partitions

SharedAggInfo * shared_info

ParallelBitmapHeapState * pstate

BitmapHeapScanInstrumentation stats

SharedBitmapHeapInstrumentation * sinstrument

SharedIndexScanInstrumentation * biss_SharedInfo

IndexScanInstrumentation biss_Instrument

Tuplestorestate * cte_table

struct CteScanState * leader

void(* ExplainCustomScan)(CustomScanState *node, List *ancestors, ExplainState *es)

const struct CustomExecMethods * methods

List * es_tuple_routing_result_relations

struct JitContext * es_jit

struct JitInstrumentation * es_jit_worker_instr

Bitmapset * es_unpruned_relids

List * es_trig_target_relations

List * es_opened_result_relations

Bitmapset * printed_subplans

ExplainWorkersState * workers_state

ExplainSerializeOption serialize

ExplainForeignScan_function ExplainForeignScan

ExplainForeignModify_function ExplainForeignModify

ExplainDirectModify_function ExplainDirectModify

struct FdwRoutine * fdwroutine

SharedHashInfo * shared_info

HashInstrumentation * hinstrument

int64 totalMemorySpaceUsed

IncrementalSortGroupInfo prefixsortGroupInfo

IncrementalSortGroupInfo fullsortGroupInfo

SharedIncrementalSortInfo * shared_info

IncrementalSortInfo incsort_info

SharedIndexScanInstrumentation * ioss_SharedInfo

IndexScanInstrumentation ioss_Instrument

ScanDirection indexorderdir

IndexScanInstrumentation iss_Instrument

SharedIndexScanInstrumentation * iss_SharedInfo

ScanDirection indexorderdir

instr_time generation_counter

instr_time optimization_counter

instr_time deform_counter

instr_time emission_counter

instr_time inlining_counter

Tuplestorestate * tuplestorestate

SharedMemoizeInfo * shared_info

MemoizeInstrumentation stats

ResultRelInfo * resultRelInfo

OnConflictAction onConflictAction

QueryEnvironment * p_queryEnv

const char * p_sourcetext

struct SharedJitInstrumentation * worker_jit_instrument

Instrumentation * instrument

WorkerInstrumentation * worker_instrument

PlannedStmt * plannedstmt

Tuplestorestate * working_table

Tuplestorestate * intermediate_table

Instrumentation * ri_TrigInstrument

TriggerDesc * ri_TrigDesc

struct FdwRoutine * ri_FdwRoutine

bool ri_usesFdwDirectModify

SharedSortInfo * shared_info

struct PlanState * planstate

Tuplestorestate * tupstore

TuplesortMethod sortMethod

TuplesortSpaceType spaceType

Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER]

TupleDesc CreateTemplateTupleDesc(int natts)

void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)

void tuplesort_get_stats(Tuplesortstate *state, TuplesortInstrumentation *stats)

const char * tuplesort_space_type_name(TuplesortSpaceType t)

const char * tuplesort_method_name(TuplesortMethod m)

#define NUM_TUPLESORTMETHODS

@ SORT_TYPE_STILL_IN_PROGRESS

void tuplestore_get_stats(Tuplestorestate *state, char **max_storage_type, int64 *max_space)

TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)

static void usage(const char *progname)

Datum bit(PG_FUNCTION_ARGS)

void CommandCounterIncrement(void)