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

1

2

3

4

5

6

7

8

9

10

11

12

13

15

47

48

49

51

52

54

55

58

59

60

61

62

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

64

77 const char *relationship, const char *plan_name,

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

104 Agg *aggnode, Sort *sortnode,

105 List *context, bool useprefix,

110 int nkeys, int nPresortedKeys, AttrNumber *keycols,

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

114 Oid sortOperator, Oid collation, bool nullsFirst);

169

170

171

172

173

174

175

176void

179{

184 List *rewritten;

185

186

188

189

193

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

196

197

198

199

200

201

202

204

205

207

208 if (rewritten == NIL)

209 {

210

211

212

213

216 }

217 else

218 {

220

221

222 foreach(l, rewritten)

223 {

226 pstate, params);

227

228

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

231 }

232 }

233

234

237

238

243 else

246

248}

249

250

251

252

253

256{

259 Oid result_type = TEXTOID;

260

261

262 foreach(lc, stmt->options)

263 {

265

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

267 {

269

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

271 result_type = XMLOID;

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

273 result_type = JSONOID;

274 else

275 result_type = TEXTOID;

276

277 }

278 }

279

280

283 result_type, -1, 0);

284 return tupdesc;

285}

286

287

288

289

290

291

292

293static void

297{

298

300 {

302 return;

303 }

304

305

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

309 else

312}

313

314

315

316

317

318void

323{

326 planduration;

328 bufusage;

332

334 {

335

336

337

338

339

340

341

342

344 "explain analyze planner context",

347 }

348

352

353

354 plan = pg_plan_query(query, queryString, cursorOptions, params, es);

355

358

360 {

363 }

364

365

367 {

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

370 }

371

372

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

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

376}

377

378

379

380

381

382

383

384

385

386

387

388

389

390void

393{

394 if (utilityStmt == NULL)

395 return;

396

398 {

399

400

401

402

404 Query *ctas_query;

405 List *rewritten;

407

408

409

410

411

413 {

418 else

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

421 return;

422 }

423

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

433 pstate, params);

434 }

436 {

437

438

439

440

441

442

443

444

446 Query *dcs_query;

447 List *rewritten;

449

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

455

460 pstate, params);

461 }

464 pstate, params);

466 {

469 else

471 }

472 else

473 {

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

477 else

479 }

480}

481

482

483

484

485

486

487

488

489

490

491

492

493

494void

500{

504 double totaltime = 0;

505 int eflags;

506 int instrument_option = 0;

508

510

515

518 if (es->wal)

520

521

522

523

524

525

527

528

529

530

531

534

535

536

537

538

539

540

541

542

543 if (into)

547 else

549

550

553 dest, params, queryEnv, instrument_option);

554

555

557 eflags = 0;

558 else

562 if (into)

564

565

567

568

570 {

572

573

576 else

578

579

581

582

584

585

587 }

588

589

592

593

595

597

598

600

601

603 {

605

607 {

611 }

612

613 if (bufusage)

615

616 if (mem_counters)

618

621

623 }

624

625 if (es->summary && planduration)

626 {

628

630 }

631

632

635

636

637

638

639

640

641

644

645

648

649

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

652 params, queryEnv);

653

654

655

656

657

659

661

663

665

666

669

671

672

673

674

675

676

677

680 es);

681

683}

684

685

686

687

688

689static void

691{

692 int num;

694

695

697 return;

698

699

701

703 {

705

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

707 {

708 char *setting;

710

712

714 }

715

717 }

718 else

719 {

721

722

723 if (num <= 0)

724 return;

725

727

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

729 {

730 char *setting;

732

733 if (i > 0)

735

737

738 if (setting)

740 else

742 }

743

745 }

746}

747

748

749

750

751

752

753

754

755

756

757

758

759void

761{

765

766

776 foreach(lc, es->rtable)

777 {

779

781 {

783 break;

784 }

785 }

786

787

788

789

790

791

792

793

794

795

798 {

801 }

803

804

805

806

807

809

810

811

812

813

814

817 {

820 }

821}

822

823

824

825

826

827

828

829

830

831

832void

834{

836 bool show_relname;

837 List *resultrels;

838 List *routerels;

839 List *targrels;

841

845

847

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

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

850 foreach(l, resultrels)

851 {

854 }

855

856 foreach(l, routerels)

857 {

860 }

861

862 foreach(l, targrels)

863 {

866 }

867

869}

870

871

872

873

874

875void

877{

879

881 return;

882

883

884

885

886

889

890

893

895}

896

897

898

899

900

901static void

903{

905

906

908 return;

909

910

912

917

919

920

922 {

926

928

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

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

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

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

935

937 {

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

947 }

948

950 }

951 else

952 {

954

961

963 {

965

969 3, es);

972 3, es);

974

977 3, es);

980 3, es);

983 3, es);

986 3, es);

987

989 }

990 }

991

993}

994

995

996

997

998

999static void

1001{

1003

1004

1007 else

1008 {

1011 }

1012

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

1014

1016 {

1023 else

1027

1029 {

1033 }

1034 }

1035 else

1036 {

1040 3, es);

1046 }

1047

1049}

1050

1051

1052

1053

1054

1055

1056

1057

1058

1059void

1061{

1064}

1065

1066

1067

1068

1069

1070

1071

1072

1073

1074void

1076{

1077 char *str;

1078

1079

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

1081 return;

1082

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

1086}

1087

1088

1089

1090

1091

1092static void

1094{

1095 int nt;

1096

1098 return;

1100 {

1104 char *conname = NULL;

1105

1106

1108

1109

1110

1111

1112

1113 if (instr->ntuples == 0)

1114 continue;

1115

1117

1121

1122

1123

1124

1125

1126

1128 {

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

1131 else

1133 if (conname)

1135 if (show_relname)

1140 else

1142 }

1143 else

1144 {

1146 if (conname)

1151 es);

1153 }

1154

1155 if (conname)

1157

1159 }

1160}

1161

1162

1163static double

1165{

1167

1171}

1172

1173

1174

1175

1176

1177

1178

1179

1180

1181

1182static bool

1184{

1186

1188 {

1189 case T_SeqScan:

1190 case T_SampleScan:

1191 case T_IndexScan:

1192 case T_IndexOnlyScan:

1193 case T_BitmapHeapScan:

1194 case T_TidScan:

1195 case T_TidRangeScan:

1196 case T_SubqueryScan:

1197 case T_FunctionScan:

1198 case T_TableFuncScan:

1199 case T_ValuesScan:

1200 case T_CteScan:

1201 case T_NamedTuplestoreScan:

1202 case T_WorkTableScan:

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

1205 break;

1206 case T_ForeignScan:

1209 break;

1210 case T_CustomScan:

1213 break;

1214 case T_ModifyTable:

1220

1221 if (plan->targetlist)

1224 break;

1225 case T_Append:

1228 break;

1229 case T_MergeAppend:

1232 break;

1233 case T_Result:

1236 break;

1237 default:

1238 break;

1239 }

1240

1242}

1243

1244

1245

1246

1247

1248

1249

1250static bool

1252{

1253 int child_disabled_nodes;

1254

1255

1256 if (plan->disabled_nodes == 0)

1257 return false;

1258

1259 child_disabled_nodes = 0;

1260

1261

1262

1263

1264

1266 {

1269

1270

1271

1272

1273

1274

1276 {

1278

1280 }

1281 }

1283 {

1286

1287

1288

1289

1290

1291

1293 {

1295

1297 }

1298 }

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

1302 {

1305

1307 {

1309

1311 }

1312 }

1313 else

1314 {

1315

1316

1317

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

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

1322 }

1323

1324

1325

1326

1327

1328 if (plan->disabled_nodes > child_disabled_nodes)

1329 return true;

1330

1331 return false;

1332}

