@ -9,7 +9,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.123 2009/04/19 21:50:09 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.124 2009/05/01 23:57:34 tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
@ -144,7 +144,7 @@ static List *read_raise_options(void);
%type <forvariable> for_variable
%type <forvariable> for_variable
%type <stmt> for_control
%type <stmt> for_control
%type <str> opt_lbl name opt_block_label opt_label
%type <str> any_identifier any_ name opt_block_label opt_label
%type <str> execsql_start
%type <str> execsql_start
%type <list> proc_sect proc_stmts stmt_else
%type <list> proc_sect proc_stmts stmt_else
@ -331,7 +331,7 @@ decl_stmts : decl_stmts decl_stmt
{ $$ = $1; }
{ $$ = $1; }
;
;
decl_stmt : '<' '<' opt_lbl name '>' '>'
decl_stmt : '<' '<' any_ name '>' '>'
{ $$ = $3; }
{ $$ = $3; }
| K_DECLARE
| K_DECLARE
{ $$ = NULL; }
{ $$ = NULL; }
@ -512,12 +512,12 @@ decl_cursor_arg : decl_varname decl_datatype
decl_is_for : K_IS | /* Oracle */
decl_is_for : K_IS | /* Oracle */
K_FOR; /* ANSI */
K_FOR; /* ANSI */
decl_aliasitem : T_WORD
decl_aliasitem : any_identifier
{
{
char *name;
char *name;
PLpgSQL_nsitem *nsi;
PLpgSQL_nsitem *nsi;
plpgsql_convert_ident(yytext , &name, 1);
plpgsql_convert_ident($1 , &name, 1);
if (name[0] != '$')
if (name[0] != '$')
yyerror("only positional parameters can be aliased");
yyerror("only positional parameters can be aliased");
@ -549,8 +549,27 @@ decl_varname : T_WORD
$$.name = name;
$$.name = name;
$$.lineno = plpgsql_scanner_lineno();
$$.lineno = plpgsql_scanner_lineno();
}
}
| T_SCALAR
{
/*
* Since the scanner is only searching the topmost
* namestack entry, getting T_SCALAR etc can only
* happen if the name is already declared in this
* block.
*/
yyerror("duplicate declaration");
}
| T_ROW
{
yyerror("duplicate declaration");
}
| T_RECORD
{
yyerror("duplicate declaration");
}
;
;
/* XXX this is broken because it doesn't allow for T_SCALAR,T_ROW,T_RECORD */
decl_renname : T_WORD
decl_renname : T_WORD
{
{
char *name;
char *name;
@ -1752,45 +1771,39 @@ proc_conditions : proc_conditions K_OR proc_condition
}
}
;
;
proc_condition : opt_lbl name
proc_condition : any_ name
{
{
$$ = plpgsql_parse_err_condition($1);
if (strcmp($1, "sqlstate") != 0)
}
{
| T_SCALAR
$$ = plpgsql_parse_err_condition($1);
{
}
/*
else
* Because we know the special sqlstate variable
{
* is at the top of the namestack (see the
PLpgSQL_condition *new;
* exception_sect production), the SQLSTATE
char *sqlstatestr;
* keyword will always lex as T_SCALAR. This
* might not be true in other parsing contexts!
*/
PLpgSQL_condition *new;
char *sqlstatestr;
if (pg_strcasecmp(yytext, "sqlstate") != 0)
yyerror("syntax error");
/* next token should be a string literal */
/* next token should be a string literal */
if (yylex() != T_STRING)
if (yylex() != T_STRING)
yyerror("syntax error");
yyerror("syntax error");
sqlstatestr = parse_string_token(yytext);
sqlstatestr = parse_string_token(yytext);
if (strlen(sqlstatestr) != 5)
if (strlen(sqlstatestr) != 5)
yyerror("invalid SQLSTATE code");
yyerror("invalid SQLSTATE code");
if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
yyerror("invalid SQLSTATE code");
yyerror("invalid SQLSTATE code");
new = palloc(sizeof(PLpgSQL_condition));
new = palloc(sizeof(PLpgSQL_condition));
new->sqlerrstate = MAKE_SQLSTATE(sqlstatestr[0],
new->sqlerrstate =
sqlstatestr[1],
MAKE_SQLSTATE(sqlstatestr[0],
sqlstatestr[2],
sqlstatestr[1],
sqlstatestr[3],
sqlstatestr[2],
sqlstatestr[4]);
sqlstatestr[3],
new->condname = sqlstatestr;
sqlstatestr[4]);
new->next = NULL;
new->condname = sqlstatestr;
new->next = NULL;
$$ = new;
$$ = new;
}
}
}
;
;
@ -1815,49 +1828,55 @@ opt_block_label :
plpgsql_ns_push(NULL);
plpgsql_ns_push(NULL);
$$ = NULL;
$$ = NULL;
}
}
| '<' '<' opt_lbl name '>' '>'
| '<' '<' any_ name '>' '>'
{
{
plpgsql_ns_push($3);
plpgsql_ns_push($3);
$$ = $3;
$$ = $3;
}
}
;
;
/*
* need all the options because scanner will have tried to resolve as variable
*/
opt_label :
opt_label :
{
{
$$ = NULL;
$$ = NULL;
}
}
| T_WORD
| any_identifier
{
{
$$ = check_label(yytext);
$$ = check_label($1);
}
;
opt_exitcond : ';'
{ $$ = NULL; }
| K_WHEN expr_until_semi
{ $$ = $2; }
;
/*
* need all the options because scanner will have tried to resolve as variable
*/
any_identifier : T_WORD
{
$$ = yytext;
}
}
| T_SCALAR
| T_SCALAR
{
{
$$ = check_label(yytext);
$$ = yytext;
}
}
| T_RECORD
| T_RECORD
{
{
$$ = check_label(yytext);
$$ = yytext;
}
}
| T_ROW
| T_ROW
{
{
$$ = check_label(yytext);
$$ = yytext;
}
}
;
;
opt_exitcond : ';'
any_name : any_identifier
{ $$ = NULL; }
| K_WHEN expr_until_semi
{ $$ = $2; }
;
opt_lblname : T_WORD
{
{
char *name;
char *name;
plpgsql_convert_ident(yytext , &name, 1);
plpgsql_convert_ident($1, &name, 1);
$$ = name;
$$ = name;
}
}
;
;