PostgreSQL Source Code: src/backend/optimizer/prep/prepunion.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

25

26#include <math.h>

27

41

42

45 List *colTypes, List *colCollations,

46 List *refnames_tlist,

47 List **pTargetList,

48 bool *istrivial_tlist);

51 List *refnames_tlist,

52 List **pTargetList);

54 bool trivial_tlist, List *child_tlist,

55 List *interesting_pathkeys,

56 double *pNumGroups);

58 List *refnames_tlist,

59 List **pTargetList);

61 List *refnames_tlist,

62 List **pTargetList);

65 List *refnames_tlist,

66 List **tlist_list,

67 List **istrivial_tlist);

71 bool hack_constants,

72 List *input_tlist,

73 List *refnames_tlist,

74 bool *trivial_tlist);

76 List *input_tlists,

77 List *refnames_tlist);

80 List *child_pathlist);

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

98{

103 Query *leftmostQuery;

105 List *top_tlist;

106

108

109

116

117

118

119

120

121

122

124 root->ec_merging_done = true;

125

126

127

128

129

130

132

133

134

135

136

137 node = topop->larg;

141 leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];

142 leftmostQuery = leftmostRTE->subquery;

143 Assert(leftmostQuery != NULL);

144

145

146

147

148 if (root->hasRecursion)

149 {

152 &top_tlist);

153 }

154 else

155 {

156 bool trivial_tlist;

157

158

159

160

161

162

164 NULL,

165 topop->colTypes, topop->colCollations,

167 &top_tlist,

168 &trivial_tlist);

169 }

170

171

172 root->processed_tlist = top_tlist;

173

174 return setop_rel;

175}

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

215 List *colTypes, List *colCollations,

216 List *refnames_tlist,

217 List **pTargetList,

218 bool *istrivial_tlist)

219{

221

222 *istrivial_tlist = true;

223

224

226

228 {

234 bool trivial_tlist;

235 char *plan_name;

236

237 Assert(subquery != NULL);

238

239

241

242

244

245

246

247

248

249

252 plan_name, root,

253 false, root->tuple_fraction,

254 parentOp);

255

256

257

258

259

260 if (root->plan_params)

261 elog(ERROR, "unexpected outer reference in set operation subquery");

262

263

266 true,

268 refnames_tlist,

269 &trivial_tlist);

271

272

273 *pTargetList = tlist;

274 *istrivial_tlist = trivial_tlist;

275 }

277 {

279

280

283 refnames_tlist,

284 pTargetList);

285 else

287 refnames_tlist,

288 pTargetList);

289

290

291

292

293

294

295

296

297

298

299

300

301

302

305 {

307 bool trivial_tlist;

309

311 0,

312 false,

313 *pTargetList,

314 refnames_tlist,

315 &trivial_tlist);

316 *istrivial_tlist = trivial_tlist;

318

319

321 {

324

328

331 }

332

333

335 {

338

340

341

345 }

346 }

348 }

349 else

350 {

351 elog(ERROR, "unrecognized node type: %d",

353 *pTargetList = NIL;

354 rel = NULL;

355 }

356

357 return rel;

358}

359

360

361

362

365 List *refnames_tlist,

366 List **pTargetList)

367{

371 *rrel;

374 List *lpath_tlist;

375 bool lpath_trivial_tlist;

376 List *rpath_tlist;

377 bool rpath_trivial_tlist;

379 List *groupList;

380 double dNumGroups;

381

382

384 elog(ERROR, "only UNION queries can be recursive");

385

387

388

389

390

391

393 NULL,

394 setOp->colTypes, setOp->colCollations,

395 refnames_tlist,

396 &lpath_tlist,

397 &lpath_trivial_tlist);

400 NIL, NULL);

402

403 root->non_recursive_path = lpath;

405 NULL,

406 setOp->colTypes, setOp->colCollations,

407 refnames_tlist,

408 &rpath_tlist,

409 &rpath_trivial_tlist);

412 NIL, NULL);

414 root->non_recursive_path = NULL;

415

416

417

418

420 list_make2(lpath_tlist, rpath_tlist),

421 refnames_tlist);

422

423 *pTargetList = tlist;

424

425

429

430

431

432

433 if (setOp->all)

434 {

435 groupList = NIL;

436 dNumGroups = 0;

437 }

438 else

439 {

440

442

443

446 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

447 errmsg("could not implement recursive UNION"),

448 errdetail("All column datatypes must be hashable.")));

