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 $$;
|
end $$;
|
||||||
NOTICE: execute = 10
|
NOTICE: execute = 10
|
||||||
NOTICE: r.strict = 1
|
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
|
* Ideally we'd never get here, because a RECFIELD datum
|
||||||
* have been built at parse time for every possible qualified
|
* should have been built at parse time for every qualified
|
||||||
* reference to fields of this record. But if we do, handle
|
* reference to a field of this record that appears in the
|
||||||
* it like field-not-found: throw error or return NULL.
|
* 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)
|
if (error_if_no_field)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("record \"%s\" has no field \"%s\"",
|
errmsg("field name \"%s\" is a reserved key word",
|
||||||
(nnames_field == 1) ? name1 : name2,
|
|
||||||
colname),
|
colname),
|
||||||
|
errhint("Use double quotes to quote it."),
|
||||||
parser_errposition(pstate, cref->location)));
|
parser_errposition(pstate, cref->location)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -50,3 +50,19 @@ begin
|
|||||||
select 1 as strict into r;
|
select 1 as strict into r;
|
||||||
raise notice 'r.strict = %', r.strict;
|
raise notice 'r.strict = %', r.strict;
|
||||||
end $$;
|
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