1333

1334

1335

1336

1337

1338

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355static void

1357 const char *relationship, const char *plan_name,

1359{

1361 const char *pname;

1362 const char *sname;

1363 const char *strategy = NULL;

1364 const char *partialmode = NULL;

1365 const char *operation = NULL;

1366 const char *custom_name = NULL;

1368 int save_indent = es->indent;

1369 bool haschildren;

1370 bool isdisabled;

1371

1372

1373

1374

1375

1378 else

1380

1381

1383 {

1384 case T_Result:

1385 pname = sname = "Result";

1386 break;

1387 case T_ProjectSet:

1388 pname = sname = "ProjectSet";

1389 break;

1390 case T_ModifyTable:

1391 sname = "ModifyTable";

1393 {

1395 pname = operation = "Insert";

1396 break;

1398 pname = operation = "Update";

1399 break;

1401 pname = operation = "Delete";

1402 break;

1404 pname = operation = "Merge";

1405 break;

1406 default:

1407 pname = "???";

1408 break;

1409 }

1410 break;

1411 case T_Append:

1412 pname = sname = "Append";

1413 break;

1414 case T_MergeAppend:

1415 pname = sname = "Merge Append";

1416 break;

1417 case T_RecursiveUnion:

1418 pname = sname = "Recursive Union";

1419 break;

1420 case T_BitmapAnd:

1421 pname = sname = "BitmapAnd";

1422 break;

1423 case T_BitmapOr:

1424 pname = sname = "BitmapOr";

1425 break;

1426 case T_NestLoop:

1427 pname = sname = "Nested Loop";

1428 break;

1429 case T_MergeJoin:

1430 pname = "Merge";

1431 sname = "Merge Join";

1432 break;

1433 case T_HashJoin:

1434 pname = "Hash";

1435 sname = "Hash Join";

1436 break;

1437 case T_SeqScan:

1438 pname = sname = "Seq Scan";

1439 break;

1440 case T_SampleScan:

1441 pname = sname = "Sample Scan";

1442 break;

1443 case T_Gather:

1444 pname = sname = "Gather";

1445 break;

1446 case T_GatherMerge:

1447 pname = sname = "Gather Merge";

1448 break;

1449 case T_IndexScan:

1450 pname = sname = "Index Scan";

1451 break;

1452 case T_IndexOnlyScan:

1453 pname = sname = "Index Only Scan";

1454 break;

1455 case T_BitmapIndexScan:

1456 pname = sname = "Bitmap Index Scan";

1457 break;

1458 case T_BitmapHeapScan:

1459 pname = sname = "Bitmap Heap Scan";

1460 break;

1461 case T_TidScan:

1462 pname = sname = "Tid Scan";

1463 break;

1464 case T_TidRangeScan:

1465 pname = sname = "Tid Range Scan";

1466 break;

1467 case T_SubqueryScan:

1468 pname = sname = "Subquery Scan";

1469 break;

1470 case T_FunctionScan:

1471 pname = sname = "Function Scan";

1472 break;

1473 case T_TableFuncScan:

1474 pname = sname = "Table Function Scan";

1475 break;

1476 case T_ValuesScan:

1477 pname = sname = "Values Scan";

1478 break;

1479 case T_CteScan:

1480 pname = sname = "CTE Scan";

1481 break;

1482 case T_NamedTuplestoreScan:

1483 pname = sname = "Named Tuplestore Scan";

1484 break;

1485 case T_WorkTableScan:

1486 pname = sname = "WorkTable Scan";

1487 break;

1488 case T_ForeignScan:

1489 sname = "Foreign Scan";

1491 {

1493 pname = "Foreign Scan";

1494 operation = "Select";

1495 break;

1497 pname = "Foreign Insert";

1498 operation = "Insert";

1499 break;

1501 pname = "Foreign Update";

1502 operation = "Update";

1503 break;

1505 pname = "Foreign Delete";

1506 operation = "Delete";

1507 break;

1508 default:

1509 pname = "???";

1510 break;

1511 }

1512 break;

1513 case T_CustomScan:

1514 sname = "Custom Scan";

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

1516 if (custom_name)

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

1518 else

1519 pname = sname;

1520 break;

1521 case T_Material:

1522 pname = sname = "Materialize";

1523 break;

1524 case T_Memoize:

1525 pname = sname = "Memoize";

1526 break;

1527 case T_Sort:

1528 pname = sname = "Sort";

1529 break;

1530 case T_IncrementalSort:

1531 pname = sname = "Incremental Sort";

1532 break;

1533 case T_Group:

1534 pname = sname = "Group";

1535 break;

1536 case T_Agg:

1537 {

1539

1540 sname = "Aggregate";

1542 {

1544 pname = "Aggregate";

1545 strategy = "Plain";

1546 break;

1548 pname = "GroupAggregate";

1549 strategy = "Sorted";

1550 break;

1552 pname = "HashAggregate";

1553 strategy = "Hashed";

1554 break;

1556 pname = "MixedAggregate";

1557 strategy = "Mixed";

1558 break;

1559 default:

1560 pname = "Aggregate ???";

1561 strategy = "???";

1562 break;

1563 }

1564

1566 {

1567 partialmode = "Partial";

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

1569 }

1571 {

1572 partialmode = "Finalize";

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

1574 }

1575 else

1576 partialmode = "Simple";

1577 }

1578 break;

1579 case T_WindowAgg:

1580 pname = sname = "WindowAgg";

1581 break;

1582 case T_Unique:

1583 pname = sname = "Unique";

1584 break;

1585 case T_SetOp:

1586 sname = "SetOp";

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

1588 {

1590 pname = "SetOp";

1591 strategy = "Sorted";

1592 break;

1594 pname = "HashSetOp";

1595 strategy = "Hashed";

1596 break;

1597 default:

1598 pname = "SetOp ???";

1599 strategy = "???";

1600 break;

1601 }

1602 break;

1603 case T_LockRows:

1604 pname = sname = "LockRows";

1605 break;

1606 case T_Limit:

1607 pname = sname = "Limit";

1608 break;

1609 case T_Hash:

1610 pname = sname = "Hash";

1611 break;

1612 default:

1613 pname = sname = "???";

1614 break;

1615 }

1616

1618 relationship ? NULL : "Plan",

1619 true, es);

1620

1622 {

1623 if (plan_name)

1624 {

1628 }

1630 {

1634 }

1635 if (plan->parallel_aware)

1637 if (plan->async_capable)

1641 }

1642 else

1643 {

1645 if (strategy)

1647 if (partialmode)

1649 if (operation)

1651 if (relationship)

1653 if (plan_name)

1655 if (custom_name)

1659 }

1660

1662 {

1663 case T_SeqScan:

1664 case T_SampleScan:

1665 case T_BitmapHeapScan:

1666 case T_TidScan:

1667 case T_TidRangeScan:

1668 case T_SubqueryScan:

1669 case T_FunctionScan:

1670 case T_TableFuncScan:

1671 case T_ValuesScan:

1672 case T_CteScan:

1673 case T_WorkTableScan:

1675 break;

1676 case T_ForeignScan:

1677 case T_CustomScan:

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

1680 break;

1681 case T_IndexScan:

1682 {

1684

1687 es);

1689 }

1690 break;

1691 case T_IndexOnlyScan:

1692 {

1694

1697 es);

1699 }

1700 break;

1701 case T_BitmapIndexScan:

1702 {

1704 const char *indexname =

1706

1710 else

1712 }

1713 break;

1714 case T_ModifyTable:

1716 break;

1717 case T_NestLoop:

1718 case T_MergeJoin:

1719 case T_HashJoin:

1720 {

1721 const char *jointype;

1722

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

1724 {

1726 jointype = "Inner";

1727 break;

1729 jointype = "Left";

1730 break;

1732 jointype = "Full";

1733 break;

1735 jointype = "Right";

1736 break;

1738 jointype = "Semi";

1739 break;

1741 jointype = "Anti";

1742 break;

1744 jointype = "Right Semi";

1745 break;

1747 jointype = "Right Anti";

1748 break;

1749 default:

1750 jointype = "???";

1751 break;

1752 }

1754 {

1755

1756

1757

1758

1763 }

1764 else

1766 }

1767 break;

1768 case T_SetOp:

1769 {

1770 const char *setopcmd;

1771

1773 {

1775 setopcmd = "Intersect";

1776 break;

1778 setopcmd = "Intersect All";

1779 break;

1781 setopcmd = "Except";

1782 break;

1784 setopcmd = "Except All";

1785 break;

1786 default:

1787 setopcmd = "???";

1788 break;

1789 }

1792 else

1794 }

1795 break;

1796 default:

1797 break;

1798 }

1799

1801 {

1803 {

1805 plan->startup_cost, plan->total_cost,

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

1807 }

1808 else

1809 {

1811 2, es);

1813 2, es);

1815 0, es);

1817 es);

1818 }

1819 }

1820

1821

1822

1823

1824

1825

1826

1827

1828

1829

1830

1833

1836 {

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

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

1841

1843 {

1845

1848

1850 }

1851 else

1852 {

1854 {

1856 3, es);

1858 3, es);

1859 }

1862 }

1863 }

1865 {

1868 else

1869 {

1871 {

1874 }

1877 }

1878 }

1879

1880

1883

1884

1888

1889

1891 {

1893

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

1895 {

1897 double nloops = instrument->nloops;

1898 double startup_ms;

1899 double total_ms;

1900 double rows;

1901

1902 if (nloops <= 0)

1903 continue;

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

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

1906 rows = instrument->ntuples / nloops;

1907

1909

1911 {

1916

1918 }

1919 else

1920 {

1922 {

1924 startup_ms, 3, es);

1926 total_ms, 3, es);

1927 }

1928

1931 }

1932

1934 }

1935 }

1936

1937

1940

1941

1943 {

1944 case T_NestLoop:

1945 case T_MergeJoin:

1946 case T_HashJoin:

1947

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

1952 es);

1953 break;

1954 default:

1955 break;

1956 }

1957

1958

1960 {

1961 case T_IndexScan:

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

1966 planstate, es);

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

1970 if (plan->qual)

1972 planstate, es);

1974 break;

1975 case T_IndexOnlyScan:

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

1980 planstate, es);

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

1984 if (plan->qual)

1986 planstate, es);

1991 break;

1992 case T_BitmapIndexScan:

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

1996 break;

1997 case T_BitmapHeapScan:

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

2002 planstate, es);

2004 if (plan->qual)

2006 planstate, es);

2008 break;

2009 case T_SampleScan:

2011 planstate, ancestors, es);

2012

2013

2014 case T_SeqScan:

2015 case T_ValuesScan:

2016 case T_CteScan:

2017 case T_NamedTuplestoreScan:

2018 case T_WorkTableScan:

2019 case T_SubqueryScan:

2021 if (plan->qual)

2023 planstate, es);

2026 break;

2027 case T_Gather:

2028 {

2030

2032 if (plan->qual)

2034 planstate, es);

2037

2039 {

2040 int nworkers;

2041

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

2044 nworkers, es);

2045 }

2046

2049 }

2050 break;

2051 case T_GatherMerge:

2052 {

2054

2056 if (plan->qual)

2058 planstate, es);

2061

2063 {

2064 int nworkers;

2065

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

2068 nworkers, es);

2069 }

2070 }

2071 break;

2072 case T_FunctionScan:

2074 {

2077

2079 {

2081

2083 }

2084

2086 "Function Call", planstate, ancestors,

2088 }

2090 if (plan->qual)

2092 planstate, es);

2093 break;

2094 case T_TableFuncScan:

2096 {

2098

2100 "Table Function Call", planstate, ancestors,

2102 }

2104 if (plan->qual)

2106 planstate, es);

2108 planstate), es);

2109 break;

2110 case T_TidScan:

2111 {

2112

2113

2114

2115

2117

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

2122 if (plan->qual)

2124 planstate, es);

2125 }

2126 break;

2127 case T_TidRangeScan:

2128 {

2129

2130

2131

2132

2134

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

2139 if (plan->qual)

2141 planstate, es);

2142 }

2143 break;

2144 case T_ForeignScan:

2146 if (plan->qual)

2148 planstate, es);

2150 break;

2151 case T_CustomScan:

2152 {

2154

2156 if (plan->qual)

2158 planstate, es);

2161 }

2162 break;

2163 case T_NestLoop:

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

2168 planstate, es);

2170 if (plan->qual)

2172 planstate, es);

2173 break;

2174 case T_MergeJoin:

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

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

2181 planstate, es);

2183 if (plan->qual)

2185 planstate, es);

2186 break;

2187 case T_HashJoin:

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

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

2194 planstate, es);

2196 if (plan->qual)

2198 planstate, es);

2199 break;

2200 case T_Agg:

2204 if (plan->qual)

2206 planstate, es);

2207 break;

2208 case T_WindowAgg:

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

2213 if (plan->qual)

2215 planstate, es);

2217 break;

2218 case T_Group:

2221 if (plan->qual)

2223 planstate, es);

2224 break;

2225 case T_Sort:

2228 break;

2229 case T_IncrementalSort:

2231 ancestors, es);

2233 es);

2234 break;

2235 case T_MergeAppend:

2237 ancestors, es);

2238 break;

2239 case T_Result:

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

2244 if (plan->qual)

2246 planstate, es);

2247 break;

2248 case T_ModifyTable:

2250 es);

2251 break;

2252 case T_Hash:

2254 break;

2255 case T_Material:

2257 break;

2258 case T_Memoize:

2260 es);

2261 break;

2262 case T_RecursiveUnion:

2264 planstate), es);

2265 break;

2266 default:

2267 break;

2268 }

2269

2270

2271

2272

2273

2275 {

2277

2278 if (w)

2279 {

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

2281 {

2286 }

2287 }

2288 }

2289

2290

2295

2296

2298 {

2300

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

2302 {

2304 double nloops = instrument->nloops;

2305

2306 if (nloops <= 0)

2307 continue;

2308

2312 if (es->wal)

2315 }

2316 }

2317

2318

2322

2323

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

2326 plan_name, es);

2327

2328

2329

2330

2331

2332

2333

2334

2335

2337 {

2338 case T_Append:

2341 es);

2342 break;

2343 case T_MergeAppend:

2346 es);

2347 break;

2348 default:

2349 break;

2350 }

2351

2352

2353 haschildren = planstate->initPlan ||

2364 if (haschildren)

2365 {

2367

2368 ancestors = lcons(plan, ancestors);

2369 }

2370

2371

2374

2375

2378 "Outer", NULL, es);

2379

2380

2383 "Inner", NULL, es);

2384

2385

2387 {

2388 case T_Append:

2391 ancestors, es);

2392 break;

2393 case T_MergeAppend:

2396 ancestors, es);

2397 break;

2398 case T_BitmapAnd:

