My Project
opt_explain_format.h
00001 /* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software Foundation,
00014    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00015 
00016 
00017 #ifndef OPT_EXPLAIN_FORMAT_INCLUDED
00018 #define OPT_EXPLAIN_FORMAT_INCLUDED
00019 
00024 #include "sql_class.h"
00025 
00026 struct st_join_table;
00027 
00028 
00033 enum Explain_context_enum
00034 {
00035   CTX_NONE= 0, 
00036   CTX_MESSAGE, 
00037   CTX_TABLE, 
00038   CTX_SELECT_LIST, 
00039   CTX_UPDATE_VALUE_LIST, 
00040   CTX_JOIN,
00041   CTX_JOIN_TAB,
00042   CTX_MATERIALIZATION,
00043   CTX_DUPLICATES_WEEDOUT,
00044   CTX_DERIVED, 
00045   CTX_WHERE, 
00046   CTX_HAVING, 
00047   CTX_ORDER_BY, 
00048   CTX_GROUP_BY, 
00049   CTX_SIMPLE_ORDER_BY, 
00050   CTX_SIMPLE_GROUP_BY, 
00051   CTX_DISTINCT, 
00052   CTX_SIMPLE_DISTINCT, 
00053   CTX_BUFFER_RESULT, 
00054   CTX_ORDER_BY_SQ, 
00055   CTX_GROUP_BY_SQ, 
00056   CTX_OPTIMIZED_AWAY_SUBQUERY, 
00057   CTX_UNION,
00058   CTX_UNION_RESULT, 
00059   CTX_QUERY_SPEC 
00060 };
00061 
00062 
00069 enum Extra_tag
00070 {
00071   ET_none,
00072   ET_USING_TEMPORARY,
00073   ET_USING_FILESORT,
00074   ET_USING_INDEX_CONDITION,
00075   ET_USING,
00076   ET_RANGE_CHECKED_FOR_EACH_RECORD,
00077   ET_USING_WHERE_WITH_PUSHED_CONDITION,
00078   ET_USING_WHERE,
00079   ET_NOT_EXISTS,
00080   ET_USING_MRR,
00081   ET_USING_INDEX,
00082   ET_FULL_SCAN_ON_NULL_KEY,
00083   ET_SKIP_OPEN_TABLE,
00084   ET_OPEN_FRM_ONLY,
00085   ET_OPEN_FULL_TABLE,
00086   ET_SCANNED_DATABASES,
00087   ET_USING_INDEX_FOR_GROUP_BY,
00088   ET_DISTINCT,
00089   ET_LOOSESCAN,
00090   ET_START_TEMPORARY,
00091   ET_END_TEMPORARY,
00092   ET_FIRST_MATCH,
00093   ET_MATERIALIZE,
00094   ET_START_MATERIALIZE,
00095   ET_END_MATERIALIZE,
00096   ET_SCAN,
00097   ET_USING_JOIN_BUFFER,
00098   ET_CONST_ROW_NOT_FOUND,
00099   ET_UNIQUE_ROW_NOT_FOUND,
00100   ET_IMPOSSIBLE_ON_CONDITION,
00101   ET_PUSHED_JOIN,
00102   //------------------------------------
00103   ET_total
00104 };
00105 
00106 
00110 class Lazy: public Sql_alloc
00111 {
00112 public:
00113   virtual ~Lazy() {}
00114 
00123   virtual bool eval(String *ret)= 0;
00124 };
00125 
00132 struct Explain_context : Sql_alloc
00133 {
00134   Explain_context_enum type; 
00135 
00136   explicit Explain_context(Explain_context_enum type_arg) : type(type_arg) {}
00137 };
00138 
00139 
00140 namespace opt_explain_json_namespace // for forward declaration of "context"
00141 {
00142   class context;
00143 }
00144 
00155 class qep_row : public Sql_alloc
00156 {
00157 private:
00158   /* Don't copy this structure */
00159   explicit qep_row(const qep_row &x); // undefined
00160   qep_row &operator=(const qep_row &x); // undefined
00161 
00162 public:
00173   template<typename T>
00174   struct column
00175   {
00176   private:
00177     bool nil; 
00178   public:
00179     T value;
00180 
00181   public:
00182     column() { cleanup(); }
00183     bool is_empty() const { return nil; }
00184     void cleanup() { nil= true; }
00185     void set(T value_arg) { value= value_arg; nil= false; }
00186     T get() const { DBUG_ASSERT(!nil); return value; }
00187   };
00188 
00201   struct mem_root_str
00202   {
00203     const char *str;
00204     size_t length;
00205     Lazy *deferred; //< encapsulated expression to evaluate it later (on demand)
00206     
00207     mem_root_str() { cleanup(); }
00208     void cleanup()
00209     {
00210       str= NULL;
00211       length= 0;
00212       deferred= NULL;
00213     }
00214     bool is_empty()
00215     {
00216       if (deferred)
00217       {
00218         StringBuffer<128> buff(system_charset_info);
00219         if (deferred->eval(&buff) || set(buff))
00220         {
00221           DBUG_ASSERT(!"OOM!");
00222           return true; // ignore OOM
00223         }
00224         deferred= NULL; // prevent double evaluation, if any
00225       }
00226       return str == NULL;
00227     }
00228     bool set(const char *str_arg)
00229     {
00230       return set(str_arg, strlen(str_arg));
00231     }
00232     bool set(const String &s)
00233     {
00234       return set(s.ptr(), s.length());
00235     }
00244     bool set(const char *str_arg, size_t length_arg)
00245     {
00246       deferred= NULL;
00247       if (!(str= strndup_root(current_thd->mem_root, str_arg, length_arg)))
00248         return true; /* purecov: inspected */
00249       length= length_arg;
00250       return false;
00251     }
00257     void set(Lazy *x)
00258     {
00259       deferred= x;
00260       str= NULL;
00261       length= 0;
00262     }
00269     void set_const(const char *str_arg)
00270     {
00271       return set_const(str_arg, strlen(str_arg));
00272     }
00273     void set_const(const char *str_arg, size_t length_arg)
00274     {
00275       deferred= NULL;
00276       str= str_arg;
00277       length= length_arg;
00278     }
00279 
00280     static char *strndup_root(MEM_ROOT *root, const char *str, size_t len)
00281     {
00282       if (len == 0 || str == NULL)
00283         return const_cast<char *>("");
00284       if (str[len - 1] == 0)
00285         return static_cast<char *>(memdup_root(root, str, len));
00286 
00287       char *ret= static_cast<char*>(alloc_root(root, len + 1));
00288       if (ret != NULL)
00289       {
00290         memcpy(ret, str, len);
00291         ret[len]= 0;
00292       }
00293       return ret;
00294     }
00295   };
00296 
00300   struct extra: public Sql_alloc
00301   {
00305     const Extra_tag tag;
00312     const char *const data;
00313 
00314     explicit extra(Extra_tag tag_arg, const char *data_arg= NULL)
00315     : tag(tag_arg), data(data_arg)
00316     {}
00317   };
00318 
00319   /*
00320     Next "col_*" fields are intended to be filling by "explain_*()" functions.
00321 
00322     NOTE: NULL value or mem_root_str.is_empty()==true means that Item_null object
00323           will be pushed into "items" list instead.
00324   */
00325   column<uint> col_id; 
00326   column<SELECT_LEX::type_enum> col_select_type; 
00327   mem_root_str col_table_name; 
00328   List<const char> col_partitions; 
00329   mem_root_str col_join_type; 
00330   List<const char> col_possible_keys; 
00331   mem_root_str col_key; 
00332   mem_root_str col_key_len; 
00333   List<const char> col_ref; 
00334   column<longlong> col_rows; 
00335   column<float>    col_filtered; 
00336   List<extra> col_extra; 
00337 
00338   // non-TRADITIONAL stuff:
00339   mem_root_str col_message; 
00340   mem_root_str col_attached_condition; 
00341 
00342   /* For structured EXPLAIN in CTX_JOIN_TAB context: */
00343   uint query_block_id; 
00344 
00348   List<opt_explain_json_namespace::context> derived_from;
00349 
00350   List<const char> col_key_parts; 
00351 
00352   bool is_dependent;
00353   bool is_cacheable;
00354   bool using_temporary;
00355   bool is_materialized_from_subquery;
00356   bool is_update; //< UPDATE modified this table
00357   bool is_delete; //< DELETE modified this table
00358 
00359   qep_row() :
00360     query_block_id(0),
00361     is_dependent(false),
00362     is_cacheable(true),
00363     using_temporary(false),
00364     is_materialized_from_subquery(false),
00365     is_update(false),
00366     is_delete(false)
00367   {}
00368 
00369   virtual ~qep_row() {}
00370 
00371   void cleanup()
00372   {
00373     col_id.cleanup();
00374     col_table_name.cleanup();
00375     col_partitions.empty();
00376     col_join_type.cleanup();
00377     col_possible_keys.empty();
00378     col_key.cleanup();
00379     col_key_len.cleanup();
00380     col_ref.empty();
00381     col_rows.cleanup();
00382     col_filtered.cleanup();
00383     col_extra.empty();
00384     col_message.cleanup();
00385     col_attached_condition.cleanup();
00386     col_key_parts.empty();
00387 
00388     /*
00389       Not needed (we call cleanup() for structured EXPLAIN only,
00390       just for the consistency).
00391     */
00392     query_block_id= 0;
00393     derived_from.empty();
00394     is_dependent= false;
00395     is_cacheable= true;
00396     using_temporary= false;
00397     is_materialized_from_subquery= false;
00398     is_update= false;
00399     is_delete= false;
00400   }
00401 
00417   virtual void register_where_subquery(SELECT_LEX_UNIT *subquery) {}
00418 };
00419 
00420 
00428 struct Explain_subquery_marker
00429 {
00430   class qep_row *destination; 
00431   Explain_context_enum type; 
00432 
00433   Explain_subquery_marker(qep_row *destination_arg,
00434                           Explain_context_enum type_arg)
00435   : destination(destination_arg), type(type_arg)
00436   {}
00437 };
00438 
00444 enum Explain_sort_clause
00445 {
00446   ESC_none          = 0,
00447   ESC_ORDER_BY      = 1,
00448   ESC_GROUP_BY      = 2,
00449   ESC_DISTINCT      = 3,
00450   ESC_BUFFER_RESULT = 4,
00451 //-----------------
00452   ESC_MAX
00453 };
00454 
00458 enum Explain_sort_property
00459 {
00460   ESP_none           = 0,
00461   ESP_EXISTS         = 1 << 0, //< Original query has this clause
00462   ESP_IS_SIMPLE      = 1 << 1, //< Clause is effective for single JOIN_TAB only
00463   ESP_USING_FILESORT = 1 << 2, //< Clause causes a filesort
00464   ESP_USING_TMPTABLE = 1 << 3, //< Clause creates an intermediate table
00465   ESP_DUPS_REMOVAL   = 1 << 4, //< Duplicate removal for DISTINCT
00466   ESP_CHECKED        = 1 << 5  //< Properties were already checked
00467 };
00468 
00469 
00470 class Explain_format_flags
00471 {
00475   uint8 sorts[ESC_MAX];
00476 
00477 public:
00478   Explain_format_flags() { memset(sorts, 0, sizeof(sorts)); }
00479 
00483   void set(Explain_sort_clause clause, Explain_sort_property property)
00484   {
00485     sorts[clause]|= property | ESP_EXISTS;
00486   }
00487 
00488   void set(Explain_format_flags &flags)
00489   {
00490     memcpy(sorts, flags.sorts, sizeof(sorts));
00491   }
00492 
00496   void reset(Explain_sort_clause clause, Explain_sort_property property)
00497   {
00498     sorts[clause]&= ~property;
00499   }
00500 
00504   bool get(Explain_sort_clause clause, Explain_sort_property property) const
00505   {
00506     return (sorts[clause] & property) || (sorts[clause] & ESP_CHECKED);
00507   }
00508 
00512   bool any(Explain_sort_property property) const
00513   {
00514     for (size_t i= ESC_none + 1; i <= ESC_MAX - 1; i++)
00515     {
00516       if (sorts[i] & property || sorts[i] & ESP_CHECKED)
00517         return true;
00518     }
00519     return false;
00520   }
00521 };
00522 
00523 
00528 class Explain_format : public Sql_alloc
00529 {
00530 private:
00531   /* Don't copy Explain_format values */
00532   Explain_format(Explain_format &); // undefined
00533   Explain_format &operator=(Explain_format &); // undefined
00534 
00535 public:
00536   select_result *output; 
00537 
00538 public:
00539   Explain_format() : output(NULL) {}
00540   virtual ~Explain_format() {}
00541 
00542 
00549   virtual bool is_hierarchical() const= 0;
00550 
00561   virtual bool send_headers(select_result *result)
00562   {
00563     output= result;
00564     return false;
00565   }
00566 
00573   virtual bool begin_context(Explain_context_enum context,
00574                              SELECT_LEX_UNIT *subquery = 0,
00575                              const Explain_format_flags *flags= NULL)= 0;
00576 
00582   virtual bool end_context(Explain_context_enum context)= 0;
00583  
00589   virtual bool flush_entry()= 0;
00590 
00594   virtual qep_row *entry()= 0;
00595 };
00596 
00597 #endif//OPT_EXPLAIN_FORMAT_INCLUDED
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines