MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
opt_explain_format.h
1 /* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 
17 #ifndef OPT_EXPLAIN_FORMAT_INCLUDED
18 #define OPT_EXPLAIN_FORMAT_INCLUDED
19 
24 #include "sql_class.h"
25 
26 struct st_join_table;
27 
28 
33 enum Explain_context_enum
34 {
35  CTX_NONE= 0,
36  CTX_MESSAGE,
37  CTX_TABLE,
38  CTX_SELECT_LIST,
39  CTX_UPDATE_VALUE_LIST,
40  CTX_JOIN,
41  CTX_JOIN_TAB,
42  CTX_MATERIALIZATION,
43  CTX_DUPLICATES_WEEDOUT,
44  CTX_DERIVED,
45  CTX_WHERE,
46  CTX_HAVING,
47  CTX_ORDER_BY,
48  CTX_GROUP_BY,
49  CTX_SIMPLE_ORDER_BY,
50  CTX_SIMPLE_GROUP_BY,
51  CTX_DISTINCT,
52  CTX_SIMPLE_DISTINCT,
53  CTX_BUFFER_RESULT,
54  CTX_ORDER_BY_SQ,
55  CTX_GROUP_BY_SQ,
56  CTX_OPTIMIZED_AWAY_SUBQUERY,
57  CTX_UNION,
58  CTX_UNION_RESULT,
59  CTX_QUERY_SPEC
60 };
61 
62 
69 enum Extra_tag
70 {
71  ET_none,
72  ET_USING_TEMPORARY,
73  ET_USING_FILESORT,
74  ET_USING_INDEX_CONDITION,
75  ET_USING,
76  ET_RANGE_CHECKED_FOR_EACH_RECORD,
77  ET_USING_WHERE_WITH_PUSHED_CONDITION,
78  ET_USING_WHERE,
79  ET_NOT_EXISTS,
80  ET_USING_MRR,
81  ET_USING_INDEX,
82  ET_FULL_SCAN_ON_NULL_KEY,
83  ET_SKIP_OPEN_TABLE,
84  ET_OPEN_FRM_ONLY,
85  ET_OPEN_FULL_TABLE,
86  ET_SCANNED_DATABASES,
87  ET_USING_INDEX_FOR_GROUP_BY,
88  ET_DISTINCT,
89  ET_LOOSESCAN,
90  ET_START_TEMPORARY,
91  ET_END_TEMPORARY,
92  ET_FIRST_MATCH,
93  ET_MATERIALIZE,
94  ET_START_MATERIALIZE,
95  ET_END_MATERIALIZE,
96  ET_SCAN,
97  ET_USING_JOIN_BUFFER,
98  ET_CONST_ROW_NOT_FOUND,
99  ET_UNIQUE_ROW_NOT_FOUND,
100  ET_IMPOSSIBLE_ON_CONDITION,
101  ET_PUSHED_JOIN,
102  //------------------------------------
103  ET_total
104 };
105 
106 
110 class Lazy: public Sql_alloc
111 {
112 public:
113  virtual ~Lazy() {}
114 
123  virtual bool eval(String *ret)= 0;
124 };
125 
133 {
134  Explain_context_enum type;
135 
136  explicit Explain_context(Explain_context_enum type_arg) : type(type_arg) {}
137 };
138 
139 
140 namespace opt_explain_json_namespace // for forward declaration of "context"
141 {
142  class context;
143 }
144 
155 class qep_row : public Sql_alloc
156 {
157 private:
158  /* Don't copy this structure */
159  explicit qep_row(const qep_row &x); // undefined
160  qep_row &operator=(const qep_row &x); // undefined
161 
162 public:
173  template<typename T>
174  struct column
175  {
176  private:
177  bool nil;
178  public:
179  T value;
180 
181  public:
182  column() { cleanup(); }
183  bool is_empty() const { return nil; }
184  void cleanup() { nil= true; }
185  void set(T value_arg) { value= value_arg; nil= false; }
186  T get() const { DBUG_ASSERT(!nil); return value; }
187  };
188 
202  {
203  const char *str;
204  size_t length;
205  Lazy *deferred; //< encapsulated expression to evaluate it later (on demand)
206 
207  mem_root_str() { cleanup(); }
208  void cleanup()
209  {
210  str= NULL;
211  length= 0;
212  deferred= NULL;
213  }
214  bool is_empty()
215  {
216  if (deferred)
217  {
218  StringBuffer<128> buff(system_charset_info);
219  if (deferred->eval(&buff) || set(buff))
220  {
221  DBUG_ASSERT(!"OOM!");
222  return true; // ignore OOM
223  }
224  deferred= NULL; // prevent double evaluation, if any
225  }
226  return str == NULL;
227  }
228  bool set(const char *str_arg)
229  {
230  return set(str_arg, strlen(str_arg));
231  }
232  bool set(const String &s)
233  {
234  return set(s.ptr(), s.length());
235  }
244  bool set(const char *str_arg, size_t length_arg)
245  {
246  deferred= NULL;
247  if (!(str= strndup_root(current_thd->mem_root, str_arg, length_arg)))
248  return true; /* purecov: inspected */
249  length= length_arg;
250  return false;
251  }
257  void set(Lazy *x)
258  {
259  deferred= x;
260  str= NULL;
261  length= 0;
262  }
269  void set_const(const char *str_arg)
270  {
271  return set_const(str_arg, strlen(str_arg));
272  }
273  void set_const(const char *str_arg, size_t length_arg)
274  {
275  deferred= NULL;
276  str= str_arg;
277  length= length_arg;
278  }
279 
280  static char *strndup_root(MEM_ROOT *root, const char *str, size_t len)
281  {
282  if (len == 0 || str == NULL)
283  return const_cast<char *>("");
284  if (str[len - 1] == 0)
285  return static_cast<char *>(memdup_root(root, str, len));
286 
287  char *ret= static_cast<char*>(alloc_root(root, len + 1));
288  if (ret != NULL)
289  {
290  memcpy(ret, str, len);
291  ret[len]= 0;
292  }
293  return ret;
294  }
295  };
296 
300  struct extra: public Sql_alloc
301  {
305  const Extra_tag tag;
312  const char *const data;
313 
314  explicit extra(Extra_tag tag_arg, const char *data_arg= NULL)
315  : tag(tag_arg), data(data_arg)
316  {}
317  };
318 
319  /*
320  Next "col_*" fields are intended to be filling by "explain_*()" functions.
321 
322  NOTE: NULL value or mem_root_str.is_empty()==true means that Item_null object
323  will be pushed into "items" list instead.
324  */
337 
338  // non-TRADITIONAL stuff:
341 
342  /* For structured EXPLAIN in CTX_JOIN_TAB context: */
344 
349 
351 
352  bool is_dependent;
353  bool is_cacheable;
354  bool using_temporary;
355  bool is_materialized_from_subquery;
356  bool is_update; //< UPDATE modified this table
357  bool is_delete; //< DELETE modified this table
358 
359  qep_row() :
360  query_block_id(0),
361  is_dependent(false),
362  is_cacheable(true),
363  using_temporary(false),
364  is_materialized_from_subquery(false),
365  is_update(false),
366  is_delete(false)
367  {}
368 
369  virtual ~qep_row() {}
370 
371  void cleanup()
372  {
373  col_id.cleanup();
374  col_table_name.cleanup();
375  col_partitions.empty();
376  col_join_type.cleanup();
377  col_possible_keys.empty();
378  col_key.cleanup();
379  col_key_len.cleanup();
380  col_ref.empty();
381  col_rows.cleanup();
382  col_filtered.cleanup();
383  col_extra.empty();
384  col_message.cleanup();
385  col_attached_condition.cleanup();
386  col_key_parts.empty();
387 
388  /*
389  Not needed (we call cleanup() for structured EXPLAIN only,
390  just for the consistency).
391  */
392  query_block_id= 0;
393  derived_from.empty();
394  is_dependent= false;
395  is_cacheable= true;
396  using_temporary= false;
397  is_materialized_from_subquery= false;
398  is_update= false;
399  is_delete= false;
400  }
401 
417  virtual void register_where_subquery(SELECT_LEX_UNIT *subquery) {}
418 };
419 
420 
429 {
431  Explain_context_enum type;
432 
433  Explain_subquery_marker(qep_row *destination_arg,
434  Explain_context_enum type_arg)
435  : destination(destination_arg), type(type_arg)
436  {}
437 };
438 
444 enum Explain_sort_clause
445 {
446  ESC_none = 0,
447  ESC_ORDER_BY = 1,
448  ESC_GROUP_BY = 2,
449  ESC_DISTINCT = 3,
450  ESC_BUFFER_RESULT = 4,
451 //-----------------
452  ESC_MAX
453 };
454 
458 enum Explain_sort_property
459 {
460  ESP_none = 0,
461  ESP_EXISTS = 1 << 0, //< Original query has this clause
462  ESP_IS_SIMPLE = 1 << 1, //< Clause is effective for single JOIN_TAB only
463  ESP_USING_FILESORT = 1 << 2, //< Clause causes a filesort
464  ESP_USING_TMPTABLE = 1 << 3, //< Clause creates an intermediate table
465  ESP_DUPS_REMOVAL = 1 << 4, //< Duplicate removal for DISTINCT
466  ESP_CHECKED = 1 << 5 //< Properties were already checked
467 };
468 
469 
471 {
475  uint8 sorts[ESC_MAX];
476 
477 public:
478  Explain_format_flags() { memset(sorts, 0, sizeof(sorts)); }
479 
483  void set(Explain_sort_clause clause, Explain_sort_property property)
484  {
485  sorts[clause]|= property | ESP_EXISTS;
486  }
487 
488  void set(Explain_format_flags &flags)
489  {
490  memcpy(sorts, flags.sorts, sizeof(sorts));
491  }
492 
496  void reset(Explain_sort_clause clause, Explain_sort_property property)
497  {
498  sorts[clause]&= ~property;
499  }
500 
504  bool get(Explain_sort_clause clause, Explain_sort_property property) const
505  {
506  return (sorts[clause] & property) || (sorts[clause] & ESP_CHECKED);
507  }
508 
512  bool any(Explain_sort_property property) const
513  {
514  for (size_t i= ESC_none + 1; i <= ESC_MAX - 1; i++)
515  {
516  if (sorts[i] & property || sorts[i] & ESP_CHECKED)
517  return true;
518  }
519  return false;
520  }
521 };
522 
523 
528 class Explain_format : public Sql_alloc
529 {
530 private:
531  /* Don't copy Explain_format values */
532  Explain_format(Explain_format &); // undefined
533  Explain_format &operator=(Explain_format &); // undefined
534 
535 public:
536  select_result *output;
537 
538 public:
539  Explain_format() : output(NULL) {}
540  virtual ~Explain_format() {}
541 
542 
549  virtual bool is_hierarchical() const= 0;
550 
561  virtual bool send_headers(select_result *result)
562  {
563  output= result;
564  return false;
565  }
566 
573  virtual bool begin_context(Explain_context_enum context,
574  SELECT_LEX_UNIT *subquery = 0,
575  const Explain_format_flags *flags= NULL)= 0;
576 
582  virtual bool end_context(Explain_context_enum context)= 0;
583 
589  virtual bool flush_entry()= 0;
590 
594  virtual qep_row *entry()= 0;
595 };
596 
597 #endif//OPT_EXPLAIN_FORMAT_INCLUDED