* Generate a suitable error about a missing column. * * Since this is a very common type of error, we work rather hard to * produce a helpful message. */
| 3904 | * produce a helpful message. |
| 3905 | */ |
| 3906 | void |
| 3907 | errorMissingColumn(ParseState *pstate, |
| 3908 | const char *relname, const char *colname, int location) |
| 3909 | { |
| 3910 | FuzzyAttrMatchState *state; |
| 3911 | char *closestfirst = NULL; |
| 3912 | |
| 3913 | /* |
| 3914 | * Search the entire rtable looking for possible matches. If we find one, |
| 3915 | * emit a hint about it. |
| 3916 | * |
| 3917 | * TODO: improve this code (and also errorMissingRTE) to mention using |
| 3918 | * LATERAL if appropriate. |
| 3919 | */ |
| 3920 | state = searchRangeTableForCol(pstate, relname, colname, location); |
| 3921 | |
| 3922 | /* |
| 3923 | * Extract closest col string for best match, if any. |
| 3924 | * |
| 3925 | * Infer an exact match referenced despite not being visible from the fact |
| 3926 | * that an attribute number was not present in state passed back -- this |
| 3927 | * is what is reported when !closestfirst. There might also be an exact |
| 3928 | * match that was qualified with an incorrect alias, in which case |
| 3929 | * closestfirst will be set (so hint is the same as generic fuzzy case). |
| 3930 | */ |
| 3931 | if (state->rfirst && AttributeNumberIsValid(state->first)) |
| 3932 | closestfirst = strVal(list_nth(state->rfirst->eref->colnames, |
| 3933 | state->first - 1)); |
| 3934 | |
| 3935 | if (!state->rsecond) |
| 3936 | { |
| 3937 | /* |
| 3938 | * Handle case where there is zero or one column suggestions to hint, |
| 3939 | * including exact matches referenced but not visible. |
| 3940 | */ |
| 3941 | ereport(ERROR, |
| 3942 | (errcode(ERRCODE_UNDEFINED_COLUMN), |
| 3943 | relname ? |
| 3944 | errmsg("column %s.%s does not exist", relname, colname) : |
| 3945 | errmsg("column \"%s\" does not exist", colname), |
| 3946 | state->rfirst ? closestfirst ? |
| 3947 | errhint("Perhaps you meant to reference the column \"%s.%s\".", |
| 3948 | state->rfirst->eref->aliasname, closestfirst) : |
| 3949 | errhint("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.", |
| 3950 | colname, state->rfirst->eref->aliasname) : 0, |
| 3951 | parser_errposition(pstate, location))); |
| 3952 | } |
| 3953 | else |
| 3954 | { |
| 3955 | /* Handle case where there are two equally useful column hints */ |
| 3956 | char *closestsecond; |
| 3957 | |
| 3958 | closestsecond = strVal(list_nth(state->rsecond->eref->colnames, |
| 3959 | state->second - 1)); |
| 3960 | |
| 3961 | ereport(ERROR, |
| 3962 | (errcode(ERRCODE_UNDEFINED_COLUMN), |
| 3963 | relname ? |
no test coverage detected