From c688efac8bbbdb603c05ac01db80edb0d8c47c4e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 14 Oct 2026 22:27:55 +0200 Subject: [PATCH] MDEV-41541 replay mismatch warnings write binary numbers print numbers in warnings messages as strings, not as binary bytes Assisted-by: Claude:claude-opus-5-5 --- .../main/opt_context_load_stats_basic.result | 27 +++++++++++++++++++ .../main/opt_context_load_stats_basic.test | 15 +++++++++++ sql/opt_context_store_replay.cc | 10 +++---- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/opt_context_load_stats_basic.result b/mysql-test/main/opt_context_load_stats_basic.result index 742817c5c17..e4ed80a9583 100644 --- a/mysql-test/main/opt_context_load_stats_basic.result +++ b/mysql-test/main/opt_context_load_stats_basic.result @@ -480,4 +480,31 @@ select hex(json_extract(@opt_context, '$.tables[0].indexes[0].rec_per_key[1]') + hex(json_extract(@opt_context, '$.tables[0].indexes[0].rec_per_key[1]') + 0.0) 0 drop table t1; +# +# Replay mismatch warnings print numbers as text +# +set optimizer_replay_context=''; +create table t1 (a int, b int, key(a)); +insert into t1 select seq%10, seq from seq_1_to_100; +explain select t1.b from t1, t1 t2 where t1.a = t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 100 Using where +1 SIMPLE t2 ref a a 5 test.t1.a 10 Using index +set @opt_context= +(select REGEXP_SUBSTR( +context, +'(?<=set @opt_context=\')([\n\r].*)*(?=\'\;#opt_context_ends)') +from information_schema.optimizer_context); +set @opt_context_mismatch= json_remove(@opt_context, +'$.tables[0].cost_for_index_read_calls'); +set optimizer_replay_context='opt_context_mismatch'; +explain select t1.b from t1, t1 t2 where t1.a = t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 100 Using where +1 SIMPLE t2 ref a a 5 test.t1.a 10 Using index +Warnings: +Warning 4270 Failed to match the stats from replay context with the optimizer stats: test.t1 with key_number:0, records:10, eq_ref:0 doesn't exist in cost_for_index_read_calls +Warning 4270 Failed to match the stats from replay context with the optimizer stats: test.t1 with key_number:0, records:10, eq_ref:0 doesn't exist in cost_for_index_read_calls +set optimizer_replay_context=''; +drop table t1; # End of 13.1 tests diff --git a/mysql-test/main/opt_context_load_stats_basic.test b/mysql-test/main/opt_context_load_stats_basic.test index 9306ade28ae..edcefa73f26 100644 --- a/mysql-test/main/opt_context_load_stats_basic.test +++ b/mysql-test/main/opt_context_load_stats_basic.test @@ -310,4 +310,19 @@ select * from t1 where a<3 and b>6; select hex(json_extract(@opt_context, '$.tables[0].indexes[0].rec_per_key[1]') + 0.0); drop table t1; +--echo # +--echo # Replay mismatch warnings print numbers as text +--echo # +set optimizer_replay_context=''; +create table t1 (a int, b int, key(a)); +insert into t1 select seq%10, seq from seq_1_to_100; +explain select t1.b from t1, t1 t2 where t1.a = t2.a; +--source include/opt_context_save_in_var.inc +set @opt_context_mismatch= json_remove(@opt_context, + '$.tables[0].cost_for_index_read_calls'); +set optimizer_replay_context='opt_context_mismatch'; +explain select t1.b from t1, t1 t2 where t1.a = t2.a; +set optimizer_replay_context=''; +drop table t1; + --echo # End of 13.1 tests diff --git a/sql/opt_context_store_replay.cc b/sql/opt_context_store_replay.cc index fe4a8335570..a44e10bf5ea 100644 --- a/sql/opt_context_store_replay.cc +++ b/sql/opt_context_store_replay.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2025, MariaDB + Copyright (c) 2025, 2026, MariaDB plc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1879,11 +1879,11 @@ bool Optimizer_context_replay::infuse_cost_for_index_read(const TABLE *tbl, String warn_msg(256); warn_msg.append(tbl_name); warn_msg.append(STRING_WITH_LEN(" with key_number:")); - warn_msg.q_append(keynr); + warn_msg.append_ulonglong(keynr); warn_msg.append(STRING_WITH_LEN(", records:")); - warn_msg.q_append_int64(records); + warn_msg.append_ulonglong(records); warn_msg.append(STRING_WITH_LEN(", eq_ref:")); - warn_msg.append(eq_ref); + warn_msg.append(eq_ref ? '1' : '0'); push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, ER_JSON_OPTIMIZER_REPLAY_CONTEXT_MATCH_FAILED, @@ -1997,7 +1997,7 @@ bool Optimizer_context_replay::infuse_records_in_range( String warn_msg(256); warn_msg.append(tbl_name); warn_msg.append(STRING_WITH_LEN(" with key_number:")); - warn_msg.q_append(keynr); + warn_msg.append_ulonglong(keynr); warn_msg.append(STRING_WITH_LEN(" with min_key:")); warn_msg.append(min_key); warn_msg.append(STRING_WITH_LEN(" with max_key:"));