* add_path_precheck * Check whether a proposed new path could possibly get accepted. * We assume we know the path's pathkeys and parameterization accurately, * and have lower bounds for its costs. * * Note that we do not know the path's rowcount, since getting an estimate for * that is too expensive to do before prechecking. We assume here that paths * of a superset parameterization
| 738 | * so the required information has to be passed piecemeal. |
| 739 | */ |
| 740 | bool |
| 741 | add_path_precheck(RelOptInfo *parent_rel, |
| 742 | Cost startup_cost, Cost total_cost, |
| 743 | List *pathkeys, Relids required_outer) |
| 744 | { |
| 745 | List *new_path_pathkeys; |
| 746 | bool consider_startup; |
| 747 | ListCell *p1; |
| 748 | |
| 749 | /* Pretend parameterized paths have no pathkeys, per add_path policy */ |
| 750 | new_path_pathkeys = required_outer ? NIL : pathkeys; |
| 751 | |
| 752 | /* Decide whether new path's startup cost is interesting */ |
| 753 | consider_startup = required_outer ? parent_rel->consider_param_startup : parent_rel->consider_startup; |
| 754 | |
| 755 | foreach(p1, parent_rel->pathlist) |
| 756 | { |
| 757 | Path *old_path = (Path *) lfirst(p1); |
| 758 | PathKeysComparison keyscmp; |
| 759 | |
| 760 | /* |
| 761 | * We are looking for an old_path with the same parameterization (and |
| 762 | * by assumption the same rowcount) that dominates the new path on |
| 763 | * pathkeys as well as both cost metrics. If we find one, we can |
| 764 | * reject the new path. |
| 765 | * |
| 766 | * Cost comparisons here should match compare_path_costs_fuzzily. |
| 767 | */ |
| 768 | if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR) |
| 769 | { |
| 770 | /* new path can win on startup cost only if consider_startup */ |
| 771 | if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR || |
| 772 | !consider_startup) |
| 773 | { |
| 774 | /* new path loses on cost, so check pathkeys... */ |
| 775 | List *old_path_pathkeys; |
| 776 | |
| 777 | old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys; |
| 778 | keyscmp = compare_pathkeys(new_path_pathkeys, |
| 779 | old_path_pathkeys); |
| 780 | if (keyscmp == PATHKEYS_EQUAL || |
| 781 | keyscmp == PATHKEYS_BETTER2) |
| 782 | { |
| 783 | /* new path does not win on pathkeys... */ |
| 784 | if (bms_equal(required_outer, PATH_REQ_OUTER(old_path))) |
| 785 | { |
| 786 | /* Found an old path that dominates the new one */ |
| 787 | return false; |
| 788 | } |
| 789 | } |
| 790 | } |
| 791 | } |
| 792 | else |
| 793 | { |
| 794 | /* |
| 795 | * Since the pathlist is sorted by total_cost, we can stop looking |
| 796 | * once we reach a path with a total_cost larger than the new |
| 797 | * path's. |
no test coverage detected