2401 ancestors, es);

2402 break;

2403 case T_BitmapOr:

2406 ancestors, es);

2407 break;

2408 case T_SubqueryScan:

2410 "Subquery", NULL, es);

2411 break;

2412 case T_CustomScan:

2414 ancestors, es);

2415 break;

2416 default:

2417 break;

2418 }

2419

2420

2423

2424

2425 if (haschildren)

2426 {

2429 }

2430

2431

2433 es->indent = save_indent;

2434

2436 relationship ? NULL : "Plan",

2437 true, es);

2438}

2439

2440

2441

2442

2443static void

2445{

2449 bool useprefix;

2451

2452

2453 if (plan->targetlist == NIL)

2454 return;

2455

2457 return;

2458

2460 return;

2462 return;

2463

2464

2465

2466

2467

2468

2469

2470

2471

2472

2473

2476 return;

2477

2478

2481 ancestors);

2483

2484

2485 foreach(lc, plan->targetlist)

2486 {

2488

2489 result = lappend(result,

2491 useprefix, false));

2492 }

2493

2494

2496}

2497

2498

2499

2500

2501static void

2505{

2507 char *exprstr;

2508

2509

2511 planstate->plan,

2512 ancestors);

2513

2514

2516

2517

2519}

2520

2521

2522

2523

2524static void

2528{

2530

2531

2532 if (qual == NIL)

2533 return;

2534

2535

2537

2538

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

2540}

2541

2542

2543

2544

2545static void

2549{

2550 bool useprefix;

2551

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

2554}

2555

2556

2557

2558

2559static void

2563{

2564 bool useprefix;

2565

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

2568}

2569

2570

2571

2572

2573static void

2575{

2577

2579 plan->numCols, 0, plan->sortColIdx,

2580 plan->sortOperators, plan->collations,

2581 plan->nullsFirst,

2582 ancestors, es);

2583}

2584

2585

2586

2587

2588static void

2591{

2593

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

2596 plan->sort.sortColIdx,

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

2598 plan->sort.nullsFirst,

2599 ancestors, es);

2600}

2601

2602

2603

2604

2605static void

2608{

2610

2612 plan->numCols, 0, plan->sortColIdx,

2613 plan->sortOperators, plan->collations,

2614 plan->nullsFirst,

2615 ancestors, es);

2616}

2617

2618

2619

2620

2621static void

2624{

2626

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

2628 {

2629

2630 ancestors = lcons(plan, ancestors);

2631

2632 if (plan->groupingSets)

2634 else

2636 plan->numCols, 0, plan->grpColIdx,

2637 NULL, NULL, NULL,

2638 ancestors, es);

2639

2641 }

2642}

2643

2644static void

2647{

2649 bool useprefix;

2651

2652

2654 planstate->plan,

2655 ancestors);

2657

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

2659

2661 context, useprefix, ancestors, es);

2662

2663 foreach(lc, agg->chain)

2664 {

2667

2669 context, useprefix, ancestors, es);

2670 }

2671

2673}

2674

2675static void

2677 Agg *aggnode, Sort *sortnode,

2680{

2682 char *exprstr;

2685 AttrNumber *keycols = aggnode->grpColIdx;

2686 const char *keyname;

2687 const char *keysetname;

2688

2690 {

2691 keyname = "Hash Key";

2692 keysetname = "Hash Keys";

2693 }

2694 else

2695 {

2696 keyname = "Group Key";

2697 keysetname = "Group Keys";

2698 }

2699

2701

2702 if (sortnode)

2703 {

2705 sortnode->numCols, 0, sortnode->sortColIdx,

2706 sortnode->sortOperators, sortnode->collations,

2707 sortnode->nullsFirst,

2708 ancestors, es);

2711 }

2712

2714

2715 foreach(lc, gsets)

2716 {

2719

2721 {

2725 keyresno);

2726

2727 if (!target)

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

2729

2731 useprefix, true);

2732

2733 result = lappend(result, exprstr);

2734 }

2735

2738 else

2740 }

2741

2743

2746

2748}

2749

2750

2751

2752

2753static void

2756{

2758

2759

2760 ancestors = lcons(plan, ancestors);

2762 plan->numCols, 0, plan->grpColIdx,

2763 NULL, NULL, NULL,

2764 ancestors, es);

2766}

2767

2768

2769

2770

2771

2772

2773static void

2775 int nkeys, int nPresortedKeys, AttrNumber *keycols,

2776 Oid *sortOperators, Oid *collations, bool *nullsFirst,

2778{

2782 List *resultPresorted = NIL;

2784 bool useprefix;

2785 int keyno;

2786

2787 if (nkeys <= 0)

2788 return;

2789

2791

2792

2795 ancestors);

2797

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

2799 {

2800

2801 AttrNumber keyresno = keycols[keyno];

2803 keyresno);

2804 char *exprstr;

2805

2806 if (!target)

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

2808

2810 useprefix, true);

2813

2814 if (sortOperators != NULL)

2817 sortOperators[keyno],

2818 collations[keyno],

2819 nullsFirst[keyno]);

2820

2822 if (keyno < nPresortedKeys)

2823 resultPresorted = lappend(resultPresorted, exprstr);

2824 }

2825

2827 if (nPresortedKeys > 0)

2829}

2830

2831

2832

2833

2834

2835static void

2837 Oid sortOperator, Oid collation, bool nullsFirst)

2838{

2840 bool reverse = false;

2842

2845

2846

2847

2848

2849

2850

2851

2852

2854 {

2856

2857 if (collname == NULL)

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

2860 }

2861

2862

2863 if (sortOperator == typentry->gt_opr)

2864 {

2866 reverse = true;

2867 }

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

2869 {

2870 char *opname = get_opname(sortOperator);

2871

2872 if (opname == NULL)

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

2875

2877 }

2878

2879

2880 if (nullsFirst && !reverse)

2881 {

2883 }

2884 else if (!nullsFirst && reverse)

2885 {

2887 }

2888}

2889

2890

2891

2892

2893static void

2895{

2898 bool needspace = false;

2899

2902

2903

2904 ancestors = lcons(wagg, ancestors);

2906 {

2910 ancestors, es);

2911 needspace = true;

2912 }

2914 {

2915 if (needspace)

2920 ancestors, es);

2921 needspace = true;

2922 }

2925 {

2927 bool useprefix;

2928 char *framestr;

2929

2930

2932 (Plan *) wagg,

2933 ancestors);

2936 wagg->startOffset,

2937 wagg->endOffset,

2939 useprefix);

2940 if (needspace)

2943 pfree(framestr);

2944 }

2947 pfree(wbuf.data);

2948}

2949

2950

2951

2952

2953

2954

2955

2956static void

2960{

2963 bool useprefix;

2964

2965

2968 ancestors);

2970

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

2972 {

2973

2974 AttrNumber keyresno = keycols[keyno];

2976 keyresno);

2977 char *exprstr;

2978

2979 if (!target)

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

2981

2983 useprefix, true);

2984 if (keyno > 0)

2988

2989

2990

2991

2992

2993

2994 }

2995}

2996

2997

2998

2999

3000static void

3002{

3004

3006 {

3009 }

3010 else

3011 {

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

3015 maxStorageType,

3016 maxSpaceUsedKB);

3017 }

3018}

3019

3020

3021

3022

3023static void

3026{

3028 bool useprefix;

3029 char *method_name;

3031 char *repeatable;

3033

3034

3036 planstate->plan,

3037 ancestors);

3039

3040

3042

3043

3044 foreach(lc, tsc->args)

3045 {

3047

3048 params = lappend(params,

3050 useprefix, false));

