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