From ff5de38d6c6f090c2c501dc3a18491d0a21d4c48 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 15 Oct 2021 00:40:06 +0530 Subject: [PATCH] MDEV-26832: ROW_NUMBER in SIGNAL/RESIGNAL causes a syntax error Analysis: Parser was missing ROW_NUMBER as syntax for SIGNAL and RESIGNAL. Fix: Fix parser and fix how m_row_number is copied like other attributes to avoid ROW_NUMBER from assuming default value. --- mysql-test/main/get_diagnostics.result | 39 +++++++++++++++++++ mysql-test/main/get_diagnostics.test | 53 ++++++++++++++++++++++++++ sql/sql_class.h | 3 +- sql/sql_error.cc | 1 + sql/sql_signal.cc | 21 ++++++++++ sql/sql_yacc.yy | 2 + 6 files changed, 118 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/get_diagnostics.result b/mysql-test/main/get_diagnostics.result index 0603e8b65d2..7d4982dbad5 100644 --- a/mysql-test/main/get_diagnostics.result +++ b/mysql-test/main/get_diagnostics.result @@ -1689,3 +1689,42 @@ SELECT @n, @m; @n @m 2 Out of range value for column 'f' at row 2 DROP TABLE t; +# +# MDEV-26832: ROW_NUMBER in SIGNAL/RESIGNAL causes a syntax error +# +# using signal +CREATE PROCEDURE signal_syntax() +BEGIN +DECLARE errno INT DEFAULT 0; +DECLARE msg TEXT DEFAULT "foo"; +DECLARE row_num INT DEFAULT 0; +DECLARE cond CONDITION FOR SQLSTATE "01234"; +DECLARE CONTINUE HANDLER for 1012 +BEGIN +GET DIAGNOSTICS CONDITION 1 errno = MYSQL_ERRNO, msg = MESSAGE_TEXT, row_num= ROW_NUMBER; +END; +SIGNAL cond SET MESSAGE_TEXT = "Signal message", MYSQL_ERRNO = 1012, ROW_NUMBER= 5; +SELECT errno, msg, row_num; +END| +CALL signal_syntax(); +errno msg row_num +1012 Signal message 5 +DROP PROCEDURE signal_syntax; +# using resignal +CREATE PROCEDURE resignal_syntax() +BEGIN +DECLARE CONTINUE HANDLER +FOR 1146 +BEGIN +RESIGNAL SET +MESSAGE_TEXT = '`temptab` does not exist', ROW_NUMBER= 105; +END; +SELECT `c` FROM `temptab`; +END| +CALL resignal_syntax(); +ERROR 42S02: `temptab` does not exist +GET DIAGNOSTICS CONDITION 1 @row_num= ROW_NUMBER; +SELECT @row_num; +@row_num +105 +DROP PROCEDURE resignal_syntax; diff --git a/mysql-test/main/get_diagnostics.test b/mysql-test/main/get_diagnostics.test index d497120d339..1876a05173e 100644 --- a/mysql-test/main/get_diagnostics.test +++ b/mysql-test/main/get_diagnostics.test @@ -1565,3 +1565,56 @@ GET DIAGNOSTICS CONDITION 2 @n= ROW_NUMBER, @m = MESSAGE_TEXT; SELECT @n, @m; DROP TABLE t; + +--echo # +--echo # MDEV-26832: ROW_NUMBER in SIGNAL/RESIGNAL causes a syntax error +--echo # + +--echo # using signal + +DELIMITER |; +CREATE PROCEDURE signal_syntax() +BEGIN + DECLARE errno INT DEFAULT 0; + DECLARE msg TEXT DEFAULT "foo"; + DECLARE row_num INT DEFAULT 0; + DECLARE cond CONDITION FOR SQLSTATE "01234"; + DECLARE CONTINUE HANDLER for 1012 + BEGIN + GET DIAGNOSTICS CONDITION 1 errno = MYSQL_ERRNO, msg = MESSAGE_TEXT, row_num= ROW_NUMBER; + END; + + SIGNAL cond SET MESSAGE_TEXT = "Signal message", MYSQL_ERRNO = 1012, ROW_NUMBER= 5; + + SELECT errno, msg, row_num; +END| +DELIMITER ;| + +CALL signal_syntax(); + +DROP PROCEDURE signal_syntax; + +--echo # using resignal + +DELIMITER |; + +CREATE PROCEDURE resignal_syntax() +BEGIN + DECLARE CONTINUE HANDLER + FOR 1146 + BEGIN + RESIGNAL SET + MESSAGE_TEXT = '`temptab` does not exist', ROW_NUMBER= 105; + END; + SELECT `c` FROM `temptab`; +END| + +DELIMITER ;| + +--error ER_NO_SUCH_TABLE +CALL resignal_syntax(); + +GET DIAGNOSTICS CONDITION 1 @row_num= ROW_NUMBER; +SELECT @row_num; + +DROP PROCEDURE resignal_syntax; diff --git a/sql/sql_class.h b/sql/sql_class.h index 964626be3d4..242d622a9a0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -560,7 +560,8 @@ typedef enum enum_diag_condition_item_name DIAG_CURSOR_NAME= 9, DIAG_MESSAGE_TEXT= 10, DIAG_MYSQL_ERRNO= 11, - LAST_DIAG_SET_PROPERTY= DIAG_MYSQL_ERRNO + DIAG_ROW_NUMBER= 12, + LAST_DIAG_SET_PROPERTY= DIAG_ROW_NUMBER } Diag_condition_item_name; /** diff --git a/sql/sql_error.cc b/sql/sql_error.cc index a2178831697..c557b30e98e 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -204,6 +204,7 @@ Sql_condition::copy_opt_attributes(const Sql_condition *cond) copy_string(m_mem_root, & m_table_name, & cond->m_table_name); copy_string(m_mem_root, & m_column_name, & cond->m_column_name); copy_string(m_mem_root, & m_cursor_name, & cond->m_cursor_name); + m_row_number= cond->m_row_number; } diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc index e023923bd1a..6ccc16c53e5 100644 --- a/sql/sql_signal.cc +++ b/sql/sql_signal.cc @@ -44,6 +44,7 @@ const LEX_CSTRING Diag_condition_item_names[]= { STRING_WITH_LEN("CURSOR_NAME") }, { STRING_WITH_LEN("MESSAGE_TEXT") }, { STRING_WITH_LEN("MYSQL_ERRNO") }, + { STRING_WITH_LEN("ROW_NUMBER") }, { STRING_WITH_LEN("CONDITION_IDENTIFIER") }, { STRING_WITH_LEN("CONDITION_NUMBER") }, @@ -309,6 +310,26 @@ int Sql_cmd_common_signal::eval_signal_informations(THD *thd, Sql_condition *con cond->m_sql_errno= (int) code; } + set= m_set_signal_information.m_item[DIAG_ROW_NUMBER]; + if (set != NULL) + { + if (set->is_null()) + { + thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR, + "ROW_NUMBER", "NULL"); + goto end; + } + longlong row_number_value= set->val_int(); + if (row_number_value < 0) + { + str= set->val_str(& str_value); + thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR, + "ROW_NUMBER", str->c_ptr_safe()); + goto end; + } + cond->m_row_number= (ulong) row_number_value; + } + /* The various item->val_xxx() methods don't return an error code, but flag thd in case of failure. diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 99bf0520541..2c29c833962 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3475,6 +3475,8 @@ signal_condition_information_item_name: { $$= DIAG_MESSAGE_TEXT; } | MYSQL_ERRNO_SYM { $$= DIAG_MYSQL_ERRNO; } + | ROW_NUMBER_SYM + { $$= DIAG_ROW_NUMBER; } ; resignal_stmt: