@ -668,7 +668,7 @@ opt_semi :
|
||||
| ';'
|
||||
;
|
||||
|
||||
pl_block : decl_sect begin_decl proc_sect exception_sect K_END opt_label
|
||||
pl_block : decl_sect K_BEGIN declare_sect proc_sect exception_sect K_END opt_label
|
||||
{
|
||||
PLpgSQL_stmt_block *newp;
|
||||
|
||||
@ -681,10 +681,10 @@ pl_block : decl_sect begin_decl proc_sect exception_sect K_END opt_label
|
||||
newp->isAutonomous = $1.isAutonomous;
|
||||
newp->n_initvars = $1.n_initvars;
|
||||
newp->initvarnos = $1.initvarnos;
|
||||
newp->body = $3;
|
||||
newp->exceptions = $4;
|
||||
newp->body = $4;
|
||||
newp->exceptions = $5;
|
||||
|
||||
check_labels($1.label, $6, @6);
|
||||
check_labels($1.label, $7, @7);
|
||||
plpgsql_ns_pop();
|
||||
|
||||
$$ = (PLpgSQL_stmt *)newp;
|
||||
@ -694,9 +694,20 @@ pl_block : decl_sect begin_decl proc_sect exception_sect K_END opt_label
|
||||
}
|
||||
;
|
||||
|
||||
begin_decl : K_BEGIN
|
||||
| K_BEGIN declare_stmts
|
||||
;
|
||||
declare_sect :
|
||||
{
|
||||
/* done with decls, so resume identifier lookup */
|
||||
u_sess->plsql_cxt.curr_compile_context->plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
|
||||
}
|
||||
| { SetErrorState();
|
||||
u_sess->plsql_cxt.curr_compile_context->plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_DECLARE;
|
||||
} declare_stmts
|
||||
{
|
||||
/* done with decls, so resume identifier lookup */
|
||||
u_sess->plsql_cxt.curr_compile_context->plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
|
||||
u_sess->plsql_cxt.pragma_autonomous = false;
|
||||
}
|
||||
;
|
||||
|
||||
declare_stmts : declare_stmts declare_stmt
|
||||
| declare_stmt
|
||||
@ -709,6 +720,11 @@ declare_stmt : T_DECLARE_CURSOR decl_varname K_CURSOR opt_scrollable
|
||||
}
|
||||
decl_cursor_args decl_is_for decl_cursor_query
|
||||
{
|
||||
int tok = -1;
|
||||
plpgsql_peek(&tok);
|
||||
if (tok != K_DECLARE) {
|
||||
u_sess->plsql_cxt.curr_compile_context->plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
|
||||
}
|
||||
PLpgSQL_var *newp;
|
||||
|
||||
/* pop local namespace for cursor args */
|
||||
@ -735,6 +751,11 @@ declare_stmt : T_DECLARE_CURSOR decl_varname K_CURSOR opt_scrollable
|
||||
}
|
||||
| T_DECLARE_CONDITION decl_varname K_CONDITION K_FOR condition_value ';'
|
||||
{
|
||||
int tok = -1;
|
||||
plpgsql_peek(&tok);
|
||||
if (tok != K_DECLARE) {
|
||||
u_sess->plsql_cxt.curr_compile_context->plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
|
||||
}
|
||||
IsInPublicNamespace($2->name);
|
||||
PLpgSQL_var *var;
|
||||
|
||||
@ -749,35 +770,31 @@ declare_stmt : T_DECLARE_CURSOR decl_varname K_CURSOR opt_scrollable
|
||||
}
|
||||
;
|
||||
|
||||
condition_value : any_identifier
|
||||
condition_value : K_SQLSTATE
|
||||
{
|
||||
if (strcmp($1, "sqlstate") == 0) {
|
||||
/* next token should be a string literal */
|
||||
char *sqlstatestr;
|
||||
if (yylex() != SCONST)
|
||||
yyerror("syntax error");
|
||||
sqlstatestr = yylval.str;
|
||||
|
||||
if (strlen(sqlstatestr) != 5)
|
||||
yyerror("invalid SQLSTATE code");
|
||||
if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
|
||||
yyerror("invalid SQLSTATE code");
|
||||
if (strncmp(sqlstatestr, "00", 2) == 0) {
|
||||
const char* message = "bad SQLSTATE";
|
||||
InsertErrorMessage(message, plpgsql_yylloc);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
errmsg("bad SQLSTATE '%s'",sqlstatestr)));
|
||||
}
|
||||
|
||||
$$ = MAKE_SQLSTATE(sqlstatestr[0],
|
||||
sqlstatestr[1],
|
||||
sqlstatestr[2],
|
||||
sqlstatestr[3],
|
||||
sqlstatestr[4]);
|
||||
} else {
|
||||
/* next token should be a string literal */
|
||||
char *sqlstatestr;
|
||||
if (yylex() != SCONST)
|
||||
yyerror("syntax error");
|
||||
sqlstatestr = yylval.str;
|
||||
|
||||
if (strlen(sqlstatestr) != 5)
|
||||
yyerror("invalid SQLSTATE code");
|
||||
if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
|
||||
yyerror("invalid SQLSTATE code");
|
||||
if (strncmp(sqlstatestr, "00", 2) == 0) {
|
||||
const char* message = "bad SQLSTATE";
|
||||
InsertErrorMessage(message, plpgsql_yylloc);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
errmsg("bad SQLSTATE '%s'",sqlstatestr)));
|
||||
}
|
||||
|
||||
$$ = MAKE_SQLSTATE(sqlstatestr[0],
|
||||
sqlstatestr[1],
|
||||
sqlstatestr[2],
|
||||
sqlstatestr[3],
|
||||
sqlstatestr[4]);
|
||||
}
|
||||
| ICONST
|
||||
{
|
||||
|
@ -669,6 +669,16 @@ void plpgsql_peek2(int* tok1_p, int* tok2_p, int* tok1_loc, int* tok2_loc)
|
||||
push_back_token(tok1, &aux1);
|
||||
}
|
||||
|
||||
void plpgsql_peek(int* tok1_p)
|
||||
{
|
||||
int tok1;
|
||||
TokenAuxData aux1;
|
||||
|
||||
tok1 = internal_yylex(&aux1);
|
||||
|
||||
*tok1_p = tok1;
|
||||
push_back_token(tok1, &aux1);
|
||||
}
|
||||
/*
|
||||
* plpgsql_scanner_errposition
|
||||
* Report an error cursor position, if possible.
|
||||
|
@ -1726,6 +1726,7 @@ extern int plpgsql_yylex(void);
|
||||
extern void plpgsql_push_back_token(int token);
|
||||
extern void plpgsql_append_source_text(StringInfo buf, int startlocation, int endlocation);
|
||||
extern void plpgsql_peek2(int* tok1_p, int* tok2_p, int* tok1_loc, int* tok2_loc);
|
||||
extern void plpgsql_peek(int* tok1_p);
|
||||
extern int plpgsql_scanner_errposition(int location);
|
||||
extern void plpgsql_yyerror(const char* message, bool isError = false);
|
||||
extern int plpgsql_location_to_lineno(int location);
|
||||
|
@ -248,6 +248,54 @@ NOTICE: oracle : usa : 2
|
||||
|
||||
(1 row)
|
||||
|
||||
create or replace procedure test_cursor_1
|
||||
as
|
||||
company_name varchar(100);
|
||||
company_loc varchar(100);
|
||||
company_no integer;
|
||||
|
||||
begin
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
if not c1_all%isopen then
|
||||
open c1_all;
|
||||
end if;
|
||||
loop
|
||||
fetch c1_all into company_name, company_loc, company_no;
|
||||
exit when c1_all%notfound;
|
||||
raise notice '% : % : %',company_name,company_loc,company_no;
|
||||
end loop;
|
||||
if c1_all%isopen then
|
||||
close c1_all;
|
||||
end if;
|
||||
end;
|
||||
/
|
||||
ERROR: duplicate declaration at or near "c1_all"
|
||||
LINE 8: declare c1_all cursor is --cursor without args
|
||||
^
|
||||
QUERY: DECLARE company_name varchar(100);
|
||||
company_loc varchar(100);
|
||||
company_no integer;
|
||||
|
||||
begin
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
if not c1_all%isopen then
|
||||
open c1_all;
|
||||
end if;
|
||||
loop
|
||||
fetch c1_all into company_name, company_loc, company_no;
|
||||
exit when c1_all%notfound;
|
||||
raise notice '% : % : %',company_name,company_loc,company_no;
|
||||
end loop;
|
||||
if c1_all%isopen then
|
||||
close c1_all;
|
||||
end if;
|
||||
end
|
||||
-- test declare condition
|
||||
create or replace procedure test_condition_1 as
|
||||
declare
|
||||
@ -306,7 +354,7 @@ exception
|
||||
END;
|
||||
END;
|
||||
/
|
||||
ERROR: syntax error at or near "DIVISION_ZERO"
|
||||
ERROR: duplicate declaration at or near "DIVISION_ZERO"
|
||||
LINE 6: declare DIVISION_ZERO condition for SQLSTATE '22005';
|
||||
^
|
||||
QUERY:
|
||||
|
@ -217,6 +217,30 @@ begin
|
||||
end;
|
||||
/
|
||||
call test_cursor_1();
|
||||
create or replace procedure test_cursor_1
|
||||
as
|
||||
company_name varchar(100);
|
||||
company_loc varchar(100);
|
||||
company_no integer;
|
||||
|
||||
begin
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
declare c1_all cursor is --cursor without args
|
||||
select name, loc, no from company order by 1, 2, 3;
|
||||
if not c1_all%isopen then
|
||||
open c1_all;
|
||||
end if;
|
||||
loop
|
||||
fetch c1_all into company_name, company_loc, company_no;
|
||||
exit when c1_all%notfound;
|
||||
raise notice '% : % : %',company_name,company_loc,company_no;
|
||||
end loop;
|
||||
if c1_all%isopen then
|
||||
close c1_all;
|
||||
end if;
|
||||
end;
|
||||
/
|
||||
-- test declare condition
|
||||
create or replace procedure test_condition_1 as
|
||||
declare
|
||||
|
Reference in New Issue
Block a user