!2357 修复declare作为标识符时相关的语法错误

Merge pull request !2357 from pengjiong/drop_ext
This commit is contained in:
opengauss-bot
2022-11-10 03:47:14 +00:00
committed by Gitee
4 changed files with 167 additions and 28 deletions

View File

@ -2310,6 +2310,17 @@ analyze_state(const char* text,PsqlScanStateData* state)
state->count_to_read = -1;
break;
case IDEN_PROCEDURE:
if (state->declare_encountered && state->begin_state == BEGIN_UNDEFINED) {
/*
* declare_encountered is true means we have met a 'declare' already, sql may like
* 'create trigger declare on declare execute procedure xx', 'declare' should be treat as an identifier
* not a keyword. PROCEDURE is a reserve keyword, so it must be a keyword not a identifier.
*/
state->declare_encountered = false;
state->gram_state[IDEN_PROCEDURE] = false;
state->gram_state[IDEN_DECLARE] = false;
break;
}
state->gram_state[IDEN_AS] = true;
state->gram_state[IDEN_IS] = true;
state->include_ora_comment = true;
@ -2365,6 +2376,7 @@ analyze_state(const char* text,PsqlScanStateData* state)
state->gram_state[IDEN_BINARY] = true;
state->gram_state[IDEN_INSENSITIVE] = true;
state->gram_state[IDEN_NO] = true;
state->gram_state[IDEN_PROCEDURE] = true;
state->declare_encountered = true;
break;
case IDEN_BEGIN:

View File

@ -108,21 +108,25 @@ List* raw_parser(const char* str, List** query_string_locationlist)
return yyextra.parsetree;
}
#define GET_NEXT_TOKEN() \
#define GET_NEXT_TOKEN_WITHOUT_YY() \
do { \
cur_yylval = lvalp->core_yystype; \
cur_yylloc = *llocp; \
if (yyextra->lookahead_num != 0) { \
next_token = yyextra->lookahead_token[yyextra->lookahead_num - 1]; \
lvalp->core_yystype = yyextra->lookahead_yylval[yyextra->lookahead_num - 1]; \
*llocp = yyextra->lookahead_yylloc[yyextra->lookahead_num - 1]; \
yyextra->lookahead_num--; \
Assert(yyextra->lookahead_num == 0); \
} else { \
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner); \
} \
} while (0)
#define GET_NEXT_TOKEN() \
do { \
cur_yylval = lvalp->core_yystype; \
cur_yylloc = *llocp; \
GET_NEXT_TOKEN_WITHOUT_YY(); \
} while (0)
#define SET_LOOKAHEAD_TOKEN() \
do { \
yyextra->lookahead_token[0] = next_token; \
@ -428,17 +432,20 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner)
/*
* DECLARE foo CUROSR must be looked ahead, and if determined as a DECLARE_CURSOR, we should set the yylaval
* and yylloc back, letting the parser read the cursor name correctly.
* here we may still have token in lookahead_token, so use GET_NEXT_TOKEN to get
*/
cur_yylval = lvalp->core_yystype;
cur_yylloc = *llocp;
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
GET_NEXT_TOKEN();
/* get first token after DECLARE. We don't care what it is */
yyextra->lookahead_token[1] = next_token;
yyextra->lookahead_yylval[1] = lvalp->core_yystype;
yyextra->lookahead_yylloc[1] = *llocp;
/* get the second token after DECLARE. If it is cursor grammer, we are sure that this is a cursr stmt */
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
/*
* get the second token after DECLARE. If it is cursor grammer, we are sure that this is a cursr stmt
* in fact we don't have any lookahead_token here for sure, cause MAX_LOOKAHEAD_NUM is 2.
* but maybe someday MAX_LOOKAHEAD_NUM increase, so we still use GET_NEXT_TOKEN_WITHOUT_SET_CURYY
*/
GET_NEXT_TOKEN_WITHOUT_YY();
yyextra->lookahead_token[0] = next_token;
yyextra->lookahead_yylval[0] = lvalp->core_yystype;
yyextra->lookahead_yylloc[0] = *llocp;
@ -523,35 +530,38 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner)
}
break;
case ON:
cur_yylval = lvalp->core_yystype;
cur_yylloc = *llocp;
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
/* here we may still have token in lookahead_token, so use GET_NEXT_TOKEN to get */
GET_NEXT_TOKEN();
/* get first token after ON (Normal UPDATE). We don't care what it is */
yyextra->lookahead_token[1] = next_token;
yyextra->lookahead_yylval[1] = lvalp->core_yystype;
yyextra->lookahead_yylloc[1] = *llocp;
/* get the second token after ON. */
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
/*
* get the second token after ON.
* in fact we don't have any lookahead_token here for sure, cause MAX_LOOKAHEAD_NUM is 2.
* but maybe someday MAX_LOOKAHEAD_NUM increase, so we still use GET_NEXT_TOKEN_WITHOUT_SET_CURYY
*/
GET_NEXT_TOKEN_WITHOUT_YY();
yyextra->lookahead_token[0] = next_token;
yyextra->lookahead_yylval[0] = lvalp->core_yystype;
yyextra->lookahead_yylloc[0] = *llocp;
yyextra->lookahead_num = 2;
switch (next_token) {
case CURRENT_TIMESTAMP:
case CURRENT_TIME:
case CURRENT_DATE:
case LOCALTIME:
case LOCALTIMESTAMP:
cur_token = ON_UPDATE_TIME;
lvalp->core_yystype = cur_yylval;
*llocp = cur_yylloc;
break;
default:
/* and back up the output info to cur_token */
lvalp->core_yystype = cur_yylval;
*llocp = cur_yylloc;
break;
case CURRENT_TIMESTAMP:
case CURRENT_TIME:
case CURRENT_DATE:
case LOCALTIME:
case LOCALTIMESTAMP:
cur_token = ON_UPDATE_TIME;
lvalp->core_yystype = cur_yylval;
*llocp = cur_yylloc;
break;
default:
/* and back up the output info to cur_token */
lvalp->core_yystype = cur_yylval;
*llocp = cur_yylloc;
break;
}
break;
default:

