MDEV-36675 Optimizer hints parser catches irrelevant thd->is_error()
set by multi-RENAME TABLE
Optimizer hints parser analyzes `thd->is_error()` flag to detect a fatal error occured during hints processing. However, this criteria is not reliable and considered a bad practice. This commit replaces the criteria with the parser's own `is_fatal_error()` flag which is related strictly to hints parsing and not something else
This commit is contained in:
parent
349f5bf2da
commit
a0e89070cc
@ -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
|
||||
#
|
||||
|
@ -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 #
|
||||
|
@ -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<bool, Optimizer_hint_parser_output *>
|
||||
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))};
|
||||
}
|
||||
|
||||
|
||||
|
@ -5001,7 +5001,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Optimizer_hint_parser_output *
|
||||
std::pair<bool, Optimizer_hint_parser_output *>
|
||||
parse_optimizer_hints(const Lex_comment_st &hint);
|
||||
};
|
||||
|
||||
|
@ -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<bool, Optimizer_hint_parser_output *> parse_res=
|
||||
Lex->parse_optimizer_hints($2);
|
||||
if (!($$= parse_res.second) && parse_res.first)
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
Loading…
x
Reference in New Issue
Block a user