1 /*
2    Copyright (c) 2010, 2021, Oracle and/or its affiliates.
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, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef ABSTRACT_QUERY_PLAN_H_INCLUDED
26 #define ABSTRACT_QUERY_PLAN_H_INCLUDED
27 
28 #include "my_global.h"      // uint
29 #include "item_cmpfunc.h"   // Item_equal_iterator
30 
31 struct TABLE;
32 class JOIN;
33 class Item;
34 class Item_field;
35 
36 /**
37   Abstract query plan (AQP) is an interface for examining certain aspects of
38   query plans without accessing mysqld internal classes (JOIN_TAB, QEP_TAB,
39   etc.) directly.
40 
41   AQP maps join execution plans, as represented by mysqld internals, to a set
42   of facade classes. Non-join operations such as sorting and aggregation is
43   currently *not* modelled in the AQP.
44 
45   The AQP models an n-way join as a sequence of the n table access operations
46   that the MySQL server would execute as part of its nested loop join
47   execution. (Each such table access operation is a scan of a table or index,
48   or an index lookup.) For each lookup operation, it is possible to examine
49   the expression that represents each field in the key.
50 
51   A storage enging will typically use the AQP for finding sections of a join
52   execution plan that may be executed in the engine rather than in mysqld. By
53   using the AQP rather than the mysqld internals directly, the coupling between
54   the engine and mysqld is reduced.
55 
56   The AQP also provides functions which allows the storage engine
57   to change the query execution plan for the part of the join which
58   it will handle. Thus be aware that although the QEP_TAB*'s are const
59   they may be modified.
60 */
61 namespace AQP
62 {
63   class Table_access;
64 
65   /**
66     This class represents a query plan for an n-way join, in the form a
67     sequence of n table access operations that will execute as a nested loop
68     join.
69   */
70   class Join_plan : public Sql_alloc
71   {
72     friend class Equal_set_iterator;
73     friend class Table_access;
74   public:
75 
76     explicit Join_plan(const JOIN* join);
77 
78     ~Join_plan();
79 
80     const Table_access* get_table_access(uint access_no) const;
81 
82     uint get_access_count() const;
83 
84   private:
85     /**
86       Array of the QEP_TABs that are the internal representation of table
87       access operations.
88     */
89     const QEP_TAB* const m_qep_tabs;
90 
91     /** Number of table access operations. */
92     const uint m_access_count;
93     Table_access* m_table_accesses;
94 
95     const QEP_TAB* get_qep_tab(uint qep_tab_no) const;
96 
97     // No copying.
98     Join_plan(const Join_plan&);
99     Join_plan& operator=(const Join_plan&);
100   };
101   // class Join_plan
102 
103 
104   /**
105     This class is an iterator for iterating over sets of fields (columns) that
106     should have the same value. For example, if the query is
107     SELECT * FROM T1, T2, T3 WHERE T1.b = T2.a AND T2.a = T3.a
108     then there would be such a set of {T1.b, T2.a, T3.a}.
109   */
110   class Equal_set_iterator : public Sql_alloc
111   {
112   public:
Equal_set_iterator(Item_equal & item_equal)113     explicit Equal_set_iterator(Item_equal& item_equal)
114     : m_iterator(item_equal) {}
115 
next()116     const Item_field* next()
117     { return m_iterator++; }
118 
119   private:
120     /**
121       This class is implemented in terms of this mysqld internal class.
122      */
123     Item_equal_iterator m_iterator;
124 
125     // No copying.
126     Equal_set_iterator(const Equal_set_iterator&);
127     Equal_set_iterator& operator=(const Equal_set_iterator&);
128   };
129   // class Equal_set_iterator
130 
131   /** The type of a table access operation. */
132   enum enum_access_type
133   {
134     /** For default initialization.*/
135     AT_VOID,
136     /** Value has already been fetched / determined by optimizer.*/
137     AT_FIXED,
138     /** Do a lookup of a single primary key.*/
139     AT_PRIMARY_KEY,
140     /** Do a lookup of a single unique index key.*/
141     AT_UNIQUE_KEY,
142     /** Scan an ordered index with a single upper and lower bound pair.*/
143     AT_ORDERED_INDEX_SCAN,
144     /** Do a multi range read for a set of primary keys.*/
145     AT_MULTI_PRIMARY_KEY,
146     /** Do a multi range read for a set of unique index keys.*/
147     AT_MULTI_UNIQUE_KEY,
148     /**
149       Do a multi range read for a mix of ranges (for which there is an
150       ordered index), and either primary keys or unique index keys.
151     */
152     AT_MULTI_MIXED,
153     /** Scan a table. (No index is assumed to be used.) */
154     AT_TABLE_SCAN,
155     /** Access method will not be chosen before the execution phase.*/
156     AT_UNDECIDED,
157     /**
158       The access method has properties that prevents it from being pushed to a
159       storage engine.
160      */
161     AT_OTHER
162   };
163 
164   /** The type of join operation require */
165   enum enum_join_type
166   {
167     JT_OUTER_JOIN,
168     JT_INNER_JOIN,
169     JT_SEMI_JOIN
170   };
171 
172   /**
173     This class represents an access operation on a table, such as a table
174     scan, or a scan or lookup via an index. A Table_access object is always
175     owned by a Join_plan object, such that the life time of the Table_access
176     object ends when the life time of the owning Join_plan object ends.
177    */
178   class Table_access : public Sql_alloc
179   {
180     friend class Join_plan;
181     friend inline bool equal(const Table_access*, const Table_access*);
182   public:
183 
184     const Join_plan* get_join_plan() const;
185 
186     enum_access_type get_access_type() const;
187 
188     const char* get_other_access_reason() const;
189 
190     enum_join_type get_join_type(const Table_access* parent) const;
191 
192     uint get_no_of_key_fields() const;
193 
194     const Item* get_key_field(uint field_no) const;
195 
196     const KEY_PART_INFO* get_key_part_info(uint field_no) const;
197 
198     uint get_access_no() const;
199 
200     int get_index_no() const;
201 
202     TABLE* get_table() const;
203 
204     double get_fanout() const;
205 
206     Item_equal* get_item_equal(const Item_field* field_item) const;
207 
208     void dbug_print() const;
209 
210     bool uses_join_cache() const;
211 
212     const Table_access* get_firstmatch_last_skipped() const;
213 
214     bool filesort_before_join() const;
215 
216     /**
217        Change the query plan for this part of the join to use
218        the pushed functions
219     */
220     void set_pushed_table_access_method() const;
221 
222   private:
223 
224     /** Backref. to the Join_plan which this Table_access is part of */
225     const Join_plan* m_join_plan;
226 
227     /** This operation corresponds to m_root_tab[m_tab_no].*/
228     uint m_tab_no;
229 
230     /** The type of this operation.*/
231     mutable enum_access_type m_access_type;
232 
233     /**
234       The reason for getting m_access_type==AT_OTHER. Used for explain extended.
235     */
236     mutable const char* m_other_access_reason;
237 
238     /** The index to use for this operation (if applicable )*/
239     mutable int m_index_no;
240 
241     explicit Table_access();
242 
243     const QEP_TAB* get_qep_tab() const;
244 
245     void compute_type_and_index() const;
246 
247     /** No copying*/
248     Table_access(const Table_access&);
249     Table_access& operator=(const Table_access&);
250   };
251   // class Table_access
252 
253   /**
254     Get the n'th table access operation.
255     @param access_no The index of the table access operation to fetch.
256     @return The access_no'th table access operation.
257   */
get_table_access(uint access_no)258   inline const Table_access* Join_plan::get_table_access(uint access_no) const
259   {
260     assert(access_no < m_access_count);
261     return m_table_accesses + access_no;
262   }
263 
264   /**
265      @return The number of table access operations in the nested loop join.
266   */
get_access_count()267   inline uint Join_plan::get_access_count() const
268   {
269     return m_access_count;
270   }
271 
272   /** Get the Join_plan that this Table_access belongs to.*/
get_join_plan()273   inline const Join_plan* Table_access::get_join_plan() const
274   {
275     return m_join_plan;
276   }
277 
278   /** Get the type of this operation.*/
get_access_type()279   inline enum_access_type Table_access::get_access_type() const
280   {
281     if (m_access_type == AT_VOID)
282       compute_type_and_index();
283     return m_access_type;
284   }
285 
286   /**
287     Get a description of the reason for getting access_type==AT_OTHER. To be
288     used for informational messages.
289     @return A string that should be assumed to have the same life time as the
290     Table_access object.
291   */
get_other_access_reason()292   inline const char* Table_access::get_other_access_reason() const
293   {
294     if (m_access_type == AT_VOID)
295       compute_type_and_index();
296     return m_other_access_reason;
297   }
298 
299   /**
300     @return The number of the index to use for this access operation (
301     or -1 for non-index operations).
302   */
get_index_no()303   inline int Table_access::get_index_no() const
304   {
305     if (m_access_type == AT_VOID)
306       compute_type_and_index();
307 
308     return m_index_no;
309   }
310 
311   /**
312     Get the number of this Table_access within the enclosing Join_plan.
313     (This number will be in the range 0 to Join_plan::get_access_count() - 1.)
314   */
get_access_no()315   inline uint Table_access::get_access_no() const
316   {
317     return m_tab_no;
318   }
319 
320 };
321 // namespace AQP
322 
323 #endif
324