3051 }

3054 useprefix, false);

3055 else

3056 repeatable = NULL;

3057

3058

3060 {

3061 bool first = true;

3062

3065 foreach(lc, params)

3066 {

3067 if (!first)

3070 first = false;

3071 }

3073 if (repeatable)

3076 }

3077 else

3078 {

3081 if (repeatable)

3083 }

3084}

3085

3086

3087

3088

3089static void

3091{

3093 return;

3094

3096 {

3099 const char *sortMethod;

3100 const char *spaceType;

3101 int64 spaceUsed;

3102

3106 spaceUsed = stats.spaceUsed;

3107

3109 {

3112 sortMethod, spaceType, spaceUsed);

3113 }

3114 else

3115 {

3119 }

3120 }

3121

3122

3123

3124

3125

3126

3127

3128

3129

3130

3132 {

3133 int n;

3134

3136 {

3138 const char *sortMethod;

3139 const char *spaceType;

3140 int64 spaceUsed;

3141

3144 continue;

3147 spaceUsed = sinstrument->spaceUsed;

3148

3151

3153 {

3157 sortMethod, spaceType, spaceUsed);

3158 }

3159 else

3160 {

3164 }

3165

3168 }

3169 }

3170}

3171

3172

3173

3174

3175

3176

3177

3178

3179

3180static void

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

3183{

3185 List *methodNames = NIL;

3186

3187

3189 {

3191

3192 if (groupInfo->sortMethods & sortMethod)

3193 {

3195

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

3197 }

3198 }

3199

3201 {

3202 if (indent)

3206

3209 else

3211 foreach(methodCell, methodNames)

3212 {

3216 }

3217

3219 {

3221 const char *spaceTypeName;

3222

3225 spaceTypeName, avgSpace,

3227 }

3228

3230 {

3232

3233 const char *spaceTypeName;

3234

3237 spaceTypeName, avgSpace,

3239 }

3240 }

3241 else

3242 {

3244

3249

3251

3253 {

3255 const char *spaceTypeName;

3257

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

3262

3266

3268 }

3270 {

3272 const char *spaceTypeName;

3274

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

3279

3283

3285 }

3286

3288 }

3289}

3290

3291

3292

3293

3294static void

3297{

3300

3302

3304 return;

3305

3306

3307

3308

3309

3310

3311

3312

3313

3314

3315 if (fullsortGroupInfo->groupCount > 0)

3316 {

3319 if (prefixsortGroupInfo->groupCount > 0)

3320 {

3324 }

3327 }

3328

3330 {

3331 int n;

3332 bool indent_first_line;

3333

3335 {

3338

3339

3340

3341

3342

3343

3345

3346

3347

3348

3349

3350

3351

3352 if (fullsortGroupInfo->groupCount == 0)

3353 continue;

3354

3357

3360 indent_first_line, es);

3362 if (prefixsortGroupInfo->groupCount > 0)

3363 {

3367 }

3370

3373 }

3374 }

3375}

3376

3377

3378

3379

3380static void

3382{

3384

3385

3386

3387

3388

3389

3390

3391

3392

3394 memcpy(&hinstrument, hashstate->hinstrument,

3396

3397

3398

3399

3400

3401

3402

3403

3404

3405

3407 {

3409 int i;

3410

3412 {

3414

3425 }

3426 }

3427

3428 if (hinstrument.nbatch > 0)

3429 {

3431

3433 {

3439 hinstrument.nbatch, es);

3443 spacePeakKb, es);

3444 }

3447 {

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

3455 spacePeakKb);

3456 }

3457 else

3458 {

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

3463 spacePeakKb);

3464 }

3465 }

3466}

3467

3468

3469

3470

3471

3472static void

3474{

3475 char *maxStorageType;

3476 int64 maxSpaceUsed;

3477

3479

3480

3481

3482

3483

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

3485 return;

3486

3489}

3490

3491

3492

3493

3494

3495static void

3497{

3498 char *maxStorageType;

3499 int64 maxSpaceUsed;

3500

3502

3503

3504

3505

3506

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

3508 return;

3509

3512}

3513

3514

3515

3516

3517

3518static void

3520{

3521 char *maxStorageType;

3522 int64 maxSpaceUsed;

3523

3525

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

3527 return;

3528

3531}

3532

3533

3534

3535

3536

3537static void

3539{

3540 char *maxStorageType;

3541 int64 maxSpaceUsed;

3542

3544

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

3546 return;

3547

3550}

3551

3552

3553

3554

3555

3556static void

3558{

3559 char *maxStorageType,

3560 *tempStorageType;

3561 int64 maxSpaceUsed,

3562 tempSpaceUsed;

3563

3565 return;

3566

3567

3568

3569

3570

3571

3573 &tempSpaceUsed);

3575 &maxSpaceUsed);

3576

3577 if (tempSpaceUsed > maxSpaceUsed)

3578 maxStorageType = tempStorageType;

3579

3580 maxSpaceUsed += tempSpaceUsed;

3582}

3583

3584

3585

3586

3587static void

3589{

3596 bool useprefix;

3597 int64 memPeakKb;

3598

3600

3601

3602

3603

3604

3606

3607

3610 ancestors);

3611

3613 {

3615

3617

3619 useprefix, false));

3621 }

3622

3625

3627

3629 {

3631 {

3633 appendStringInfo(es->str, "Estimates: capacity=%u distinct keys=%.0f lookups=%.0f hit percent=%.2f%%\n",

3636 }

3637 else

3638 {

3643 }

3644 }

3645

3647 return;

3648

3650 {

3651

3652

3653

3654

3657 else

3659

3661 {

3667 }

3668 else

3669 {

3677 memPeakKb);

3678 }

3679 }

3680

3682 return;

3683

3684

3686 {

3688

3690

3691

3692

3693

3694

3696 continue;

3697

3700

3701

3702

3703

3704

3705

3706

3708

3710 {

3716 memPeakKb);

3717 }

3718 else

3719 {

3729 es);

3730 }

3731

3734 }

3735}

3736

3737

3738

3739

3740static void

3742{

3745

3748 return;

3749

3751 {

3755

3756

3757

3758

3759

3760

3762 {

3768 }

3769 }

3770 else

3771 {

3772 bool gotone = false;

3773

3775 {

3779 gotone = true;

3780 }

3781

3782

3783

3784

3785

3786

3788 {

3789 if (!gotone)

3791 else

3793

3796 gotone = true;

3797

3798

3800 {

3803 }

3804 }

3805

3806 if (gotone)

3808 }

3809

3810

3812 {

3814 {

3816 uint64 hash_disk_used;

3817 int hash_batches_used;

3818

3820

3822 continue;

3826

3829

3831 {

3833

3835 hash_batches_used, memPeakKb);

3836

3837

3838 if (hash_batches_used > 1)

3840 hash_disk_used);

3842 }

3843 else

3844 {

3846 hash_batches_used, es);

3848 es);

3850 }

3851

3854 }

3855 }

3856}

3857

3858

3859

3860

3861

3862static void

3864{

3867 uint64 nsearches = 0;

3868

3870 return;

3871

3872

3874 {

3875 case T_IndexScan:

3876 {

3878

3881 break;

3882 }

3883 case T_IndexOnlyScan:

3884 {

3886

3889 break;

3890 }

3891 case T_BitmapIndexScan:

3892 {

3894

3897 break;

3898 }

3899 default:

3900 break;

3901 }

3902

3903

3904 if (SharedInfo)

3905 {

3907 {

3909

3910 nsearches += winstrument->nsearches;

3911 }

3912 }

3913

3915}

