My Project
|
00001 /* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software Foundation, 00014 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 00015 00016 00017 #ifndef OPT_EXPLAIN_FORMAT_INCLUDED 00018 #define OPT_EXPLAIN_FORMAT_INCLUDED 00019 00024 #include "sql_class.h" 00025 00026 struct st_join_table; 00027 00028 00033 enum Explain_context_enum 00034 { 00035 CTX_NONE= 0, 00036 CTX_MESSAGE, 00037 CTX_TABLE, 00038 CTX_SELECT_LIST, 00039 CTX_UPDATE_VALUE_LIST, 00040 CTX_JOIN, 00041 CTX_JOIN_TAB, 00042 CTX_MATERIALIZATION, 00043 CTX_DUPLICATES_WEEDOUT, 00044 CTX_DERIVED, 00045 CTX_WHERE, 00046 CTX_HAVING, 00047 CTX_ORDER_BY, 00048 CTX_GROUP_BY, 00049 CTX_SIMPLE_ORDER_BY, 00050 CTX_SIMPLE_GROUP_BY, 00051 CTX_DISTINCT, 00052 CTX_SIMPLE_DISTINCT, 00053 CTX_BUFFER_RESULT, 00054 CTX_ORDER_BY_SQ, 00055 CTX_GROUP_BY_SQ, 00056 CTX_OPTIMIZED_AWAY_SUBQUERY, 00057 CTX_UNION, 00058 CTX_UNION_RESULT, 00059 CTX_QUERY_SPEC 00060 }; 00061 00062 00069 enum Extra_tag 00070 { 00071 ET_none, 00072 ET_USING_TEMPORARY, 00073 ET_USING_FILESORT, 00074 ET_USING_INDEX_CONDITION, 00075 ET_USING, 00076 ET_RANGE_CHECKED_FOR_EACH_RECORD, 00077 ET_USING_WHERE_WITH_PUSHED_CONDITION, 00078 ET_USING_WHERE, 00079 ET_NOT_EXISTS, 00080 ET_USING_MRR, 00081 ET_USING_INDEX, 00082 ET_FULL_SCAN_ON_NULL_KEY, 00083 ET_SKIP_OPEN_TABLE, 00084 ET_OPEN_FRM_ONLY, 00085 ET_OPEN_FULL_TABLE, 00086 ET_SCANNED_DATABASES, 00087 ET_USING_INDEX_FOR_GROUP_BY, 00088 ET_DISTINCT, 00089 ET_LOOSESCAN, 00090 ET_START_TEMPORARY, 00091 ET_END_TEMPORARY, 00092 ET_FIRST_MATCH, 00093 ET_MATERIALIZE, 00094 ET_START_MATERIALIZE, 00095 ET_END_MATERIALIZE, 00096 ET_SCAN, 00097 ET_USING_JOIN_BUFFER, 00098 ET_CONST_ROW_NOT_FOUND, 00099 ET_UNIQUE_ROW_NOT_FOUND, 00100 ET_IMPOSSIBLE_ON_CONDITION, 00101 ET_PUSHED_JOIN, 00102 //------------------------------------ 00103 ET_total 00104 }; 00105 00106 00110 class Lazy: public Sql_alloc 00111 { 00112 public: 00113 virtual ~Lazy() {} 00114 00123 virtual bool eval(String *ret)= 0; 00124 }; 00125 00132 struct Explain_context : Sql_alloc 00133 { 00134 Explain_context_enum type; 00135 00136 explicit Explain_context(Explain_context_enum type_arg) : type(type_arg) {} 00137 }; 00138 00139 00140 namespace opt_explain_json_namespace // for forward declaration of "context" 00141 { 00142 class context; 00143 } 00144 00155 class qep_row : public Sql_alloc 00156 { 00157 private: 00158 /* Don't copy this structure */ 00159 explicit qep_row(const qep_row &x); // undefined 00160 qep_row &operator=(const qep_row &x); // undefined 00161 00162 public: 00173 template<typename T> 00174 struct column 00175 { 00176 private: 00177 bool nil; 00178 public: 00179 T value; 00180 00181 public: 00182 column() { cleanup(); } 00183 bool is_empty() const { return nil; } 00184 void cleanup() { nil= true; } 00185 void set(T value_arg) { value= value_arg; nil= false; } 00186 T get() const { DBUG_ASSERT(!nil); return value; } 00187 }; 00188 00201 struct mem_root_str 00202 { 00203 const char *str; 00204 size_t length; 00205 Lazy *deferred; //< encapsulated expression to evaluate it later (on demand) 00206 00207 mem_root_str() { cleanup(); } 00208 void cleanup() 00209 { 00210 str= NULL; 00211 length= 0; 00212 deferred= NULL; 00213 } 00214 bool is_empty() 00215 { 00216 if (deferred) 00217 { 00218 StringBuffer<128> buff(system_charset_info); 00219 if (deferred->eval(&buff) || set(buff)) 00220 { 00221 DBUG_ASSERT(!"OOM!"); 00222 return true; // ignore OOM 00223 } 00224 deferred= NULL; // prevent double evaluation, if any 00225 } 00226 return str == NULL; 00227 } 00228 bool set(const char *str_arg) 00229 { 00230 return set(str_arg, strlen(str_arg)); 00231 } 00232 bool set(const String &s) 00233 { 00234 return set(s.ptr(), s.length()); 00235 } 00244 bool set(const char *str_arg, size_t length_arg) 00245 { 00246 deferred= NULL; 00247 if (!(str= strndup_root(current_thd->mem_root, str_arg, length_arg))) 00248 return true; /* purecov: inspected */ 00249 length= length_arg; 00250 return false; 00251 } 00257 void set(Lazy *x) 00258 { 00259 deferred= x; 00260 str= NULL; 00261 length= 0; 00262 } 00269 void set_const(const char *str_arg) 00270 { 00271 return set_const(str_arg, strlen(str_arg)); 00272 } 00273 void set_const(const char *str_arg, size_t length_arg) 00274 { 00275 deferred= NULL; 00276 str= str_arg; 00277 length= length_arg; 00278 } 00279 00280 static char *strndup_root(MEM_ROOT *root, const char *str, size_t len) 00281 { 00282 if (len == 0 || str == NULL) 00283 return const_cast<char *>(""); 00284 if (str[len - 1] == 0) 00285 return static_cast<char *>(memdup_root(root, str, len)); 00286 00287 char *ret= static_cast<char*>(alloc_root(root, len + 1)); 00288 if (ret != NULL) 00289 { 00290 memcpy(ret, str, len); 00291 ret[len]= 0; 00292 } 00293 return ret; 00294 } 00295 }; 00296 00300 struct extra: public Sql_alloc 00301 { 00305 const Extra_tag tag; 00312 const char *const data; 00313 00314 explicit extra(Extra_tag tag_arg, const char *data_arg= NULL) 00315 : tag(tag_arg), data(data_arg) 00316 {} 00317 }; 00318 00319 /* 00320 Next "col_*" fields are intended to be filling by "explain_*()" functions. 00321 00322 NOTE: NULL value or mem_root_str.is_empty()==true means that Item_null object 00323 will be pushed into "items" list instead. 00324 */ 00325 column<uint> col_id; 00326 column<SELECT_LEX::type_enum> col_select_type; 00327 mem_root_str col_table_name; 00328 List<const char> col_partitions; 00329 mem_root_str col_join_type; 00330 List<const char> col_possible_keys; 00331 mem_root_str col_key; 00332 mem_root_str col_key_len; 00333 List<const char> col_ref; 00334 column<longlong> col_rows; 00335 column<float> col_filtered; 00336 List<extra> col_extra; 00337 00338 // non-TRADITIONAL stuff: 00339 mem_root_str col_message; 00340 mem_root_str col_attached_condition; 00341 00342 /* For structured EXPLAIN in CTX_JOIN_TAB context: */ 00343 uint query_block_id; 00344 00348 List<opt_explain_json_namespace::context> derived_from; 00349 00350 List<const char> col_key_parts; 00351 00352 bool is_dependent; 00353 bool is_cacheable; 00354 bool using_temporary; 00355 bool is_materialized_from_subquery; 00356 bool is_update; //< UPDATE modified this table 00357 bool is_delete; //< DELETE modified this table 00358 00359 qep_row() : 00360 query_block_id(0), 00361 is_dependent(false), 00362 is_cacheable(true), 00363 using_temporary(false), 00364 is_materialized_from_subquery(false), 00365 is_update(false), 00366 is_delete(false) 00367 {} 00368 00369 virtual ~qep_row() {} 00370 00371 void cleanup() 00372 { 00373 col_id.cleanup(); 00374 col_table_name.cleanup(); 00375 col_partitions.empty(); 00376 col_join_type.cleanup(); 00377 col_possible_keys.empty(); 00378 col_key.cleanup(); 00379 col_key_len.cleanup(); 00380 col_ref.empty(); 00381 col_rows.cleanup(); 00382 col_filtered.cleanup(); 00383 col_extra.empty(); 00384 col_message.cleanup(); 00385 col_attached_condition.cleanup(); 00386 col_key_parts.empty(); 00387 00388 /* 00389 Not needed (we call cleanup() for structured EXPLAIN only, 00390 just for the consistency). 00391 */ 00392 query_block_id= 0; 00393 derived_from.empty(); 00394 is_dependent= false; 00395 is_cacheable= true; 00396 using_temporary= false; 00397 is_materialized_from_subquery= false; 00398 is_update= false; 00399 is_delete= false; 00400 } 00401 00417 virtual void register_where_subquery(SELECT_LEX_UNIT *subquery) {} 00418 }; 00419 00420 00428 struct Explain_subquery_marker 00429 { 00430 class qep_row *destination; 00431 Explain_context_enum type; 00432 00433 Explain_subquery_marker(qep_row *destination_arg, 00434 Explain_context_enum type_arg) 00435 : destination(destination_arg), type(type_arg) 00436 {} 00437 }; 00438 00444 enum Explain_sort_clause 00445 { 00446 ESC_none = 0, 00447 ESC_ORDER_BY = 1, 00448 ESC_GROUP_BY = 2, 00449 ESC_DISTINCT = 3, 00450 ESC_BUFFER_RESULT = 4, 00451 //----------------- 00452 ESC_MAX 00453 }; 00454 00458 enum Explain_sort_property 00459 { 00460 ESP_none = 0, 00461 ESP_EXISTS = 1 << 0, //< Original query has this clause 00462 ESP_IS_SIMPLE = 1 << 1, //< Clause is effective for single JOIN_TAB only 00463 ESP_USING_FILESORT = 1 << 2, //< Clause causes a filesort 00464 ESP_USING_TMPTABLE = 1 << 3, //< Clause creates an intermediate table 00465 ESP_DUPS_REMOVAL = 1 << 4, //< Duplicate removal for DISTINCT 00466 ESP_CHECKED = 1 << 5 //< Properties were already checked 00467 }; 00468 00469 00470 class Explain_format_flags 00471 { 00475 uint8 sorts[ESC_MAX]; 00476 00477 public: 00478 Explain_format_flags() { memset(sorts, 0, sizeof(sorts)); } 00479 00483 void set(Explain_sort_clause clause, Explain_sort_property property) 00484 { 00485 sorts[clause]|= property | ESP_EXISTS; 00486 } 00487 00488 void set(Explain_format_flags &flags) 00489 { 00490 memcpy(sorts, flags.sorts, sizeof(sorts)); 00491 } 00492 00496 void reset(Explain_sort_clause clause, Explain_sort_property property) 00497 { 00498 sorts[clause]&= ~property; 00499 } 00500 00504 bool get(Explain_sort_clause clause, Explain_sort_property property) const 00505 { 00506 return (sorts[clause] & property) || (sorts[clause] & ESP_CHECKED); 00507 } 00508 00512 bool any(Explain_sort_property property) const 00513 { 00514 for (size_t i= ESC_none + 1; i <= ESC_MAX - 1; i++) 00515 { 00516 if (sorts[i] & property || sorts[i] & ESP_CHECKED) 00517 return true; 00518 } 00519 return false; 00520 } 00521 }; 00522 00523 00528 class Explain_format : public Sql_alloc 00529 { 00530 private: 00531 /* Don't copy Explain_format values */ 00532 Explain_format(Explain_format &); // undefined 00533 Explain_format &operator=(Explain_format &); // undefined 00534 00535 public: 00536 select_result *output; 00537 00538 public: 00539 Explain_format() : output(NULL) {} 00540 virtual ~Explain_format() {} 00541 00542 00549 virtual bool is_hierarchical() const= 0; 00550 00561 virtual bool send_headers(select_result *result) 00562 { 00563 output= result; 00564 return false; 00565 } 00566 00573 virtual bool begin_context(Explain_context_enum context, 00574 SELECT_LEX_UNIT *subquery = 0, 00575 const Explain_format_flags *flags= NULL)= 0; 00576 00582 virtual bool end_context(Explain_context_enum context)= 0; 00583 00589 virtual bool flush_entry()= 0; 00590 00594 virtual qep_row *entry()= 0; 00595 }; 00596 00597 #endif//OPT_EXPLAIN_FORMAT_INCLUDED