List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:May 24 2011 9:36am
Subject:bzr commit into mysql-trunk branch (guilhem.bichot:3375) Bug#12582933
View as plain text  
#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#12582933Guilhem Bichot24 May