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