Commit 497d8627 authored by Igor Babaev's avatar Igor Babaev

MDEV-17017 Explain for query using derived table specified with

           a table value constructor shows wrong number of rows

This is another attempt to fix this bug. The previous patch did not take
into account that a transformation for ALL/ANY subqueries could be applied
to the materialized table that wrapped the table value constructor used as
a specification of the subselect used an ALL/ANY subquery. In this case
the result of the derived table used a sink of the class select_subselect
rather than of the class select_unit. Thus the previous fix could cause
memory overwrites when running EXPLAIN for queries with table value
constructors in ALL/ANY subselects.
parent a290b807
......@@ -1123,5 +1123,3 @@ PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
......@@ -4956,7 +4956,8 @@ class select_result :public select_result_sink
SELECT_LEX_UNIT *unit;
/* Something used only by the parser: */
public:
select_result(THD *thd_arg): select_result_sink(thd_arg) {}
ha_rows est_records; /* estimated number of records in the result */
select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {}
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
virtual ~select_result() {};
/**
......@@ -5528,7 +5529,6 @@ class select_unit :public select_result_interceptor
TMP_TABLE_PARAM tmp_table_param;
int write_err; /* Error code from the last send_data->ha_write_row call. */
TABLE *table;
ha_rows records;
select_unit(THD *thd_arg):
select_result_interceptor(thd_arg),
......@@ -5566,7 +5566,6 @@ class select_unit :public select_result_interceptor
curr_sel= UINT_MAX;
step= UNION_TYPE;
write_err= 0;
records= 0;
}
void change_select();
};
......
......@@ -4678,18 +4678,18 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
return;
}
select_unit *result= (select_unit*)unit->result;
select_result *result= unit->result;
switch (linkage)
{
case INTERSECT_TYPE:
// result of intersect can't be more then one of components
set_if_smaller(result->records, records);
set_if_smaller(result->est_records, records);
case EXCEPT_TYPE:
// in worse case none of record will be removed
break;
default:
// usual UNION
result->records+= records;
result->est_records+= records;
break;
}
}
......
......@@ -8334,7 +8334,7 @@ int TABLE_LIST::fetch_number_of_rows()
}
if (is_materialized_derived() && !fill_me)
{
table->file->stats.records= ((select_unit*)(get_unit()->result))->records;
table->file->stats.records= get_unit()->result->est_records;
set_if_bigger(table->file->stats.records, 2);
table->used_stat_records= table->file->stats.records;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment