Commit 47f0135d authored by Igor Babaev's avatar Igor Babaev

MDEV-32245 Test from subselect.test fails with statement memory protection

With this patch st_select_lex::ref_pointer_array is never re-allocated.

Approved by Oleksandr Byelkin <sanja@mariadb.com>
parent 50a2e8b1
...@@ -2413,6 +2413,7 @@ void st_select_lex::init_query() ...@@ -2413,6 +2413,7 @@ void st_select_lex::init_query()
max_equal_elems= 0; max_equal_elems= 0;
ref_pointer_array.reset(); ref_pointer_array.reset();
select_n_where_fields= 0; select_n_where_fields= 0;
order_group_num= 0;
select_n_reserved= 0; select_n_reserved= 0;
select_n_having_items= 0; select_n_having_items= 0;
n_sum_items= 0; n_sum_items= 0;
...@@ -2978,46 +2979,40 @@ ulong st_select_lex::get_table_join_options() ...@@ -2978,46 +2979,40 @@ ulong st_select_lex::get_table_join_options()
} }
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) uint st_select_lex::get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg)
{ {
if (!((options & SELECT_DISTINCT) && !group_list.elements)) if (!((options & SELECT_DISTINCT) && !group_list.elements))
hidden_bit_fields= 0; hidden_bit_fields= 0;
// find_order_in_list() may need some extra space, so multiply by two. if (!order_group_num)
order_group_num*= 2; order_group_num= order_group_num_arg;
/* /*
We have to create array in prepared statement memory if it is a find_order_in_list() may need some extra space,
prepared statement so multiply order_group_num by 2
*/ */
Query_arena *arena= thd->stmt_arena; uint n= n_sum_items +
const size_t n_elems= (n_sum_items + n_child_sum_items +
n_child_sum_items + item_list.elements +
item_list.elements + select_n_reserved +
select_n_reserved + select_n_having_items +
select_n_having_items + select_n_where_fields +
select_n_where_fields + order_group_num * 2 +
order_group_num + hidden_bit_fields +
hidden_bit_fields + fields_in_window_functions;
fields_in_window_functions) * (size_t) 5; return n;
DBUG_ASSERT(n_elems % 5 == 0); }
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
uint n_elems= get_cardinality_of_ref_ptrs_slice(order_group_num) * 5;
if (!ref_pointer_array.is_null()) if (!ref_pointer_array.is_null())
{ return false;
/* Item **array= static_cast<Item**>(thd->stmt_arena->alloc(sizeof(Item*) *
We need to take 'n_sum_items' into account when allocating the array, n_elems));
and this may actually increase during the optimization phase due to
MIN/MAX rewrite in Item_in_subselect::single_value_transformer.
In the usual case we can reuse the array from the prepare phase.
If we need a bigger array, we must allocate a new one.
*/
if (ref_pointer_array.size() >= n_elems)
return false;
}
Item **array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems));
if (likely(array != NULL)) if (likely(array != NULL))
ref_pointer_array= Ref_ptr_array(array, n_elems); ref_pointer_array= Ref_ptr_array(array, n_elems);
return array == NULL; return array == NULL;
} }
......
...@@ -1176,6 +1176,8 @@ class st_select_lex: public st_select_lex_node ...@@ -1176,6 +1176,8 @@ class st_select_lex: public st_select_lex_node
and all inner subselects. and all inner subselects.
*/ */
uint select_n_where_fields; uint select_n_where_fields;
/* Total number of elements in group by and order by lists */
uint order_group_num;
/* reserved for exists 2 in */ /* reserved for exists 2 in */
uint select_n_reserved; uint select_n_reserved;
/* /*
...@@ -1416,6 +1418,7 @@ class st_select_lex: public st_select_lex_node ...@@ -1416,6 +1418,7 @@ class st_select_lex: public st_select_lex_node
init_select(); init_select();
} }
bool setup_ref_array(THD *thd, uint order_group_num); bool setup_ref_array(THD *thd, uint order_group_num);
uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg);
void print(THD *thd, String *str, enum_query_type query_type); void print(THD *thd, String *str, enum_query_type query_type);
void print_item_list(THD *thd, String *str, enum_query_type query_type); void print_item_list(THD *thd, String *str, enum_query_type query_type);
void print_set_clause(THD *thd, String *str, enum_query_type query_type); void print_set_clause(THD *thd, String *str, enum_query_type query_type);
......
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