* add_path * Consider a potential implementation path for the specified parent rel, * and add it to the rel's pathlist if it is worthy of consideration. * A path is worthy if it has a better sort order (better pathkeys) or * cheaper cost (on either dimension), or generates fewer rows, than any * existing path that has the same or superset parameterization rels. * We also consider
| 450 | * Returns nothing, but modifies parent_rel->pathlist. |
| 451 | */ |
| 452 | void |
| 453 | add_path(RelOptInfo *parent_rel, Path *new_path, PlannerInfo *root) |
| 454 | { |
| 455 | bool accept_new = true; /* unless we find a superior old path */ |
| 456 | int insert_at = 0; /* where to insert new item */ |
| 457 | List *new_path_pathkeys; |
| 458 | ListCell *p1; |
| 459 | |
| 460 | /* |
| 461 | * This is a convenient place to check for query cancel --- no part of the |
| 462 | * planner goes very long without calling add_path(). |
| 463 | */ |
| 464 | CHECK_FOR_INTERRUPTS(); |
| 465 | |
| 466 | if (!new_path) |
| 467 | return; |
| 468 | |
| 469 | /* |
| 470 | * GPDB: Check that the correct locus has been determined for the Path. |
| 471 | * This can easily be missing from upstream code that construct Paths |
| 472 | * that haven't been modified in GPDB to set the locus correctly. |
| 473 | */ |
| 474 | if (!CdbLocusType_IsValid(new_path->locus.locustype)) |
| 475 | elog(ERROR, "path of type %u is missing distribution locus", new_path->pathtype); |
| 476 | Assert(cdbpathlocus_is_valid(new_path->locus)); |
| 477 | |
| 478 | /* Pretend parameterized paths have no pathkeys, per comment above */ |
| 479 | new_path_pathkeys = new_path->param_info ? NIL : new_path->pathkeys; |
| 480 | |
| 481 | /* |
| 482 | * Loop to check proposed new path against old paths. Note it is possible |
| 483 | * for more than one old path to be tossed out because new_path dominates |
| 484 | * it. |
| 485 | */ |
| 486 | foreach(p1, parent_rel->pathlist) |
| 487 | { |
| 488 | Path *old_path = (Path *) lfirst(p1); |
| 489 | bool remove_old = false; /* unless new proves superior */ |
| 490 | PathCostComparison costcmp; |
| 491 | PathKeysComparison keyscmp; |
| 492 | BMS_Comparison outercmp; |
| 493 | |
| 494 | /* |
| 495 | * Do a fuzzy cost comparison with standard fuzziness limit. |
| 496 | */ |
| 497 | costcmp = compare_path_costs_fuzzily(new_path, old_path, |
| 498 | STD_FUZZ_FACTOR); |
| 499 | |
| 500 | /* |
| 501 | * If the two paths compare differently for startup and total cost, |
| 502 | * then we want to keep both, and we can skip comparing pathkeys and |
| 503 | * required_outer rels. If they compare the same, proceed with the |
| 504 | * other comparisons. Row count is checked last. (We make the tests |
| 505 | * in this order because the cost comparison is most likely to turn |
| 506 | * out "different", and the pathkeys comparison next most likely. As |
| 507 | * explained above, row count very seldom makes a difference, so even |
| 508 | * though it's cheap to compare there's not much point in checking it |
| 509 | * earlier.) |