diff --git a/mysql-test/main/opt_hints_join_order.result b/mysql-test/main/opt_hints_join_order.result index 6c8c3a5cf6e..1d4c30e33b4 100644 --- a/mysql-test/main/opt_hints_join_order.result +++ b/mysql-test/main/opt_hints_join_order.result @@ -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; diff --git a/mysql-test/main/opt_hints_join_order.test b/mysql-test/main/opt_hints_join_order.test index fabe20ea1e4..53f79897345 100644 --- a/mysql-test/main/opt_hints_join_order.test +++ b/mysql-test/main/opt_hints_join_order.test @@ -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; diff --git a/sql/opt_hints.cc b/sql/opt_hints.cc index 1a6038aa17c..c57e94ce50a 100644 --- a/sql/opt_hints.cc +++ b/sql/opt_hints.cc @@ -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(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()); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index d054e160c64..33596265da4 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -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; } diff --git a/sql/sql_error.h b/sql/sql_error.h index 984ed227ea9..68cfde8533c 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -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,