3916

3917

3918

3919

3920static void

3922{

3924 return;

3925

3927 {

3932 }

3933 else

3934 {

3936 {

3944 }

3945 }

3946

3947

3948 if (planstate->pstate != NULL)

3949 {

3951 {

3953

3955 continue;

3956

3959

3961 {

3969 }

3970 else

3971 {

3976 }

3977

3980 }

3981 }

3982}

3983

3984

3985

3986

3987

3988

3989static void

3992{

3993 double nfiltered;

3994 double nloops;

3995

3997 return;

3998

3999 if (which == 2)

4001 else

4004

4005

4007 {

4008 if (nloops > 0)

4010 else

4012 }

4013}

4014

4015

4016

4017

4018static void

4020{

4022

4023

4025 {

4028 }

4029 else

4030 {

4033 }

4034}

4035

4036

4037

4038

4039

4040

4041

4042

4043

4044

4045

4046static const char *

4048{

4049 const char *result;

4050

4052 result = (*explain_get_index_name_hook) (indexId);

4053 else

4054 result = NULL;

4055 if (result == NULL)

4056 {

4057

4059 if (result == NULL)

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

4061 }

4062 return result;

4063}

4064

4065

4066

4067

4068

4069

4070static bool

4072{

4073 bool has_shared;

4074 bool has_local;

4075 bool has_temp;

4076 bool has_shared_timing;

4077 bool has_local_timing;

4078 bool has_temp_timing;

4079

4080 if (usage == NULL)

4081 return false;

4082

4084 return true;

4085

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

4087 usage->shared_blks_read > 0 ||

4088 usage->shared_blks_dirtied > 0 ||

4089 usage->shared_blks_written > 0);

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

4091 usage->local_blks_read > 0 ||

4092 usage->local_blks_dirtied > 0 ||

4093 usage->local_blks_written > 0);

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

4095 usage->temp_blks_written > 0);

4102

4103 return has_shared || has_local || has_temp || has_shared_timing ||

4104 has_local_timing || has_temp_timing;

4105}

4106

4107

4108

4109

4110static void

4112{

4114 {

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

4116 usage->shared_blks_read > 0 ||

4117 usage->shared_blks_dirtied > 0 ||

4118 usage->shared_blks_written > 0);

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

4120 usage->local_blks_read > 0 ||

4121 usage->local_blks_dirtied > 0 ||

4122 usage->local_blks_written > 0);

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

4124 usage->temp_blks_written > 0);

4131

4132

4133 if (has_shared || has_local || has_temp)

4134 {

4137

4138 if (has_shared)

4139 {

4141 if (usage->shared_blks_hit > 0)

4143 usage->shared_blks_hit);

4144 if (usage->shared_blks_read > 0)

4146 usage->shared_blks_read);

4147 if (usage->shared_blks_dirtied > 0)

4149 usage->shared_blks_dirtied);

4150 if (usage->shared_blks_written > 0)

4152 usage->shared_blks_written);

4153 if (has_local || has_temp)

4155 }

4156 if (has_local)

4157 {

4159 if (usage->local_blks_hit > 0)

4161 usage->local_blks_hit);

4162 if (usage->local_blks_read > 0)

4164 usage->local_blks_read);

4165 if (usage->local_blks_dirtied > 0)

4167 usage->local_blks_dirtied);

4168 if (usage->local_blks_written > 0)

4170 usage->local_blks_written);

4171 if (has_temp)

4173 }

4174 if (has_temp)

4175 {

4177 if (usage->temp_blks_read > 0)

4179 usage->temp_blks_read);

4180 if (usage->temp_blks_written > 0)

4182 usage->temp_blks_written);

4183 }

4185 }

4186

4187

4188 if (has_shared_timing || has_local_timing || has_temp_timing)

4189 {

4192

4193 if (has_shared_timing)

4194 {

4202 if (has_local_timing || has_temp_timing)

4204 }

4205 if (has_local_timing)

4206 {

4214 if (has_temp_timing)

4216 }

4217 if (has_temp_timing)

4218 {

4226 }

4228 }

4229 }

4230 else

4231 {

4233 usage->shared_blks_hit, es);

4235 usage->shared_blks_read, es);

4237 usage->shared_blks_dirtied, es);

4239 usage->shared_blks_written, es);

4241 usage->local_blks_hit, es);

4243 usage->local_blks_read, es);

4245 usage->local_blks_dirtied, es);

4247 usage->local_blks_written, es);

4249 usage->temp_blks_read, es);

4251 usage->temp_blks_written, es);

4253 {

4256 3, es);

4259 3, es);

4262 3, es);

4265 3, es);

4268 3, es);

4271 3, es);

4272 }

4273 }

4274}

4275

4276

4277

4278

4279static void

4281{

4283 {

4284

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

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

4287 (usage->wal_fpi_bytes > 0))

4288 {

4291

4292 if (usage->wal_records > 0)

4294 usage->wal_records);

4295 if (usage->wal_fpi > 0)

4297 usage->wal_fpi);

4298 if (usage->wal_bytes > 0)

4300 usage->wal_bytes);

4301 if (usage->wal_fpi_bytes > 0)

4303 usage->wal_fpi_bytes);

4304 if (usage->wal_buffers_full > 0)

4306 usage->wal_buffers_full);

4308 }

4309 }

4310 else

4311 {

4313 usage->wal_records, es);

4315 usage->wal_fpi, es);

4317 usage->wal_bytes, es);

4319 usage->wal_fpi_bytes, es);

4321 usage->wal_buffers_full, es);

4322 }

4323}

4324

4325

4326

4327

4328static void

4330{

4334

4336 {

4340 memUsedkB, memAllocatedkB);

4342 }

4343 else

4344 {

4347 }

4348}

4349

4350

4351

4352

4353

4354static void

4357{

4359

4361 {

4365 }

4366 else

4367 {

4368 const char *scandir;

4369

4370 switch (indexorderdir)

4371 {

4373 scandir = "Backward";

4374 break;

4376 scandir = "Forward";

4377 break;

4378 default:

4379 scandir = "???";

4380 break;

4381 }

4384 }

4385}

4386

4387

4388

4389

4390static void

4392{

4394}

4395

4396

4397

4398

4399

4400

4401

4402

4403static void

4405{

4407}

4408

4409

4410

4411

4412static void

4414{

4415 char *objectname = NULL;

4416 char *namespace = NULL;

4417 const char *objecttag = NULL;

4419 char *refname;

4420

4423 if (refname == NULL)

4424 refname = rte->eref->aliasname;

4425

4427 {

4428 case T_SeqScan:

4429 case T_SampleScan:

4430 case T_IndexScan:

4431 case T_IndexOnlyScan:

4432 case T_BitmapHeapScan:

4433 case T_TidScan:

4434 case T_TidRangeScan:

4435 case T_ForeignScan:

4436 case T_CustomScan:

4437 case T_ModifyTable:

4438

4443 objecttag = "Relation Name";

4444 break;

4445 case T_FunctionScan:

4446 {

4448

4449

4451

4452

4453

4454

4455

4456

4457

4459 {

4461

4463 {

4466

4470 }

4471 }

4472 objecttag = "Function Name";

4473 }

4474 break;

4475 case T_TableFuncScan:

4476 {

4478

4480 switch (tablefunc->functype)

4481 {

4483 objectname = "xmltable";

4484 break;

4486 objectname = "json_table";

4487 break;

4488 default:

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

4491 }

4492 objecttag = "Table Function Name";

4493 }

4494 break;

4495 case T_ValuesScan:

4497 break;

4498 case T_CteScan:

4499

4501 Assert(!rte->self_reference);

4502 objectname = rte->ctename;

4503 objecttag = "CTE Name";

4504 break;

4505 case T_NamedTuplestoreScan:

4507 objectname = rte->enrname;

4508 objecttag = "Tuplestore Name";

4509 break;

4510 case T_WorkTableScan:

4511

4513 Assert(rte->self_reference);

4514 objectname = rte->ctename;

4515 objecttag = "CTE Name";

4516 break;

4517 default:

4518 break;

4519 }

4520

4522 {

4524 if (namespace != NULL)

4527 else if (objectname != NULL)

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

4531 }

4532 else

4533 {

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

4536 if (namespace != NULL)

4539 }

4540}

