List:Commits« Previous MessageNext Message »
From:Sneha Modi Date:November 22 2011 10:58am
Subject:bzr push into mysql-trunk branch (sneha.modi:3640 to 3641) Bug#11748731
View as plain text  
 3641 Sneha Modi	2011-11-22 [merge]
      Null merge of fix for Bug#11748731 from mysql-5.5 -> mysql-trunk

 3640 Olav Sandstaa	2011-11-22
                           + ORDER BY
      This crash occurred in the function copy_funcs() due to the array of
      functions pointers was not correctly terminated. This caused data
      following the func_ptr array to be interpreted as pointers to
      functions/items. The funct_ptr array given to copy_funcs() is stored
      inside the join's tmp_table_param structure's member called items_to_copy.
      In this case we had added one more entry than we had allocated space for
      so the value of the last entry was a pointer to a real item instead of a
      NULL pointer. The reason for why an extra pointer was added:
      1. When preparing the query we create Item objects for the where,
         group by and order by conditions. Since this query involves a view 
         several of these will be subclasses of Item_ref. In the function
         create_view_field() we create three Item_direct_view_ref
         objects representing the "v1.i2" for the two instances in the where
         clause and one for the order by clause. What is important to
         notice is that three separate Item_direct_view_ref objects are
         created but the ref pointer of all these points to a common
         (Item*) variable (which again points to the actual Item_field object).
      2. When optimizing the query we call optimize_conds() which will
         build_equal_items and among other things substitute fields with
         constants where possible. In this query it will use that "v1.i2 =
         211" to replace "v1.i2 > 7" with "211 > 7". To do this replacement
         it will use the Item class' compile and transform functions. The
         v1.i2 is represented by a subclass of Item_ref. The current code
         for Item_ref::compile() will first compile the item object found
         through the ref pointer. This will cause the field "i2" to be
         replaced by the constant field "211". Because of this the next step
         done by Item_ref::compile() is to replace the content in the ref* 
         variable to point to this constant field. This gives the correct 
         result for the item three that is being optimized but it causes an
         inconsistency for the ORDER BY clause. Since the
         Item_direct_view_ref created for the ORDER BY clause points to the
         same (Item*) variable as for the Item_direct_view_ref in the where
         clause, the update of the ref* in the Item_direct_view_ref of the
         where clause will also cause the same change to be done to the
         ORDER BY clause. So the result from running optimize_conds() is
         that the ORDER BY clause has been changed from "v1.i2" to the
         constant "211".
      3. When creating the temporary table used for the ORDER BY we will use
         the updated Item_direct_view_ref object that now points to the
         constant "211". Since this is a constant we do not allocate space
         for it in the items_to_copy array but still insert it into the
         array (causing the terminating NULL value to be written outside of
         the allocated array).
      Summary of the bug: Item_ref's compile() and transform() functions
      update the ref* variable when the item they reference changes. The
      ref* can be shared between multiple Item_ref objects. This causes all
      other Item_ref objects that share the common ref* variable to be
      wrongly updated.
      The fix is to change Item_ref's compile() and transform() functions to
      not update the ref* variable but instead they will return the new
      object as the result of the compile() or transform() operation.  The
      result of this change will be that when the object that the Item_ref
      references is replaced, the entire Item_ref objects will be replaced
      by the new object instead of doing changes to the Item_ref's ref
      The original substitution is wrong in yet another situation: If we have 
      two conditions combined with OR, substituting one field reference in one
      of the conditions would actually replace the same field in the second
      conditions, potentially causing a wrong result.
     @ mysql-test/r/join.result
        Test case for Bug#13102033 "CRASH IN COPY_FUNCS IN SQL_SELECT.CC ON JOIN
        + GROUP BY + ORDER BY"
     @ mysql-test/t/join.test
        Test case for Bug#13102033 "CRASH IN COPY_FUNCS IN SQL_SELECT.CC ON JOIN
        + GROUP BY + ORDER BY"
        This test contains two queries. The first query contains an ORDER
        BY on a field from a view that is also present in the WHERE
        condition. These will be represented by Item_direct_view_ref
        objects that share a commont *ref pointer. This query will test
        that when we do constant propagation on the Item_direct_view_ref
        of the WHERE condition it should not change the ORDER BY.
        The second query tests that if we have two conditions represented by 
        Item_direct_view_ref objects combined with OR, constant propagation
        for one of these will not replace the second condition and cause
        wrong result.
     @ sql/
        Change Item_ref's compile() and transform() functions from doing updates
        of the ref pointer when the object they references is replaced with a
        new object. Instead these functions will return the new object as the
        result of the compile/transform.

No bundle (reason: useless for push emails).
bzr push into mysql-trunk branch (sneha.modi:3640 to 3641) Bug#11748731Sneha Modi22 Nov