List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:April 5 2011 7:34am
Subject:bzr commit into mysql-trunk branch (guilhem.bichot:3286)
View as plain text  
#At file:///home/mysql_src/bzrrepos_new/mysql-next-mr-opt-backporting-wl4800/ based on revid:guilhem.bichot@stripped

 3286 Guilhem Bichot	2011-04-05
      review comments. Also see change in sql_array.h.

    modified:
      WL4800_TODO.txt
      include/my_sys.h
      mysys/my_alloc.c
      mysys/my_getopt.c
      sql/item_cmpfunc.h
      sql/item_subselect.cc
      sql/opt_range.cc
      sql/opt_trace.cc
      sql/opt_trace.h
      sql/opt_trace2server.cc
      sql/sql_array.h
      sql/sql_delete.cc
      sql/sql_select.cc
      unittest/gunit/opt_trace-t.cc
=== modified file 'WL4800_TODO.txt'
--- a/WL4800_TODO.txt	2011-04-04 13:56:54 +0000
+++ b/WL4800_TODO.txt	2011-04-05 07:34:13 +0000
@@ -17,7 +17,8 @@ not forget to bump the version when doin
 changes? any little change? maybe).
 
 Coding style:
-Make sure long code lines are wrapped.
+Make sure long code lines are wrapped, and no trailing white space is
+added.
 
 Misc security issues as discussed already.
 
@@ -46,3 +47,6 @@ developer notices a syntax error when ru
 sql_print_warning() is an idea.
 
 get a review for http://lists.mysql.com/commits/133482
+
+Move Buffer out of Opt_trace_stmt, in unnamed namespace in
+opt_trace.cc.

=== modified file 'include/my_sys.h'
--- a/include/my_sys.h	2011-03-21 17:55:41 +0000
+++ b/include/my_sys.h	2011-04-05 07:34:13 +0000
@@ -164,7 +164,9 @@ extern char *my_strndup(const char *from
 #else
 #define TRASH_SUB(A,B)
 #endif
-#define TRASH(A,B) do{TRASH_SUB(A,B); MEM_CHECK_ADDRESSABLE(A,B);MEM_UNDEFINED(A,B);} while (0)
+#define TRASH(A,B) do {                                                 \
+    TRASH_SUB(A,B); MEM_CHECK_ADDRESSABLE(A,B); MEM_UNDEFINED(A,B);     \
+  } while (0)
 #if defined(ENABLED_DEBUG_SYNC)
 extern void (*debug_sync_C_callback_ptr)(const char *, size_t);
 #define DEBUG_SYNC_C(_sync_point_name_) do {                            \

=== modified file 'mysys/my_alloc.c'
--- a/mysys/my_alloc.c	2011-02-16 15:06:06 +0000
+++ b/mysys/my_alloc.c	2011-04-05 07:34:13 +0000
@@ -72,7 +72,7 @@ void init_alloc_root(MEM_ROOT *mem_root,
   DBUG_VOID_RETURN;
 }
 
-
+/** This is a no-op unless the build is debug or for Valgrind. */
 #define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
 
 

=== modified file 'mysys/my_getopt.c'
--- a/mysys/my_getopt.c	2011-03-21 17:55:41 +0000
+++ b/mysys/my_getopt.c	2011-04-05 07:34:13 +0000
@@ -954,7 +954,7 @@ longlong getopt_ll_limit_value(longlong 
 
   if (num > max_of_type)
   {
-    num= (longlong) max_of_type;
+    num= max_of_type;
     adjusted= TRUE;
   }
 

=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h	2011-03-21 17:55:41 +0000
+++ b/sql/item_cmpfunc.h	2011-04-05 07:34:13 +0000
@@ -510,8 +510,8 @@ public:
      @param trig_type_arg type of 'f'
   */
   Item_func_trig_cond(Item *a, bool *f, struct st_join_table *tab,
-                      enum_trig_type trig_type_arg) :
-  Item_bool_func(a), trig_var(f), trig_tab(tab), trig_type(trig_type_arg)
+                      enum_trig_type trig_type_arg)
+    : Item_bool_func(a), trig_var(f), trig_tab(tab), trig_type(trig_type_arg)
   {}
   longlong val_int() { return *trig_var ? args[0]->val_int() : 1; }
   enum Functype functype() const { return TRIG_COND_FUNC; };

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2011-03-21 17:55:41 +0000
+++ b/sql/item_subselect.cc	2011-04-05 07:34:13 +0000
@@ -317,7 +317,7 @@ bool Item_subselect::exec()
 
   Opt_trace_object trace_wrapper(trace);
   Opt_trace_object trace_exec(trace, "subselect_execution");
-  opt_trace_add_select_number(&trace_exec, get_select_lex()->select_number);
+  trace_exec.add_select_number(get_select_lex()->select_number);
   Opt_trace_array trace_steps(trace, "steps");
 #endif
 
@@ -1323,7 +1323,8 @@ Item_in_subselect::single_value_in_to_ex
         within a trig_cond.
       */
       item= new Item_func_trig_cond(item, get_cond_guard(0), NULL,
-                                    Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL);
+                                    Item_func_trig_cond::
+                                    OUTER_FIELD_IS_NOT_NULL);
     }
     
     /*
@@ -1367,7 +1368,8 @@ Item_in_subselect::single_value_in_to_ex
         {
           if (!(having= new Item_func_trig_cond(having,
                                                 get_cond_guard(0), NULL,
-                                                Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                                Item_func_trig_cond::
+                                                OUTER_FIELD_IS_NOT_NULL)))
             DBUG_RETURN(RES_ERROR);
         }
 	/*
@@ -1397,7 +1399,8 @@ Item_in_subselect::single_value_in_to_ex
       if (!abort_on_null && left_expr->maybe_null)
       {
         if (!(item= new Item_func_trig_cond(item, get_cond_guard(0), NULL,
-                                            Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                            Item_func_trig_cond::
+                                            OUTER_FIELD_IS_NOT_NULL)))
           DBUG_RETURN(RES_ERROR);
       }
       /*
@@ -1441,7 +1444,9 @@ Item_in_subselect::single_value_in_to_ex
         {
           if (!(new_having= new Item_func_trig_cond(new_having,
                                                     get_cond_guard(0),
-                                                    NULL, Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                                    NULL,
+                                                    Item_func_trig_cond::
+                                                    OUTER_FIELD_IS_NOT_NULL)))
             DBUG_RETURN(RES_ERROR);
         }
         new_having->name= (char*)in_having_cond;
@@ -1630,7 +1635,8 @@ Item_in_subselect::row_value_in_to_exist
       if (!abort_on_null && left_expr->element_index(i)->maybe_null)
       {
         if (!(col_item= new Item_func_trig_cond(col_item, get_cond_guard(i),
-                                                NULL, Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                                NULL, Item_func_trig_cond::
+                                                OUTER_FIELD_IS_NOT_NULL)))
           DBUG_RETURN(RES_ERROR);
       }
       having_item= and_items(having_item, col_item);
@@ -1646,7 +1652,8 @@ Item_in_subselect::row_value_in_to_exist
       {
         if (!(item_nnull_test= 
               new Item_func_trig_cond(item_nnull_test, get_cond_guard(i),
-                                      NULL, Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                      NULL, Item_func_trig_cond::
+                                      OUTER_FIELD_IS_NOT_NULL)))
           DBUG_RETURN(RES_ERROR);
       }
       item_having_part2= and_items(item_having_part2, item_nnull_test);
@@ -1727,11 +1734,13 @@ Item_in_subselect::row_value_in_to_exist
         if (left_expr->element_index(i)->maybe_null)
         {
           if (!(item= new Item_func_trig_cond(item, get_cond_guard(i), NULL,
-                                              Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                              Item_func_trig_cond::
+                                              OUTER_FIELD_IS_NOT_NULL)))
             DBUG_RETURN(RES_ERROR);
           if (!(having_col_item= 
                 new Item_func_trig_cond(having_col_item, get_cond_guard(i), NULL,
-                                        Item_func_trig_cond::OUTER_FIELD_IS_NOT_NULL)))
+                                        Item_func_trig_cond::
+                                        OUTER_FIELD_IS_NOT_NULL)))
             DBUG_RETURN(RES_ERROR);
         }
         having_item= and_items(having_item, having_col_item);

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2011-03-21 20:50:40 +0000
+++ b/sql/opt_range.cc	2011-04-05 07:34:13 +0000
@@ -836,7 +836,6 @@ TRP_GROUP_MIN_MAX *get_best_group_min_ma
 #ifndef DBUG_OFF
 static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
                            const char *msg);
-// print_ror_scans_arr declared 'static' but never defined
 static void print_ror_scans_arr(TABLE *table, const char *msg,
                                 struct st_ror_scan_info **start,
                                 struct st_ror_scan_info **end);

=== modified file 'sql/opt_trace.cc'
--- a/sql/opt_trace.cc	2011-04-04 13:56:54 +0000
+++ b/sql/opt_trace.cc	2011-04-05 07:34:13 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -58,7 +58,7 @@ public:
   void set_allowed_mem_size(size_t size);
 
   /// @sa Opt_trace_context::set_query()
-  bool set_query(const char* query, size_t length,
+  void set_query(const char* query, size_t length,
                  const CHARSET_INFO *charset);
 
   /* Below, functions for filling the statement's trace */
@@ -67,14 +67,14 @@ public:
      When creating an Opt_trace_struct: adds a key and the opening bracket to
      the trace buffer, updates current_struct.
      @param  key              key or NULL
-     @param  struc            structure being created
+     @param  ots              structure being created
      @param  feature          optimizer feature to which the structure belongs
      @param  opening_bracket  opening bracket to use
      @retval false ok
      @retval true  error, Opt_trace_struct must set itself to dummy; trace
      may have been written to, will likely be invalid JSON.
   */
-  bool open_struct(const char *key, Opt_trace_struct *struc,
+  bool open_struct(const char *key, Opt_trace_struct *ots,
                    Opt_trace_context::feature_value feature,
                    char opening_bracket);
   /**
@@ -229,8 +229,14 @@ private:
   {
     support_I_S= stack_of_values_of_support_I_S.pop();
   }
+  friend Opt_trace_disable_I_S::Opt_trace_disable_I_S(Opt_trace_context*, bool);
+  friend Opt_trace_disable_I_S::~Opt_trace_disable_I_S();
 
-  /// A wrapper of class String, for storing query or trace.
+  /**
+    A wrapper of class String, for storing query or trace.
+    Any memory allocation error in this class is reported by my_error(), see
+    OOM_HANDLING in opt_trace.h.
+  */
   class Buffer
   {
   private:
@@ -239,9 +245,10 @@ private:
     String string_buf;
   public:
     Buffer() : allowed_mem_size(0), missing_bytes(0) {}
+
     uint32 alloced_length() const { return string_buf.alloced_length(); }
     uint32 length() const { return string_buf.length(); }
-    bool prealloc();    ///< pro-actively extend buffer if soon short of space
+    void prealloc();    ///< pro-actively extend buffer if soon short of space
     char *c_ptr_safe()
     {
       // Alas, String::c_ptr_safe() does no realloc error checking
@@ -258,16 +265,16 @@ private:
        @param  str     String, in this instance's charset
        @param  length  length of string
     */
-    bool append(const char *str, size_t length);
-    bool append(const char *str) { return append(str, strlen(str)); }
+    void append(const char *str, size_t length);
+    void append(const char *str) { return append(str, strlen(str)); }
     /**
        Like @c append() but escapes certain characters for string values to
        be JSON-compliant.
        @param  str     String in UTF8
        @param  length  length of string
     */
-    bool append_escaped(const char *str, size_t length);
-    bool append(char chr);
+    void append_escaped(const char *str, size_t length);
+    void append(char chr);
 
     size_t get_allowed_mem_size() const { return allowed_mem_size; }
     size_t get_missing_bytes() const { return missing_bytes; }
@@ -277,8 +284,6 @@ private:
 
   Buffer trace_buffer;                    ///< Where the trace is accumulated
   Buffer query_buffer;                    ///< Where the original query is put
-
-  friend class Opt_trace_disable_I_S;
 };
 
 
@@ -526,7 +531,7 @@ void Opt_trace_stmt::set_allowed_mem_siz
 }
 
 
-bool Opt_trace_stmt::set_query(const char *query, size_t length,
+void Opt_trace_stmt::set_query(const char *query, size_t length,
                                const CHARSET_INFO *charset)
 {
   // Should be called only once per statement.
@@ -538,7 +543,7 @@ bool Opt_trace_stmt::set_query(const cha
       Query won't be read, don't waste resources storing it. Still we have set
       the charset, which is necessary.
     */
-    return false;
+    return;
   }
   // We are taking a bit of space from 'trace_buffer'.
   size_t available=
@@ -546,17 +551,16 @@ bool Opt_trace_stmt::set_query(const cha
     0 : (trace_buffer.get_allowed_mem_size() - trace_buffer.alloced_length());
   query_buffer.set_allowed_mem_size(available);
   // No need to escape query, this is not for JSON.
-  const bool rc= query_buffer.append(query, length);
+  query_buffer.append(query, length);
   // Space which query took is taken out of the trace:
   const size_t new_allowed_mem_size=
     (query_buffer.alloced_length() >= trace_buffer.get_allowed_mem_size()) ?
     0 : (trace_buffer.get_allowed_mem_size() - query_buffer.alloced_length());
   trace_buffer.set_allowed_mem_size(new_allowed_mem_size);
-  return rc;
 }
 
 
-bool Opt_trace_stmt::open_struct(const char *key, Opt_trace_struct *struc,
+bool Opt_trace_stmt::open_struct(const char *key, Opt_trace_struct *ots,
                                  Opt_trace_context::feature_value feature,
                                  char opening_bracket)
 {
@@ -603,11 +607,8 @@ bool Opt_trace_stmt::open_struct(const c
       trace_buffer.append(opening_bracket);
     }
   }
-  Struct_desc d;
-  d.current_struct=   current_struct;
-  d.has_disabled_I_S= has_disabled_I_S;
-  d.current_struct_empty= current_struct_empty;
   {
+    Struct_desc d= { current_struct, has_disabled_I_S, current_struct_empty};
     DBUG_EXECUTE_IF("opt_trace_oom_in_open_struct",
                     DBUG_SET("+d,simulate_out_of_memory"););
     const bool rc= stack_of_current_structs.append(d);
@@ -621,7 +622,7 @@ bool Opt_trace_stmt::open_struct(const c
     if (unlikely(rc))
       goto err;
   }
-  current_struct= struc;
+  current_struct= ots;
   current_struct_empty= true;
   return false;
 err:
@@ -681,8 +682,8 @@ void Opt_trace_stmt::next_line()
     return;
   trace_buffer.append('\n');
 
-  int to_be_printed= 2 * stack_of_current_structs.elements();
-  const int spaces_len= sizeof(my_spaces) - 1;
+  uint to_be_printed= 2 * stack_of_current_structs.elements();
+  const size_t spaces_len= sizeof(my_spaces) - 1;
   while (to_be_printed > spaces_len)
   {
     trace_buffer.append(my_spaces, spaces_len);
@@ -771,147 +772,119 @@ const char *Opt_trace_stmt::trace_buffer
 
 // Implementation of class Opt_trace_stmt::Buffer
 
-bool Opt_trace_stmt::Buffer::append_escaped(const char *str, size_t length)
+void Opt_trace_stmt::Buffer::append_escaped(const char *str, size_t length)
 {
-  bool rc;
   if (alloced_length() >= allowed_mem_size)
   {
     missing_bytes+= length;
-    rc= true;
+    return;
   }
-  else
+  const char *pstr, *pstr_end;
+  char buf[128];                     // Temporary output buffer.
+  char *pbuf= buf;
+  for (pstr= str, pstr_end= (str + length) ; pstr < pstr_end ; pstr++)
   {
-    rc= false;
-    const char *pstr, *pstr_end;
-    char buf[128];                     // Temporary output buffer.
-    char *pbuf= buf;
-    for (pstr= str, pstr_end= (str + length) ; pstr < pstr_end ; pstr++)
+    char esc;
+    const char c= *pstr;
+    /*
+      JSON syntax says that control characters must be escaped. Experience
+      confirms that this means ASCII 0->31 and " and \ . A few of
+      them are accepted with a short escaping syntax (using \ : like \n)
+      but for most of them, only \uXXXX works, where XXXX is a
+      hexadecimal value for the code point.
+      Rules also mention escaping / , but Python's and Perl's json modules
+      do not require it, and somewhere on Internet someone said JSON
+      allows escaping of / but does not require it.
+
+      Because UTF8 has the same characters in range 0-127 as ASCII does, and
+      other UTF8 characters don't contain 0-127 bytes, if we see a byte
+      equal to 0 it is really the UTF8 u0000 character (a.k.a. ASCII NUL)
+      and not a part of a longer character; if we see a newline, same,
+      etc. That wouldn't necessarily be true with another character set.
+    */
+    switch (c)
     {
-      char esc;
-      const char c= *pstr;
-      /*
-        JSON syntax says that control characters must be escaped. Experience
-        confirms that this means ASCII 0->31 and " and \ . A few of
-        them are accepted with a short escaping syntax (using \ : like \n)
-        but for most of them, only \uXXXX works, where XXXX is a
-        hexadecimal value for the code point.
-        Rules also mention escaping / , but Python's and Perl's json modules
-        do not require it, and somewhere on Internet someone said JSON
-        allows escaping of / but does not require it.
-
-        Because UTF8 has the same characters in range 0-127 as ASCII does, and
-        other UTF8 characters don't contain 0-127 bytes, if we see a byte
-        equal to 0 it is really the UTF8 u0000 character (a.k.a. ASCII NUL)
-        and not a part of a longer character; if we see a newline, same,
-        etc. That wouldn't necessarily be true with another character set.
-      */
-      switch (c)
-      {
-        // Don't use \u when possible for common chars, \ is easier to read:
-      case '\\':
-        esc= '\\';
-        break;
-      case '"':
-        esc= '\"';
-        break;
-      case '\n':
-        esc= 'n';
-        break;
-      case '\r':
-        esc= 'r';
-        break;
-      case '\t':
-        esc= 't';
-        break;
-      default:
-        esc= 0;
-        break;
-      }
-      if (esc != 0)                           // Escaping with backslash.
+      // Don't use \u when possible for common chars, \ is easier to read:
+    case '\\': esc= '\\'; break;
+    case '"' : esc= '\"'; break;
+    case '\n': esc= 'n' ; break;
+    case '\r': esc= 'r' ; break;
+    case '\t': esc= 't' ; break;
+    default  : esc= 0   ; break;
+    }
+    if (esc != 0)                           // Escaping with backslash.
+    {
+      *pbuf++= '\\';
+      *pbuf++= esc;
+    }
+    else
+    {
+      uint ascii_code= (uint)c;
+      if (ascii_code < 32)                  // Escaping with \u
       {
         *pbuf++= '\\';
-        *pbuf++= esc;
-      }
-      else
-      {
-        uint ascii_code= (uint)c;
-        if (ascii_code < 32)                  // Escaping with \u
+        *pbuf++= 'u';
+        *pbuf++= '0';
+        *pbuf++= '0';
+        if (ascii_code < 16)
         {
-          *pbuf++= '\\';
-          *pbuf++= 'u';
-          *pbuf++= '0';
           *pbuf++= '0';
-          if (ascii_code < 16)
-          {
-            *pbuf++= '0';
-          }
-          else
-          {
-            *pbuf++= '1';
-            ascii_code-= 16;
-          }
-          *pbuf++= _dig_vec_lower[ascii_code];
         }
         else
-          *pbuf++= c; // Normal character, no escaping needed.
-      }
-      /*
-        To fit a next character, we need at most 6 bytes (happens when using
-        \uXXXX syntax) before the buffer's end:
-      */
-      if (pbuf > buf + (sizeof(buf) - 6))
-      {
-        // Possibly no room in 'buf' for next char, so flush buf.
-        rc|= string_buf.append(buf, pbuf - buf);
-        pbuf= buf; // back to buf's start
+        {
+          *pbuf++= '1';
+          ascii_code-= 16;
+        }
+        *pbuf++= _dig_vec_lower[ascii_code];
       }
+      else
+        *pbuf++= c; // Normal character, no escaping needed.
+    }
+    /*
+      To fit a next character, we need at most 6 bytes (happens when using
+      \uXXXX syntax) before the buffer's end:
+    */
+    if (pbuf > buf + (sizeof(buf) - 6))
+    {
+      // Possibly no room in 'buf' for next char, so flush buf.
+      string_buf.append(buf, pbuf - buf);
+      pbuf= buf; // back to buf's start
     }
-    // Flush any chars left in 'buf'.
-    rc|= string_buf.append(buf, pbuf - buf);
   }
-  return rc;
+  // Flush any chars left in 'buf'.
+  string_buf.append(buf, pbuf - buf);
 }
 
 
-bool Opt_trace_stmt::Buffer::append(const char *str, size_t length)
+void Opt_trace_stmt::Buffer::append(const char *str, size_t length)
 {
-  bool rc;
   if (alloced_length() >= allowed_mem_size)
   {
     missing_bytes+= length;
-    rc= true;
-  }
-  else
-  {
-    DBUG_EXECUTE_IF("opt_trace_oom_in_buffers",
-                    DBUG_SET("+d,simulate_out_of_memory"););
-    rc= string_buf.append(str, length);
-    DBUG_EXECUTE_IF("opt_trace_oom_in_buffers",
-                    DBUG_SET("-d,simulate_out_of_memory"););
+    return;
   }
-  return rc;
+  DBUG_EXECUTE_IF("opt_trace_oom_in_buffers",
+                  DBUG_SET("+d,simulate_out_of_memory"););
+  string_buf.append(str, length);
+  DBUG_EXECUTE_IF("opt_trace_oom_in_buffers",
+                  DBUG_SET("-d,simulate_out_of_memory"););
 }
 
 
-bool Opt_trace_stmt::Buffer::append(char chr)
+void Opt_trace_stmt::Buffer::append(char chr)
 {
-  bool rc;
   if (alloced_length() >= allowed_mem_size)
   {
     missing_bytes++;
-    rc= true;
-  }
-  else
-  {
-    // No need for escaping chr, given how this function is used.
-    rc= string_buf.append(chr);
+    return;
   }
-  return rc;
+  // No need for escaping chr, given how this function is used.
+  string_buf.append(chr);
 }
 
 
 
-bool Opt_trace_stmt::Buffer::prealloc()
+void Opt_trace_stmt::Buffer::prealloc()
 {
   const size_t alloced=   alloced_length();
   const size_t first_increment= 1024;
@@ -949,10 +922,9 @@ bool Opt_trace_stmt::Buffer::prealloc()
       if (new_size > max_size) // Don't pre-allocate more than the limit.
         new_size= max_size;
       if (new_size >= alloced) // Never shrink string.
-        return string_buf.realloc(new_size);
+        string_buf.realloc(new_size);
     }
   }
-  return false;
 }
 
 
@@ -1258,10 +1230,10 @@ size_t Opt_trace_context::allowed_mem_si
 }
 
 
-bool Opt_trace_context::set_query(const char *query, size_t length,
+void Opt_trace_context::set_query(const char *query, size_t length,
                                   const CHARSET_INFO *charset)
 {
-  return current_stmt_in_gen->set_query(query, length, charset);
+  current_stmt_in_gen->set_query(query, length, charset);
 }
 
 

=== modified file 'sql/opt_trace.h'
--- a/sql/opt_trace.h	2011-03-22 10:08:27 +0000
+++ b/sql/opt_trace.h	2011-04-05 07:34:13 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -91,7 +91,7 @@ struct TABLE;
 
 @verbatim
   SET SESSION OPTIMIZER_TRACE="enabled=on"; # enable tracing
-  statement to trace; # like SELECT, EXPLAIN SELECT, UPDATE, DELETE...
+  <statement to trace>; # like SELECT, EXPLAIN SELECT, UPDATE, DELETE...
   SELECT * FROM information_schema.OPTIMIZER_TRACE;
   [ repeat last two steps at will ]
   SET SESSION OPTIMIZER_TRACE="enabled=off"; # disable tracing
@@ -399,7 +399,7 @@ enum enum_support_I_S
   "current object or array" accessible from the Opt_trace_context context;
   it's a pointer to an instance of Opt_trace_struct, and the function deep
   down (frame #0) grabs it from the context, where it was depositted by the
-  function high up (frame #13 in the last example).
+  function high up (frame #3 in the last example).
 */
 
 class Opt_trace_context
@@ -453,16 +453,15 @@ public:
      @param   query    query
      @param   length   query's length
      @param   charset  charset which was used to encode this query
-     @retval  false    ok
-     @retval  true     error
   */
-  bool set_query(const char* query, size_t length,
+  void set_query(const char* query, size_t length,
                  const CHARSET_INFO *charset);
 
   /**
      @returns a pointer to the last bytes of the current trace, 0-terminated.
      Can be called only if is_started() is true.
-     @param  size  how many last bytes are wanted
+     @param  size  How many last bytes are wanted. If greater than the trace's
+     length, then the entire trace is returned.
   */
   const char *get_tail(size_t size);
 
@@ -489,8 +488,10 @@ public:
 
   /** Flags' numeric values for @@@@optimizer_trace variable */
   enum {
-    FLAG_DEFAULT= 0, FLAG_ENABLED= 1 << 0,
-    FLAG_END_MARKER= 1 << 1, FLAG_ONE_LINE= 1 << 2
+    FLAG_DEFAULT=    0,
+    FLAG_ENABLED=    1 << 0,
+    FLAG_END_MARKER= 1 << 1,
+    FLAG_ONE_LINE=   1 << 2
   };
 
   /**
@@ -508,10 +509,10 @@ public:
 
   /** Features' numeric values for @@@@optimizer_trace_features variable */
   enum feature_value {
-    GREEDY_SEARCH= (1 << 0),
-    RANGE_OPTIMIZER= (1 << 1),
-    DYNAMIC_RANGE= (1 << 2),
-    REPEATED_SUBSELECT= (1 << 3), ///@todo join cache, semijoin...
+    GREEDY_SEARCH=      1 << 0,
+    RANGE_OPTIMIZER=    1 << 1,
+    DYNAMIC_RANGE=      1 << 2,
+    REPEATED_SUBSELECT= 1 << 3, ///@todo join cache, semijoin...
     /*
       If you add here, update feature_value of empty implementation
       and default_features!
@@ -522,7 +523,7 @@ public:
        This feature cannot be disabled by the user; for this it is important
        that it always has biggest flag; flag's value itself does not matter.
     */
-    MISC= (1 << 7)
+    MISC=               1 << 7
   };
   static const feature_value default_features;
 
@@ -530,17 +531,13 @@ public:
      @returns whether an optimizer feature should be traced.
      @param  f  feature
   */
-  bool feature_enabled (Opt_trace_context::feature_value f) const
+  bool feature_enabled (feature_value f) const
   { return features & f; }
 
   /**
      Opt_trace_struct is passed Opt_trace_context*, and needs to know
      to which statement's trace to attach, so Opt_trace_context must provide
      this information.
-     This cannot return pointer-to-const, but as the definition of
-     Opt_trace_stmt is confined to opt_trace.cc, this is ok (includer of
-     opt_trace.h is ignorant of the layout of the pointed instance so cannot
-     use it).
   */
   Opt_trace_stmt *get_current_stmt_in_gen() { return current_stmt_in_gen; }
 
@@ -612,12 +609,11 @@ private:
   Dynamic_array<Opt_trace_stmt *> all_stmts_to_del;
 
   bool end_marker;          ///< copy of parameter of Opt_trace_context::start
-  bool one_line;            ///< copy of parameter of Opt_trace_context::start
-  /// copy of parameter of Opt_trace_context::start
-  Opt_trace_context::feature_value features;
-  long offset;              ///< copy of parameter of Opt_trace_context::start
-  long limit;               ///< copy of parameter of Opt_trace_context::start
-  size_t max_mem_size;      ///< copy of parameter of Opt_trace_context::start
+  bool one_line;
+  feature_value features;
+  long offset;
+  long limit;
+  size_t max_mem_size;
 
   /**
      Number of statements traced so far since "offset 0", for comparison with
@@ -642,8 +638,7 @@ private:
      being updated at this moment: this must be the trace of a top
      statement calling a substatement which is the current trace now: trace's
      top statement is not being updated at this moment.
-     So the length of all those other traces is "a given", and the current
-     trace can grow in the room left by them.
+     So the current trace can grow in the room left by all traces above.
   */
   size_t allowed_mem_size_for_current_stmt() const;
 
@@ -969,6 +964,18 @@ public:
     return do_add_utf8_table(tab);
   }
   /**
+     Helper to put the number of select_lex in an object.
+     @param  select_number  number of select_lex
+  */
+  Opt_trace_struct& add_select_number(uint select_number)
+  {
+    return unlikely(select_number >= INT_MAX) ?
+      // Clearer than any huge number.
+      add_alnum("select#", "fake") :
+      add("select#", select_number);
+  }
+
+  /**
     The exception to RAII: this function is an explicit way of ending a
     structure before it goes out of scope. Don't use it unless RAII mandates
     a new scope which mandates re-indenting lots of code lines.
@@ -1101,7 +1108,7 @@ public:
 
 
 /**
-   Instantiate an instance of this class for specific, punctual cases where
+   Instantiate an instance of this class for specific cases where
    optimizer trace, in a certain section of Optimizer code, should write only
    to DBUG and not I_S. Example: see sql_select.cc.
    Note that this class should rarely be used; the "feature" parameter of
@@ -1194,23 +1201,14 @@ void opt_trace_print_expanded_query(THD 
                                     st_select_lex *select_lex);
 
 /**
-   Adds a select_lex's number to an object
-   @param  s              object
-   @param  select_number  number of select_lex
-*/
-void opt_trace_add_select_number(Opt_trace_struct *s,
-                                 uint select_number);
-/**
    Set the "original" query (not transformed, as sent by client) for the
    current trace.
    @param   trace    trace context
    @param   query    query
    @param   length   query's length
    @param   charset  charset which was used to encode this query
-   @retval  false    ok
-   @retval  true     error
 */
-bool opt_trace_set_query(Opt_trace_context *trace, const char *query,
+void opt_trace_set_query(Opt_trace_context *trace, const char *query,
                          size_t query_length,
                          const CHARSET_INFO *query_charset);
 
@@ -1241,11 +1239,11 @@ class Opt_trace_context
 public:
   /// We need this enum even if tracing is disabled
   enum feature_value {
-    GREEDY_SEARCH= (1 << 0),
-    RANGE_OPTIMIZER= (1 << 1),
-    DYNAMIC_RANGE= (1 << 2),
-    REPEATED_SUBSELECT= (1 << 3),
-    MISC= (1 << 7)
+    GREEDY_SEARCH=      1 << 0,
+    RANGE_OPTIMIZER=    1 << 1,
+    DYNAMIC_RANGE=      1 << 2,
+    REPEATED_SUBSELECT= 1 << 3,
+    MISC=               1 << 7
   };
 };
 
@@ -1276,6 +1274,7 @@ public:
   Opt_trace_object& add(const char *key, ulonglong value) { return *this; }
   Opt_trace_object& add(const char *key, double value) { return *this; }
   Opt_trace_object& add_utf8_table(TABLE *tab) { return *this; }
+  Opt_trace_object& add_select_number(uint select_number) { return *this; }
   void end() {}
 };
 
@@ -1304,6 +1303,7 @@ public:
   Opt_trace_array& add(ulonglong value) { return *this; }
   Opt_trace_array& add(double value) { return *this; }
   Opt_trace_array& add_utf8_table(TABLE *tab) { return *this; }
+  Opt_trace_array& add_select_number(uint select_number) { return *this; }
   void end() {}
 };
 
@@ -1317,7 +1317,6 @@ public:
 #define opt_trace_start(thd, tbl, sql_command) (false)
 #define opt_trace_end(thd, started) do {} while (0)
 #define opt_trace_print_expanded_query(thd, select_lex) do {} while (0)
-#define opt_trace_add_select_number(s, select_number) do {} while (0)
 #define opt_trace_set_query(trace,q,ql,cs) do {} while (0)
 
 #endif /* OPTIMIZER_TRACE */
@@ -1344,7 +1343,7 @@ public:
                             select_number,from,to)                      \
   Opt_trace_object object_level0(trace);                                \
   Opt_trace_object object_level1(trace, "transformation");              \
-  opt_trace_add_select_number(&object_level1, select_number);           \
+  object_level1.add_select_number(select_number);                       \
   object_level1.add_alnum("from", from).add_alnum("to", to);
 
 #if !defined(DBUG_OFF) && !defined(OPTIMIZER_TRACE) \

=== modified file 'sql/opt_trace2server.cc'
--- a/sql/opt_trace2server.cc	2011-03-22 10:08:27 +0000
+++ b/sql/opt_trace2server.cc	2011-04-05 07:34:13 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -233,24 +233,11 @@ void opt_trace_print_expanded_query(THD 
 }
 
 
-void opt_trace_add_select_number(Opt_trace_struct *s,
-                                 uint select_number)
-{
-  if (unlikely(select_number >= INT_MAX))
-  {
-    // Clearer than any huge number.
-    s->add_alnum("select#", "fake");
-  }
-  else
-    s->add("select#", select_number);
-}
-
-
-bool opt_trace_set_query(Opt_trace_context *trace, const char *query,
+void opt_trace_set_query(Opt_trace_context *trace, const char *query,
                          size_t query_length,
                          const CHARSET_INFO *query_charset)
 {
-  return trace->set_query(query, query_length, query_charset);
+  trace->set_query(query, query_length, query_charset);
 }
 
 

=== modified file 'sql/sql_array.h'
--- a/sql/sql_array.h	2011-02-28 15:51:31 +0000
+++ b/sql/sql_array.h	2011-04-05 07:34:13 +0000
@@ -69,7 +69,11 @@ public:
     return insert_dynamic(&array, &el);
   }
 
-  Elem& pop()
+  /**
+     Pops the last element. The returned element must not be used after the
+     next update to the array.
+  */
+  const Elem& pop()
   {
     return *static_cast<Elem *>(pop_dynamic(&array));
   }

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2011-03-21 17:55:41 +0000
+++ b/sql/sql_delete.cc	2011-04-05 07:34:13 +0000
@@ -207,9 +207,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *
          errors when unwinding the stack after calling Item::val_xxx().
       */
       if (thd->is_error())
-        DBUG_RETURN(TRUE);
+        DBUG_RETURN(true);
       my_ok(thd, 0);
-      DBUG_RETURN(0);				// Nothing to delete
+      DBUG_RETURN(false);                       // Nothing to delete
     }
   } // Ends scope for optimizer trace wrapper
 

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-03-21 17:55:41 +0000
+++ b/sql/sql_select.cc	2011-04-05 07:34:13 +0000
@@ -565,7 +565,7 @@ JOIN::prepare(Item ***rref_pointer_array
   Opt_trace_context * const trace= thd->opt_trace;
   Opt_trace_object trace_wrapper(trace);
   Opt_trace_object trace_prepare(trace, "join_preparation");
-  opt_trace_add_select_number(&trace_prepare, select_lex->select_number);
+  trace_prepare.add_select_number(select_lex->select_number);
   Opt_trace_array trace_steps(trace, "steps");
 
   /* Check that all tables, fields, conds and order are ok */
@@ -1825,7 +1825,7 @@ JOIN::optimize()
   Opt_trace_context * const trace= thd->opt_trace;
   Opt_trace_object trace_wrapper(trace);
   Opt_trace_object trace_optimize(trace, "join_optimization");
-  opt_trace_add_select_number(&trace_optimize, select_lex->select_number);
+  trace_optimize.add_select_number(select_lex->select_number);
   Opt_trace_array trace_steps(trace, "steps");
 
   /* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
@@ -2827,7 +2827,7 @@ JOIN::exec()
   Opt_trace_context * const trace= thd->opt_trace;
   Opt_trace_object trace_wrapper(trace);
   Opt_trace_object trace_exec(trace, "join_execution");
-  opt_trace_add_select_number(&trace_exec, select_lex->select_number);
+  trace_exec.add_select_number(select_lex->select_number);
   Opt_trace_array trace_steps(trace, "steps");
 
   List<Item> *columns_list= &fields_list;
@@ -4891,291 +4891,287 @@ make_join_statistics(JOIN *join, TABLE_L
   /* Read tables with 0 or 1 rows (system tables) */
   join->const_table_map= 0;
 
-  {
-    for (POSITION *p_pos= join->positions, *p_end= p_pos + const_count;
-         p_pos < p_end ;
-         p_pos++)
-    {
-      int tmp;
-      s= p_pos->table;
-      s->type= JT_SYSTEM;
-      join->const_table_map|= s->table->map;
-      if ((tmp= join_read_const_table(s, p_pos)))
-      {
-        if (tmp > 0)
-          goto error;		// Fatal error
-      }
-      else
-      {
-        found_const_table_map|= s->table->map;
-        s->table->pos_in_table_list->optimized_away= TRUE;
-      }
+  for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
+       p_pos < p_end ;
+       p_pos++)
+  {
+    int tmp;
+    s= p_pos->table;
+    s->type=JT_SYSTEM;
+    join->const_table_map|=s->table->map;
+    if ((tmp=join_read_const_table(s, p_pos)))
+    {
+      if (tmp > 0)
+	goto error;		// Fatal error
     }
-
-    /* loop until no more const tables are found */
-    int ref_changed;
-    do
+    else
     {
+      found_const_table_map|= s->table->map;
+      s->table->pos_in_table_list->optimized_away= TRUE;
+    }
+  }
+
+  /* loop until no more const tables are found */
+  int ref_changed;
+  do
+  {
   more_const_tables_found:
-      ref_changed = 0;
-      found_ref= 0;
+    ref_changed = 0;
+    found_ref=0;
 
-      /*
-        We only have to loop from stat_vector + const_count as
-        set_position() will move all const_tables first in stat_vector
-      */
+    /*
+      We only have to loop from stat_vector + const_count as
+      set_position() will move all const_tables first in stat_vector
+    */
 
-      for (JOIN_TAB **pos= stat_vector + const_count ; (s= *pos) ; pos++)
-      {
-        table= s->table;
+    for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
+    {
+      table=s->table;
 
-        /*
-          If equi-join condition by a key is null rejecting and after a
-          substitution of a const table the key value happens to be null
-          then we can state that there are no matches for this equi-join.
-        */
-        if ((keyuse= s->keyuse) && *s->on_expr_ref && !s->embedding_map)
+      /* 
+        If equi-join condition by a key is null rejecting and after a
+        substitution of a const table the key value happens to be null
+        then we can state that there are no matches for this equi-join.
+      */  
+      if ((keyuse= s->keyuse) && *s->on_expr_ref && !s->embedding_map)
+      {
+        /* 
+          When performing an outer join operation if there are no matching rows
+          for the single row of the outer table all the inner tables are to be
+          null complemented and thus considered as constant tables.
+          Here we apply this consideration to the case of outer join operations 
+          with a single inner table only because the case with nested tables
+          would require a more thorough analysis.
+          TODO. Apply single row substitution to null complemented inner tables
+          for nested outer join operations. 
+	*/              
+        while (keyuse->table == table)
         {
-          /*
-            When performing an outer join operation if there are no matching rows
-            for the single row of the outer table all the inner tables are to be
-            null complemented and thus considered as constant tables.
-            Here we apply this consideration to the case of outer join operations
-            with a single inner table only because the case with nested tables
-            would require a more thorough analysis.
-            TODO. Apply single row substitution to null complemented inner tables
-            for nested outer join operations.
-          */
-          while (keyuse->table == table)
+          if (!(keyuse->val->used_tables() & ~join->const_table_map) &&
+              keyuse->val->is_null() && keyuse->null_rejecting)
           {
-            if (!(keyuse->val->used_tables() & ~join->const_table_map) &&
-                keyuse->val->is_null() && keyuse->null_rejecting)
-            {
-              s->type= JT_CONST;
-              mark_as_null_row(table);
-              found_const_table_map|= table->map;
-              join->const_table_map|= table->map;
-              set_position(join, const_count++, s, NULL);
-              goto more_const_tables_found;
-            }
-            keyuse++;
-          }
+            s->type= JT_CONST;
+            mark_as_null_row(table);
+            found_const_table_map|= table->map;
+	    join->const_table_map|= table->map;
+	    set_position(join, const_count++, s, NULL);
+            goto more_const_tables_found;
+           }
+	  keyuse++;
         }
+      }
 
-        if (s->dependent)				// If dependent on some table
-        {
-          // All dep. must be constants
-          if (s->dependent & ~(join->const_table_map))
-            continue;
-          if (table->file->stats.records <= 1L &&
-              (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
-              !table->pos_in_table_list->in_outer_join_nest())
-          {					// system table
-            int tmp= 0;
-            s->type= JT_SYSTEM;
-            join->const_table_map|= table->map;
-            set_position(join, const_count++, s, NULL);
-            if ((tmp= join_read_const_table(s, join->positions +
-                                            const_count - 1)))
-            {
-              if (tmp > 0)
-                goto error;			// Fatal error
-            }
-            else
-              found_const_table_map|= table->map;
-            continue;
-          }
-        }
-        /* check if table can be read by key or table only uses const refs */
-        if ((keyuse= s->keyuse))
-        {
-          s->type= JT_REF;
-          while (keyuse->table == table)
-          {
-            start_keyuse= keyuse;
-            key= keyuse->key;
-            s->keys.set_bit(key);               // QQ: remove this ?
-
-            refs= 0;
-            key_map const_ref, eq_part;
-            do
-            {
-              if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
-              {
-                if (!((~found_const_table_map) & keyuse->used_tables))
-                  const_ref.set_bit(keyuse->keypart);
-                else
-                  refs|= keyuse->used_tables;
-                eq_part.set_bit(keyuse->keypart);
-              }
-              keyuse++;
-            } while (keyuse->table == table && keyuse->key == key);
+      if (s->dependent)				// If dependent on some table
+      {
+	// All dep. must be constants
+        if (s->dependent & ~(join->const_table_map))
+	  continue;
+	if (table->file->stats.records <= 1L &&
+	    (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
+            !table->pos_in_table_list->in_outer_join_nest())
+	{					// system table
+	  int tmp= 0;
+	  s->type=JT_SYSTEM;
+	  join->const_table_map|=table->map;
+	  set_position(join, const_count++, s, NULL);
+	  if ((tmp= join_read_const_table(s, join->positions+const_count-1)))
+	  {
+	    if (tmp > 0)
+	      goto error;			// Fatal error
+	  }
+	  else
+	    found_const_table_map|= table->map;
+	  continue;
+	}
+      }
+      /* check if table can be read by key or table only uses const refs */
+      if ((keyuse=s->keyuse))
+      {
+	s->type= JT_REF;
+	while (keyuse->table == table)
+	{
+	  start_keyuse=keyuse;
+	  key=keyuse->key;
+	  s->keys.set_bit(key);               // QQ: remove this ?
+
+	  refs=0;
+          key_map const_ref, eq_part;
+	  do
+	  {
+	    if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
+	    {
+	      if (!((~found_const_table_map) & keyuse->used_tables))
+		const_ref.set_bit(keyuse->keypart);
+	      else
+		refs|=keyuse->used_tables;
+	      eq_part.set_bit(keyuse->keypart);
+	    }
+	    keyuse++;
+	  } while (keyuse->table == table && keyuse->key == key);
 
-            /*
-              TODO (low priority): currently we ignore the const tables that
-              are within a semi-join nest which is within an outer join nest.
-              The effect of this is that we don't do const substitution for
-              such tables.
-            */
-            if (eq_part.is_prefix(table->key_info[key].key_parts) &&
-                !table->fulltext_searched &&
-                !table->pos_in_table_list->in_outer_join_nest())
+          /*
+            TODO (low priority): currently we ignore the const tables that
+            are within a semi-join nest which is within an outer join nest.
+            The effect of this is that we don't do const substitution for
+            such tables.
+          */
+	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
+              !table->fulltext_searched && 
+              !table->pos_in_table_list->in_outer_join_nest())
+	  {
+            if (table->key_info[key].flags & HA_NOSAME)
             {
-              if (table->key_info[key].flags & HA_NOSAME)
-              {
-                if (const_ref == eq_part)
-                {					// Found everything for ref.
-                  int tmp;
-                  ref_changed = 1;
-                  s->type= JT_CONST;
-                  join->const_table_map|= table->map;
-                  set_position(join, const_count++, s, start_keyuse);
-                  if (create_ref_for_key(join, s, start_keyuse,
-                                         found_const_table_map))
-                    goto error;
-                  if ((tmp= join_read_const_table(s,
-                                                  join->positions +
-                                                  const_count - 1)))
-                  {
-                    if (tmp > 0)
-                      goto error;			// Fatal error
-                  }
-                  else
-                    found_const_table_map|= table->map;
-                  break;
-                }
-                else
-                  found_ref|= refs;      // Table is const if all refs are const
-              }
-              else if (const_ref == eq_part)
-                s->const_keys.set_bit(key);
-            }
+	      if (const_ref == eq_part)
+	      {					// Found everything for ref.
+	        int tmp;
+	        ref_changed = 1;
+	        s->type= JT_CONST;
+	        join->const_table_map|=table->map;
+	        set_position(join,const_count++,s,start_keyuse);
+	        if (create_ref_for_key(join, s, start_keyuse,
+				       found_const_table_map))
+                  goto error;
+	        if ((tmp=join_read_const_table(s,
+                                               join->positions+const_count-1)))
+	        {
+		  if (tmp > 0)
+		    goto error;			// Fatal error
+	        }
+	        else
+		  found_const_table_map|= table->map;
+	        break;
+	      }
+	      else
+	        found_ref|= refs;      // Table is const if all refs are const
+	    }
+            else if (const_ref == eq_part)
+              s->const_keys.set_bit(key);
           }
-        }
+	}
       }
-    } while (join->const_table_map & found_ref && ref_changed);
-
-    /*
-      Update info on indexes that can be used for search lookups as
-      reading const tables may has added new sargable predicates. 
-    */
-    if (const_count && sargables)
+    }
+  } while (join->const_table_map & found_ref && ref_changed);
+ 
+  /* 
+    Update info on indexes that can be used for search lookups as
+    reading const tables may has added new sargable predicates. 
+  */
+  if (const_count && sargables)
+  {
+    for( ; sargables->field ; sargables++)
     {
-      for( ; sargables->field ; sargables++)
-      {
-        Field *field= sargables->field;
-        JOIN_TAB *join_tab= field->table->reginfo.join_tab;
-        key_map possible_keys= field->key_start;
-        possible_keys.intersect(field->table->keys_in_use_for_query);
-        bool is_const= 1;
-        for (uint j= 0; j < sargables->num_values; j++)
-          is_const&= sargables->arg_value[j]->const_item();
-        if (is_const)
-          join_tab[0].const_keys.merge(possible_keys);
-      }
+      Field *field= sargables->field;
+      JOIN_TAB *join_tab= field->table->reginfo.join_tab;
+      key_map possible_keys= field->key_start;
+      possible_keys.intersect(field->table->keys_in_use_for_query);
+      bool is_const= 1;
+      for (uint j=0; j < sargables->num_values; j++)
+        is_const&= sargables->arg_value[j]->const_item();
+      if (is_const)
+        join_tab[0].const_keys.merge(possible_keys);
     }
+  }
 
+  {
     Opt_trace_object trace_wrapper(trace);
-    {
-      /* Calc how many (possible) matched records in each table */
-      Opt_trace_array trace_records(trace, "records_estimation");
+    /* Calc how many (possible) matched records in each table */
+    Opt_trace_array trace_records(trace, "records_estimation");
 
-      for (s= stat ; s < stat_end ; s++)
+    for (s= stat ; s < stat_end ; s++)
+    {
+      Opt_trace_object trace_table(trace);
+      trace_table.add_utf8_table(s->table);
+      if (s->type == JT_SYSTEM || s->type == JT_CONST)
       {
-        Opt_trace_object trace_table(trace);
-        trace_table.add_utf8_table(s->table);
-        if (s->type == JT_SYSTEM || s->type == JT_CONST)
-        {
-          trace_table.add("records", 1).add("cost", 1);
-          trace_table.add_alnum("table_type", (s->type == JT_SYSTEM) ?
-                                "system": "const");
+        trace_table.add("records", 1).add("cost", 1);
+        trace_table.add_alnum("table_type", (s->type == JT_SYSTEM) ?
+                              "system": "const");
 
-          /* Only one matching row */
-          s->found_records= s->records= s->read_time=1; s->worst_seeks= 1.0;
-          continue;
-        }
-        /* Approximate found rows and time to read them */
-        s->found_records= s->records= s->table->file->stats.records;
-        s->read_time= (ha_rows) s->table->file->scan_time();
+        /* Only one matching row */
+        s->found_records= s->records= s->read_time=1; s->worst_seeks= 1.0;
+        continue;
+      }
+      /* Approximate found rows and time to read them */
+      s->found_records= s->records= s->table->file->stats.records;
+      s->read_time= (ha_rows) s->table->file->scan_time();
 
-        /*
-          Set a max range of how many seeks we can expect when using keys
-          This is can't be to high as otherwise we are likely to use
-          table scan.
-        */
-        s->worst_seeks= min((double) s->found_records / 10,
-                            (double) s->read_time*3);
-        if (s->worst_seeks < 2.0)			// Fix for small tables
-          s->worst_seeks= 2.0;
+      /*
+        Set a max range of how many seeks we can expect when using keys
+        This is can't be to high as otherwise we are likely to use
+        table scan.
+      */
+      s->worst_seeks= min((double) s->found_records / 10,
+                          (double) s->read_time*3);
+      if (s->worst_seeks < 2.0)			// Fix for small tables
+        s->worst_seeks= 2.0;
 
-        /*
-          Add to stat->const_keys those indexes for which all group fields or
-          all select distinct fields participate in one index.
-        */
-        add_group_and_distinct_keys(join, s);
+      /*
+        Add to stat->const_keys those indexes for which all group fields or
+        all select distinct fields participate in one index.
+      */
+      add_group_and_distinct_keys(join, s);
     
-        /*
-          Perform range analysis if there are keys it could use (1). 
-          Don't do range analysis if we're on the inner side of an outer join (2).
-          Do range analysis if we're on the inner side of a semi-join (3).
-        */
-        if (!s->const_keys.is_clear_all() &&                        // (1)
-            (!s->table->pos_in_table_list->embedding ||             // (2)
-             (s->table->pos_in_table_list->embedding &&             // (3)
-              s->table->pos_in_table_list->embedding->sj_on_expr))) // (3)
-        {
-          ha_rows records;
-          SQL_SELECT *select;
-          select= make_select(s->table, found_const_table_map,
-                              found_const_table_map,
-                              *s->on_expr_ref ? *s->on_expr_ref : conds,
-                              1, &error);
-          if (!select)
-            goto error;
-          records= get_quick_record_count(join->thd, select, s->table,
-                                          &s->const_keys, join->row_limit);
-          s->quick= select->quick;
-          s->needed_reg= select->needed_reg;
-          select->quick= 0;
-          if (records == 0 && s->table->reginfo.impossible_range)
+      /*
+        Perform range analysis if there are keys it could use (1). 
+        Don't do range analysis if we're on the inner side of an outer join (2).
+        Do range analysis if we're on the inner side of a semi-join (3).
+      */
+      if (!s->const_keys.is_clear_all() &&                        // (1)
+          (!s->table->pos_in_table_list->embedding ||             // (2)
+           (s->table->pos_in_table_list->embedding &&             // (3)
+            s->table->pos_in_table_list->embedding->sj_on_expr))) // (3)
+      {
+        ha_rows records;
+        SQL_SELECT *select;
+        select= make_select(s->table, found_const_table_map,
+                            found_const_table_map,
+                            *s->on_expr_ref ? *s->on_expr_ref : conds,
+                            1, &error);
+        if (!select)
+          goto error;
+        records= get_quick_record_count(join->thd, select, s->table,
+                                        &s->const_keys, join->row_limit);
+        s->quick= select->quick;
+        s->needed_reg= select->needed_reg;
+        select->quick= 0;
+        if (records == 0 && s->table->reginfo.impossible_range)
+        {
+          /*
+            Impossible WHERE or ON expression
+            In case of ON, we mark that the we match one empty NULL row.
+            In case of WHERE, don't set found_const_table_map to get the
+            caller to abort with a zero row result.
+          */
+          join->const_table_map|= s->table->map;
+          set_position(join, const_count++, s, NULL);
+          s->type= JT_CONST;
+          if (*s->on_expr_ref)
           {
-            /*
-              Impossible WHERE or ON expression
-              In case of ON, we mark that the we match one empty NULL row.
-              In case of WHERE, don't set found_const_table_map to get the
-              caller to abort with a zero row result.
-            */
-            join->const_table_map|= s->table->map;
-            set_position(join, const_count++, s, NULL);
+            /* Generate empty row */
+            s->info= "Impossible ON condition";
+            trace_table.add("returning_empty_null_row", true).
+              add_alnum("cause", "impossible_on_condition");
+            found_const_table_map|= s->table->map;
             s->type= JT_CONST;
-            if (*s->on_expr_ref)
-            {
-              /* Generate empty row */
-              s->info= "Impossible ON condition";
-              trace_table.add("returning_empty_null_row", true).
-                add_alnum("cause", "impossible_on_condition");
-              found_const_table_map|= s->table->map;
-              s->type= JT_CONST;
-              mark_as_null_row(s->table);		// All fields are NULL
-            } 
-            else 
-            {
-              trace_table.add("records", 0).
-                add_alnum("cause", "impossible_where_condition");
-            }
-          }
-          if (records != HA_POS_ERROR)
+            mark_as_null_row(s->table);		// All fields are NULL
+          } 
+          else 
           {
-            s->found_records= records;
-            s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
+            trace_table.add("records", 0).
+              add_alnum("cause", "impossible_where_condition");
           }
-          delete select;
         }
-        else
-          Opt_trace_object(trace, "table_scan").
-            add("records", s->found_records).
-            add("cost", s->read_time);
+        if (records != HA_POS_ERROR)
+        {
+          s->found_records= records;
+          s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
+        }
+        delete select;
       }
+      else
+        Opt_trace_object(trace, "table_scan").
+          add("records", s->found_records).
+          add("cost", s->read_time);
     }
   }
 

=== modified file 'unittest/gunit/opt_trace-t.cc'
--- a/unittest/gunit/opt_trace-t.cc	2011-03-21 17:55:41 +0000
+++ b/unittest/gunit/opt_trace-t.cc	2011-04-05 07:34:13 +0000
@@ -148,6 +148,7 @@ TEST_F(TraceContentTest, NormalUsage)
                            all_features));
   {
     Opt_trace_object oto(&trace);
+    oto.add_select_number(123456);
     {
       Opt_trace_array ota(&trace, "one array");
       ota.add(200.4);
@@ -172,6 +173,7 @@ TEST_F(TraceContentTest, NormalUsage)
   it.get_value(&info);
   const char expected[]=
     "{\n"
+    "  \"select#\": 123456,\n"
     "  \"one array\": [\n"
     "    200.4,\n"
     "    {\n"


Attachment: [text/bzr-bundle] bzr/guilhem.bichot@oracle.com-20110405073413-bepme8rz1hqy133b.bundle
Thread
bzr commit into mysql-trunk branch (guilhem.bichot:3286) Guilhem Bichot5 Apr