* add_partial_path_precheck * Check whether a proposed new partial path could possibly get accepted. * * Unlike add_path_precheck, we can ignore startup cost and parameterization, * since they don't matter for partial paths (see add_partial_path). But * we do want to make sure we don't add a partial path if there's already * a complete path that dominates it, since in that case the propos
| 961 | * is surely a loser. |
| 962 | */ |
| 963 | bool |
| 964 | add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost, |
| 965 | List *pathkeys) |
| 966 | { |
| 967 | ListCell *p1; |
| 968 | |
| 969 | /* |
| 970 | * Our goal here is twofold. First, we want to find out whether this path |
| 971 | * is clearly inferior to some existing partial path. If so, we want to |
| 972 | * reject it immediately. Second, we want to find out whether this path |
| 973 | * is clearly superior to some existing partial path -- at least, modulo |
| 974 | * final cost computations. If so, we definitely want to consider it. |
| 975 | * |
| 976 | * Unlike add_path(), we always compare pathkeys here. This is because we |
| 977 | * expect partial_pathlist to be very short, and getting a definitive |
| 978 | * answer at this stage avoids the need to call add_path_precheck. |
| 979 | */ |
| 980 | foreach(p1, parent_rel->partial_pathlist) |
| 981 | { |
| 982 | Path *old_path = (Path *) lfirst(p1); |
| 983 | PathKeysComparison keyscmp; |
| 984 | |
| 985 | keyscmp = compare_pathkeys(pathkeys, old_path->pathkeys); |
| 986 | if (keyscmp != PATHKEYS_DIFFERENT) |
| 987 | { |
| 988 | if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR && |
| 989 | keyscmp != PATHKEYS_BETTER1) |
| 990 | return false; |
| 991 | if (old_path->total_cost > total_cost * STD_FUZZ_FACTOR && |
| 992 | keyscmp != PATHKEYS_BETTER2) |
| 993 | return true; |
| 994 | } |
| 995 | } |
| 996 | |
| 997 | /* |
| 998 | * This path is neither clearly inferior to an existing partial path nor |
| 999 | * clearly good enough that it might replace one. Compare it to |
| 1000 | * non-parallel plans. If it loses even before accounting for the cost of |
| 1001 | * the Gather node, we should definitely reject it. |
| 1002 | * |
| 1003 | * Note that we pass the total_cost to add_path_precheck twice. This is |
| 1004 | * because it's never advantageous to consider the startup cost of a |
| 1005 | * partial path; the resulting plans, if run in parallel, will be run to |
| 1006 | * completion. |
| 1007 | */ |
| 1008 | if (!add_path_precheck(parent_rel, total_cost, total_cost, pathkeys, |
| 1009 | NULL)) |
| 1010 | return false; |
| 1011 | |
| 1012 | return true; |
| 1013 | } |
| 1014 | |
| 1015 | |
| 1016 | /***************************************************************************** |
no test coverage detected