* searchRangeTableForCol * See if any RangeTblEntry could possibly provide the given column name (or * find the best match available). Returns state with relevant details. * * This is different from colNameToVar in that it considers every entry in * the ParseState's rangetable(s), not only those that are currently visible * in the p_namespace list(s). This behavior is invalid per the S
| 949 | * and 'second' will contain the attribute number for the second match. |
| 950 | */ |
| 951 | static FuzzyAttrMatchState * |
| 952 | searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname, |
| 953 | int location) |
| 954 | { |
| 955 | ParseState *orig_pstate = pstate; |
| 956 | FuzzyAttrMatchState *fuzzystate = palloc(sizeof(FuzzyAttrMatchState)); |
| 957 | |
| 958 | fuzzystate->distance = MAX_FUZZY_DISTANCE + 1; |
| 959 | fuzzystate->rfirst = NULL; |
| 960 | fuzzystate->rsecond = NULL; |
| 961 | fuzzystate->first = InvalidAttrNumber; |
| 962 | fuzzystate->second = InvalidAttrNumber; |
| 963 | |
| 964 | while (pstate != NULL) |
| 965 | { |
| 966 | ListCell *l; |
| 967 | |
| 968 | foreach(l, pstate->p_rtable) |
| 969 | { |
| 970 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); |
| 971 | int fuzzy_rte_penalty = 0; |
| 972 | |
| 973 | /* |
| 974 | * Typically, it is not useful to look for matches within join |
| 975 | * RTEs; they effectively duplicate other RTEs for our purposes, |
| 976 | * and if a match is chosen from a join RTE, an unhelpful alias is |
| 977 | * displayed in the final diagnostic message. |
| 978 | */ |
| 979 | if (rte->rtekind == RTE_JOIN) |
| 980 | continue; |
| 981 | |
| 982 | /* |
| 983 | * If the user didn't specify an alias, then matches against one |
| 984 | * RTE are as good as another. But if the user did specify an |
| 985 | * alias, then we want at least a fuzzy - and preferably an exact |
| 986 | * - match for the range table entry. |
| 987 | */ |
| 988 | if (alias != NULL) |
| 989 | fuzzy_rte_penalty = |
| 990 | varstr_levenshtein_less_equal(alias, strlen(alias), |
| 991 | rte->eref->aliasname, |
| 992 | strlen(rte->eref->aliasname), |
| 993 | 1, 1, 1, |
| 994 | MAX_FUZZY_DISTANCE + 1, |
| 995 | true); |
| 996 | |
| 997 | /* |
| 998 | * Scan for a matching column; if we find an exact match, we're |
| 999 | * done. Otherwise, update fuzzystate. |
| 1000 | */ |
| 1001 | if (scanRTEForColumn(orig_pstate, rte, rte->eref, colname, location, |
| 1002 | fuzzy_rte_penalty, fuzzystate) |
| 1003 | && fuzzy_rte_penalty == 0) |
| 1004 | { |
| 1005 | fuzzystate->rfirst = rte; |
| 1006 | fuzzystate->first = InvalidAttrNumber; |
| 1007 | fuzzystate->rsecond = NULL; |
| 1008 | fuzzystate->second = InvalidAttrNumber; |
no test coverage detected