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.
This commit is contained in:
parent
a290b807e8
commit
497d86276f
@ -1123,5 +1123,3 @@ PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t";
|
|||||||
EXECUTE stmt;
|
EXECUTE stmt;
|
||||||
EXECUTE stmt;
|
EXECUTE stmt;
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
|
||||||
|
@ -4956,7 +4956,8 @@ protected:
|
|||||||
SELECT_LEX_UNIT *unit;
|
SELECT_LEX_UNIT *unit;
|
||||||
/* Something used only by the parser: */
|
/* Something used only by the parser: */
|
||||||
public:
|
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; }
|
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
|
||||||
virtual ~select_result() {};
|
virtual ~select_result() {};
|
||||||
/**
|
/**
|
||||||
@ -5528,7 +5529,6 @@ public:
|
|||||||
TMP_TABLE_PARAM tmp_table_param;
|
TMP_TABLE_PARAM tmp_table_param;
|
||||||
int write_err; /* Error code from the last send_data->ha_write_row call. */
|
int write_err; /* Error code from the last send_data->ha_write_row call. */
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
ha_rows records;
|
|
||||||
|
|
||||||
select_unit(THD *thd_arg):
|
select_unit(THD *thd_arg):
|
||||||
select_result_interceptor(thd_arg),
|
select_result_interceptor(thd_arg),
|
||||||
@ -5566,7 +5566,6 @@ public:
|
|||||||
curr_sel= UINT_MAX;
|
curr_sel= UINT_MAX;
|
||||||
step= UNION_TYPE;
|
step= UNION_TYPE;
|
||||||
write_err= 0;
|
write_err= 0;
|
||||||
records= 0;
|
|
||||||
}
|
}
|
||||||
void change_select();
|
void change_select();
|
||||||
};
|
};
|
||||||
|
@ -4678,18 +4678,18 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
select_unit *result= (select_unit*)unit->result;
|
select_result *result= unit->result;
|
||||||
switch (linkage)
|
switch (linkage)
|
||||||
{
|
{
|
||||||
case INTERSECT_TYPE:
|
case INTERSECT_TYPE:
|
||||||
// result of intersect can't be more then one of components
|
// 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:
|
case EXCEPT_TYPE:
|
||||||
// in worse case none of record will be removed
|
// in worse case none of record will be removed
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// usual UNION
|
// usual UNION
|
||||||
result->records+= records;
|
result->est_records+= records;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8334,7 +8334,7 @@ int TABLE_LIST::fetch_number_of_rows()
|
|||||||
}
|
}
|
||||||
if (is_materialized_derived() && !fill_me)
|
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);
|
set_if_bigger(table->file->stats.records, 2);
|
||||||
table->used_stat_records= table->file->stats.records;
|
table->used_stat_records= table->file->stats.records;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user