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:
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:
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);
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:
164   enum explain_node_type get_type() { return EXPLAIN_BASIC_JOIN; }
165 
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 
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:
208   enum explain_node_type get_type() { return EXPLAIN_SELECT; }
209 
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 
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;
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:
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:
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:
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:
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 
337 /*
338   Explain structure for a UNION.
339 
340   A UNION may or may not have "Using filesort".
341 */
342 
343 class Explain_union : public Explain_node
344 {
345 public:
346   Explain_union(MEM_ROOT *root, bool is_analyze) :
347     Explain_node(root),
348     is_recursive_cte(false),
349     fake_select_lex_explain(root, is_analyze)
350   {}
351 
352   enum explain_node_type get_type() { return EXPLAIN_UNION; }
353   unit_common_op operation;
354 
355   int get_select_id()
356   {
357     DBUG_ASSERT(union_members.elements() > 0);
358     return union_members.at(0);
359   }
360   /*
361     Members of the UNION.  Note: these are different from UNION's "children".
362     Example:
363 
364       (select * from t1) union
365       (select * from t2) order by (select col1 from t3 ...)
366 
367     here
368       - select-from-t1 and select-from-t2 are "union members",
369       - select-from-t3 is the only "child".
370   */
371   Dynamic_array<int> union_members;
372 
373   void add_select(int select_no)
374   {
375     union_members.append(select_no);
376   }
377   int print_explain(Explain_query *query, select_result_sink *output,
378                     uint8 explain_flags, bool is_analyze);
379   void print_explain_json(Explain_query *query, Json_writer *writer,
380                           bool is_analyze);
381 
382   const char *fake_select_type;
383   bool using_filesort;
384   bool using_tmp;
385   bool is_recursive_cte;
386 
387   /*
388     Explain data structure for "fake_select_lex" (i.e. for the degenerate
389     SELECT that reads UNION result).
390     It doesn't have a query plan, but we still need execution tracker, etc.
391   */
392   Explain_select fake_select_lex_explain;
393 
394   Table_access_tracker *get_fake_select_lex_tracker()
395   {
396     return &fake_select_lex_tracker;
397   }
398   Table_access_tracker *get_tmptable_read_tracker()
399   {
400     return &tmptable_read_tracker;
401   }
402 private:
403   uint make_union_table_name(char *buf);
404 
405   Table_access_tracker fake_select_lex_tracker;
406   /* This one is for reading after ORDER BY */
407   Table_access_tracker tmptable_read_tracker;
408 };
409 
410 
411 class Explain_update;
412 class Explain_delete;
413 class Explain_insert;
414 
415 
416 /*
417   Explain structure for a query (i.e. a statement).
418 
419   This should be able to survive when the query plan was deleted. Currently,
420   we do not intend for it survive until after query's MEM_ROOT is freed. It
421   does surivive freeing of query's items.
422 
423   For reference, the process of post-query cleanup is as follows:
424 
425     >dispatch_command
426     | >mysql_parse
427     | |  ...
428     | | lex_end()
429     | |  ...
430     | | >THD::cleanup_after_query
431     | | | ...
432     | | | free_items()
433     | | | ...
434     | | <THD::cleanup_after_query
435     | |
436     | <mysql_parse
437     |
438     | log_slow_statement()
439     |
440     | free_root()
441     |
442     >dispatch_command
443 
444   That is, the order of actions is:
445     - free query's Items
446     - write to slow query log
447     - free query's MEM_ROOT
448 
449 */
450 
451 class Explain_query : public Sql_alloc
452 {
453 public:
454   Explain_query(THD *thd, MEM_ROOT *root);
455   ~Explain_query();
456 
457   /* Add a new node */
458   void add_node(Explain_node *node);
459   void add_insert_plan(Explain_insert *insert_plan_arg);
460   void add_upd_del_plan(Explain_update *upd_del_plan_arg);
461 
462   /* This will return a select, or a union */
463   Explain_node *get_node(uint select_id);
464 
465   /* This will return a select (even if there is a union with this id) */
466   Explain_select *get_select(uint select_id);
467 
468   Explain_union *get_union(uint select_id);
469 
470   /* Produce a tabular EXPLAIN output */
471   int print_explain(select_result_sink *output, uint8 explain_flags,
472                     bool is_analyze);
473 
474   /* Send tabular EXPLAIN to the client */
475   int send_explain(THD *thd);
476 
477   /* Return tabular EXPLAIN output as a text string */
478   bool print_explain_str(THD *thd, String *out_str, bool is_analyze);
479 
480   void print_explain_json(select_result_sink *output, bool is_analyze);
481 
482   /* If true, at least part of EXPLAIN can be printed */
483   bool have_query_plan() { return insert_plan || upd_del_plan|| get_node(1) != NULL; }
484 
485   void query_plan_ready();
486 
487   MEM_ROOT *mem_root;
488 
489   Explain_update *get_upd_del_plan() { return upd_del_plan; }
490 private:
491   /* Explain_delete inherits from Explain_update */
492   Explain_update *upd_del_plan;
493 
494   /* Query "plan" for INSERTs */
495   Explain_insert *insert_plan;
496 
497   Dynamic_array<Explain_union*> unions;
498   Dynamic_array<Explain_select*> selects;
499 
500   THD *thd; // for APC start/stop
501   bool apc_enabled;
502   /*
503     Debugging aid: count how many times add_node() was called. Ideally, it
504     should be one, we currently allow O(1) query plan saves for each
505     select or union.  The goal is not to have O(#rows_in_some_table), which
506     is unacceptable.
507   */
508   longlong operations;
509 };
510 
511 
512 /*
513   Some of the tags have matching text. See extra_tag_text for text names, and
514   Explain_table_access::append_tag_name() for code to convert from tag form to text
515   form.
516 */
517 enum explain_extra_tag
518 {
519   ET_none= 0, /* not-a-tag */
520   ET_USING_INDEX_CONDITION,
521   ET_USING_INDEX_CONDITION_BKA,
522   ET_USING, /* For quick selects of various kinds */
523   ET_RANGE_CHECKED_FOR_EACH_RECORD,
524   ET_USING_WHERE_WITH_PUSHED_CONDITION,
525   ET_USING_WHERE,
526   ET_NOT_EXISTS,
527 
528   ET_USING_INDEX,
529   ET_FULL_SCAN_ON_NULL_KEY,
530   ET_SKIP_OPEN_TABLE,
531   ET_OPEN_FRM_ONLY,
532   ET_OPEN_FULL_TABLE,
533 
534   ET_SCANNED_0_DATABASES,
535   ET_SCANNED_1_DATABASE,
536   ET_SCANNED_ALL_DATABASES,
537 
538   ET_USING_INDEX_FOR_GROUP_BY,
539 
540   ET_USING_MRR, // does not print "Using mrr".
541 
542   ET_DISTINCT,
543   ET_LOOSESCAN,
544   ET_START_TEMPORARY,
545   ET_END_TEMPORARY,
546   ET_FIRST_MATCH,
547 
548   ET_USING_JOIN_BUFFER,
549 
550   ET_CONST_ROW_NOT_FOUND,
551   ET_UNIQUE_ROW_NOT_FOUND,
552   ET_IMPOSSIBLE_ON_CONDITION,
553 
554   ET_total
555 };
556 
557 
558 /*
559   Explain data structure describing join buffering use.
560 */
561 
562 class EXPLAIN_BKA_TYPE
563 {
564 public:
565   EXPLAIN_BKA_TYPE() : join_alg(NULL) {}
566 
567   size_t join_buffer_size;
568 
569   bool incremental;
570 
571   /*
572     NULL if no join buferring used.
makePattern(const DenseSet<Operation * > & parallelLoops,int vectorRank,ArrayRef<int64_t> fastestVaryingPattern)573     Other values: BNL, BNLH, BKA, BKAH.
574   */
575   const char *join_alg;
576 
577   /* Information about MRR usage.  */
578   StringBuffer<64> mrr_type;
579 
580   bool is_using_jbuf() { return (join_alg != NULL); }
581 };
582 
583 
584 /*
585   Data about how an index is used by some access method
586 */
587 class Explain_index_use : public Sql_alloc
588 {
589   char *key_name;
590   uint key_len;
591 public:
592   String_list key_parts_list;
593 
594   Explain_index_use()
vectorTransferPattern()595   {
596     clear();
597   }
598 
599   void clear()
600   {
601     key_name= NULL;
602     key_len= (uint)-1;
603   }
604   bool set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
605   bool set_pseudo_key(MEM_ROOT *root, const char *key_name);
606 
607   inline const char *get_key_name() const { return key_name; }
608   inline uint get_key_len() const { return key_len; }
609 };
610 
611 
612 /*
613   QPF for quick range selects, as well as index_merge select
Vectorize(ArrayRef<int64_t> virtualVectorSize)614 */
615 class Explain_quick_select : public Sql_alloc
616 {
617 public:
618   Explain_quick_select(int quick_type_arg) : quick_type(quick_type_arg)
619   {}
620 
621   const int quick_type;
622 
623   bool is_basic()
624   {
625     return (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE ||
626             quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC ||
627             quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX);
628   }
629 
630   /* This is used when quick_type == QUICK_SELECT_I::QS_TYPE_RANGE */
631   Explain_index_use range;
632 
633   /* Used in all other cases */
634   List<Explain_quick_select> children;
635 
636   void print_extra(String *str);
637   void print_key(String *str);
638   void print_key_len(String *str);
639 
640   void print_json(Json_writer *writer);
641 
642   void print_extra_recursive(String *str);
643 private:
644   const char *get_name_by_type();
645 };
analyzeProfitability(ArrayRef<NestedMatch> matches,unsigned depthInPattern,unsigned patternDepth,VectorizationStrategy * strategy)646 
647 
648 /*
649   Data structure for "range checked for each record".
650   It's a set of keys, tabular explain prints hex bitmap, json prints key names.
651 */
652 
653 typedef const char* NAME;
654 
655 class Explain_range_checked_fer : public Sql_alloc
656 {
657 public:
658   String_list key_set;
659   key_map keys_map;
660 private:
661   ha_rows full_scan, index_merge;
662   ha_rows *keys_stat;
663   NAME *keys_stat_names;
664   uint keys;
665 
666 public:
VectorizationState__anonb1a5bee80311::VectorizationState667   Explain_range_checked_fer()
668     :Sql_alloc(), full_scan(0), index_merge(0),
669     keys_stat(0), keys_stat_names(0), keys(0)
670   {}
671 
672   int append_possible_keys_stat(MEM_ROOT *alloc,
673                                 TABLE *table, key_map possible_keys);
674   void collect_data(QUICK_SELECT_I *quick);
675   void print_json(Json_writer *writer, bool is_analyze);
676 };
677 
678 /*
679   EXPLAIN data structure for a single JOIN_TAB.
680 */
681 
682 class Explain_table_access : public Sql_alloc
683 {
684 public:
685   Explain_table_access(MEM_ROOT *root) :
686     derived_select_number(0),
687     non_merged_sjm_number(0),
688     extra_tags(root),
689     range_checked_fer(NULL),
690     full_scan_on_null_key(false),
691     start_dups_weedout(false),
692     end_dups_weedout(false),
693     where_cond(NULL),
694     cache_cond(NULL),
695     pushed_index_cond(NULL),
696     sjm_nest(NULL),
697     pre_join_sort(NULL)
698   {}
699   ~Explain_table_access() { delete sjm_nest; }
700 
701   void push_extra(enum explain_extra_tag extra_tag);
702 
703   /* Internals */
704 
705   /* id and 'select_type' are cared-of by the parent Explain_select */
706   StringBuffer<32> table_name;
707   StringBuffer<32> used_partitions;
708   String_list used_partitions_list;
709   // valid with ET_USING_MRR
710   StringBuffer<32> mrr_type;
711   StringBuffer<32> firstmatch_table_name;
712 
713   /*
714     Non-zero number means this is a derived table. The number can be used to
715     find the query plan for the derived table
716   */
717   int derived_select_number;
718   /* TODO: join with the previous member. */
719   int non_merged_sjm_number;
720 
721   enum join_type type;
722 
723   bool used_partitions_set;
724 
725   /* Empty means "NULL" will be printed */
726   String_list possible_keys;
727 
728   bool rows_set; /* not set means 'NULL' should be printed */
729   bool filtered_set; /* not set means 'NULL' should be printed */
730   // Valid if ET_USING_INDEX_FOR_GROUP_BY is present
731   bool loose_scan_is_scanning;
732 
733   /*
734     Index use: key name and length.
735     Note: that when one is accessing I_S tables, those may show use of
736     non-existant indexes.
737 
738     key.key_name == NULL means 'NULL' will be shown in tabular output.
739     key.key_len == (uint)-1 means 'NULL' will be shown in tabular output.
740   */
741   Explain_index_use key;
742 
743   /*
744     when type==JT_HASH_NEXT, 'key' stores the hash join pseudo-key.
745     hash_next_key stores the table's key.
746   */
747   Explain_index_use hash_next_key;
748 
749   String_list ref_list;
750 
751   ha_rows rows;
752   double filtered;
753 
754   /*
755     Contents of the 'Extra' column. Some are converted into strings, some have
756     parameters, values for which are stored below.
757   */
758   Dynamic_array<enum explain_extra_tag> extra_tags;
759 
760   // Valid if ET_USING tag is present
761   Explain_quick_select *quick_info;
762 
763   /* Non-NULL value means this tab uses "range checked for each record" */
764   Explain_range_checked_fer *range_checked_fer;
765 
766   bool full_scan_on_null_key;
767 
768   // valid with ET_USING_JOIN_BUFFER
769   EXPLAIN_BKA_TYPE bka_type;
770 
771   bool start_dups_weedout;
772   bool end_dups_weedout;
773 
774   /*
775     Note: lifespan of WHERE condition is less than lifespan of this object.
registerOpVectorReplacement(Operation * replaced,Operation * replacement)776     The below two are valid if tags include "ET_USING_WHERE".
777     (TODO: indexsubquery may put ET_USING_WHERE without setting where_cond?)
778   */
779   Item *where_cond;
780   Item *cache_cond;
781 
782   /*
783     This is either pushed index condition, or BKA's index condition.
784     (the latter refers to columns of other tables and so can only be checked by
785      BKA code). Examine extra_tags to tell which one it is.
786   */
787   Item *pushed_index_cond;
788 
789   Explain_basic_join *sjm_nest;
790 
791   /*
792     This describes a possible filesort() call that is done before doing the
793     join operation.
794   */
795   Explain_aggr_filesort *pre_join_sort;
796 
797   /* ANALYZE members */
798 
799   /* Tracker for reading the table */
800   Table_access_tracker tracker;
801   Exec_time_tracker op_tracker;
802   Table_access_tracker jbuf_tracker;
803 
registerValueVectorReplacement(Value replaced,Operation * replacement)804   int print_explain(select_result_sink *output, uint8 explain_flags,
805                     bool is_analyze,
806                     uint select_id, const char *select_type,
807                     bool using_temporary, bool using_filesort);
808   void print_explain_json(Explain_query *query, Json_writer *writer,
809                           bool is_analyze);
810 
811 private:
812   void append_tag_name(String *str, enum explain_extra_tag tag);
813   void fill_key_str(String *key_str, bool is_json) const;
814   void fill_key_len_str(String *key_len_str) const;
815   double get_r_filtered();
816   void tag_to_json(Json_writer *writer, enum explain_extra_tag tag);
817 };
818 
registerBlockArgVectorReplacement(BlockArgument replaced,BlockArgument replacement)819 
820 /*
821   EXPLAIN structure for single-table UPDATE.
822 
823   This is similar to Explain_table_access, except that it is more restrictive.
824   Also, it can have UPDATE operation options, but currently there aren't any.
825 
826   Explain_delete inherits from this.
827 */
828 
829 class Explain_update : public Explain_node
830 {
831 public:
832 
833   Explain_update(MEM_ROOT *root, bool is_analyze) :
834     Explain_node(root),
835     filesort_tracker(NULL),
836     command_tracker(is_analyze)
837   {}
838 
839   virtual enum explain_node_type get_type() { return EXPLAIN_UPDATE; }
840   virtual int get_select_id() { return 1; /* always root */ }
841 
842   const char *select_type;
843 
844   StringBuffer<32> used_partitions;
845   String_list used_partitions_list;
846   bool used_partitions_set;
847 
848   bool impossible_where;
849   bool no_partitions;
850   StringBuffer<64> table_name;
851 
852   enum join_type jtype;
853   String_list possible_keys;
854 
855   /* Used key when doing a full index scan (possibly with limit) */
856   Explain_index_use key;
857 
858   /*
859     MRR that's used with quick select. This should probably belong to the
860     quick select
861   */
862   StringBuffer<64> mrr_type;
863 
864   Explain_quick_select *quick_info;
865 
866   bool using_where;
867   Item *where_cond;
868 
869   ha_rows rows;
870 
871   bool using_io_buffer;
872 
873   /* Tracker for doing reads when filling the buffer */
874   Table_access_tracker buf_tracker;
875 
876   bool is_using_filesort() { return filesort_tracker? true: false; }
877   /*
878     Non-null value of filesort_tracker means "using filesort"
879 
880     if we are using filesort, then table_tracker is for the io done inside
881     filesort.
882 
883     'tracker' is for tracking post-filesort reads.
884   */
885   Filesort_tracker *filesort_tracker;
886 
887   /* ANALYZE members and methods */
888   Table_access_tracker tracker;
889 
890   /* This tracks execution of the whole command */
891   Time_and_counter_tracker command_tracker;
892 
893   /* TODO: This tracks time to read rows from the table */
894   Exec_time_tracker table_tracker;
895 
896   virtual int print_explain(Explain_query *query, select_result_sink *output,
897                             uint8 explain_flags, bool is_analyze);
898   virtual void print_explain_json(Explain_query *query, Json_writer *writer,
899                                   bool is_analyze);
900 };
901 
902 
903 /*
904   EXPLAIN data structure for an INSERT.
905 
906   At the moment this doesn't do much as we don't really have any query plans
907   for INSERT statements.
908 */
909 
910 class Explain_insert : public Explain_node
911 {
912 public:
913   Explain_insert(MEM_ROOT *root) :
914   Explain_node(root)
isVectorizableLoopPtrFactory(const DenseSet<Operation * > & parallelLoops,int fastestVaryingMemRefDimension)915   {}
916 
__anonb1a5bee80402(Operation &forOp) 917   StringBuffer<64> table_name;
918 
919   enum explain_node_type get_type() { return EXPLAIN_INSERT; }
920   int get_select_id() { return 1; /* always root */ }
921 
922   int print_explain(Explain_query *query, select_result_sink *output,
923                     uint8 explain_flags, bool is_analyze);
924   void print_explain_json(Explain_query *query, Json_writer *writer,
925                           bool is_analyze);
926 };
927 
928 
929 /*
930   EXPLAIN data of a single-table DELETE.
931 */
932 
933 class Explain_delete: public Explain_update
getVectorType(Type scalarTy,const VectorizationStrategy * strategy)934 {
935 public:
936   Explain_delete(MEM_ROOT *root, bool is_analyze) :
937   Explain_update(root, is_analyze)
938   {}
939 
940   /*
941     TRUE means we're going to call handler->delete_all_rows() and not read any
942     rows.
943   */
944   bool deleting_all_rows;
945 
946   virtual enum explain_node_type get_type() { return EXPLAIN_DELETE; }
947   virtual int get_select_id() { return 1; /* always root */ }
948 
949   virtual int print_explain(Explain_query *query, select_result_sink *output,
950                             uint8 explain_flags, bool is_analyze);
951   virtual void print_explain_json(Explain_query *query, Json_writer *writer,
952                                   bool is_analyze);
953 };
954 
955 
956 #endif //SQL_EXPLAIN_INCLUDED
957