diff --git a/mysql-test/main/opt_hints.result b/mysql-test/main/opt_hints.result index 6442cb62347..1399e5b3770 100644 --- a/mysql-test/main/opt_hints.result +++ b/mysql-test/main/opt_hints.result @@ -1985,5 +1985,21 @@ DROP TABLE t1; set optimizer_switch = DEFAULT; set join_cache_level = DEFAULT; # -# End of 11.7 tests +# MDEV-36675 Optimizer hints parser catches irrelevant `thd->is_error()` +# set by multi-RENAME TABLE +# +CREATE TABLE t1 (a INT); +CREATE TRIGGER t1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (0); +RENAME TABLE t1 TO t2, t3 TO t4; +ERROR 42S02: Table 'test.t3' doesn't exist +SHOW CREATE TRIGGER t1; +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created +t1 CREATE DEFINER=`root`@`localhost` TRIGGER t1 AFTER INSERT ON `t1` FOR EACH ROW INSERT INTO t1 VALUES (0) utf8mb3 utf8mb3_uca1400_ai_ci utf8mb4_uca1400_ai_ci # +RENAME TABLE t1 TO t2; +SHOW CREATE TRIGGER t1; +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created +t1 CREATE DEFINER=`root`@`localhost` TRIGGER t1 AFTER INSERT ON `t2` FOR EACH ROW INSERT INTO t1 VALUES (0) utf8mb3 utf8mb3_uca1400_ai_ci utf8mb4_uca1400_ai_ci # +DROP TABLE t2; +# +# End of 12.0 tests # diff --git a/mysql-test/main/opt_hints.test b/mysql-test/main/opt_hints.test index d04a8922496..79f5f59b9c8 100644 --- a/mysql-test/main/opt_hints.test +++ b/mysql-test/main/opt_hints.test @@ -1021,6 +1021,24 @@ SELECT DROP TABLE t1; set optimizer_switch = DEFAULT; set join_cache_level = DEFAULT; + --echo # ---echo # End of 11.7 tests +--echo # MDEV-36675 Optimizer hints parser catches irrelevant `thd->is_error()` +--echo # set by multi-RENAME TABLE +--echo # +CREATE TABLE t1 (a INT); +CREATE TRIGGER t1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (0); +--error ER_NO_SUCH_TABLE +RENAME TABLE t1 TO t2, t3 TO t4; + +--replace_column 7 # +SHOW CREATE TRIGGER t1; +RENAME TABLE t1 TO t2; + +--replace_column 7 # +SHOW CREATE TRIGGER t1; +DROP TABLE t2; + +--echo # +--echo # End of 12.0 tests --echo # diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 79f649e75a9..b4406a4f592 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -12932,22 +12932,22 @@ bool SELECT_LEX_UNIT::is_derived_eliminated() const /* Parse optimizer hints and return as Hint_list allocated on thd->mem_root. - The caller should check both return value and thd->is_error() + The caller should check both parts of the return value to know what happened, as follows: - Return value thd->is_error() Meaning + Retval.first Retval.second Meaning ------------ --------------- ------- - rc != nullptr false the hints were parsed without errors - rc != nullptr true not possible - rc == nullptr false no hints, empty hints, hint parse error - rc == nullptr true fatal error, such as EOM + false != nullptr the hints were parsed without errors + true != nullptr impossible combination + false == nullptr no hints, empty hints, hint parse error + true == nullptr fatal error, such as EOM */ -Optimizer_hint_parser_output * +std::pair LEX::parse_optimizer_hints(const Lex_comment_st &hints_str) { DBUG_ASSERT(!hints_str.str || hints_str.length >= 5); if (!hints_str.str) - return nullptr; // There were no a hint comment + return {false, nullptr}; // There were no a hint comment // Instantiate the query hint parser. // Remove the leading '/*+' and trailing '*/' @@ -12965,17 +12965,17 @@ LEX::parse_optimizer_hints(const Lex_comment_st &hints_str) The SQL error should be in DA already. */ DBUG_ASSERT(thd->is_error()); - return nullptr; // Continue, the caller will test thd->is_error() + return {true, nullptr}; // Set the flag of fatal error } if (!hints) // Hint parsing failed with a syntax error { p.push_warning_syntax_error(thd, hints_str.lineno); - return nullptr; // Continue and ignore hints. + return {false, nullptr}; // Continue and ignore hints. } // Hints were not empty and were parsed without errors - return new (thd->mem_root) Optimizer_hint_parser_output(std::move(hints)); + return {false, new (thd->mem_root) Optimizer_hint_parser_output(std::move(hints))}; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 90dfc4da30a..adbacd1cb75 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -5001,7 +5001,7 @@ public: return nullptr; } - Optimizer_hint_parser_output * + std::pair parse_optimizer_hints(const Lex_comment_st &hint); }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e48340ca727..6d03c0a7cc4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8971,7 +8971,9 @@ opt_optimizer_hint: opt_hint_comment { YYLIP->hint_comment= false; - if (!($$= Lex->parse_optimizer_hints($2)) && thd->is_error()) + std::pair parse_res= + Lex->parse_optimizer_hints($2); + if (!($$= parse_res.second) && parse_res.first) MYSQL_YYABORT; } ;