diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index df25b8d71d2bc..1eed8e39dec3c 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -11156,4 +11156,25 @@ valid_json json_detailed(json_extract(trace,'$**.expanded_query')) 1 ["Error: failed to escape query string for JSON output"] SET NAMES DEFAULT; set optimizer_trace=@saved_optimizer_trace; +# +# MDEV-24658: Optimizer trace reads a column not marked for read +# +set @saved_optimizer_trace=@@optimizer_trace; +set optimizer_trace='enabled=on'; +create table t1 (i int); +create table t2 (c int); +insert into t2 values (1); +select 1 from (select 1 in (select 1 from t1 where (select 1 from t2 having c)) from t2) as z; +1 +1 +select json_valid(trace) as valid_json, +json_detailed(json_extract(trace, '$**.original_condition')) as original_condition +from information_schema.optimizer_trace; +valid_json original_condition +1 [ + "(/* select#4 */ select 1 from t2 having 1 <> 0)", + "1 <> 0" +] +drop table t1, t2; +set optimizer_trace=@saved_optimizer_trace; # End of 10.11 tests diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index a23bef4b26a3c..7cd5376d44c05 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -1310,4 +1310,34 @@ SET NAMES DEFAULT; set optimizer_trace=@saved_optimizer_trace; --enable_view_protocol +--echo # +--echo # MDEV-24658: Optimizer trace reads a column not marked for read +--echo # + +set @saved_optimizer_trace=@@optimizer_trace; +set optimizer_trace='enabled=on'; +# Disable the view and ps protocols here. The view protocol +# renumbers the block printed in the condition. The ps protocol keeps +# condition processing in the prepare phase, so the trace read here +# has no original condition. +--disable_view_protocol +--disable_ps_protocol + +create table t1 (i int); +create table t2 (c int); +insert into t2 values (1); + +# t2 has one row, so it is a const/system table whose column c is a known +# constant. A table with more than one row can be constant only through a +# unique key equality, and then the read column stays in the read set. +select 1 from (select 1 in (select 1 from t1 where (select 1 from t2 having c)) from t2) as z; +select json_valid(trace) as valid_json, + json_detailed(json_extract(trace, '$**.original_condition')) as original_condition + from information_schema.optimizer_trace; + +drop table t1, t2; +--enable_ps_protocol +--enable_view_protocol +set optimizer_trace=@saved_optimizer_trace; + --echo # End of 10.11 tests diff --git a/sql/field.cc b/sql/field.cc index 22e2d1e3c043f..a30e8daf670f6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -60,7 +60,12 @@ const char field_separator=','; // Column marked for read or the field set to read out of record[0] bool Field::marked_for_read() const { + /* + (1) A const table's row is read during optimization and remains + materialized in record[0], so reading it is safe. + */ return !table || + table->const_table || // (1) (!table->read_set || bitmap_is_set(table->read_set, field_index) || (!(ptr >= table->record[0] &&