From 2adf38c12e80b942ef3728d7f68ce044c15d1758 Mon Sep 17 00:00:00 2001 From: "davi@moksha.com.br" <> Date: Thu, 11 Oct 2007 17:38:40 -0300 Subject: [PATCH] Bug#29223 declare cursor c for SHOW ..... "DECLARE CURSOR FOR SHOW ..." is a syntax that currently appears to work, but is untested for some SHOW commands and does not work for other SHOW commands. Since this is an un-intended feature that leaked as a result of a coding bug (in the parser grammar), the correct fix is to fix the grammar to not accept this construct. In other words, "DECLARE CURSOR FOR SHOW " is not considered a bug, and we will not implement other features to make all the SHOW commands usable inside a cursor just because someone exploited a bug. --- mysql-test/r/sp-error.result | 21 ++++++++++++++++++++- mysql-test/t/information_schema.test | 2 +- mysql-test/t/sp-error.test | 23 ++++++++++++++++++++++- sql/sql_yacc.yy | 18 +++--------------- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index bfcd64e89d3..46b8adb85b8 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -142,7 +142,10 @@ declare c cursor for insert into test.t1 values ("foo", 42); open c; close c; end| -ERROR 42000: Cursor statement must be a SELECT +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 'insert into test.t1 values ("foo", 42); +open c; +close c; +end' at line 3 create procedure p() begin declare x int; @@ -1491,3 +1494,19 @@ ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; RETURN 0; END// ERROR HY000: Can't drop or alter a DATABASE from within another stored routine +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE c char(100); +DECLARE cur1 CURSOR FOR SHOW TABLES; +OPEN cur1; +FETCH cur1 INTO c; +select c; +CLOSE cur1; +END| +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 'SHOW TABLES; +OPEN cur1; +FETCH cur1 INTO c; +select c; +CLOSE cur1; +END' at line 4 diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 6bcc14d4e49..9ad658645bd 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -953,7 +953,7 @@ BEGIN DECLARE col1, col2, col3, col4, col6 CHAR(255); DECLARE default_val VARCHAR(65532); DECLARE done INT DEFAULT 0; - DECLARE cur1 CURSOR FOR SHOW COLUMNS FROM bug23037; + DECLARE cur1 CURSOR FOR SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='bug23037'; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN cur1; FETCH cur1 INTO col1, col2, col3, col4, default_val, col6; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index c9145859405..ad516f028e6 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -196,7 +196,7 @@ select f(10)| drop function f| ---error 1322 +--error ER_PARSE_ERROR create procedure p() begin declare c cursor for insert into test.t1 values ("foo", 42); @@ -2178,6 +2178,27 @@ END// delimiter ;// +# +# Bug#29223 declare cursor c for SHOW ..... +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings +--delimiter | +--error ER_PARSE_ERROR +CREATE PROCEDURE p1() +BEGIN + DECLARE c char(100); + DECLARE cur1 CURSOR FOR SHOW TABLES; + + OPEN cur1; + FETCH cur1 INTO c; + select c; + CLOSE cur1; +END| +--delimiter ; + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 39175297753..0989e6e6b24 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2540,25 +2540,13 @@ sp_decl: sp_cursor_stmt: { Lex->sphead->reset_lex(YYTHD); - - /* - We use statement here just be able to get a better - error message. Using 'select' works too, but will then - result in a generic "syntax error" if a non-select - statement is given. - */ } - statement + select { LEX *lex= Lex; - if (lex->sql_command != SQLCOM_SELECT && - !(sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)) - { - my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY), - MYF(0)); - MYSQL_YYABORT; - } + DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT); + if (lex->result) { my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT),