1 /*
2    Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
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 <sys/types.h>
29 
30 #include "my_dbug.h"
31 #include "sql/item_cmpfunc.h" // Item_equal_iterator
32 
33 class Item;
34 class Item_field;
35 class JOIN;
36 class KEY_PART_INFO;
37 class QEP_TAB;
38 struct TABLE;
39 
40 /**
41   Abstract query plan (AQP) is an interface for examining certain aspects of
42   query plans without accessing mysqld internal classes (JOIN_TAB, QEP_TAB,
43   etc.) directly.
44 
45   AQP maps join execution plans, as represented by mysqld internals, to a set
46   of facade classes. Non-join operations such as sorting and aggregation is
47   currently *not* modelled in the AQP.
48 
49   The AQP models an n-way join as a sequence of the n table access operations
50   that the MySQL server would execute as part of its nested loop join
51   execution. (Each such table access operation is a scan of a table or index,
52   or an index lookup.) For each lookup operation, it is possible to examine
53   the expression that represents each field in the key.
54 
55   A storage enging will typically use the AQP for finding sections of a join
56   execution plan that may be executed in the engine rather than in mysqld. By
57   using the AQP rather than the mysqld internals directly, the coupling between
58   the engine and mysqld is reduced.
59 
60   The AQP also provides functions which allows the storage engine
61   to change the query execution plan for the part of the join which
62   it will handle. Thus be aware that although the QEP_TAB*'s are const
63   they may be modified.
64 */
65 namespace AQP
66 {
67   class Table_access;
68 
69   /**
70     This class represents a query plan for an n-way join, in the form a
71     sequence of n table access operations that will execute as a nested loop
72     join.
73   */
74   class Join_plan
75   {
76     friend class Equal_set_iterator;
77     friend class Table_access;
78   public:
79 
80     explicit Join_plan(const JOIN* join);
81 
82     ~Join_plan();
83 
84     Table_access* get_table_access(uint access_no) const;
85 
86     uint get_access_count() const;
87 
88   private:
89     /**
90       Array of the QEP_TABs that are the internal representation of table
91       access operations.
92     */
93     const QEP_TAB* const m_qep_tabs;
94 
95     /** Number of table access operations. */
96     uint m_access_count;
97     Table_access* m_table_accesses;
98 
99     const QEP_TAB* get_qep_tab(uint qep_tab_no) const;
100 
101     // No copying.
102     Join_plan(const Join_plan&);
103     Join_plan& operator=(const Join_plan&);
104   };
105   // class Join_plan
106 
107 
108   /**
109     This class is an iterator for iterating over sets of fields (columns) that
110     should have the same value. For example, if the query is
111     SELECT * FROM T1, T2, T3 WHERE T1.b = T2.a AND T2.a = T3.a
112     then there would be such a set of {T1.b, T2.a, T3.a}.
113   */
114   class Equal_set_iterator
115   {
116   public:
Equal_set_iterator(Item_equal & item_equal)117     explicit Equal_set_iterator(Item_equal& item_equal)
118     : m_iterator(item_equal) {}
119 
next()120     const Item_field* next()
121     { return m_iterator++; }
122 
123   private:
124     /**
125       This class is implemented in terms of this mysqld internal class.
126      */
127     Item_equal_iterator m_iterator;
128 
129     // No copying.
130     Equal_set_iterator(const Equal_set_iterator&);
131     Equal_set_iterator& operator=(const Equal_set_iterator&);
132   };
133   // class Equal_set_iterator
134 
135   /** The type of a table access operation. */
136   enum enum_access_type
137   {
138     /** For default initialization.*/
139     AT_VOID,
140     /** Value has already been fetched / determined by optimizer.*/
141     AT_FIXED,
142     /** Do a lookup of a single primary key.*/
143     AT_PRIMARY_KEY,
144     /** Do a lookup of a single unique index key.*/
145     AT_UNIQUE_KEY,
146     /** Scan an ordered index with a single upper and lower bound pair.*/
147     AT_ORDERED_INDEX_SCAN,
148     /** Do a multi range read for a set of primary keys.*/
149     AT_MULTI_PRIMARY_KEY,
150     /** Do a multi range read for a set of unique index keys.*/
151     AT_MULTI_UNIQUE_KEY,
152     /**
153       Do a multi range read for a mix of ranges (for which there is an
154       ordered index), and either primary keys or unique index keys.
155     */
156     AT_MULTI_MIXED,
157     /** Scan a table. (No index is assumed to be used.) */
158     AT_TABLE_SCAN,
159     /** Access method will not be chosen before the execution phase.*/
160     AT_UNDECIDED,
161     /**
162       The access method has properties that prevents it from being pushed to a
163       storage engine.
164      */
165     AT_OTHER
166   };
167 
168   /**
169     This class represents an access operation on a table, such as a table
170     scan, or a scan or lookup via an index. A Table_access object is always
171     owned by a Join_plan object, such that the life time of the Table_access
172     object ends when the life time of the owning Join_plan object ends.
173    */
174   class Table_access
175   {
176     friend class Join_plan;
177     friend inline bool equal(const Table_access*, const Table_access*);
178   public:
179 
180     const Join_plan* get_join_plan() const;
181 
182     enum_access_type get_access_type() const;
183 
184     const char* get_other_access_reason() const;
185 
186     uint get_no_of_key_fields() const;
187 
188     const Item* get_key_field(uint field_no) const;
189 
190     const KEY_PART_INFO* get_key_part_info(uint field_no) const;
191 
192     uint get_access_no() const;
193 
194     int get_index_no() const;
195 
196     TABLE* get_table() const;
197 
198     Item_equal* get_item_equal(const Item_field* field_item) const;
199 
200     void dbug_print() const;
201 
202     bool uses_join_cache() const;
203 
204     bool filesort_before_join() const;
205 
206     Item* get_condition() const;
207     void set_condition(Item* cond);
208 
209     uint get_first_inner() const;
210     uint get_last_inner() const;
211     int get_first_upper() const;
212 
213     int get_first_sj_inner() const;
214     int get_last_sj_inner() const;
215 
216     // Is member of a firstMatch sj_nest?
217     bool is_sj_firstmatch() const;
218     // Get the upper-table we skip out to upon a firstMatch
219     int get_firstmatch_return() const;
220 
221     bool is_antijoin() const;
222 
223     /**
224       Getter and setters for an opaque object for each table.
225       Used by the handler's to persist 'pushability-flags' to avoid
226       overhead by recalculating it for each ::engine_push()
227     */
228     uint get_table_properties() const;
229     void set_table_properties(uint);
230 
231   private:
232 
233     /** Backref. to the Join_plan which this Table_access is part of */
234     const Join_plan* m_join_plan;
235 
236     /** This operation corresponds to m_root_tab[m_tab_no].*/
237     uint m_tab_no;
238 
239     /** The type of this operation.*/
240     mutable enum_access_type m_access_type;
241 
242     /**
243       The reason for getting m_access_type==AT_OTHER. Used for explain extended.
244     */
245     mutable const char* m_other_access_reason;
246 
247     /** The index to use for this operation (if applicable )*/
248     mutable int m_index_no;
249 
250     /** May store an opaque property / flag */
251     uint m_properties;
252 
253     explicit Table_access();
254 
255     const QEP_TAB* get_qep_tab() const;
256 
257     void compute_type_and_index() const;
258 
259     /** No copying*/
260     Table_access(const Table_access&);
261     Table_access& operator=(const Table_access&);
262   };
263   // class Table_access
264 
265   /**
266     Get the n'th table access operation.
267     @param access_no The index of the table access operation to fetch.
268     @return The access_no'th table access operation.
269   */
get_table_access(uint access_no)270   inline Table_access* Join_plan::get_table_access(uint access_no) const
271   {
272     DBUG_ASSERT(access_no < m_access_count);
273     return m_table_accesses + access_no;
274   }
275 
276   /**
277      @return The number of table access operations in the nested loop join.
278   */
get_access_count()279   inline uint Join_plan::get_access_count() const
280   {
281     return m_access_count;
282   }
283 
284   /** Get the Join_plan that this Table_access belongs to.*/
get_join_plan()285   inline const Join_plan* Table_access::get_join_plan() const
286   {
287     return m_join_plan;
288   }
289 
290   /** Get the type of this operation.*/
get_access_type()291   inline enum_access_type Table_access::get_access_type() const
292   {
293     if (m_access_type == AT_VOID)
294       compute_type_and_index();
295     return m_access_type;
296   }
297 
298   /**
299     Get a description of the reason for getting access_type==AT_OTHER. To be
300     used for informational messages.
301     @return A string that should be assumed to have the same life time as the
302     Table_access object.
303   */
get_other_access_reason()304   inline const char* Table_access::get_other_access_reason() const
305   {
306     if (m_access_type == AT_VOID)
307       compute_type_and_index();
308     return m_other_access_reason;
309   }
310 
311   /**
312     @return The number of the index to use for this access operation (
313     or -1 for non-index operations).
314   */
get_index_no()315   inline int Table_access::get_index_no() const
316   {
317     if (m_access_type == AT_VOID)
318       compute_type_and_index();
319 
320     return m_index_no;
321   }
322 
323   /**
324     Get the number of this Table_access within the enclosing Join_plan.
325     (This number will be in the range 0 to Join_plan::get_access_count() - 1.)
326   */
get_access_no()327   inline uint Table_access::get_access_no() const
328   {
329     return m_tab_no;
330   }
331 
get_table_properties()332   inline uint Table_access::get_table_properties() const
333   {
334     return m_properties;
335   }
336 
set_table_properties(uint val)337   inline void Table_access::set_table_properties(uint val)
338   {
339     m_properties = val;
340   }
341 
342 }
343 // namespace AQP
344 
345 #endif
346