4541

4542

4543

4544

4545

4546

4547

4548

4549

4550static void

4553{

4555 const char *operation;

4556 const char *foperation;

4557 bool labeltargets;

4558 int j;

4561

4563 {

4565 operation = "Insert";

4566 foperation = "Foreign Insert";

4567 break;

4569 operation = "Update";

4570 foperation = "Foreign Update";

4571 break;

4573 operation = "Delete";

4574 foperation = "Foreign Delete";

4575 break;

4577 operation = "Merge";

4578

4579 foperation = "Foreign Merge";

4580 break;

4581 default:

4582 operation = "???";

4583 foperation = "Foreign ???";

4584 break;

4585 }

4586

4587

4588

4589

4590

4591

4592

4593

4594

4595

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

4601

4602 if (labeltargets)

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

4604

4606 {

4609

4610 if (labeltargets)

4611 {

4612

4614

4615

4616

4617

4618

4620 {

4623 fdwroutine ? foperation : operation);

4624 }

4625

4626

4629 es);

4630

4632 {

4635 }

4636 }

4637

4638

4640 fdwroutine != NULL &&

4642 {

4644

4646 resultRelInfo,

4647 fdw_private,

4648 j,

4649 es);

4650 }

4651

4652 if (labeltargets)

4653 {

4654

4657

4658

4660 }

4661 }

4662

4663

4665 {

4667

4668 idxNames = lappend(idxNames, indexname);

4669 }

4670

4672 {

4675 "NOTHING" : "UPDATE",

4676 es);

4677

4678

4679

4680

4681

4682 if (idxNames)

4684

4685

4687 {

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

4691 }

4692

4693

4695 {

4696 double total;

4697 double insert_path;

4698 double other_path;

4699

4701

4702

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

4705 insert_path = total - other_path;

4706

4708 insert_path, 0, es);

4710 other_path, 0, es);

4711 }

4712 }

4714 {

4715

4717 {

4718 double total;

4719 double insert_path;

4720 double update_path;

4721 double delete_path;

4722 double skipped_path;

4723

4725

4726

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

4731 skipped_path = total - insert_path - update_path - delete_path;

4732 Assert(skipped_path >= 0);

4733

4735 {

4736 if (total > 0)

4737 {

4740 if (insert_path > 0)

4742 if (update_path > 0)

4744 if (delete_path > 0)

4746 if (skipped_path > 0)

4749 }

4750 }

4751 else

4752 {

4757 }

4758 }

4759 }

4760

4761 if (labeltargets)

4763}

4764

4765

4766

4767

4768static void

4770{

4772 int nrels = 0;

4773 int rti = -1;

4774 bool found_non_result = false;

4775 char *replacement_type = "???";

4776

4777

4779 return;

4780

4781

4783

4785 {

4787 replacement_type = "Gating";

4788 break;

4790 replacement_type = "Scan";

4791 break;

4793 replacement_type = "Join";

4794 break;

4796

4797 replacement_type = "Aggregate";

4798 break;

4800 replacement_type = "MinMaxAggregate";

4801 break;

4802 }

4803

4804

4805

4806

4807

4810 {

4812 char *refname;

4813

4814

4815

4816

4817

4818

4819

4820

4822 continue;

4823

4824

4825 ++nrels;

4826

4827

4829 if (refname == NULL)

4830 refname = rte->eref->aliasname;

4831 if (buf.len > 0)

4834

4835

4837 found_non_result = true;

4838 }

4839

4840

4841

4842

4843

4844

4845

4846 if (nrels <= 1 && !found_non_result &&

4848 return;

4849

4850

4851 if (buf.len == 0)

4853 else

4854 {

4855 char *s = psprintf("%s on %s", replacement_type, buf.data);

4856

4858 }

4859}

4860

4861

4862

4863

4864

4865

4866

4867

4868static void

4871{

4872 int j;

4873

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

4876 "Member", NULL, es);

4877}

4878

4879

4880

4881

4882

4883

4884

4885

4886static void

4888{

4891 nchildren - nplans, es);

4892}

4893

4894

4895

4896

4897

4898

4899

4900static void

4903{

4905

4906 foreach(lst, plans)

4907 {

4910 char *cooked_plan_name;

4911

4912

4913

4914

4915

4916

4917

4918

4919

4920

4921

4923 continue;

4926

4927

4928

4929

4930

4931

4932 ancestors = lcons(sp, ancestors);

4933

4934

4935

4936

4937

4938

4943 else

4945

4947 relationship, cooked_plan_name, es);

4948

4950 }

4951}

4952

4953

4954

4955

4956static void

4958{

4960 const char *label =

4962

4965}

4966

4967

4968

4969

4970

4971

4972

4973

4974

4975

4976

4977

4980{

4982

4989 return wstate;

4990}

4991

4992

4993

4994

4995static void

4997{

4999

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

5002

5003

5005

5007 {

5008

5011

5012

5013

5014

5015

5016

5018

5019

5020

5021

5022

5025

5027 }

5028 else

5029 {

5030

5032

5033

5035 }

5036

5037

5038

5039

5040

5041

5043 {

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

5045 {

5048 }

5049

5051 }

5052}

5053

5054

5055

5056

5057static void

5059{

5061

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

5065

5066

5067

5068

5069

5071

5072

5073

5074

5075

5076

5077

5079 {

5082

5084 }

5085

5086

5088}

5089

5090

5091

5092

5093static void

5095{

5097

5100 {

5102 {

5103

5107

5109 }

5110 }

5112

5117}

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

int bms_next_member(const Bitmapset *a, int prevbit)

bool bms_is_member(int x, const Bitmapset *a)

Bitmapset * bms_add_member(Bitmapset *a, int x)

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

#define unconstify(underlying_type, expr)

#define OidIsValid(objectId)

bool CreateTableAsRelExists(CreateTableAsStmt *ctas)

int GetIntoRelEFlags(IntoClause *intoClause)

DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)

char * defGetString(DefElem *def)

DestReceiver * None_Receiver

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

void ExecutorStart(QueryDesc *queryDesc, int eflags)

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

const TupleTableSlotOps TTSOpsVirtual

void end_tup_output(TupOutputState *tstate)

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

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

#define outerPlanState(node)

#define innerPlanState(node)

#define EXEC_FLAG_EXPLAIN_GENERIC

#define do_text_output_oneline(tstate, str_to_emit)

#define EXEC_FLAG_EXPLAIN_ONLY

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

#define BYTES_TO_KILOBYTES(b)

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

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

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

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

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

static void show_result_replacement_info(Result *result, ExplainState *es)

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

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

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

static const char * explain_get_index_name(Oid indexId)

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

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

ExplainOneQuery_hook_type ExplainOneQuery_hook

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

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

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

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

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

explain_get_index_name_hook_type explain_get_index_name_hook

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

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

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

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

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

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

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

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

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

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

explain_per_node_hook_type explain_per_node_hook

