diff options
author | Marc Alff <marc.alff@sun.com> | 2008-07-07 15:53:20 -0600 |
---|---|---|
committer | Marc Alff <marc.alff@sun.com> | 2008-07-07 15:53:20 -0600 |
commit | 8aaccbfc212e7d8bb99e96f2e9686da68cf2de09 (patch) | |
tree | b1b9220fc9e099b361f84152b88dae41d33f35b2 | |
parent | 50853ac31a5f158d02c986a9eec5144cf20d00b9 (diff) | |
parent | c7724872d85cebf07df3380757cf7259f9116682 (diff) | |
download | mariadb-git-8aaccbfc212e7d8bb99e96f2e9686da68cf2de09.tar.gz |
Manual merge of bug#26030 in mysql-5.1-bugteam
-rw-r--r-- | mysql-test/r/comments.result | 2 | ||||
-rw-r--r-- | mysql-test/r/parser.result | 68 | ||||
-rw-r--r-- | mysql-test/r/ps.result | 4 | ||||
-rw-r--r-- | mysql-test/t/parser.test | 47 | ||||
-rw-r--r-- | sql/sql_lex.cc | 21 | ||||
-rw-r--r-- | sql/sql_parse.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 110 |
7 files changed, 160 insertions, 97 deletions
diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result index d8ac68e2468..99fab38d7a7 100644 --- a/mysql-test/r/comments.result +++ b/mysql-test/r/comments.result @@ -45,7 +45,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;"; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;*"; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';*' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*' at line 1 prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';"; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*!98765' AND b = 'bar'' at line 1 prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';*"; diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index e10bcba36c2..270c1ec5670 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -284,6 +284,74 @@ Field Type Null Key Default Extra DROP TABLE table_25930_a; DROP TABLE table_25930_b; SET @@sql_mode=@save_sql_mode; +DROP PROCEDURE IF EXISTS p26030; +select "non terminated"$$ +non terminated +non terminated +select "terminated";$$ +terminated +terminated +select "non terminated, space" $$ +non terminated, space +non terminated, space +select "terminated, space"; $$ +terminated, space +terminated, space +select "non terminated, comment" /* comment */$$ +non terminated, comment +non terminated, comment +select "terminated, comment"; /* comment */$$ +terminated, comment +terminated, comment +select "stmt 1";select "stmt 2 non terminated"$$ +stmt 1 +stmt 1 +stmt 2 non terminated +stmt 2 non terminated +select "stmt 1";select "stmt 2 terminated";$$ +stmt 1 +stmt 1 +stmt 2 terminated +stmt 2 terminated +select "stmt 1";select "stmt 2 non terminated, space" $$ +stmt 1 +stmt 1 +stmt 2 non terminated, space +stmt 2 non terminated, space +select "stmt 1";select "stmt 2 terminated, space"; $$ +stmt 1 +stmt 1 +stmt 2 terminated, space +stmt 2 terminated, space +select "stmt 1";select "stmt 2 non terminated, comment" /* comment */$$ +stmt 1 +stmt 1 +stmt 2 non terminated, comment +stmt 2 non terminated, comment +select "stmt 1";select "stmt 2 terminated, comment"; /* comment */$$ +stmt 1 +stmt 1 +stmt 2 terminated, comment +stmt 2 terminated, comment +select "stmt 1"; select "space, stmt 2"$$ +stmt 1 +stmt 1 +space, stmt 2 +space, stmt 2 +select "stmt 1";/* comment */select "comment, stmt 2"$$ +stmt 1 +stmt 1 +comment, stmt 2 +comment, stmt 2 +DROP PROCEDURE IF EXISTS p26030; CREATE PROCEDURE p26030() BEGIN SELECT 1; END; CALL p26030() +$$ +1 +1 +DROP PROCEDURE IF EXISTS p26030; CREATE PROCEDURE p26030() SELECT 1; CALL p26030() +$$ +1 +1 +DROP PROCEDURE p26030; select pi(3.14); ERROR 42000: Incorrect parameter count in the call to native function 'pi' select tan(); diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 4cae3928097..05b2d18889b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -85,9 +85,9 @@ NULL NULL NULL prepare stmt6 from 'select 1; select2'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; select2' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select2' at line 1 prepare stmt6 from 'insert into t1 values (5,"five"); select2'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; select2' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select2' at line 1 explain prepare stmt6 from 'insert into t1 values (5,"five"); select2'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from 'insert into t1 values (5,"five"); select2'' at line 1 create table t2 diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 800d717cf6b..7efc519e441 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -6,6 +6,11 @@ # LEXICAL PARSER (lex) #============================================================================= +# +# Maintainer: these tests are for the lexical parser, so every character, +# even whitespace or comments, is significant here. +# + SET @save_sql_mode=@@sql_mode; # @@ -387,6 +392,48 @@ DROP TABLE table_25930_b; SET @@sql_mode=@save_sql_mode; +# +# Bug#26030 (Parsing fails for stored routine w/multi-statement execution +# enabled) +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p26030; +--enable_warnings + +delimiter $$; + +select "non terminated"$$ +select "terminated";$$ +select "non terminated, space" $$ +select "terminated, space"; $$ +select "non terminated, comment" /* comment */$$ +select "terminated, comment"; /* comment */$$ + +# Multi queries can not be used in --ps-protocol test mode +--disable_ps_protocol + +select "stmt 1";select "stmt 2 non terminated"$$ +select "stmt 1";select "stmt 2 terminated";$$ +select "stmt 1";select "stmt 2 non terminated, space" $$ +select "stmt 1";select "stmt 2 terminated, space"; $$ +select "stmt 1";select "stmt 2 non terminated, comment" /* comment */$$ +select "stmt 1";select "stmt 2 terminated, comment"; /* comment */$$ + +select "stmt 1"; select "space, stmt 2"$$ +select "stmt 1";/* comment */select "comment, stmt 2"$$ + +DROP PROCEDURE IF EXISTS p26030; CREATE PROCEDURE p26030() BEGIN SELECT 1; END; CALL p26030() +$$ + +DROP PROCEDURE IF EXISTS p26030; CREATE PROCEDURE p26030() SELECT 1; CALL p26030() +$$ + +--enable_ps_protocol + +delimiter ;$$ +DROP PROCEDURE p26030; + #============================================================================= # SYNTACTIC PARSER (bison) #============================================================================= diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 449c2fccb0b..64c2a911313 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1317,23 +1317,8 @@ int MYSQLlex(void *arg, void *yythd) lip->yySkip(); return (SET_VAR); case MY_LEX_SEMICOLON: // optional line terminator - if (lip->yyPeek()) - { - if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) && - !lip->stmt_prepare_mode) - { - lex->safe_to_cache_query= 0; - lip->found_semicolon= lip->get_ptr(); - thd->server_status|= SERVER_MORE_RESULTS_EXISTS; - lip->next_state= MY_LEX_END; - lip->set_echo(TRUE); - return (END_OF_INPUT); - } - state= MY_LEX_CHAR; // Return ';' - break; - } - lip->next_state=MY_LEX_END; // Mark for next loop - return(END_OF_INPUT); + state= MY_LEX_CHAR; // Return ';' + break; case MY_LEX_EOL: if (lip->eof()) { @@ -1352,7 +1337,7 @@ int MYSQLlex(void *arg, void *yythd) case MY_LEX_END: lip->next_state=MY_LEX_END; return(0); // We found end of input last time - + /* Actually real shouldn't start with . but allow them anyhow */ case MY_LEX_REAL_OR_POINT: if (my_isdigit(cs,lip->yyPeek())) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b8f2228d6e7..349e92b00d3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5641,6 +5641,11 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, (thd->query_length= (ulong)(*found_semicolon - thd->query))) thd->query_length--; /* Actually execute the query */ + if (*found_semicolon) + { + lex->safe_to_cache_query= 0; + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; + } lex->set_trg_event_type_for_tables(); mysql_execute_command(thd); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 54399c3791c..3652fe8d6b4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1355,12 +1355,44 @@ query: my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0)); MYSQL_YYABORT; } + thd->lex->sql_command= SQLCOM_EMPTY_QUERY; + thd->m_lip->found_semicolon= NULL; + } + | verb_clause + { + Lex_input_stream *lip = YYTHD->m_lip; + + if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) && + ! lip->stmt_prepare_mode && + ! lip->eof()) + { + /* + We found a well formed query, and multi queries are allowed: + - force the parser to stop after the ';' + - mark the start of the next query for the next invocation + of the parser. + */ + lip->next_state= MY_LEX_END; + lip->found_semicolon= lip->get_ptr(); + } else { - thd->lex->sql_command= SQLCOM_EMPTY_QUERY; + /* Single query, terminated. */ + lip->found_semicolon= NULL; } } - | verb_clause END_OF_INPUT {} + ';' + opt_end_of_input + | verb_clause END_OF_INPUT + { + /* Single query, not terminated. */ + YYTHD->m_lip->found_semicolon= NULL; + } + ; + +opt_end_of_input: + /* empty */ + | END_OF_INPUT ; verb_clause: @@ -1774,10 +1806,6 @@ server_option: event_tail: EVENT_SYM opt_if_not_exists sp_name - /* - BE CAREFUL when you add a new rule to update the block where - YYTHD->client_capabilities is set back to original value - */ { THD *thd= YYTHD; LEX *lex=Lex; @@ -1787,14 +1815,6 @@ event_tail: MYSQL_YYABORT; lex->event_parse_data->identifier= $3; - /* - We have to turn of CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; - thd->client_capabilities &= (~CLIENT_MULTI_QUERIES); - lex->sql_command= SQLCOM_CREATE_EVENT; /* We need that for disallowing subqueries */ } @@ -1805,15 +1825,6 @@ event_tail: DO_SYM ev_sql_stmt { /* - Restore flag if it was cleared above - $1 - EVENT_SYM - $2 - opt_if_not_exists - $3 - sp_name - $4 - the block above - */ - YYTHD->client_capabilities |= $<ulong_num>4; - - /* sql_command is set here because some rules in ev_sql_stmt can overwrite it */ @@ -5406,10 +5417,6 @@ alter: view_tail {} | ALTER definer_opt EVENT_SYM sp_name - /* - BE CAREFUL when you add a new rule to update the block where - YYTHD->client_capabilities is set back to original value - */ { /* It is safe to use Lex->spname because @@ -5423,14 +5430,6 @@ alter: MYSQL_YYABORT; Lex->event_parse_data->identifier= $4; - /* - We have to turn off CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; - Lex->sql_command= SQLCOM_ALTER_EVENT; } ev_alter_on_schedule_completion @@ -5439,15 +5438,6 @@ alter: opt_ev_comment opt_ev_sql_stmt { - /* - $1 - ALTER - $2 - definer_opt - $3 - EVENT_SYM - $4 - sp_name - $5 - the block above - */ - YYTHD->client_capabilities |= $<ulong_num>5; - if (!($6 || $7 || $8 || $9 || $10)) { my_parse_error(ER(ER_SYNTAX_ERROR)); @@ -12181,13 +12171,6 @@ trigger_tail: lex->sphead= sp; lex->spname= $3; - /* - We have to turn of CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; - thd->client_capabilities &= ~CLIENT_MULTI_QUERIES; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sphead->m_chistics= &lex->sp_chistics; @@ -12200,9 +12183,6 @@ trigger_tail: lex->sql_command= SQLCOM_CREATE_TRIGGER; sp->set_stmt_end(YYTHD); - /* Restore flag if it was cleared above */ - - YYTHD->client_capabilities |= $<ulong_num>15; sp->restore_thd_mem_root(YYTHD); if (sp->is_not_allowed_in_function("trigger")) @@ -12294,13 +12274,6 @@ sf_tail: sp->m_type= TYPE_ENUM_FUNCTION; lex->sphead= sp; - /* - We have to turn off CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; - thd->client_capabilities &= ~CLIENT_MULTI_QUERIES; tmp_param_begin= lip->get_cpp_tok_start(); tmp_param_begin++; @@ -12406,8 +12379,6 @@ sf_tail: ER(ER_NATIVE_FCT_NAME_COLLISION), sp->m_name.str); } - /* Restore flag if it was cleared above */ - thd->client_capabilities |= $<ulong_num>5; sp->restore_thd_mem_root(thd); } ; @@ -12434,13 +12405,6 @@ sp_tail: sp->init_sp_name(YYTHD, $3); lex->sphead= sp; - /* - * We have to turn of CLIENT_MULTI_QUERIES while parsing a - * stored procedure, otherwise yylex will chop it into pieces - * at each ';'. - */ - $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); } '(' { @@ -12479,12 +12443,6 @@ sp_tail: sp->set_stmt_end(YYTHD); lex->sql_command= SQLCOM_CREATE_PROCEDURE; - /* - Restore flag if it was cleared above - Be careful with counting. the block where we save the value - is $4. - */ - YYTHD->client_capabilities |= $<ulong_num>4; sp->restore_thd_mem_root(YYTHD); } ; |