@ -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;
|
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->isAutonomous = $1.isAutonomous;
|
||||||
newp->n_initvars = $1.n_initvars;
|
newp->n_initvars = $1.n_initvars;
|
||||||
newp->initvarnos = $1.initvarnos;
|
newp->initvarnos = $1.initvarnos;
|
||||||
newp->body = $3;
|
newp->body = $4;
|
||||||
newp->exceptions = $4;
|
newp->exceptions = $5;
|
||||||
|
|
||||||
check_labels($1.label, $6, @6);
|
check_labels($1.label, $7, @7);
|
||||||
plpgsql_ns_pop();
|
plpgsql_ns_pop();
|
||||||
|
|
||||||
$$ = (PLpgSQL_stmt *)newp;
|
$$ = (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
|
declare_sect :
|
||||||
| K_BEGIN declare_stmts
|
{
|
||||||
;
|
/* 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_stmts : declare_stmts declare_stmt
|
||||||
| 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
|
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;
|
PLpgSQL_var *newp;
|
||||||
|
|
||||||
/* pop local namespace for cursor args */
|
/* 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 ';'
|
| 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);
|
IsInPublicNamespace($2->name);
|
||||||
PLpgSQL_var *var;
|
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 */
|
||||||
/* next token should be a string literal */
|
char *sqlstatestr;
|
||||||
char *sqlstatestr;
|
if (yylex() != SCONST)
|
||||||
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 {
|
|
||||||
yyerror("syntax error");
|
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
|
| 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);
|
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
|
* plpgsql_scanner_errposition
|
||||||
* Report an error cursor position, if possible.
|
* 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_push_back_token(int token);
|
||||||
extern void plpgsql_append_source_text(StringInfo buf, int startlocation, int endlocation);
|
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_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 int plpgsql_scanner_errposition(int location);
|
||||||
extern void plpgsql_yyerror(const char* message, bool isError = false);
|
extern void plpgsql_yyerror(const char* message, bool isError = false);
|
||||||
extern int plpgsql_location_to_lineno(int location);
|
extern int plpgsql_location_to_lineno(int location);
|
||||||
|
@ -248,6 +248,54 @@ NOTICE: oracle : usa : 2
|
|||||||
|
|
||||||
(1 row)
|
(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
|
-- test declare condition
|
||||||
create or replace procedure test_condition_1 as
|
create or replace procedure test_condition_1 as
|
||||||
declare
|
declare
|
||||||
@ -306,7 +354,7 @@ exception
|
|||||||
END;
|
END;
|
||||||
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';
|
LINE 6: declare DIVISION_ZERO condition for SQLSTATE '22005';
|
||||||
^
|
^
|
||||||
QUERY:
|
QUERY:
|
||||||
|
@ -217,6 +217,30 @@ begin
|
|||||||
end;
|
end;
|
||||||
/
|
/
|
||||||
call test_cursor_1();
|
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
|
-- test declare condition
|
||||||
create or replace procedure test_condition_1 as
|
create or replace procedure test_condition_1 as
|
||||||
declare
|
declare
|
||||||
|
Reference in New Issue
Block a user