TupleDesc ExplainResultDesc(ExplainStmt *stmt)

static void ExplainFlushWorkersState(ExplainState *es)

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

void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)

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

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

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

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

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

static double elapsed_time(instr_time *starttime)

void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc)

explain_per_plan_hook_type explain_per_plan_hook

static bool plan_is_disabled(Plan *plan)

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

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

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

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

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

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

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

void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)

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

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

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

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

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

static void ExplainPrintSettings(ExplainState *es)

static void ExplainCloseWorker(int n, ExplainState *es)

static void ExplainOpenWorker(int n, ExplainState *es)

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

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

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

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

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

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

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

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

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

static ExplainWorkersState * ExplainCreateWorkersState(int num_workers)

void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)

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

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

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

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

const char *(* explain_get_index_name_hook_type)(Oid indexId)

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

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

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

SerializeMetrics GetSerializationMetrics(DestReceiver *dest)

DestReceiver * CreateExplainSerializeDestReceiver(ExplainState *es)

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

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

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

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

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

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

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

void ExplainSeparatePlans(ExplainState *es)

void ExplainEndOutput(ExplainState *es)

void ExplainIndentText(ExplainState *es)

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

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

void ExplainBeginOutput(ExplainState *es)

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

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

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

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

ExplainState * NewExplainState(void)

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

@ EXPLAIN_SERIALIZE_BINARY

#define palloc_object(type)

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

struct config_generic ** get_explain_guc_options(int *num)

Assert(PointerIsAligned(start, uint64))

#define INSTR_TIME_SET_CURRENT(t)

#define INSTR_TIME_ADD(x, y)

#define INSTR_TIME_IS_ZERO(t)

#define INSTR_TIME_GET_DOUBLE(t)

#define INSTR_TIME_SUBTRACT(x, y)

#define INSTR_TIME_GET_MILLISEC(t)

#define INSTR_TIME_SET_ZERO(t)

void InstrEndLoop(Instrumentation *instr)

BufferUsage pgBufferUsage

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

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

void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)

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

List * list_delete_first(List *list)

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

char * get_rel_name(Oid relid)

char * get_opname(Oid opno)

Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)

Oid get_rel_namespace(Oid relid)

Oid get_typcollation(Oid typid)

char * get_collation_name(Oid colloid)

char * get_namespace_name_or_temp(Oid nspid)

char * get_constraint_name(Oid conoid)

char * get_func_name(Oid funcid)

Oid get_func_namespace(Oid funcid)

Expr * make_orclause(List *orclauses)

Expr * make_ands_explicit(List *andclauses)

Expr * make_andclause(List *andclauses)

void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)

char * pstrdup(const char *in)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext CurrentMemoryContext

#define AllocSetContextCreate

#define ALLOCSET_DEFAULT_SIZES

Oid exprType(const Node *expr)

#define planstate_tree_walker(ps, w, c)

#define DO_AGGSPLIT_SKIPFINAL(as)

#define IsA(nodeptr, _type_)

#define DO_AGGSPLIT_COMBINE(as)

#define castNode(_type_, nodeptr)

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

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

TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)

#define CURSOR_OPT_PARALLEL_OK

#define FRAMEOPTION_NONDEFAULT

post_parse_analyze_hook_type post_parse_analyze_hook

#define rt_fetch(rangetable_index, rangetable)

#define lfirst_node(type, lc)

static int list_length(const List *l)

#define linitial_node(type, l)

#define foreach_current_index(var_or_cell)

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

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

static char buf[DEFAULT_XLOG_SEG_SIZE]

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

void FreeQueryDesc(QueryDesc *qdesc)

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

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

@ COMPUTE_QUERY_ID_REGRESS

static bool IsQueryIdEnabled(void)

JumbleState * JumbleQuery(Query *query)

static const struct fns functions

#define RelationGetRelationName(relation)

List * QueryRewrite(Query *parsetree)

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

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

const char * quote_identifier(const char *ident)

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

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

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

#define ScanDirectionIsBackward(direction)

@ NoMovementScanDirection

void UpdateActiveSnapshotCommandId(void)

void PopActiveSnapshot(void)

void PushCopiedSnapshot(Snapshot snapshot)

Snapshot GetActiveSnapshot(void)

void resetStringInfo(StringInfo str)

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

void appendStringInfoSpaces(StringInfo str, int count)

void appendStringInfoString(StringInfo str, const char *s)

void appendStringInfoChar(StringInfo str, char ch)

void initStringInfo(StringInfo str)

int hash_planned_partitions

SharedAggInfo * shared_info

ParallelBitmapHeapState * pstate

BitmapHeapScanInstrumentation stats

SharedBitmapHeapInstrumentation * sinstrument

SharedIndexScanInstrumentation * biss_SharedInfo

IndexScanInstrumentation biss_Instrument

Tuplestorestate * cte_table

struct CteScanState * leader

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

const struct CustomExecMethods * methods

List * es_tuple_routing_result_relations

struct JitContext * es_jit

struct JitInstrumentation * es_jit_worker_instr

Bitmapset * es_unpruned_relids

List * es_trig_target_relations

List * es_opened_result_relations

Bitmapset * printed_subplans

ExplainWorkersState * workers_state

ExplainSerializeOption serialize

ExplainForeignScan_function ExplainForeignScan

ExplainForeignModify_function ExplainForeignModify

ExplainDirectModify_function ExplainDirectModify

struct FdwRoutine * fdwroutine

SharedHashInfo * shared_info

HashInstrumentation * hinstrument

int64 totalMemorySpaceUsed

IncrementalSortGroupInfo prefixsortGroupInfo

IncrementalSortGroupInfo fullsortGroupInfo

SharedIncrementalSortInfo * shared_info

IncrementalSortInfo incsort_info

SharedIndexScanInstrumentation * ioss_SharedInfo

IndexScanInstrumentation ioss_Instrument

ScanDirection indexorderdir

IndexScanInstrumentation iss_Instrument

SharedIndexScanInstrumentation * iss_SharedInfo

ScanDirection indexorderdir

instr_time generation_counter

instr_time optimization_counter

instr_time deform_counter

instr_time emission_counter

instr_time inlining_counter

Tuplestorestate * tuplestorestate

SharedMemoizeInfo * shared_info

MemoizeInstrumentation stats

Cardinality est_unique_keys

ResultRelInfo * resultRelInfo

OnConflictAction onConflictAction

QueryEnvironment * p_queryEnv

const char * p_sourcetext

struct SharedJitInstrumentation * worker_jit_instrument

Instrumentation * instrument

WorkerInstrumentation * worker_instrument

PlannedStmt * plannedstmt

Tuplestorestate * working_table

Tuplestorestate * intermediate_table

Instrumentation * ri_TrigInstrument

TriggerDesc * ri_TrigDesc

struct FdwRoutine * ri_FdwRoutine

bool ri_usesFdwDirectModify

SharedSortInfo * shared_info

Tuplestorestate * tupstore

TuplesortMethod sortMethod

TuplesortSpaceType spaceType

Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER]

TupleDesc CreateTemplateTupleDesc(int natts)

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

void tuplesort_get_stats(Tuplesortstate *state, TuplesortInstrumentation *stats)

const char * tuplesort_space_type_name(TuplesortSpaceType t)

const char * tuplesort_method_name(TuplesortMethod m)

#define NUM_TUPLESORTMETHODS

@ SORT_TYPE_STILL_IN_PROGRESS

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

TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)

static void usage(const char *progname)

Datum bit(PG_FUNCTION_ARGS)

void CommandCounterIncrement(void)