#At file:///home/mysql_src/bzrrepos_new/mysql-next-mr-opt-backporting/ based on revid:guilhem.bichot@stripped
3375 Guilhem Bichot 2011-05-24
Fix for Bug#12582933 "HARD TO REPRODUCE ASSERTION FAILURE IN SUBSELECT_HASH_SJ_ENGINE::~SUBSELECT_HASH":
set the 'tab' member only when object is fully constructed.
@ sql/item_subselect.cc
If out-of-memory it can happen that we leave subselect_hash_sj_engine::setup()
with an error code of 'true', but after setting 'tab'.
Then we are in this code:
if (((subselect_hash_sj_engine *) engine)
->setup(unit->get_unit_column_types()))
{
/*
For some reason we cannot use materialization for this IN predicate.
Delete all materialization-related objects, and return error.
*/
delete engine;
which calls the destructor. But subselect_hash_sj_engine::~subselect_hash_sj_engine
asserts that 'tab' is NULL.
Solution: set 'tab' later in setup() when we know it cannot fail.
modified:
sql/item_subselect.cc
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2011-04-06 11:13:33 +0000
+++ b/sql/item_subselect.cc 2011-05-24 09:36:11 +0000
@@ -3181,23 +3181,24 @@ bool subselect_hash_sj_engine::setup(Lis
- here we initialize only those members that are used by
subselect_uniquesubquery_engine, so these objects are incomplete.
*/
- if (!(tab= new (thd->mem_root) JOIN_TAB))
+ JOIN_TAB * const tmp_tab= new (thd->mem_root) JOIN_TAB;
+ if (tmp_tab == NULL)
DBUG_RETURN(TRUE);
- tab->table= tmp_table;
- tab->ref.key= 0; /* The only temp table index. */
- tab->ref.key_length= tmp_key->key_length;
- if (!(tab->ref.key_buff=
+ tmp_tab->table= tmp_table;
+ tmp_tab->ref.key= 0; /* The only temp table index. */
+ tmp_tab->ref.key_length= tmp_key->key_length;
+ if (!(tmp_tab->ref.key_buff=
(uchar*) thd->calloc(ALIGN_SIZE(tmp_key->key_length) * 2)) ||
- !(tab->ref.key_copy=
+ !(tmp_tab->ref.key_copy=
(store_key**) thd->alloc((sizeof(store_key*) *
(tmp_key_parts + 1)))) ||
- !(tab->ref.items=
+ !(tmp_tab->ref.items=
(Item**) thd->alloc(sizeof(Item*) * tmp_key_parts)))
DBUG_RETURN(TRUE);
KEY_PART_INFO *cur_key_part= tmp_key->key_part;
- store_key **ref_key= tab->ref.key_copy;
- uchar *cur_ref_buff= tab->ref.key_buff;
+ store_key **ref_key= tmp_tab->ref.key_copy;
+ uchar *cur_ref_buff= tmp_tab->ref.key_buff;
/*
Create an artificial condition to post-filter those rows matched by index
@@ -3235,10 +3236,10 @@ bool subselect_hash_sj_engine::setup(Lis
/* Item for the corresponding field from the materialized temp table. */
Item_field *right_col_item;
int null_count= test(cur_key_part->field->real_maybe_null());
- tab->ref.items[i]= item_in->left_expr->element_index(i);
+ tmp_tab->ref.items[i]= item_in->left_expr->element_index(i);
if (!(right_col_item= new Item_field(thd, context, cur_key_part->field)) ||
- !(eq_cond= new Item_func_eq(tab->ref.items[i], right_col_item)) ||
+ !(eq_cond= new Item_func_eq(tmp_tab->ref.items[i], right_col_item)) ||
((Item_cond_and*)cond)->add(eq_cond))
{
delete cond;
@@ -3255,16 +3256,19 @@ bool subselect_hash_sj_engine::setup(Lis
*/
cur_ref_buff + null_count,
null_count ? cur_ref_buff : 0,
- cur_key_part->length, tab->ref.items[i]);
+ cur_key_part->length, tmp_tab->ref.items[i]);
cur_ref_buff+= cur_key_part->store_length;
}
*ref_key= NULL; /* End marker. */
- tab->ref.key_err= 1;
- tab->ref.key_parts= tmp_key_parts;
+ tmp_tab->ref.key_err= 1;
+ tmp_tab->ref.key_parts= tmp_key_parts;
if (cond->fix_fields(thd, &cond))
DBUG_RETURN(TRUE);
+ // Set 'tab' only when function cannot fail, because of assert in destructor
+ tab= tmp_tab;
+
/*
Create and optimize the JOIN that will be used to materialize
the subquery if not yet created.
Attachment: [text/bzr-bundle] bzr/guilhem.bichot@oracle.com-20110524093611-uusfmcwjyxn69u61.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk branch (guilhem.bichot:3375) Bug#12582933 | Guilhem Bichot | 24 May |