View File

@ -1594,3 +1594,72 @@ drop table depth_a, depth_b, depth_c;
drop function depth_a_tf();
drop function depth_b_tf();
drop function depth_c_tf();
-- test declare + on in one sql.
create schema trigger_declare_test;
set current_schema to trigger_declare_test;
create table declare_test(id int);
create index declare on declare_test(id);
\d declare_test
Table "trigger_declare_test.declare_test"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Indexes:
"declare" btree (id) TABLESPACE pg_default
drop index declare;
create table declare(id int);
create index id_test on declare(id);
\d declare
Table "trigger_declare_test.declare"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Indexes:
"id_test" btree (id) TABLESPACE pg_default
CREATE OR REPLACE FUNCTION declare() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO declare_test VALUES(NEW.id);
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER declare AFTER INSERT ON declare FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare values(1);
drop TRIGGER declare on declare cascade;
CREATE TRIGGER declare_test AFTER INSERT ON declare FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare values(2);
drop TRIGGER declare_test on declare cascade;
CREATE OR REPLACE FUNCTION declare() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO declare VALUES(NEW.id);
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER declare AFTER INSERT ON declare_test FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare_test values(3);
drop TRIGGER declare on declare_test cascade;
select * from declare order by 1;
id
----
1
2
3
(3 rows)
select * from declare_test order by 1;
id
----
1
2
3
(3 rows)
drop table declare;
drop table declare_test;
drop schema trigger_declare_test cascade;
NOTICE: drop cascades to function declare()

View File

@ -1044,3 +1044,51 @@ drop table depth_a, depth_b, depth_c;
drop function depth_a_tf();
drop function depth_b_tf();
drop function depth_c_tf();
-- test declare + on in one sql.
create schema trigger_declare_test;
set current_schema to trigger_declare_test;
create table declare_test(id int);
create index declare on declare_test(id);
\d declare_test
drop index declare;
create table declare(id int);
create index id_test on declare(id);
\d declare
CREATE OR REPLACE FUNCTION declare() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO declare_test VALUES(NEW.id);
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER declare AFTER INSERT ON declare FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare values(1);
drop TRIGGER declare on declare cascade;
CREATE TRIGGER declare_test AFTER INSERT ON declare FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare values(2);
drop TRIGGER declare_test on declare cascade;
CREATE OR REPLACE FUNCTION declare() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO declare VALUES(NEW.id);
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
CREATE TRIGGER declare AFTER INSERT ON declare_test FOR EACH ROW EXECUTE PROCEDURE declare();
insert into declare_test values(3);
drop TRIGGER declare on declare_test cascade;
select * from declare order by 1;
select * from declare_test order by 1;
drop table declare;
drop table declare_test;
drop schema trigger_declare_test cascade;