Commit 3988dfff authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-6899 extra semicolon in show create event syntax

to detect the end of SP definition correctly we need to know where
the parser stopped parsing the SP. lip->get_cpp_ptr() shows the
current parsing position, lip->get_cpp_tok_start() shows the start of
the last parsed token. The actual value depends on whether
the parser has performed a look-ahead. For example, in

  CREATE PROCEDURE ... BEGIN ... END ;

the parser reads 'END' and knows that this ends the procedure definition,
it does not need to read the next token for this. But in

  CREATE PROCEDURE ... SELECT 1 ;

the parser cannot know that the procedure ends at '1'. It has to read
the semicolon first (it could be '1 + 2' for example).

In the first case, the "current parsing position" is after END, before
the semicolon, in the second case it's *after* the semicolon. Note that
SP definition in both cases ends before the semicolon.

To be able to detect the end of SP deterministically, we need the parser
to do the look-ahead always or never.

The bug fix introduces a new parser token FORCE_LOOKAHEAD. Lexer never
returns it, so this token can never match. But the parser cannot know
it so it will have to perform a look-ahead to determine that the next
token is not FORCE_LOOKAHEAD. This way we deterministically end
SP parsing with a look-ahead.
parent 7753eae1
......@@ -1367,5 +1367,47 @@ SELECT tmp 1.e.test FROM scientific_notation AS tmp;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1.e.test FROM scientific_notation AS tmp' at line 1
DROP TABLE scientific_notation;
#
# MDEV-6899 extra semicolon in show create event syntax
#
set timestamp=unix_timestamp('2020-10-10 5:5:5');
create table t1 (a int);
create trigger a before insert on t1 for each row set @a:=1;select 2$
2
2
show create trigger a;
Trigger a
sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
SQL Original Statement CREATE DEFINER=`root`@`localhost` trigger a before insert on t1 for each row set @a:=1
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
Created 2020-10-10 05:05:05.00
drop table t1;
create procedure a() select 1;select 2$
2
2
show create procedure a;
Procedure a
sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Create Procedure CREATE DEFINER=`root`@`localhost` PROCEDURE `a`()
select 1
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
drop procedure a;
create function a() returns int return 1;select 2$
2
2
show create function a;
Function a
sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Create Function CREATE DEFINER=`root`@`localhost` FUNCTION `a`() RETURNS int(11)
return 1
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
drop function a;
set timestamp=default;
#
# End of 10.2 tests
#
......@@ -102,3 +102,23 @@ ROLLBACK AND NO CHAIN NO RELEASE;
#
# End of 5.5 tests
#
#
# MDEV-6899 extra semicolon in show create event syntax
#
set timestamp=unix_timestamp('2020-10-10 5:5:5');
create event a on schedule every 1 day do set @a:=1;select 2$
2
2
show create event a;
Event a
sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
time_zone SYSTEM
Create Event CREATE DEFINER=`root`@`localhost` EVENT `a` ON SCHEDULE EVERY 1 DAY STARTS '2020-10-10 05:05:05' ON COMPLETION NOT PRESERVE ENABLE DO set @a:=1
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
drop event a;
set timestamp=default;
#
# End of 10.2 tests
#
......@@ -1408,6 +1408,30 @@ SELECT tmp 1.e.test FROM scientific_notation AS tmp;
DROP TABLE scientific_notation;
--echo #
--echo # MDEV-6899 extra semicolon in show create event syntax
--echo #
set timestamp=unix_timestamp('2020-10-10 5:5:5');
create table t1 (a int);
delimiter $;
create trigger a before insert on t1 for each row set @a:=1;select 2$
delimiter ;$
query_vertical show create trigger a;
drop table t1;
delimiter $;
create procedure a() select 1;select 2$
delimiter ;$
query_vertical show create procedure a;
drop procedure a;
delimiter $;
create function a() returns int return 1;select 2$
delimiter ;$
query_vertical show create function a;
drop function a;
set timestamp=default;
--echo #
--echo # End of 10.2 tests
--echo #
......@@ -99,3 +99,18 @@ ROLLBACK AND NO CHAIN NO RELEASE;
--echo #
--echo # End of 5.5 tests
--echo #
--echo #
--echo # MDEV-6899 extra semicolon in show create event syntax
--echo #
set timestamp=unix_timestamp('2020-10-10 5:5:5');
delimiter $;
create event a on schedule every 1 day do set @a:=1;select 2$
delimiter ;$
query_vertical show create event a;
drop event a;
set timestamp=default;
--echo #
--echo # End of 10.2 tests
--echo #
......@@ -700,7 +700,7 @@ void
sp_head::set_stmt_end(THD *thd)
{
Lex_input_stream *lip= & thd->m_parser_state->m_lip; /* shortcut */
const char *end_ptr= lip->get_cpp_ptr(); /* shortcut */
const char *end_ptr= lip->get_cpp_tok_start(); /* shortcut */
uint not_used;
/* Make the string of parameters. */
......
......@@ -1035,10 +1035,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 98 shift/reduce conflicts.
Currently there are 119 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 115
%expect 119
/*
Comments for TOKENS.
......@@ -1258,6 +1258,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token FOLLOWS_SYM /* MYSQL trigger*/
%token FOLLOWING_SYM /* SQL-2011-N */
%token FORCE_SYM
%token FORCE_LOOKAHEAD /* INTERNAL never returned by the lexer */
%token FOREIGN /* SQL-2003-R */
%token FOR_SYM /* SQL-2003-R */
%token FORMAT_SYM
......@@ -2710,6 +2711,9 @@ server_option:
}
;
/* this rule is used to force look-ahead in the parser */
force_lookahead: {} | FORCE_LOOKAHEAD {} ;
event_tail:
remember_name EVENT_SYM opt_if_not_exists sp_name
{
......@@ -2854,7 +2858,7 @@ ev_sql_stmt:
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
sp_proc_stmt
sp_proc_stmt force_lookahead
{
LEX *lex= thd->lex;
......@@ -16838,8 +16842,8 @@ trigger_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
sp_proc_stmt /* $20 */
{ /* $21 */
sp_proc_stmt force_lookahead
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
......@@ -16939,7 +16943,7 @@ sf_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
sp_proc_stmt_in_returns_clause /* $15 */
sp_proc_stmt_in_returns_clause /* $15 */ force_lookahead
{
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
......@@ -17020,7 +17024,7 @@ sp_tail:
{
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_proc_stmt
sp_proc_stmt force_lookahead
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment