MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Jorgen Loland Date:July 1 2010 9:35am
Subject:bzr commit into mysql-next-mr-bugfixing branch (jorgen.loland:3278) Bug#54511
View as plain text  
#At file:///localhome/jl208045/mysql/mysql-next-mr-bugfixing/ based on revid:alfranio.correia@stripped

 3278 Jorgen Loland	2010-07-01
      Bug#54511: Assertion failed: cache != 0L in file 
                 sql_select.cc::sub_select_cache on HAVING
      
      Code cleanup followup patch: 
       * remove JOIN::having_value and JOIN::cond_value and use 
         select_lex variables with same name instead to avoid 
         duplication of information.
       * Add documentation about the relationship between 
         st_select_lex::{where|having} and JOIN::{conds|having} 
       * Add documentation about the relationship between 
         st_select_lex::{having|cond}_value and 
         JOIN::{conds|having}
     @ sql/sql_lex.h
        Add documentation to st_select_lex::having_value and cond_value
     @ sql/sql_select.cc
        Remove usage of JOIN::having_value and cond_value and use 
        select_lex variables with same name instead to avoid duplicate
        variables. Also documented optimize_cond()
     @ sql/sql_select.h
        Remove variables JOIN::having_value and cond_value and use 
        select_lex variables with same name instead to avoid duplicate
        variables. Also documented the relationship between 
        JOIN::{having|conds}, st_select_lex::{where|having} and 
        st_select_lex::{cond|having}_value.

    modified:
      sql/sql_lex.h
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-06-26 07:43:14 +0000
+++ b/sql/sql_lex.h	2010-07-01 09:35:45 +0000
@@ -639,7 +639,14 @@ public:
   Item *where, *having;                         /* WHERE & HAVING clauses */
   Item *prep_where; /* saved WHERE clause for prepared statement processing */
   Item *prep_having;/* saved HAVING clause for prepared statement processing */
-  /* Saved values of the WHERE and HAVING clauses*/
+  /**
+    Saved values of the WHERE and HAVING clauses. Allowed values are: 
+     - COND_UNDEF if the condition was not specified in the query or if it 
+       has not been optimized yet
+     - COND_TRUE if the condition is always true
+     - COND_FALSE if the condition is impossible
+     - COND_OK otherwise
+  */
   Item::cond_result cond_value, having_value;
   /* point on lex in which it was created, used in view subquery detection */
   LEX *parent_lex;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-06-26 07:43:14 +0000
+++ b/sql/sql_select.cc	2010-07-01 09:35:45 +0000
@@ -898,7 +898,7 @@ JOIN::optimize()
       thd->restore_active_arena(arena, &backup);
   }
 
-  conds= optimize_cond(this, conds, join_list, &cond_value);   
+  conds= optimize_cond(this, conds, join_list, &select_lex->cond_value);
   if (thd->is_error())
   {
     error= 1;
@@ -907,24 +907,20 @@ JOIN::optimize()
   }
 
   {
-    having= optimize_cond(this, having, join_list, &having_value);
+    having= optimize_cond(this, having, join_list, &select_lex->having_value);
     if (thd->is_error())
     {
       error= 1;
       DBUG_PRINT("error",("Error from optimize_cond"));
       DBUG_RETURN(1);
     }
-    if (select_lex->where)
-      select_lex->cond_value= cond_value;
-    if (select_lex->having)
-      select_lex->having_value= having_value;
-
-    if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE || 
+    if (select_lex->cond_value == Item::COND_FALSE || 
+        select_lex->having_value == Item::COND_FALSE || 
         (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
     {						/* Impossible cond */
-      DBUG_PRINT("info", (having_value == Item::COND_FALSE ? 
+      DBUG_PRINT("info", (select_lex->having_value == Item::COND_FALSE ? 
                             "Impossible HAVING" : "Impossible WHERE"));
-      zero_result_cause=  having_value == Item::COND_FALSE ?
+      zero_result_cause=  select_lex->having_value == Item::COND_FALSE ?
                            "Impossible HAVING" : "Impossible WHERE";
       tables= 0;
       error= 0;
@@ -1149,10 +1145,9 @@ JOIN::optimize()
   if (having && const_table_map)
   {
     having->update_used_tables();
-    having= remove_eq_conds(thd, having, &having_value);
-    if (having_value == Item::COND_FALSE)
+    having= remove_eq_conds(thd, having, &select_lex->having_value);
+    if (select_lex->having_value == Item::COND_FALSE)
     {
-      having= new Item_int((longlong) 0,1);
       zero_result_cause= "Impossible HAVING noticed after reading const tables";
       error= 0;
       DBUG_RETURN(0);
@@ -1823,8 +1818,8 @@ JOIN::exec()
         In this case JOIN::exec must check for JOIN::having_value, in the
         same way it checks for JOIN::cond_value.
       */
-      if (cond_value != Item::COND_FALSE &&
-          having_value != Item::COND_FALSE &&
+      if (select_lex->cond_value != Item::COND_FALSE &&
+          select_lex->having_value != Item::COND_FALSE &&
           (!conds || conds->val_int()) &&
           (!having || having->val_int()))
       {
@@ -9278,6 +9273,28 @@ static void restore_prev_nj_state(JOIN_T
 }
 
 
+/**
+  Optimize conditions by 
+
+     a) applying transitivity to build multiple equality predicates
+        (MEP): if x=y and y=z the MEP x=y=z is built. 
+     b) apply constants where possible. If the value of x is known to be
+        42, x is replaced with a constant of value 42. By transitivity, this
+        also applies to MEPs, so the MEP in a) will become 42=x=y=z.
+     c) remove conditions that are impossible or always true
+  
+  @param      join         pointer to the structure providing all context info
+                           for the query
+  @param      conds        conditions to optimize
+  @param      join_list    list of join tables to which the condition
+                           refers to
+  @param[out] cond_value   Not changed if conds was empty 
+                           COND_TRUE if conds is always true
+                           COND_FALSE if conds is impossible
+                           COND_OK otherwise
+
+  @return optimized conditions
+*/
 static COND *
 optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
               Item::cond_result *cond_value)
@@ -9285,9 +9302,7 @@ optimize_cond(JOIN *join, COND *conds, L
   THD *thd= join->thd;
   DBUG_ENTER("optimize_cond");
 
-  if (!conds)
-    *cond_value= Item::COND_TRUE;
-  else
+  if (conds)
   {
     /* 
       Build all multiple equality predicates and eliminate equality

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2010-06-22 20:57:34 +0000
+++ b/sql/sql_select.h	2010-07-01 09:35:45 +0000
@@ -349,9 +349,6 @@ public:
   /** second copy of sumfuncs (for queries with 2 temporary tables */
   Item_sum  **sum_funcs2, ***sum_funcs_end2;
   Procedure *procedure;
-  Item	    *having;
-  Item      *tmp_having; ///< To store having when processed temporary table
-  Item      *having_history; ///< Store having for explain
   ulonglong  select_options;
   select_result *result;
   TMP_TABLE_PARAM tmp_table_param;
@@ -418,7 +415,6 @@ public:
 
   bool need_tmp, hidden_group_fields;
   DYNAMIC_ARRAY keyuse;
-  Item::cond_result cond_value, having_value;
   List<Item> all_fields; ///< to store all fields that used in query
   ///Above list changed to use temporary table
   List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
@@ -429,8 +425,28 @@ public:
   int error;
 
   ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
-  COND *conds;                            // ---"---
-  Item *conds_history;                    // store WHERE for explain
+  /** 
+    JOIN::having is initially equal to select_lex->having, but may
+    later be changed by optimizations performed by JOIN.
+    The relationship between the JOIN::having condition and the
+    associated variable select_lex->having_value is so that
+    having_value can be:
+     - COND_UNDEF if a having clause was not specified in the query or
+       if it has not been optimized yet
+     - COND_TRUE if the having clause is always true, in which case
+       JOIN::having is set to NULL.
+     - COND_FALSE if the having clause is impossible, in which case
+       JOIN::having is set to NULL
+     - COND_OK otherwise, meaning that the having clause needs to be
+       further evaluated
+    All of the above also applies to the conds/select_lex->cond_value
+    pair.
+  */
+  COND       *conds;                      ///< The where clause item tree
+  Item       *having;                     ///< The having clause item tree
+  Item       *conds_history;              ///< store WHERE for explain
+  Item       *having_history;             ///< Store having for explain
+  Item       *tmp_having; ///< To store having when processed temporary table
   TABLE_LIST *tables_list;           ///<hold 'tables' parameter of mysql_select
   List<TABLE_LIST> *join_list;       ///< list of joined tables in reverse order
   COND_EQUAL *cond_equal;
@@ -573,7 +589,7 @@ public:
   bool send_row_on_empty_set()
   {
     return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
-	    !group_list && having_value != Item::COND_FALSE);
+	    !group_list && select_lex->having_value != Item::COND_FALSE);
   }
   bool change_result(select_result *result);
   bool is_top_level_join() const


Attachment: [text/bzr-bundle] bzr/jorgen.loland@sun.com-20100701093545-a5u6murhuocqnxda.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (jorgen.loland:3278) Bug#54511Jorgen Loland1 Jul
  • Re: bzr commit into mysql-next-mr-bugfixing branch(jorgen.loland:3278) Bug#54511Guilhem Bichot1 Jul