mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Improve error report for PL/pgSQL reserved word used as a field name.
The current code in resolve_column_ref (dating to commits01f7d2990
andfe24d7816
) believes that not finding a RECFIELD datum is a can't-happen case, in consequence of which I didn't spend a whole lot of time considering what to do if it did happen. But it turns out that it *can* happen if the would-be field name is a fully-reserved PL/pgSQL keyword. Change the error message to describe that situation, and add a test case demonstrating it. This might need further refinement if anyone can find other ways to trigger a failure here; but without an example it's not clear what other error to throw. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Discussion: https://postgr.es/m/2185258.1745617445@sss.pgh.pa.us
This commit is contained in:
@ -79,3 +79,25 @@ begin
|
||||
end $$;
|
||||
NOTICE: execute = 10
|
||||
NOTICE: r.strict = 1
|
||||
-- Test handling of a reserved keyword as a record field name.
|
||||
do $$ declare r record;
|
||||
begin
|
||||
select 1 as x, 2 as foreach into r;
|
||||
raise notice 'r.x = %', r.x;
|
||||
raise notice 'r.foreach = %', r.foreach; -- fails
|
||||
end $$;
|
||||
NOTICE: r.x = 1
|
||||
ERROR: field name "foreach" is a reserved key word
|
||||
LINE 1: r.foreach
|
||||
^
|
||||
HINT: Use double quotes to quote it.
|
||||
QUERY: r.foreach
|
||||
CONTEXT: PL/pgSQL function inline_code_block line 5 at RAISE
|
||||
do $$ declare r record;
|
||||
begin
|
||||
select 1 as x, 2 as foreach into r;
|
||||
raise notice 'r.x = %', r.x;
|
||||
raise notice 'r."foreach" = %', r."foreach"; -- ok
|
||||
end $$;
|
||||
NOTICE: r.x = 1
|
||||
NOTICE: r."foreach" = 2
|
||||
|
@ -1211,17 +1211,22 @@ resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
|
||||
}
|
||||
|
||||
/*
|
||||
* We should not get here, because a RECFIELD datum should
|
||||
* have been built at parse time for every possible qualified
|
||||
* reference to fields of this record. But if we do, handle
|
||||
* it like field-not-found: throw error or return NULL.
|
||||
* Ideally we'd never get here, because a RECFIELD datum
|
||||
* should have been built at parse time for every qualified
|
||||
* reference to a field of this record that appears in the
|
||||
* source text. However, plpgsql_yylex will not build such a
|
||||
* datum unless the field name lexes as token type IDENT.
|
||||
* Hence, if the would-be field name is a PL/pgSQL reserved
|
||||
* word, we lose. Assume that that's what happened and tell
|
||||
* the user to quote it, unless the caller prefers we just
|
||||
* return NULL.
|
||||
*/
|
||||
if (error_if_no_field)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("record \"%s\" has no field \"%s\"",
|
||||
(nnames_field == 1) ? name1 : name2,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("field name \"%s\" is a reserved key word",
|
||||
colname),
|
||||
errhint("Use double quotes to quote it."),
|
||||
parser_errposition(pstate, cref->location)));
|
||||
}
|
||||
break;
|
||||
|
@ -50,3 +50,19 @@ begin
|
||||
select 1 as strict into r;
|
||||
raise notice 'r.strict = %', r.strict;
|
||||
end $$;
|
||||
|
||||
-- Test handling of a reserved keyword as a record field name.
|
||||
|
||||
do $$ declare r record;
|
||||
begin
|
||||
select 1 as x, 2 as foreach into r;
|
||||
raise notice 'r.x = %', r.x;
|
||||
raise notice 'r.foreach = %', r.foreach; -- fails
|
||||
end $$;
|
||||
|
||||
do $$ declare r record;
|
||||
begin
|
||||
select 1 as x, 2 as foreach into r;
|
||||
raise notice 'r.x = %', r.x;
|
||||
raise notice 'r."foreach" = %', r."foreach"; -- ok
|
||||
end $$;
|
||||
|
Reference in New Issue
Block a user