* updateFuzzyAttrMatchState * Using Levenshtein distance, consider if column is best fuzzy match. */
| 573 | * Using Levenshtein distance, consider if column is best fuzzy match. |
| 574 | */ |
| 575 | static void |
| 576 | updateFuzzyAttrMatchState(int fuzzy_rte_penalty, |
| 577 | FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte, |
| 578 | const char *actual, const char *match, int attnum) |
| 579 | { |
| 580 | int columndistance; |
| 581 | int matchlen; |
| 582 | |
| 583 | /* Bail before computing the Levenshtein distance if there's no hope. */ |
| 584 | if (fuzzy_rte_penalty > fuzzystate->distance) |
| 585 | return; |
| 586 | |
| 587 | /* |
| 588 | * Outright reject dropped columns, which can appear here with apparent |
| 589 | * empty actual names, per remarks within scanRTEForColumn(). |
| 590 | */ |
| 591 | if (actual[0] == '\0') |
| 592 | return; |
| 593 | |
| 594 | /* Use Levenshtein to compute match distance. */ |
| 595 | matchlen = strlen(match); |
| 596 | columndistance = |
| 597 | varstr_levenshtein_less_equal(actual, strlen(actual), match, matchlen, |
| 598 | 1, 1, 1, |
| 599 | fuzzystate->distance + 1 |
| 600 | - fuzzy_rte_penalty, |
| 601 | true); |
| 602 | |
| 603 | /* |
| 604 | * If more than half the characters are different, don't treat it as a |
| 605 | * match, to avoid making ridiculous suggestions. |
| 606 | */ |
| 607 | if (columndistance > matchlen / 2) |
| 608 | return; |
| 609 | |
| 610 | /* |
| 611 | * From this point on, we can ignore the distinction between the RTE-name |
| 612 | * distance and the column-name distance. |
| 613 | */ |
| 614 | columndistance += fuzzy_rte_penalty; |
| 615 | |
| 616 | /* |
| 617 | * If the new distance is less than or equal to that of the best match |
| 618 | * found so far, update fuzzystate. |
| 619 | */ |
| 620 | if (columndistance < fuzzystate->distance) |
| 621 | { |
| 622 | /* Store new lowest observed distance for RTE */ |
| 623 | fuzzystate->distance = columndistance; |
| 624 | fuzzystate->rfirst = rte; |
| 625 | fuzzystate->first = attnum; |
| 626 | fuzzystate->rsecond = NULL; |
| 627 | fuzzystate->second = InvalidAttrNumber; |
| 628 | } |
| 629 | else if (columndistance == fuzzystate->distance) |
| 630 | { |
| 631 | /* |
| 632 | * This match distance may equal a prior match within this same range |