449

450

451

452

453

454 dNumGroups = lpath->rows + rpath->rows * 10;

455 }

456

457

458

459

461 result_rel,

462 lpath,

463 rpath,

465 groupList,

466 root->wt_param_id,

467 dNumGroups);

468

471 return result_rel;

472}

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487static void

489 bool trivial_tlist, List *child_tlist,

490 List *interesting_pathkeys, double *pNumGroups)

491{

495

496

498

499

500 if (interesting_pathkeys != NIL)

502 rel,

503 child_tlist,

504 interesting_pathkeys);

505

506

507

508

509

510

512

513

514

515

516

519

520

521 foreach(lc, final_rel->pathlist)

522 {

524 List *pathkeys;

526 bool is_sorted;

527 int presorted_keys;

528

529

531 {

533 continue;

534 }

535

536

537

538

539

540

541 if (subpath == cheapest_input_path)

542 {

543

546

547

549 rel,

551 trivial_tlist,

552 pathkeys,

553 NULL));

554 }

555

556

557 if (interesting_pathkeys == NIL)

558 continue;

559

560

561

562

563

564

567 &presorted_keys);

568

569 if (!is_sorted)

570 {

572

573

574

575

576

577

578

579

580 if (subpath != cheapest_input_path &&

582 continue;

583

584

585

586

587

588

591 final_rel,

593 setop_pathkeys,

594 limittuples);

595 else

597 final_rel,

599 setop_pathkeys,

600 presorted_keys,

601 limittuples);

602 }

603

604

605

606

607

608

609 if (subpath != cheapest_input_path)

610 {

611

614

615

617 rel,

619 trivial_tlist,

620 pathkeys,

621 NULL));

622 }

623 }

624

625

628

629

630

631

632

633

636 {

637 Path *partial_subpath;

638 Path *partial_path;

639

641 partial_path = (Path *)

643 trivial_tlist,

644 NIL, NULL);

646 }

647

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668 if (pNumGroups)

669 {

672

675 subquery->hasAggs)

677 else

681 NULL,

682 NULL);

683 }

684}

685

686

687

688

691 List *refnames_tlist,

692 List **pTargetList)

693{

694 Relids relids = NULL;

699 List *cheapest_pathlist = NIL;

700 List *ordered_pathlist = NIL;

701 List *partial_pathlist = NIL;

702 bool partial_paths_valid = true;

703 bool consider_parallel = true;

704 List *rellist;

705 List *tlist_list;

706 List *trivial_tlist_list;

710 Path *gpath = NULL;

711 bool try_sorted = false;

712 List *union_pathkeys = NIL;

713

714

715

716

717

718

719

721 op,

722 refnames_tlist,

723 &tlist_list,

724 &trivial_tlist_list);

725

726

727

728

729

730

731

732

734 tlist_list, refnames_tlist);

735 *pTargetList = tlist;

736

737

738 if (!op->all)

739 {

740

742

744 {

745 try_sorted = true;

746

748 tlist);

749

750 root->query_pathkeys = union_pathkeys;

751 }

752 }

753

754

755

756

757

758 forthree(lc, rellist, lc2, trivial_tlist_list, lc3, tlist_list)

759 {

761 bool trivial_tlist = lfirst_int(lc2);

763

764

767 union_pathkeys, NULL);

768 }

769

770

771 foreach(lc, rellist)

772 {

774 Path *ordered_path;

775

776

777

778

779

781

782

784 continue;

785

786 cheapest_pathlist = lappend(cheapest_pathlist,

788

789 if (try_sorted)

790 {

792 union_pathkeys,

793 NULL,

795 false);

796

797 if (ordered_path != NULL)

798 ordered_pathlist = lappend(ordered_pathlist, ordered_path);

799 else

800 {

801

802

803

804

805

806

807 try_sorted = false;

808 }

809 }

810

811 if (consider_parallel)

812 {

814 {

815 consider_parallel = false;

816 partial_paths_valid = false;

817 }

819 partial_paths_valid = false;

820 else

821 partial_pathlist = lappend(partial_pathlist,

823 }

824 }

825

826

829 cheapest_pathlist);

832

833

834 if (cheapest_pathlist == NIL)

835 {

837

838 return result_rel;

839 }

840

841

842

843

844

846 NIL, NIL, NULL, 0, false, -1);

847

848

849

850

851

852

853 result_rel->rows = apath->rows;

854

855

856

857

858

859 if (partial_paths_valid)

860 {

861 Path *papath;

862 int parallel_workers = 0;

863

864

865 foreach(lc, partial_pathlist)

866 {

868

869 parallel_workers = Max(parallel_workers,

870 subpath->parallel_workers);

871 }

872 Assert(parallel_workers > 0);

873

874

875

876

877

878

879

880

882 {

883 parallel_workers = Max(parallel_workers,

885 parallel_workers = Min(parallel_workers,

887 }

888 Assert(parallel_workers > 0);

889

890 papath = (Path *)

892 NIL, NULL, parallel_workers,

894 gpath = (Path *)

896 result_rel->reltarget, NULL, NULL);

897 }

898

899 if (!op->all)

900 {

901 double dNumGroups;

904 Path *first_path = linitial(cheapest_pathlist);

905

906

907

908

909

910

911

912

913

914 if (list_length(cheapest_pathlist) == 1 &&

916 {

918 first_path->pathtarget->exprs,

919 first_path->rows,

920 NULL,

921 NULL);

922 }

923 else

924 {

925

926

927

928

929

930

931

932

933 dNumGroups = apath->rows;

934 }

935

936 if (can_hash)

937 {

939

940

941

942

943

945 result_rel,

946 apath,

950 groupList,

952 NULL,

953 dNumGroups);

955

956

957 if (gpath != NULL)

958 {

959

961 result_rel,

962 gpath,

966 groupList,

968 NULL,

969 dNumGroups);

971 }

972 }

973

974 if (can_sort)

975 {

976 Path *path = apath;

977

978

979 if (groupList != NIL)

982 -1.0);

983

985 result_rel,

986 path,

988 dNumGroups);

989

991

992

993 if (gpath != NULL)

994 {

995 path = gpath;

996

999 -1.0);

1000

1002 result_rel,

1003 path,

1005 dNumGroups);

1007 }

1008 }

1009

1010

1011

1012

1013

1014 if (try_sorted && groupList != NIL)

1015 {

1017

1019 result_rel,

1020 ordered_pathlist,

1021 union_pathkeys,

1022 NULL);

1023

1024

1026 result_rel,

1027 path,

1029 dNumGroups);

1030

1032 }

1033 }

1034 else

1035 {

1036

1037 add_path(result_rel, apath);

1038

1039 if (gpath != NULL)

1040 add_path(result_rel, gpath);

1041 }

1042

1043 return result_rel;

1044}

1045

1046

1047

1048

1051 List *refnames_tlist,

1052 List **pTargetList)

1053{

1056 *rrel;

1057 double save_fraction = root->tuple_fraction;

1058 Path *lpath,

1059 *rpath,

1060 *path;

1061 List *lpath_tlist,

1062 *rpath_tlist,

1063 *tlist,

1064 *groupList;

1065 bool lpath_trivial_tlist,

1066 rpath_trivial_tlist,

1067 result_trivial_tlist;

1068 List *nonunion_pathkeys = NIL;

1069 double dLeftGroups,

1070 dRightGroups,

1071 dNumGroups,

1072 dNumOutputRows;

1073 bool can_sort;

1074 bool can_hash;

1076

1077

1078

1079

1080 root->tuple_fraction = 0.0;

1081

1082

1084 op,

1085 op->colTypes, op->colCollations,

1086 refnames_tlist,

1087 &lpath_tlist,

1088 &lpath_trivial_tlist);

1089

1091 op,

1092 op->colTypes, op->colCollations,

1093 refnames_tlist,

1094 &rpath_tlist,

1095 &rpath_trivial_tlist);

1096

1097

1098

1099

1100

1101

1102

1103

1105 0, false, lpath_tlist, refnames_tlist,

1106 &result_trivial_tlist);

1107

1108

1109 Assert(result_trivial_tlist);

1110

1111 *pTargetList = tlist;

1112

1113

1115

1116

1119 if (!can_sort && !can_hash)

1121 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1122

1123 errmsg("could not implement %s",

1125 errdetail("Some of the datatypes only support hashing, while others only support sorting.")));

1126

1127 if (can_sort)

1128 {

1129

1131 tlist);

1132

1133 root->query_pathkeys = nonunion_pathkeys;

1134 }

1135

1136

1137

1138

1141 nonunion_pathkeys, &dLeftGroups);

1142 else

