1 /*
2    Copyright (c) 2013 Monty Program Ab
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
16 
17 /*
18 
19 == EXPLAIN/ANALYZE architecture ==
20 
21 === [SHOW] EXPLAIN data ===
22 Query optimization produces two data structures:
23 1. execution data structures themselves (eg. JOINs, JOIN_TAB, etc, etc)
24 2. Explain data structures.
25 
26 #2 are self contained set of data structures that has sufficient info to
27 produce output of SHOW EXPLAIN, EXPLAIN [FORMAT=JSON], or
28 ANALYZE [FORMAT=JSON], without accessing the execution data structures.
29 
30 (the only exception is that Explain data structures keep Item* pointers,
31 and we require that one might call item->print(QT_EXPLAIN) when printing
32 FORMAT=JSON output)
33 
34 === ANALYZE data ===
35 EXPLAIN data structures have embedded ANALYZE data structures. These are
36 objects that are used to track how the parts of query plan were executed:
37 how many times each part of query plan was invoked, how many rows were
38 read/returned, etc.
39 
40 Each execution data structure keeps a direct pointer to its ANALYZE data
41 structure. It is needed so that execution code can quickly increment the
42 counters.
43 
44 (note that this increases the set of data that is frequently accessed
45 during the execution. What is the impact of this?)
46 
47 Since ANALYZE/EXPLAIN data structures are separated from execution data
48 structures, it is easy to have them survive until the end of the query,
49 where we can return ANALYZE [FORMAT=JSON] output to the user, or print
50 it into the slow query log.
51 
52 */
53 
54 #ifndef SQL_EXPLAIN_INCLUDED
55 #define SQL_EXPLAIN_INCLUDED
56 
57 class String_list: public List<char>
58 {
59 public:
60   const char *append_str(MEM_ROOT *mem_root, const char *str);
61 };
62 
63 class Json_writer;
64 
65 /**************************************************************************************
66 
67   Data structures for producing EXPLAIN outputs.
68 
69   These structures
70   - Can be produced inexpensively from query plan.
71   - Store sufficient information to produce tabular EXPLAIN output (the goal is
72     to be able to produce JSON also)
73 
74 *************************************************************************************/
75 
76 
77 const int FAKE_SELECT_LEX_ID= (int)UINT_MAX;
78 
79 class Explain_query;
80 
81 /*
82   A node can be either a SELECT, or a UNION.
83 */
84 class Explain_node : public Sql_alloc
85 {
86 public:
Explain_node(MEM_ROOT * root)87   Explain_node(MEM_ROOT *root) :
88     cache_tracker(NULL),
89     connection_type(EXPLAIN_NODE_OTHER),
90     children(root)
91   {}
92   /* A type specifying what kind of node this is */
93   enum explain_node_type
94   {
95     EXPLAIN_UNION,
96     EXPLAIN_SELECT,
97     EXPLAIN_BASIC_JOIN,
98     EXPLAIN_UPDATE,
99     EXPLAIN_DELETE,
100     EXPLAIN_INSERT
101   };
102 
103   /* How this node is connected */
104   enum explain_connection_type {
105     EXPLAIN_NODE_OTHER,
106     EXPLAIN_NODE_DERIVED, /* Materialized derived table */
107     EXPLAIN_NODE_NON_MERGED_SJ /* aka JTBM semi-join */
108   };
109 
110   virtual enum explain_node_type get_type()= 0;
111   virtual int get_select_id()= 0;
112 
113   /**
114     expression cache statistics
115   */
116   Expression_cache_tracker* cache_tracker;
117 
118   /*
119     How this node is connected to its parent.
120     (NOTE: EXPLAIN_NODE_NON_MERGED_SJ is set very late currently)
121   */
122   enum explain_connection_type connection_type;
123 
124 protected:
125   /*
126     A node may have children nodes. When a node's explain structure is
127     created, children nodes may not yet have QPFs. This is why we store ids.
128   */
129   Dynamic_array<int> children;
130 public:
add_child(int select_no)131   void add_child(int select_no)
132   {
133     children.append(select_no);
134   }
135 
136   virtual int print_explain(Explain_query *query, select_result_sink *output,
137                             uint8 explain_flags, bool is_analyze)=0;
138   virtual void print_explain_json(Explain_query *query, Json_writer *writer,
139                                   bool is_analyze)= 0;
140 
141   int print_explain_for_children(Explain_query *query, select_result_sink *output,
142                                  uint8 explain_flags, bool is_analyze);
143   void print_explain_json_for_children(Explain_query *query,
144                                        Json_writer *writer, bool is_analyze);
145   bool print_explain_json_cache(Json_writer *writer, bool is_analyze);
~Explain_node()146   virtual ~Explain_node(){}
147 };
148 
149 
150 class Explain_table_access;
151 
152 
153 /*
154   A basic join. This is only used for SJ-Materialization nests.
155 
156   Basic join doesn't have ORDER/GROUP/DISTINCT operations. It also cannot be
157   degenerate.
158 
159   It has its own select_id.
160 */
161 class Explain_basic_join : public Explain_node
162 {
163 public:
get_type()164   enum explain_node_type get_type() { return EXPLAIN_BASIC_JOIN; }
165 
Explain_basic_join(MEM_ROOT * root)166   Explain_basic_join(MEM_ROOT *root) : Explain_node(root), join_tabs(NULL) {}
167   ~Explain_basic_join();
168 
169   bool add_table(Explain_table_access *tab, Explain_query *query);
170 
get_select_id()171   int get_select_id() { return select_id; }
172 
173   int select_id;
174 
175   int print_explain(Explain_query *query, select_result_sink *output,
176                     uint8 explain_flags, bool is_analyze);
177   void print_explain_json(Explain_query *query, Json_writer *writer,
178                           bool is_analyze);
179 
180   void print_explain_json_interns(Explain_query *query, Json_writer *writer,
181                                   bool is_analyze);
182 
183   /* A flat array of Explain structs for tables. */
184   Explain_table_access** join_tabs;
185   uint n_join_tabs;
186 };
187 
188 
189 class Explain_aggr_node;
190 /*
191   EXPLAIN structure for a SELECT.
192 
193   A select can be:
194   1. A degenerate case. In this case, message!=NULL, and it contains a
195      description of what kind of degenerate case it is (e.g. "Impossible
196      WHERE").
197   2. a non-degenrate join. In this case, join_tabs describes the join.
198 
199   In the non-degenerate case, a SELECT may have a GROUP BY/ORDER BY operation.
200 
201   In both cases, the select may have children nodes. class Explain_node
202   provides a way get node's children.
203 */
204 
205 class Explain_select : public Explain_basic_join
206 {
207 public:
get_type()208   enum explain_node_type get_type() { return EXPLAIN_SELECT; }
209 
Explain_select(MEM_ROOT * root,bool is_analyze)210   Explain_select(MEM_ROOT *root, bool is_analyze) :
211   Explain_basic_join(root),
212 #ifndef DBUG_OFF
213     select_lex(NULL),
214 #endif
215     linkage(UNSPECIFIED_TYPE),
216     is_lateral(false),
217     message(NULL),
218     having(NULL), having_value(Item::COND_UNDEF),
219     using_temporary(false), using_filesort(false),
220     time_tracker(is_analyze),
221     aggr_tree(NULL)
222   {}
223 
224   void add_linkage(Json_writer *writer);
225 
226 public:
227 #ifndef DBUG_OFF
228   SELECT_LEX *select_lex;
229 #endif
230   const char *select_type;
231   enum sub_select_type linkage;
232   bool is_lateral;
233 
234   /*
235     If message != NULL, this is a degenerate join plan, and all subsequent
236     members have no info
237   */
238   const char *message;
239 
240   /* Expensive constant condition */
241   Item *exec_const_cond;
242   Item *outer_ref_cond;
243   Item *pseudo_bits_cond;
244 
245   /* HAVING condition */
246   Item *having;
247   Item::cond_result having_value;
248 
249   /* Global join attributes. In tabular form, they are printed on the first row */
250   bool using_temporary;
251   bool using_filesort;
252 
253   /* ANALYZE members */
254   Time_and_counter_tracker time_tracker;
255 
256   /*
257     Part of query plan describing sorting, temp.table usage, and duplicate
258     removal
259   */
260   Explain_aggr_node* aggr_tree;
261 
262   int print_explain(Explain_query *query, select_result_sink *output,
263                     uint8 explain_flags, bool is_analyze);
264   void print_explain_json(Explain_query *query, Json_writer *writer,
265                           bool is_analyze);
266 
get_using_temporary_read_tracker()267   Table_access_tracker *get_using_temporary_read_tracker()
268   {
269     return &using_temporary_read_tracker;
270   }
271 private:
272   Table_access_tracker using_temporary_read_tracker;
273 };
274 
275 /////////////////////////////////////////////////////////////////////////////
276 // EXPLAIN structures for ORDER/GROUP operations.
277 /////////////////////////////////////////////////////////////////////////////
278 typedef enum
279 {
280   AGGR_OP_TEMP_TABLE,
281   AGGR_OP_FILESORT,
282   //AGGR_OP_READ_SORTED_FILE, // need this?
283   AGGR_OP_REMOVE_DUPLICATES,
284   AGGR_OP_WINDOW_FUNCS
285   //AGGR_OP_JOIN // Need this?
286 } enum_explain_aggr_node_type;
287 
288 
289 class Explain_aggr_node : public Sql_alloc
290 {
291 public:
292   virtual enum_explain_aggr_node_type get_type()= 0;
~Explain_aggr_node()293   virtual ~Explain_aggr_node() {}
294   Explain_aggr_node *child;
295 };
296 
297 class Explain_aggr_filesort : public Explain_aggr_node
298 {
299   List<Item> sort_items;
300   List<ORDER::enum_order> sort_directions;
301 public:
get_type()302   enum_explain_aggr_node_type get_type() { return AGGR_OP_FILESORT; }
303   Filesort_tracker tracker;
304 
305   Explain_aggr_filesort(MEM_ROOT *mem_root, bool is_analyze,
306                         Filesort *filesort);
307 
308   void print_json_members(Json_writer *writer, bool is_analyze);
309 };
310 
311 class Explain_aggr_tmp_table : public Explain_aggr_node
312 {
313 public:
get_type()314   enum_explain_aggr_node_type get_type() { return AGGR_OP_TEMP_TABLE; }
315 };
316 
317 class Explain_aggr_remove_dups : public Explain_aggr_node
318 {
319 public:
get_type()320   enum_explain_aggr_node_type get_type() { return AGGR_OP_REMOVE_DUPLICATES; }
321 };
322 
323 class Explain_aggr_window_funcs : public Explain_aggr_node
324 {
325   List<Explain_aggr_filesort> sorts;
326 public:
get_type()327   enum_explain_aggr_node_type get_type() { return AGGR_OP_WINDOW_FUNCS; }
328 
329   void print_json_members(Json_writer *writer, bool is_analyze);
330   friend class Window_funcs_computation;
331 };
332 
333 /////////////////////////////////////////////////////////////////////////////
334 
335 extern const char *unit_operation_text[4];
336 extern const char *pushed_derived_text;
337 extern const char *pushed_select_text;
338 
339 /*
340   Explain structure for a UNION.
341 
342   A UNION may or may not have "Using filesort".
343 */
344 
345 class Explain_union : public Explain_node
346 {
347 public:
Explain_union(MEM_ROOT * root,bool is_analyze)348   Explain_union(MEM_ROOT *root, bool is_analyze) :
349     Explain_node(root),
350     is_recursive_cte(false),
351     fake_select_lex_explain(root, is_analyze)
352   {}
353 
get_type()354   enum explain_node_type get_type() { return EXPLAIN_UNION; }
355   unit_common_op operation;
356 
get_select_id()357   int get_select_id()
358   {
359     DBUG_ASSERT(union_members.elements() > 0);
360     return union_members.at(0);
361   }
362   /*
363     Members of the UNION.  Note: these are different from UNION's "children".
364     Example:
365 
366       (select * from t1) union
367       (select * from t2) order by (select col1 from t3 ...)
368 
369     here
370       - select-from-t1 and select-from-t2 are "union members",
371       - select-from-t3 is the only "child".
372   */
373   Dynamic_array<int> union_members;
374 
add_select(int select_no)375   void add_select(int select_no)
376   {
377     union_members.append(select_no);
378   }
379   int print_explain(Explain_query *query, select_result_sink *output,
380                     uint8 explain_flags, bool is_analyze);
381   void print_explain_json(Explain_query *query, Json_writer *writer,
382                           bool is_analyze);
383 
384   const char *fake_select_type;
385   bool using_filesort;
386   bool using_tmp;
387   bool is_recursive_cte;
388 
389   /*
390     Explain data structure for "fake_select_lex" (i.e. for the degenerate
391     SELECT that reads UNION result).
392     It doesn't have a query plan, but we still need execution tracker, etc.
393   */
394   Explain_select fake_select_lex_explain;
395 
get_fake_select_lex_tracker()396   Table_access_tracker *get_fake_select_lex_tracker()
397   {
398     return &fake_select_lex_tracker;
399   }
get_tmptable_read_tracker()400   Table_access_tracker *get_tmptable_read_tracker()
401   {
402     return &tmptable_read_tracker;
403   }
404 private:
405   uint make_union_table_name(char *buf);
406 
407   Table_access_tracker fake_select_lex_tracker;
408   /* This one is for reading after ORDER BY */
409   Table_access_tracker tmptable_read_tracker;
410 };
411 
412 
413 class Explain_update;
414 class Explain_delete;
415 class Explain_insert;
416 
417 
418 /*
419   Explain structure for a query (i.e. a statement).
420 
421   This should be able to survive when the query plan was deleted. Currently,
422   we do not intend for it survive until after query's MEM_ROOT is freed. It
423   does surivive freeing of query's items.
424 
425   For reference, the process of post-query cleanup is as follows:
426 
427     >dispatch_command
428     | >mysql_parse
429     | |  ...
430     | | lex_end()
431     | |  ...
432     | | >THD::cleanup_after_query
433     | | | ...
434     | | | free_items()
435     | | | ...
436     | | <THD::cleanup_after_query
437     | |
438     | <mysql_parse
439     |
440     | log_slow_statement()
441     |
442     | free_root()
443     |
444     >dispatch_command
445 
446   That is, the order of actions is:
447     - free query's Items
448     - write to slow query log
449     - free query's MEM_ROOT
450 
451 */
452 
453 class Explain_query : public Sql_alloc
454 {
455 public:
456   Explain_query(THD *thd, MEM_ROOT *root);
457   ~Explain_query();
458 
459   /* Add a new node */
460   void add_node(Explain_node *node);
461   void add_insert_plan(Explain_insert *insert_plan_arg);
462   void add_upd_del_plan(Explain_update *upd_del_plan_arg);
463 
464   /* This will return a select, or a union */
465   Explain_node *get_node(uint select_id);
466 
467   /* This will return a select (even if there is a union with this id) */
468   Explain_select *get_select(uint select_id);
469 
470   Explain_union *get_union(uint select_id);
471 
472   /* Produce a tabular EXPLAIN output */
473   int print_explain(select_result_sink *output, uint8 explain_flags,
474                     bool is_analyze);
475 
476   /* Send tabular EXPLAIN to the client */
477   int send_explain(THD *thd);
478 
479   /* Return tabular EXPLAIN output as a text string */
480   bool print_explain_str(THD *thd, String *out_str, bool is_analyze);
481 
482   void print_explain_json(select_result_sink *output, bool is_analyze);
483 
484   /* If true, at least part of EXPLAIN can be printed */
have_query_plan()485   bool have_query_plan() { return insert_plan || upd_del_plan|| get_node(1) != NULL; }
486 
487   void query_plan_ready();
488 
489   MEM_ROOT *mem_root;
490 
get_upd_del_plan()491   Explain_update *get_upd_del_plan() { return upd_del_plan; }
492 private:
493   /* Explain_delete inherits from Explain_update */
494   Explain_update *upd_del_plan;
495 
496   /* Query "plan" for INSERTs */
497   Explain_insert *insert_plan;
498 
499   Dynamic_array<Explain_union*> unions;
500   Dynamic_array<Explain_select*> selects;
501 
502   THD *thd; // for APC start/stop
503   bool apc_enabled;
504   /*
505     Debugging aid: count how many times add_node() was called. Ideally, it
506     should be one, we currently allow O(1) query plan saves for each
507     select or union.  The goal is not to have O(#rows_in_some_table), which
508     is unacceptable.
509   */
510   longlong operations;
511 };
512 
513 
514 /*
515   Some of the tags have matching text. See extra_tag_text for text names, and
516   Explain_table_access::append_tag_name() for code to convert from tag form to text
517   form.
518 */
519 enum explain_extra_tag
520 {
521   ET_none= 0, /* not-a-tag */
522   ET_USING_INDEX_CONDITION,
523   ET_USING_INDEX_CONDITION_BKA,
524   ET_USING, /* For quick selects of various kinds */
525   ET_RANGE_CHECKED_FOR_EACH_RECORD,
526   ET_USING_WHERE_WITH_PUSHED_CONDITION,
527   ET_USING_WHERE,
528   ET_NOT_EXISTS,
529 
530   ET_USING_INDEX,
531   ET_FULL_SCAN_ON_NULL_KEY,
532   ET_SKIP_OPEN_TABLE,
533   ET_OPEN_FRM_ONLY,
534   ET_OPEN_FULL_TABLE,
535 
536   ET_SCANNED_0_DATABASES,
537   ET_SCANNED_1_DATABASE,
538   ET_SCANNED_ALL_DATABASES,
539 
540   ET_USING_INDEX_FOR_GROUP_BY,
541 
542   ET_USING_MRR, // does not print "Using mrr".
543 
544   ET_DISTINCT,
545   ET_LOOSESCAN,
546   ET_START_TEMPORARY,
547   ET_END_TEMPORARY,
548   ET_FIRST_MATCH,
549 
550   ET_USING_JOIN_BUFFER,
551 
552   ET_CONST_ROW_NOT_FOUND,
553   ET_UNIQUE_ROW_NOT_FOUND,
554   ET_IMPOSSIBLE_ON_CONDITION,
555 
556   ET_total
557 };
558 
559 
560 /*
561   Explain data structure describing join buffering use.
562 */
563 
564 class EXPLAIN_BKA_TYPE
565 {
566 public:
EXPLAIN_BKA_TYPE()567   EXPLAIN_BKA_TYPE() : join_alg(NULL) {}
568 
569   size_t join_buffer_size;
570 
571   bool incremental;
572 
573   /*
574     NULL if no join buferring used.
575     Other values: BNL, BNLH, BKA, BKAH.
576   */
577   const char *join_alg;
578 
579   /* Information about MRR usage.  */
580   StringBuffer<64> mrr_type;
581 
is_using_jbuf()582   bool is_using_jbuf() { return (join_alg != NULL); }
583 };
584 
585 
586 /*
587   Data about how an index is used by some access method
588 */
589 class Explain_index_use : public Sql_alloc
590 {
591   char *key_name;
592   uint key_len;
593   char *filter_name;
594   uint filter_len;
595 public:
596   String_list key_parts_list;
597 
Explain_index_use()598   Explain_index_use()
599   {
600     clear();
601   }
602 
clear()603   void clear()
604   {
605     key_name= NULL;
606     key_len= (uint)-1;
607     filter_name= NULL;
608     filter_len= (uint)-1;
609   }
610   bool set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
611   bool set_pseudo_key(MEM_ROOT *root, const char *key_name);
612 
get_key_name()613   inline const char *get_key_name() const { return key_name; }
get_key_len()614   inline uint get_key_len() const { return key_len; }
615   //inline const char *get_filter_name() const { return filter_name; }
616 };
617 
618 
619 /*
620   Query Plan data structure for Rowid filter.
621 */
622 class Explain_rowid_filter : public Sql_alloc
623 {
624 public:
625   /* Quick select used to collect the rowids into filter */
626   Explain_quick_select *quick;
627 
628   /* How many rows the above quick select is expected to return */
629   ha_rows rows;
630 
631   /* Expected selectivity for the filter */
632   double selectivity;
633 
634   /* Tracker with the information about how rowid filter is executed */
635   Rowid_filter_tracker *tracker;
636 
637   void print_explain_json(Explain_query *query, Json_writer *writer,
638                           bool is_analyze);
639 
640   /*
641     TODO:
642       Here should be ANALYZE members:
643       - r_rows for the quick select
644       - An object that tracked the table access time
645       - real selectivity of the filter.
646   */
647 };
648 
649 
650 /*
651   QPF for quick range selects, as well as index_merge select
652 */
653 class Explain_quick_select : public Sql_alloc
654 {
655 public:
Explain_quick_select(int quick_type_arg)656   Explain_quick_select(int quick_type_arg) : quick_type(quick_type_arg)
657   {}
658 
659   const int quick_type;
660 
is_basic()661   bool is_basic()
662   {
663     return (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE ||
664             quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC ||
665             quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX);
666   }
667 
668   /* This is used when quick_type == QUICK_SELECT_I::QS_TYPE_RANGE */
669   Explain_index_use range;
670 
671   /* Used in all other cases */
672   List<Explain_quick_select> children;
673 
674   void print_extra(String *str);
675   void print_key(String *str);
676   void print_key_len(String *str);
677 
678   void print_json(Json_writer *writer);
679 
680   void print_extra_recursive(String *str);
681 private:
682   const char *get_name_by_type();
683 };
684 
685 
686 /*
687   Data structure for "range checked for each record".
688   It's a set of keys, tabular explain prints hex bitmap, json prints key names.
689 */
690 
691 typedef const char* NAME;
692 
693 class Explain_range_checked_fer : public Sql_alloc
694 {
695 public:
696   String_list key_set;
697   key_map keys_map;
698 private:
699   ha_rows full_scan, index_merge;
700   ha_rows *keys_stat;
701   NAME *keys_stat_names;
702   uint keys;
703 
704 public:
Explain_range_checked_fer()705   Explain_range_checked_fer()
706     :Sql_alloc(), full_scan(0), index_merge(0),
707     keys_stat(0), keys_stat_names(0), keys(0)
708   {}
709 
710   int append_possible_keys_stat(MEM_ROOT *alloc,
711                                 TABLE *table, key_map possible_keys);
712   void collect_data(QUICK_SELECT_I *quick);
713   void print_json(Json_writer *writer, bool is_analyze);
714 };
715 
716 
717 /*
718   EXPLAIN data structure for a single JOIN_TAB.
719 */
720 
721 class Explain_table_access : public Sql_alloc
722 {
723 public:
Explain_table_access(MEM_ROOT * root)724   Explain_table_access(MEM_ROOT *root) :
725     derived_select_number(0),
726     non_merged_sjm_number(0),
727     extra_tags(root),
728     range_checked_fer(NULL),
729     full_scan_on_null_key(false),
730     start_dups_weedout(false),
731     end_dups_weedout(false),
732     where_cond(NULL),
733     cache_cond(NULL),
734     pushed_index_cond(NULL),
735     sjm_nest(NULL),
736     pre_join_sort(NULL),
737     rowid_filter(NULL)
738   {}
~Explain_table_access()739   ~Explain_table_access() { delete sjm_nest; }
740 
741   void push_extra(enum explain_extra_tag extra_tag);
742 
743   /* Internals */
744 
745   /* id and 'select_type' are cared-of by the parent Explain_select */
746   StringBuffer<32> table_name;
747   StringBuffer<32> used_partitions;
748   String_list used_partitions_list;
749   // valid with ET_USING_MRR
750   StringBuffer<32> mrr_type;
751   StringBuffer<32> firstmatch_table_name;
752 
753   /*
754     Non-zero number means this is a derived table. The number can be used to
755     find the query plan for the derived table
756   */
757   int derived_select_number;
758   /* TODO: join with the previous member. */
759   int non_merged_sjm_number;
760 
761   enum join_type type;
762 
763   bool used_partitions_set;
764 
765   /* Empty means "NULL" will be printed */
766   String_list possible_keys;
767 
768   bool rows_set; /* not set means 'NULL' should be printed */
769   bool filtered_set; /* not set means 'NULL' should be printed */
770   // Valid if ET_USING_INDEX_FOR_GROUP_BY is present
771   bool loose_scan_is_scanning;
772 
773   /*
774     Index use: key name and length.
775     Note: that when one is accessing I_S tables, those may show use of
776     non-existant indexes.
777 
778     key.key_name == NULL means 'NULL' will be shown in tabular output.
779     key.key_len == (uint)-1 means 'NULL' will be shown in tabular output.
780   */
781   Explain_index_use key;
782 
783   /*
784     when type==JT_HASH_NEXT, 'key' stores the hash join pseudo-key.
785     hash_next_key stores the table's key.
786   */
787   Explain_index_use hash_next_key;
788 
789   String_list ref_list;
790 
791   ha_rows rows;
792   double filtered;
793 
794   /*
795     Contents of the 'Extra' column. Some are converted into strings, some have
796     parameters, values for which are stored below.
797   */
798   Dynamic_array<enum explain_extra_tag> extra_tags;
799 
800   // Valid if ET_USING tag is present
801   Explain_quick_select *quick_info;
802 
803   /* Non-NULL value means this tab uses "range checked for each record" */
804   Explain_range_checked_fer *range_checked_fer;
805 
806   bool full_scan_on_null_key;
807 
808   // valid with ET_USING_JOIN_BUFFER
809   EXPLAIN_BKA_TYPE bka_type;
810 
811   bool start_dups_weedout;
812   bool end_dups_weedout;
813 
814   /*
815     Note: lifespan of WHERE condition is less than lifespan of this object.
816     The below two are valid if tags include "ET_USING_WHERE".
817     (TODO: indexsubquery may put ET_USING_WHERE without setting where_cond?)
818   */
819   Item *where_cond;
820   Item *cache_cond;
821 
822   /*
823     This is either pushed index condition, or BKA's index condition.
824     (the latter refers to columns of other tables and so can only be checked by
825      BKA code). Examine extra_tags to tell which one it is.
826   */
827   Item *pushed_index_cond;
828 
829   Explain_basic_join *sjm_nest;
830 
831   /*
832     This describes a possible filesort() call that is done before doing the
833     join operation.
834   */
835   Explain_aggr_filesort *pre_join_sort;
836 
837   /* ANALYZE members */
838 
839   /* Tracker for reading the table */
840   Table_access_tracker tracker;
841   Exec_time_tracker op_tracker;
842   Table_access_tracker jbuf_tracker;
843 
844   Explain_rowid_filter *rowid_filter;
845 
846   int print_explain(select_result_sink *output, uint8 explain_flags,
847                     bool is_analyze,
848                     uint select_id, const char *select_type,
849                     bool using_temporary, bool using_filesort);
850   void print_explain_json(Explain_query *query, Json_writer *writer,
851                           bool is_analyze);
852 
853 private:
854   void append_tag_name(String *str, enum explain_extra_tag tag);
855   void fill_key_str(String *key_str, bool is_json) const;
856   void fill_key_len_str(String *key_len_str, bool is_json) const;
857   double get_r_filtered();
858   void tag_to_json(Json_writer *writer, enum explain_extra_tag tag);
859 };
860 
861 
862 /*
863   EXPLAIN structure for single-table UPDATE.
864 
865   This is similar to Explain_table_access, except that it is more restrictive.
866   Also, it can have UPDATE operation options, but currently there aren't any.
867 
868   Explain_delete inherits from this.
869 */
870 
871 class Explain_update : public Explain_node
872 {
873 public:
874 
Explain_update(MEM_ROOT * root,bool is_analyze)875   Explain_update(MEM_ROOT *root, bool is_analyze) :
876     Explain_node(root),
877     filesort_tracker(NULL),
878     command_tracker(is_analyze)
879   {}
880 
get_type()881   virtual enum explain_node_type get_type() { return EXPLAIN_UPDATE; }
get_select_id()882   virtual int get_select_id() { return 1; /* always root */ }
883 
884   const char *select_type;
885 
886   StringBuffer<32> used_partitions;
887   String_list used_partitions_list;
888   bool used_partitions_set;
889 
890   bool impossible_where;
891   bool no_partitions;
892   StringBuffer<64> table_name;
893 
894   enum join_type jtype;
895   String_list possible_keys;
896 
897   /* Used key when doing a full index scan (possibly with limit) */
898   Explain_index_use key;
899 
900   /*
901     MRR that's used with quick select. This should probably belong to the
902     quick select
903   */
904   StringBuffer<64> mrr_type;
905 
906   Explain_quick_select *quick_info;
907 
908   bool using_where;
909   Item *where_cond;
910 
911   ha_rows rows;
912 
913   bool using_io_buffer;
914 
915   /* Tracker for doing reads when filling the buffer */
916   Table_access_tracker buf_tracker;
917 
is_using_filesort()918   bool is_using_filesort() { return filesort_tracker? true: false; }
919   /*
920     Non-null value of filesort_tracker means "using filesort"
921 
922     if we are using filesort, then table_tracker is for the io done inside
923     filesort.
924 
925     'tracker' is for tracking post-filesort reads.
926   */
927   Filesort_tracker *filesort_tracker;
928 
929   /* ANALYZE members and methods */
930   Table_access_tracker tracker;
931 
932   /* This tracks execution of the whole command */
933   Time_and_counter_tracker command_tracker;
934 
935   /* TODO: This tracks time to read rows from the table */
936   Exec_time_tracker table_tracker;
937 
938   virtual int print_explain(Explain_query *query, select_result_sink *output,
939                             uint8 explain_flags, bool is_analyze);
940   virtual void print_explain_json(Explain_query *query, Json_writer *writer,
941                                   bool is_analyze);
942 };
943 
944 
945 /*
946   EXPLAIN data structure for an INSERT.
947 
948   At the moment this doesn't do much as we don't really have any query plans
949   for INSERT statements.
950 */
951 
952 class Explain_insert : public Explain_node
953 {
954 public:
Explain_insert(MEM_ROOT * root)955   Explain_insert(MEM_ROOT *root) :
956   Explain_node(root)
957   {}
958 
959   StringBuffer<64> table_name;
960 
get_type()961   enum explain_node_type get_type() { return EXPLAIN_INSERT; }
get_select_id()962   int get_select_id() { return 1; /* always root */ }
963 
964   int print_explain(Explain_query *query, select_result_sink *output,
965                     uint8 explain_flags, bool is_analyze);
966   void print_explain_json(Explain_query *query, Json_writer *writer,
967                           bool is_analyze);
968 };
969 
970 
971 /*
972   EXPLAIN data of a single-table DELETE.
973 */
974 
975 class Explain_delete: public Explain_update
976 {
977 public:
Explain_delete(MEM_ROOT * root,bool is_analyze)978   Explain_delete(MEM_ROOT *root, bool is_analyze) :
979   Explain_update(root, is_analyze)
980   {}
981 
982   /*
983     TRUE means we're going to call handler->delete_all_rows() and not read any
984     rows.
985   */
986   bool deleting_all_rows;
987 
get_type()988   virtual enum explain_node_type get_type() { return EXPLAIN_DELETE; }
get_select_id()989   virtual int get_select_id() { return 1; /* always root */ }
990 
991   virtual int print_explain(Explain_query *query, select_result_sink *output,
992                             uint8 explain_flags, bool is_analyze);
993   virtual void print_explain_json(Explain_query *query, Json_writer *writer,
994                                   bool is_analyze);
995 };
996 
997 
998 #endif //SQL_EXPLAIN_INCLUDED
999