Skip to content

Commit a0e8907

Browse files
committed
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
1 parent 349f5bf commit a0e8907

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

mysql-test/main/opt_hints.result

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,5 +1985,21 @@ DROP TABLE t1;
19851985
set optimizer_switch = DEFAULT;
19861986
set join_cache_level = DEFAULT;
19871987
#
1988-
# End of 11.7 tests
1988+
# MDEV-36675 Optimizer hints parser catches irrelevant `thd->is_error()`
1989+
# set by multi-RENAME TABLE
1990+
#
1991+
CREATE TABLE t1 (a INT);
1992+
CREATE TRIGGER t1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (0);
1993+
RENAME TABLE t1 TO t2, t3 TO t4;
1994+
ERROR 42S02: Table 'test.t3' doesn't exist
1995+
SHOW CREATE TRIGGER t1;
1996+
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created
1997+
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 #
1998+
RENAME TABLE t1 TO t2;
1999+
SHOW CREATE TRIGGER t1;
2000+
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created
2001+
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 #
2002+
DROP TABLE t2;
2003+
#
2004+
# End of 12.0 tests
19892005
#

mysql-test/main/opt_hints.test

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,24 @@ SELECT
10211021
DROP TABLE t1;
10221022
set optimizer_switch = DEFAULT;
10231023
set join_cache_level = DEFAULT;
1024+
1025+
--echo #
1026+
--echo # MDEV-36675 Optimizer hints parser catches irrelevant `thd->is_error()`
1027+
--echo # set by multi-RENAME TABLE
1028+
--echo #
1029+
CREATE TABLE t1 (a INT);
1030+
CREATE TRIGGER t1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (0);
1031+
--error ER_NO_SUCH_TABLE
1032+
RENAME TABLE t1 TO t2, t3 TO t4;
1033+
1034+
--replace_column 7 #
1035+
SHOW CREATE TRIGGER t1;
1036+
RENAME TABLE t1 TO t2;
1037+
1038+
--replace_column 7 #
1039+
SHOW CREATE TRIGGER t1;
1040+
DROP TABLE t2;
1041+
10241042
--echo #
1025-
--echo # End of 11.7 tests
1043+
--echo # End of 12.0 tests
10261044
--echo #

sql/sql_lex.cc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12932,22 +12932,22 @@ bool SELECT_LEX_UNIT::is_derived_eliminated() const
1293212932
/*
1293312933
Parse optimizer hints and return as Hint_list allocated on thd->mem_root.
1293412934
12935-
The caller should check both return value and thd->is_error()
12935+
The caller should check both parts of the return value
1293612936
to know what happened, as follows:
1293712937
12938-
Return value thd->is_error() Meaning
12938+
Retval.first Retval.second Meaning
1293912939
------------ --------------- -------
12940-
rc != nullptr false the hints were parsed without errors
12941-
rc != nullptr true not possible
12942-
rc == nullptr false no hints, empty hints, hint parse error
12943-
rc == nullptr true fatal error, such as EOM
12940+
false != nullptr the hints were parsed without errors
12941+
true != nullptr impossible combination
12942+
false == nullptr no hints, empty hints, hint parse error
12943+
true == nullptr fatal error, such as EOM
1294412944
*/
12945-
Optimizer_hint_parser_output *
12945+
std::pair<bool, Optimizer_hint_parser_output *>
1294612946
LEX::parse_optimizer_hints(const Lex_comment_st &hints_str)
1294712947
{
1294812948
DBUG_ASSERT(!hints_str.str || hints_str.length >= 5);
1294912949
if (!hints_str.str)
12950-
return nullptr; // There were no a hint comment
12950+
return {false, nullptr}; // There were no a hint comment
1295112951

1295212952
// Instantiate the query hint parser.
1295312953
// Remove the leading '/*+' and trailing '*/'
@@ -12965,17 +12965,17 @@ LEX::parse_optimizer_hints(const Lex_comment_st &hints_str)
1296512965
The SQL error should be in DA already.
1296612966
*/
1296712967
DBUG_ASSERT(thd->is_error());
12968-
return nullptr; // Continue, the caller will test thd->is_error()
12968+
return {true, nullptr}; // Set the flag of fatal error
1296912969
}
1297012970

1297112971
if (!hints) // Hint parsing failed with a syntax error
1297212972
{
1297312973
p.push_warning_syntax_error(thd, hints_str.lineno);
12974-
return nullptr; // Continue and ignore hints.
12974+
return {false, nullptr}; // Continue and ignore hints.
1297512975
}
1297612976

1297712977
// Hints were not empty and were parsed without errors
12978-
return new (thd->mem_root) Optimizer_hint_parser_output(std::move(hints));
12978+
return {false, new (thd->mem_root) Optimizer_hint_parser_output(std::move(hints))};
1297912979
}
1298012980

1298112981

sql/sql_lex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5001,7 +5001,7 @@ struct LEX: public Query_tables_list
50015001
return nullptr;
50025002
}
50035003

5004-
Optimizer_hint_parser_output *
5004+
std::pair<bool, Optimizer_hint_parser_output *>
50055005
parse_optimizer_hints(const Lex_comment_st &hint);
50065006
};
50075007

sql/sql_yacc.yy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8971,7 +8971,9 @@ opt_optimizer_hint:
89718971
opt_hint_comment
89728972
{
89738973
YYLIP->hint_comment= false;
8974-
if (!($$= Lex->parse_optimizer_hints($2)) && thd->is_error())
8974+
std::pair<bool, Optimizer_hint_parser_output *> parse_res=
8975+
Lex->parse_optimizer_hints($2);
8976+
if (!($$= parse_res.second) && parse_res.first)
89758977
MYSQL_YYABORT;
89768978
}
89778979
;

0 commit comments

Comments
 (0)