1143 dLeftGroups = lrel->rows;

1146 nonunion_pathkeys, &dRightGroups);

1147 else

1148 dRightGroups = rrel->rows;

1149

1150

1151 root->tuple_fraction = save_fraction;

1152

1153

1154

1155

1156

1157

1158

1159

1160

1161 if (op->op != SETOP_EXCEPT && dLeftGroups > dRightGroups)

1162 {

1163

1165 List *tmplist;

1166 double tmpd;

1167

1168 tmprel = lrel;

1169 lrel = rrel;

1170 rrel = tmprel;

1171 tmplist = lpath_tlist;

1172 lpath_tlist = rpath_tlist;

1173 rpath_tlist = tmplist;

1174 tmpd = dLeftGroups;

1175 dLeftGroups = dRightGroups;

1176 dRightGroups = tmpd;

1177 }

1178

1181

1182

1185

1186

1187

1188

1189

1190

1194 else

1197

1198

1200 {

1201

1202

1203

1204

1205

1207 {

1209

1210 return result_rel;

1211 }

1212

1213

1215 {

1216 if (op->all)

1217 {

1218 Path *apath;

1219

1220

1221

1222

1223

1224

1225

1226

1228 NIL, NIL, NULL, 0, false, -1);

1229

1230 add_path(result_rel, apath);

1231

1232 return result_rel;

1233 }

1234 else

1235 {

1236

1237

1238

1239

1240

1241

1242 }

1243 }

1244 }

1245 else

1246 {

1247

1248

1249

1250

1251

1252

1254 {

1256

1257 return result_rel;

1258 }

1259 }

1260

1261

1262

1263

1264

1265

1266

1267

1268

1270 {

1271 dNumGroups = dLeftGroups;

1272 dNumOutputRows = op->all ? lpath->rows : dNumGroups;

1273 }

1274 else

1275 {

1276 dNumGroups = dLeftGroups;

1277 dNumOutputRows = op->all ? Min(lpath->rows, rpath->rows) : dNumGroups;

1278 }

1279 result_rel->rows = dNumOutputRows;

1280

1281

1282 switch (op->op)

1283 {

1286 break;

1289 break;

1290 default:

1291 elog(ERROR, "unrecognized set op: %d", (int) op->op);

1293 break;

1294 }

1295

1296

1297

1298

1299 if (can_hash)

1300 {

1302 result_rel,

1303 lpath,

1304 rpath,

1305 cmd,

1307 groupList,

1308 dNumGroups,

1309 dNumOutputRows);

1311 }

1312

1313

1314

1315

1316

1317 if (can_sort)

1318 {

1319 List *pathkeys;

1320 Path *slpath,

1321 *srpath;

1322

1323

1325 groupList,

1326 lpath_tlist);

1328 slpath = lpath;

1329 else

1330 {

1332 nonunion_pathkeys,

1333 NULL,

1335 false);

1336

1337 if (slpath == NULL)

1339 lpath->parent,

1340 lpath,

1341 pathkeys,

1342 -1.0);

1343 }

1344

1345

1347 groupList,

1348 rpath_tlist);

1350 srpath = rpath;

1351 else

1352 {

1354 nonunion_pathkeys,

1355 NULL,

1357 false);

1358

1359 if (srpath == NULL)

1361 rpath->parent,

1362 rpath,

1363 pathkeys,

1364 -1.0);

1365 }

1366

1368 result_rel,

1369 slpath,

1370 srpath,

1371 cmd,

1373 groupList,

1374 dNumGroups,

1375 dNumOutputRows);

1377 }

1378

1379 return result_rel;

1380}

1381

1382

1383

1384

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394static List *

1397 List *refnames_tlist,

1398 List **tlist_list,

1399 List **istrivial_tlist)

1400{

1403 List *child_tlist;

1404 bool trivial_tlist;

1405

1406 *tlist_list = NIL;

1407 *istrivial_tlist = NIL;

1408

1409 while (pending_rels != NIL)

1410 {

1412

1414

1416 {

1418

1419 if (op->op == top_union->op &&

1420 (op->all == top_union->all || op->all) &&

1421 equal(op->colTypes, top_union->colTypes) &&

1422 equal(op->colCollations, top_union->colCollations))

1423 {

1424

1425 pending_rels = lcons(op->rarg, pending_rels);

1426 pending_rels = lcons(op->larg, pending_rels);

1427 continue;

1428 }

1429 }

1430

1431

1432

1433

1434

1435

1436

1437

1438

1440 top_union->all ? NULL : top_union,

1441 top_union->colTypes,

1442 top_union->colCollations,

1443 refnames_tlist,

1444 &child_tlist,

1445 &trivial_tlist));

1446 *tlist_list = lappend(*tlist_list, child_tlist);

1447 *istrivial_tlist = lappend_int(*istrivial_tlist, trivial_tlist);

1448 }

1449

1450 return result;

1451}

1452

1453

1454

1455

1456static void

1458{

1459

1460

1461

1462

1465 NULL, rel, NULL);

1466

1467

1469}

1470

1471

1472

1473

1474

1475

1476

1477

1478

1479

1480

1481

1482static List *

1485 bool hack_constants,

1486 List *input_tlist,

1487 List *refnames_tlist,

1488 bool *trivial_tlist)

1489{

1491 int resno = 1;

1493 *cclc,

1494 *itlc,

1495 *rtlc;

1498

1499 *trivial_tlist = true;

1500

1501 forfour(ctlc, colTypes, cclc, colCollations,

1502 itlc, input_tlist, rtlc, refnames_tlist)

1503 {

1508

1511 Assert(!inputtle->resjunk);

1512 Assert(!reftle->resjunk);

1513

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523

1524

1525

1526

1527

1528

1529

1530 if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))

1531 expr = (Node *) inputtle->expr;

1532 else

1534 inputtle->resno,

1538 0);

1539

1540 if (exprType(expr) != colType)

1541 {

1542

1543

1544

1545

1546

1547

1548

1549

1551 expr,

1552 colType,

1553 "UNION/INTERSECT/EXCEPT");

1554 *trivial_tlist = false;

1555 }

1556

1557

1558

1559

1560

1561

1562

1563

1564

1565

1566

1567

1569 {

1573 *trivial_tlist = false;

1574 }

1575

1578 pstrdup(reftle->resname),

1579 false);

1580

1581

1582

1583

1584

1585

1587

1588 tlist = lappend(tlist, tle);

1589 }

1590

1591 return tlist;

1592}

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1608

1609

1610static List *

1612 List *input_tlists,

1613 List *refnames_tlist)

1614{

1616 int resno = 1;

1620 int colindex;

1624 int32 *colTypmods;

1625

1626

1627

1628

1629

1630

1631

1633

1634 foreach(tlistl, input_tlists)

1635 {

1638

1639 curColType = list_head(colTypes);

1640 colindex = 0;

1641 foreach(subtlistl, subtlist)

1642 {

1644

1645 Assert(!subtle->resjunk);

1646 Assert(curColType != NULL);

1648 {

1649

1651

1652 if (tlistl == list_head(input_tlists))

1653 colTypmods[colindex] = subtypmod;

1654 else if (subtypmod != colTypmods[colindex])

1655 colTypmods[colindex] = -1;

1656 }

1657 else

1658 {

1659

1660 colTypmods[colindex] = -1;

1661 }

1662 curColType = lnext(colTypes, curColType);

1663 colindex++;

1664 }

1665 Assert(curColType == NULL);

1666 }

1667

1668

1669

1670

1671 colindex = 0;

1672 forthree(curColType, colTypes, curColCollation, colCollations,

1673 ref_tl_item, refnames_tlist)

1674 {

1676 int32 colTypmod = colTypmods[colindex++];

1679

1681 Assert(!reftle->resjunk);

1683 resno,

1684 colType,

1685 colTypmod,

1686 colColl,

1687 0);

1690 pstrdup(reftle->resname),

1691 false);

1692

1693

1694

1695

1696

1697

1699

1700 tlist = lappend(tlist, tle);

1701 }

1702

1703 pfree(colTypmods);

1704

1705 return tlist;

1706}

1707

1708

1709

1710

1711

1712

1713

1714

1715

1716

1717

1718

1719static List *

1721{

1725

1727 foreach(lt, targetlist)

1728 {

1731

1732 Assert(!tle->resjunk);

1733

1734

1736

1737

1740 lg = lnext(grouplist, lg);

1742

1744 }

1746 return grouplist;

1747}

1748

1749

1750

1751

1752

1753

1754

1755

1756

1757

1758

1761{

1764 double parent_rows = 0;

1765 double parent_size = 0;

1766

1768

1769

1770 foreach(lc, child_pathlist)

1771 {

1773

1774 parent_rows += path->rows;

1775 parent_size += path->parent->reltarget->width * path->rows;

1776 }

1777

1778 if (parent_rows > 0)

1779 reltarget->width = rint(parent_size / parent_rows);

1780

1781 return reltarget;

1782}

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

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

int max_parallel_workers_per_gather

void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)

bool enable_parallel_append

bool enable_incremental_sort

int errdetail(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

bool equal(const void *a, const void *b)

void add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, List *child_tlist, List *setop_pathkeys)

#define palloc_array(type, count)

Assert(PointerIsAligned(start, uint64))

bool is_dummy_rel(RelOptInfo *rel)

void mark_dummy_rel(RelOptInfo *rel)

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

List * list_delete_first(List *list)

List * lappend_int(List *list, int datum)

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

Datum subpath(PG_FUNCTION_ARGS)

Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)

TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)

char * pstrdup(const char *in)

void pfree(void *pointer)

Oid exprType(const Node *expr)

int32 exprTypmod(const Node *expr)

Oid exprCollation(const Node *expr)

Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)

#define IsA(nodeptr, _type_)

#define castNode(_type_, nodeptr)

Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)

Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)

bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)

List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)

List * convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *subquery_pathkeys, List *subquery_tlist)

bool pathkeys_contained_in(List *keys1, List *keys2)

SetOpPath * create_setop_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, List *groupList, double numGroups, double outputRows)

ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)

Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)

void set_cheapest(RelOptInfo *parent_rel)

void add_partial_path(RelOptInfo *parent_rel, Path *new_path)

AppendPath * create_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *partial_subpaths, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows)

SubqueryScanPath * create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, bool trivial_pathtarget, List *pathkeys, Relids required_outer)

IncrementalSortPath * create_incremental_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)

SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)

GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)

void add_path(RelOptInfo *parent_rel, Path *new_path)

UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)

AggPath * create_agg_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, AggStrategy aggstrategy, AggSplit aggsplit, List *groupClause, List *qual, const AggClauseCosts *aggcosts, double numGroups)

RecursiveUnionPath * create_recursiveunion_path(PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, PathTarget *target, List *distinctList, int wtParam, double numGroups)

MergeAppendPath * create_merge_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *pathkeys, Relids required_outer)

static int pg_leftmost_one_pos32(uint32 word)

#define lfirst_node(type, lc)

static int list_length(const List *l)

#define forthree(cell1, list1, cell2, list2, cell3, list3)

#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)

static ListCell * list_head(const List *l)

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

#define list_make2(x1, x2)

char * choose_plan_name(PlannerGlobal *glob, const char *name, bool always_number)

PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)

create_upper_paths_hook_type create_upper_paths_hook

RelOptInfo * plan_set_operations(PlannerInfo *root)

static List * generate_setop_grouplist(SetOperationStmt *op, List *targetlist)

static RelOptInfo * generate_union_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)

static RelOptInfo * generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, List *refnames_tlist, List **pTargetList)

static PathTarget * create_setop_pathtarget(PlannerInfo *root, List *tlist, List *child_pathlist)

static void postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel)

static List * generate_setop_tlist(List *colTypes, List *colCollations, Index varno, bool hack_constants, List *input_tlist, List *refnames_tlist, bool *trivial_tlist)

static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, SetOperationStmt *parentOp, List *colTypes, List *colCollations, List *refnames_tlist, List **pTargetList, bool *istrivial_tlist)

static RelOptInfo * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)

static List * generate_append_tlist(List *colTypes, List *colCollations, List *input_tlists, List *refnames_tlist)

static List * plan_union_children(PlannerInfo *root, SetOperationStmt *top_union, List *refnames_tlist, List **tlist_list, List **istrivial_tlist)

static void build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel, bool trivial_tlist, List *child_tlist, List *interesting_pathkeys, double *pNumGroups)

static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)

void setup_simple_rel_arrays(PlannerInfo *root)

RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)

RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)

double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)

void check_stack_depth(void)

struct PathTarget * reltarget

struct Path * cheapest_total_path

bool tlist_same_collations(List *tlist, List *colCollations, bool junkOK)

bool grouping_is_sortable(List *groupClause)

List * make_tlist_from_pathtarget(PathTarget *target)

List * get_tlist_exprs(List *tlist, bool includeJunk)

bool grouping_is_hashable(List *groupClause)

bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)

#define create_pathtarget(root, tlist)