* create_merge_append_path * Creates a path corresponding to a MergeAppend plan, returning the * pathnode. */
| 1576 | * pathnode. |
| 1577 | */ |
| 1578 | MergeAppendPath * |
| 1579 | create_merge_append_path(PlannerInfo *root, |
| 1580 | RelOptInfo *rel, |
| 1581 | List *subpaths, |
| 1582 | List *pathkeys, |
| 1583 | Relids required_outer) |
| 1584 | { |
| 1585 | MergeAppendPath *pathnode = makeNode(MergeAppendPath); |
| 1586 | Cost input_startup_cost; |
| 1587 | Cost input_total_cost; |
| 1588 | ListCell *l; |
| 1589 | |
| 1590 | pathnode->path.pathtype = T_MergeAppend; |
| 1591 | pathnode->path.parent = rel; |
| 1592 | pathnode->path.pathtarget = rel->reltarget; |
| 1593 | pathnode->path.param_info = get_appendrel_parampathinfo(rel, |
| 1594 | required_outer); |
| 1595 | pathnode->path.parallel_aware = false; |
| 1596 | pathnode->path.parallel_safe = rel->consider_parallel; |
| 1597 | pathnode->path.parallel_workers = 0; |
| 1598 | pathnode->path.pathkeys = pathkeys; |
| 1599 | pathnode->subpaths = subpaths; |
| 1600 | |
| 1601 | /* |
| 1602 | * Apply query-wide LIMIT if known and path is for sole base relation. |
| 1603 | * (Handling this at this low level is a bit klugy.) |
| 1604 | */ |
| 1605 | if (bms_equal(rel->relids, root->all_baserels)) |
| 1606 | pathnode->limit_tuples = root->limit_tuples; |
| 1607 | else |
| 1608 | pathnode->limit_tuples = -1.0; |
| 1609 | |
| 1610 | /* |
| 1611 | * Add Motions to the child nodes as needed, and determine the locus |
| 1612 | * of the MergeAppend itself. |
| 1613 | */ |
| 1614 | if (!set_append_path_locus(root, (Path *) pathnode, rel, pathkeys, 0, false)) |
| 1615 | return NULL; |
| 1616 | |
| 1617 | /* |
| 1618 | * Add up the sizes and costs of the input paths. |
| 1619 | */ |
| 1620 | pathnode->path.rows = 0; |
| 1621 | input_startup_cost = 0; |
| 1622 | input_total_cost = 0; |
| 1623 | foreach(l, subpaths) |
| 1624 | { |
| 1625 | Path *subpath = (Path *) lfirst(l); |
| 1626 | |
| 1627 | pathnode->path.rows += subpath->rows; |
| 1628 | pathnode->path.parallel_safe = pathnode->path.parallel_safe && |
| 1629 | subpath->parallel_safe; |
| 1630 | |
| 1631 | if (pathkeys_contained_in(pathkeys, subpath->pathkeys)) |
| 1632 | { |
| 1633 | /* Subpath is adequately ordered, we won't need to sort it */ |
| 1634 | input_startup_cost += subpath->startup_cost; |
| 1635 | input_total_cost += subpath->total_cost; |
no test coverage detected