MDEV-36638 Some optimizer hint warnings are returned as errors
With strict SQL_MODE warnings generated during DDL statements are threated as errors. This is done to prevent potential data corruption. However, optimizer hints cannot affect the integrity of data, so warnings during their parsing or application should not be escalated to the level of errors. This commit introduces `push_warning_safe()` method that guarantees that a warning is not treated as an error, and generation of warnings during hints processing now uses this method instead of traditional `push_warning_printf()`
This commit is contained in:
parent
6cd27dbc43
commit
6e2a0501b6
@ -1324,3 +1324,44 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
Warnings:
|
||||
Note 1003 select /*+ JOIN_PREFIX(@`select#1` `t2`@`qb2`,`t4`@`qb1`,`ta3`,`ta4`) */ count(0) AS `COUNT(*)` from `test`.`t1` semi join (`test`.`t4`) semi join (`test`.`t2`) join `test`.`t2` `ta3` join `test`.`t2` `ta4` where `test`.`ta4`.`f1` = `test`.`t4`.`f1` and `test`.`ta3`.`f2` = `test`.`t2`.`f2`
|
||||
DROP TABLE t1, t2, t4;
|
||||
|
||||
MDEV-36638 Some optimizer hint warnings are returned as errors
|
||||
|
||||
SET @save_sql_mode = @@sql_mode;
|
||||
SET SQL_MODE = 'STRICT_TRANS_TABLES';
|
||||
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, f1 INT NOT NULL, PRIMARY KEY (id));
|
||||
INSERT INTO t1 (id, f1) VALUES (1,9),(2,0), (3,7);
|
||||
CREATE TABLE t2 (id int(11), f2 INT NOT NULL);
|
||||
INSERT INTO t2 (id, f2) VALUES
|
||||
(4,5),(3,3),(1,0),(1,3),(6,1),(2,0),(4,1),(2,7),(2,1),(1,0),(3,0),(5,8),(5,4),
|
||||
(3,9),(2,0),(7,2),(2,0),(1,8),(6,5),(4,1);
|
||||
CREATE TABLE tn (fn_1 INT, fn_2 INT);
|
||||
EXPLAIN EXTENDED
|
||||
INSERT INTO tn (fn_1, fn_2)
|
||||
SELECT /*+ JOIN_ORDER(t2,t1) JOIN_FIXED_ORDER() */ f1,f2
|
||||
FROM t2 JOIN t1 ON t1.id=t2.id ORDER BY f1, f2;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 20 100.00 Using temporary; Using filesort
|
||||
1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 33.33 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Warning 4217 Hint JOIN_FIXED_ORDER() is ignored as conflicting/duplicated
|
||||
Note 1003 insert into `test`.`tn`(fn_1,fn_2) select /*+ JOIN_ORDER(@`select#2` `t2`,`t1`) */ `test`.`t1`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`id` = `test`.`t2`.`id` order by `test`.`t1`.`f1`,`test`.`t2`.`f2`
|
||||
EXPLAIN EXTENDED
|
||||
INSERT INTO tn (fn_1, fn_2)
|
||||
SELECT /*+ JOIN_ORDER(t1,t2) */ f1,f2 FROM t2 LEFT JOIN t1 ON t1.id=t2.id
|
||||
ORDER BY f1, f2;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 20 100.00 Using temporary; Using filesort
|
||||
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 100.00 Using where
|
||||
Warnings:
|
||||
Warning 4217 Hint JOIN_ORDER(`t1`,`t2`) is ignored as conflicting/duplicated
|
||||
Note 1003 insert into `test`.`tn`(fn_1,fn_2) select `test`.`t1`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2` from `test`.`t2` left join `test`.`t1` on(`test`.`t1`.`id` = `test`.`t2`.`id` and `test`.`t2`.`id` is not null) where 1 order by `test`.`t1`.`f1`,`test`.`t2`.`f2`
|
||||
DROP TABLE tn;
|
||||
DROP TABLE t1, t2;
|
||||
CREATE TABLE t1 (a int, b varchar(50), c varchar(50));
|
||||
INSERT t1 (a,b) VALUES (1,'1'), (2,'2'), (3,'3');
|
||||
CREATE TRIGGER tr BEFORE UPDATE ON t1 FOR EACH ROW
|
||||
SET new.c = (SELECT /*+ NO_RANGE_OPTIMIZATION(t1) */ 1);
|
||||
UPDATE t1 SET t1.b = 10;
|
||||
DROP TABLE t1;
|
||||
SET SQL_MODE = @save_sql_mode;
|
||||
|
@ -789,3 +789,42 @@ eval $query;
|
||||
eval explain extended $query;
|
||||
|
||||
DROP TABLE t1, t2, t4;
|
||||
|
||||
--echo
|
||||
--echo MDEV-36638 Some optimizer hint warnings are returned as errors
|
||||
--echo
|
||||
|
||||
SET @save_sql_mode = @@sql_mode;
|
||||
SET SQL_MODE = 'STRICT_TRANS_TABLES';
|
||||
|
||||
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, f1 INT NOT NULL, PRIMARY KEY (id));
|
||||
INSERT INTO t1 (id, f1) VALUES (1,9),(2,0), (3,7);
|
||||
|
||||
CREATE TABLE t2 (id int(11), f2 INT NOT NULL);
|
||||
INSERT INTO t2 (id, f2) VALUES
|
||||
(4,5),(3,3),(1,0),(1,3),(6,1),(2,0),(4,1),(2,7),(2,1),(1,0),(3,0),(5,8),(5,4),
|
||||
(3,9),(2,0),(7,2),(2,0),(1,8),(6,5),(4,1);
|
||||
|
||||
CREATE TABLE tn (fn_1 INT, fn_2 INT);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
INSERT INTO tn (fn_1, fn_2)
|
||||
SELECT /*+ JOIN_ORDER(t2,t1) JOIN_FIXED_ORDER() */ f1,f2
|
||||
FROM t2 JOIN t1 ON t1.id=t2.id ORDER BY f1, f2;
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
INSERT INTO tn (fn_1, fn_2)
|
||||
SELECT /*+ JOIN_ORDER(t1,t2) */ f1,f2 FROM t2 LEFT JOIN t1 ON t1.id=t2.id
|
||||
ORDER BY f1, f2;
|
||||
|
||||
DROP TABLE tn;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
CREATE TABLE t1 (a int, b varchar(50), c varchar(50));
|
||||
INSERT t1 (a,b) VALUES (1,'1'), (2,'2'), (3,'3');
|
||||
CREATE TRIGGER tr BEFORE UPDATE ON t1 FOR EACH ROW
|
||||
SET new.c = (SELECT /*+ NO_RANGE_OPTIMIZATION(t1) */ 1);
|
||||
UPDATE t1 SET t1.b = 10;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET SQL_MODE = @save_sql_mode;
|
||||
|
@ -55,6 +55,28 @@ struct st_opt_hint_info opt_hint_info[]=
|
||||
|
||||
const LEX_CSTRING sys_qb_prefix= {"select#", 7};
|
||||
|
||||
|
||||
/*
|
||||
This is a version of push_warning_printf() guaranteeing no escalation of
|
||||
the warning to the level of error
|
||||
*/
|
||||
void push_warning_safe(THD *thd, Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
DBUG_ENTER("push_warning_safe");
|
||||
DBUG_PRINT("enter",("warning: %u", code));
|
||||
|
||||
va_start(args,format);
|
||||
bool save_abort_on_warning= thd->abort_on_warning;
|
||||
thd->abort_on_warning= false; // Don't escalate to the level of error
|
||||
push_warning_printf_va_list(thd, level,code, format, args);
|
||||
va_end(args);
|
||||
thd->abort_on_warning= save_abort_on_warning;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
bool hint_state,
|
||||
const Lex_ident_sys *qb_name_arg,
|
||||
@ -74,9 +96,9 @@ void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
{
|
||||
String qb_name_str;
|
||||
append_identifier(thd, &qb_name_str, qb_name_arg->str, qb_name_arg->length);
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
qb_name_str.c_ptr_safe(), str.c_ptr_safe());
|
||||
push_warning_safe(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
qb_name_str.c_ptr_safe(), str.c_ptr_safe());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,9 +108,9 @@ void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
DBUG_ASSERT(hint);
|
||||
String args;
|
||||
hint->append_args(thd, &args);
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
args.c_ptr_safe(), str.c_ptr_safe());
|
||||
push_warning_safe(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
args.c_ptr_safe(), str.c_ptr_safe());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -131,9 +153,8 @@ void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
}
|
||||
|
||||
str.append(')');
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code), str.c_ptr_safe());
|
||||
push_warning_safe(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code), str.c_ptr_safe());
|
||||
}
|
||||
|
||||
|
||||
@ -335,11 +356,11 @@ void Opt_hints::print_unfixed_warnings(THD *thd)
|
||||
{
|
||||
hint_type_str.length(0);
|
||||
append_hint_type(&hint_type_str, static_cast<opt_hints_enum>(i));
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
get_unfixed_warning_code(),
|
||||
ER_THD(thd, get_unfixed_warning_code()),
|
||||
hint_name_str.c_ptr_safe(),
|
||||
hint_type_str.c_ptr_safe());
|
||||
push_warning_safe(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
get_unfixed_warning_code(),
|
||||
ER_THD(thd, get_unfixed_warning_code()),
|
||||
hint_name_str.c_ptr_safe(),
|
||||
hint_type_str.c_ptr_safe());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -923,9 +944,10 @@ void Opt_hints_qb::print_join_order_warn(THD *thd, opt_hints_enum type,
|
||||
hint_type_str.append(opt_hint_info[type].hint_type);
|
||||
append_table_name(thd, &tbl_name_str, tbl_name.table_name, tbl_name.qb_name);
|
||||
uint err_code= ER_UNRESOLVED_TABLE_HINT_NAME;
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
tbl_name_str.c_ptr_safe(), hint_type_str.c_ptr_safe());
|
||||
|
||||
push_warning_safe(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
err_code, ER_THD(thd, err_code),
|
||||
tbl_name_str.c_ptr_safe(), hint_type_str.c_ptr_safe());
|
||||
}
|
||||
|
||||
|
||||
|
@ -783,22 +783,36 @@ void push_warning(THD *thd, Sql_condition::enum_warning_level level,
|
||||
*/
|
||||
|
||||
void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, ...)
|
||||
uint code, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char warning[MYSQL_ERRMSG_SIZE];
|
||||
DBUG_ENTER("push_warning_printf");
|
||||
DBUG_PRINT("enter",("warning: %u", code));
|
||||
|
||||
va_start(args,format);
|
||||
push_warning_printf_va_list(thd, level,code, format, args);
|
||||
va_end(args);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is an overload of push_warning_printf() accepting va_list as a list
|
||||
of format arguments.
|
||||
*/
|
||||
|
||||
void push_warning_printf_va_list(THD *thd,
|
||||
Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, va_list args)
|
||||
{
|
||||
char warning[MYSQL_ERRMSG_SIZE];
|
||||
|
||||
DBUG_ASSERT(code != 0);
|
||||
DBUG_ASSERT(format != NULL);
|
||||
|
||||
va_start(args,format);
|
||||
my_vsnprintf_ex(&my_charset_utf8mb3_general_ci, warning,
|
||||
sizeof(warning), format, args);
|
||||
va_end(args);
|
||||
push_warning(thd, level, code, warning);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1335,6 +1335,10 @@ void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, ...)
|
||||
ATTRIBUTE_FORMAT(printf, 4, 5);
|
||||
|
||||
void push_warning_printf_va_list(THD *thd,
|
||||
Sql_condition::enum_warning_level level,
|
||||
uint code, const char *format, va_list args);
|
||||
|
||||
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
|
||||
|
||||
size_t convert_error_message(char *to, size_t to_length,
|
||||
|
Loading…
x
Reference in New Issue
Block a user