Skip to content

Commit b3ccaee

Browse files
author
Sreeharsha Ramanavarapu
committed
Bug #21346081: MEMORY LEAK IN CREATE_TMP_TABLE
Issue: ----- If an error occurs during the setup phase of the subquery materialization (used to compute an IN predicate), cleanup of temporary table does not happen. This creates valgrind errors. SOLUTION: --------- An error can be caused in the setup phase of subselect_hash_sj_engine, when a fix_fields() triggers the evaluation of a constant inner subquery because it returned more than one row. In such a scenario, the object is deleted. But before doing this, it is important to cleanup the object since it also contains a temporary table.
1 parent 529de87 commit b3ccaee

File tree

1 file changed

+19
-22
lines changed

1 file changed

+19
-22
lines changed

sql/item_subselect.cc

+19-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights
1+
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights
22
reserved.
33
44
This program is free software; you can redistribute it and/or modify
@@ -295,6 +295,7 @@ bool Item_in_subselect::finalize_materialization_transform(JOIN *join)
295295
For some reason we cannot use materialization for this IN predicate.
296296
Delete all materialization-related objects, and return error.
297297
*/
298+
new_engine->cleanup();
298299
delete new_engine;
299300
return true;
300301
}
@@ -2747,7 +2748,7 @@ bool subselect_single_select_engine::exec()
27472748
if (join->optimize())
27482749
{
27492750
optimize_error= true;
2750-
rc= join->error ? join->error : 1;
2751+
rc= 1;
27512752
goto exit;
27522753
}
27532754
if (item->engine_changed)
@@ -3560,21 +3561,20 @@ bool subselect_hash_sj_engine::setup(List<Item> *tmp_columns)
35603561
- here we initialize only those members that are used by
35613562
subselect_indexsubquery_engine, so these objects are incomplete.
35623563
*/
3563-
JOIN_TAB * const tmp_tab= new (thd->mem_root) JOIN_TAB;
3564-
if (tmp_tab == NULL)
3564+
if (!(tab= new (thd->mem_root) JOIN_TAB))
35653565
DBUG_RETURN(TRUE);
3566-
tmp_tab->table= tmp_table;
3567-
tmp_tab->ref.key= 0; /* The only temp table index. */
3568-
tmp_tab->ref.key_length= tmp_key->key_length;
3569-
if (!(tmp_tab->ref.key_buff=
3566+
tab->table= tmp_table;
3567+
tab->ref.key= 0; /* The only temp table index. */
3568+
tab->ref.key_length= tmp_key->key_length;
3569+
if (!(tab->ref.key_buff=
35703570
(uchar*) thd->calloc(ALIGN_SIZE(tmp_key->key_length) * 2)) ||
3571-
!(tmp_tab->ref.key_copy=
3571+
!(tab->ref.key_copy=
35723572
(store_key**) thd->alloc((sizeof(store_key*) * tmp_key_parts))) ||
3573-
!(tmp_tab->ref.items=
3573+
!(tab->ref.items=
35743574
(Item**) thd->alloc(sizeof(Item*) * tmp_key_parts)))
35753575
DBUG_RETURN(TRUE);
35763576

3577-
uchar *cur_ref_buff= tmp_tab->ref.key_buff;
3577+
uchar *cur_ref_buff= tab->ref.key_buff;
35783578

35793579
/*
35803580
Like semijoin-materialization-lookup (see create_subquery_equalities()),
@@ -3618,11 +3618,11 @@ bool subselect_hash_sj_engine::setup(List<Item> *tmp_columns)
36183618
/* Item for the corresponding field from the materialized temp table. */
36193619
Item_field *right_col_item;
36203620
const bool nullable= key_parts[part_no].field->real_maybe_null();
3621-
tmp_tab->ref.items[part_no]= item_in->left_expr->element_index(part_no);
3621+
tab->ref.items[part_no]= item_in->left_expr->element_index(part_no);
36223622

36233623
if (!(right_col_item= new Item_field(thd, context,
36243624
key_parts[part_no].field)) ||
3625-
!(eq_cond= new Item_func_eq(tmp_tab->ref.items[part_no],
3625+
!(eq_cond= new Item_func_eq(tab->ref.items[part_no],
36263626
right_col_item)) ||
36273627
((Item_cond_and*)cond)->add(eq_cond))
36283628
{
@@ -3631,7 +3631,7 @@ bool subselect_hash_sj_engine::setup(List<Item> *tmp_columns)
36313631
DBUG_RETURN(TRUE);
36323632
}
36333633

3634-
tmp_tab->ref.key_copy[part_no]=
3634+
tab->ref.key_copy[part_no]=
36353635
new store_key_item(thd, key_parts[part_no].field,
36363636
/* TODO:
36373637
the NULL byte is taken into account in
@@ -3642,34 +3642,31 @@ bool subselect_hash_sj_engine::setup(List<Item> *tmp_columns)
36423642
cur_ref_buff + (nullable ? 1 : 0),
36433643
nullable ? cur_ref_buff : 0,
36443644
key_parts[part_no].length,
3645-
tmp_tab->ref.items[part_no]);
3645+
tab->ref.items[part_no]);
36463646
if (nullable && // nullable column in tmp table,
36473647
// and UNKNOWN should not be interpreted as FALSE
36483648
!item_in->is_top_level_item())
36493649
{
36503650
// It must be the single column, or we wouldn't be here
36513651
DBUG_ASSERT(tmp_key_parts == 1);
36523652
// Be ready to search for NULL into inner column:
3653-
tmp_tab->ref.null_ref_key= cur_ref_buff;
3653+
tab->ref.null_ref_key= cur_ref_buff;
36543654
mat_table_has_nulls= NEX_UNKNOWN;
36553655
}
36563656
else
36573657
{
3658-
tmp_tab->ref.null_ref_key= NULL;
3658+
tab->ref.null_ref_key= NULL;
36593659
mat_table_has_nulls= NEX_IRRELEVANT_OR_FALSE;
36603660
}
36613661

36623662
cur_ref_buff+= key_parts[part_no].store_length;
36633663
}
3664-
tmp_tab->ref.key_err= 1;
3665-
tmp_tab->ref.key_parts= tmp_key_parts;
3664+
tab->ref.key_err= 1;
3665+
tab->ref.key_parts= tmp_key_parts;
36663666

36673667
if (cond->fix_fields(thd, &cond))
36683668
DBUG_RETURN(TRUE);
36693669

3670-
// Set 'tab' only when function cannot fail, because of assert in destructor
3671-
tab= tmp_tab;
3672-
36733670
/*
36743671
Create and optimize the JOIN that will be used to materialize
36753672
the subquery if not yet created.

0 commit comments

Comments
 (0)