mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Clean up plpgsql grammar to make sure that check_assignable() is applied
consistently. This is mostly cosmetic right at the moment because check_assignable() does nothing for ROW or RECORD datums, but that might not always be so. This also syncs several different places that read INTO target lists. They're just enough different that it seems impractical to factor them into a single routine, but they surely should be the same as much as possible.
This commit is contained in:
parent
136c3b87ac
commit
f7d9874415
@ -4,7 +4,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.82 2005/10/13 15:34:19 tgl Exp $
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.83 2006/02/12 04:59:32 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -881,9 +881,15 @@ for_control :
|
|||||||
new->cmd_type = PLPGSQL_STMT_DYNFORS;
|
new->cmd_type = PLPGSQL_STMT_DYNFORS;
|
||||||
new->lineno = $1;
|
new->lineno = $1;
|
||||||
if ($2.rec)
|
if ($2.rec)
|
||||||
|
{
|
||||||
new->rec = $2.rec;
|
new->rec = $2.rec;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->rec);
|
||||||
|
}
|
||||||
else if ($2.row)
|
else if ($2.row)
|
||||||
|
{
|
||||||
new->row = $2.row;
|
new->row = $2.row;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->row);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
plpgsql_error_lineno = $1;
|
plpgsql_error_lineno = $1;
|
||||||
@ -942,6 +948,7 @@ for_control :
|
|||||||
|
|
||||||
expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
|
expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
|
||||||
|
|
||||||
|
/* create loop's private variable */
|
||||||
fvar = (PLpgSQL_var *)
|
fvar = (PLpgSQL_var *)
|
||||||
plpgsql_build_variable($2.name,
|
plpgsql_build_variable($2.name,
|
||||||
$2.lineno,
|
$2.lineno,
|
||||||
@ -986,9 +993,15 @@ for_control :
|
|||||||
new->cmd_type = PLPGSQL_STMT_FORS;
|
new->cmd_type = PLPGSQL_STMT_FORS;
|
||||||
new->lineno = $1;
|
new->lineno = $1;
|
||||||
if ($2.rec)
|
if ($2.rec)
|
||||||
|
{
|
||||||
new->rec = $2.rec;
|
new->rec = $2.rec;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->rec);
|
||||||
|
}
|
||||||
else if ($2.row)
|
else if ($2.row)
|
||||||
|
{
|
||||||
new->row = $2.row;
|
new->row = $2.row;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->row);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
plpgsql_error_lineno = $1;
|
plpgsql_error_lineno = $1;
|
||||||
@ -1002,6 +1015,17 @@ for_control :
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Processing the for_variable is tricky because we don't yet know if the
|
||||||
|
* FOR is an integer FOR loop or a loop over query results. In the former
|
||||||
|
* case, the variable is just a name that we must instantiate as a loop
|
||||||
|
* local variable, regardless of any other definition it might have.
|
||||||
|
* Therefore, we always save the actual identifier into $$.name where it
|
||||||
|
* can be used for that case. We also save the outer-variable definition,
|
||||||
|
* if any, because that's what we need for the loop-over-query case. Note
|
||||||
|
* that we must NOT apply check_assignable() or any other semantic check
|
||||||
|
* until we know what's what.
|
||||||
|
*/
|
||||||
for_variable : T_SCALAR
|
for_variable : T_SCALAR
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
@ -1304,13 +1328,13 @@ stmt_dynexecute : K_EXECUTE lno
|
|||||||
switch (yylex())
|
switch (yylex())
|
||||||
{
|
{
|
||||||
case T_ROW:
|
case T_ROW:
|
||||||
check_assignable((PLpgSQL_datum *) yylval.row);
|
|
||||||
new->row = yylval.row;
|
new->row = yylval.row;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_RECORD:
|
case T_RECORD:
|
||||||
check_assignable((PLpgSQL_datum *) yylval.row);
|
|
||||||
new->rec = yylval.rec;
|
new->rec = yylval.rec;
|
||||||
|
check_assignable((PLpgSQL_datum *) new->rec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_SCALAR:
|
case T_SCALAR:
|
||||||
@ -1917,11 +1941,13 @@ make_select_stmt(void)
|
|||||||
{
|
{
|
||||||
case T_ROW:
|
case T_ROW:
|
||||||
row = yylval.row;
|
row = yylval.row;
|
||||||
|
check_assignable((PLpgSQL_datum *) row);
|
||||||
have_into = true;
|
have_into = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_RECORD:
|
case T_RECORD:
|
||||||
rec = yylval.rec;
|
rec = yylval.rec;
|
||||||
|
check_assignable((PLpgSQL_datum *) rec);
|
||||||
have_into = true;
|
have_into = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2028,10 +2054,12 @@ make_fetch_stmt(void)
|
|||||||
{
|
{
|
||||||
case T_ROW:
|
case T_ROW:
|
||||||
row = yylval.row;
|
row = yylval.row;
|
||||||
|
check_assignable((PLpgSQL_datum *) row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_RECORD:
|
case T_RECORD:
|
||||||
rec = yylval.rec;
|
rec = yylval.rec;
|
||||||
|
check_assignable((PLpgSQL_datum *) rec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_SCALAR:
|
case T_SCALAR:
|
||||||
@ -2039,7 +2067,12 @@ make_fetch_stmt(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
yyerror("syntax error");
|
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
|
errmsg("syntax error at \"%s\"", yytext),
|
||||||
|
errdetail("Expected record variable, row variable, "
|
||||||
|
"or list of scalar variables.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = yylex();
|
tok = yylex();
|
||||||
@ -2136,13 +2169,13 @@ read_into_scalar_list(const char *initial_name,
|
|||||||
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("\"%s\" is not a variable",
|
errmsg("\"%s\" is not a scalar variable",
|
||||||
yytext)));
|
yytext)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We read an extra, non-comma character from yylex(), so push it
|
* We read an extra, non-comma token from yylex(), so push it
|
||||||
* back onto the input stream
|
* back onto the input stream
|
||||||
*/
|
*/
|
||||||
plpgsql_push_back_token(tok);
|
plpgsql_push_back_token(tok);
|
||||||
|
Loading…
Reference in New Issue
Block a user