My Project
|
00001 /* Copyright (c) 2011, 2012, 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 00014 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00015 00016 #ifndef OPT_TRACE_INCLUDED 00017 #define OPT_TRACE_INCLUDED 00018 00019 #include "my_config.h" // OPTIMIZER_TRACE 00020 #include "sql_array.h" // Dynamic_array 00021 #include "sql_list.h" // because sql_cmd.h needs it 00022 #include "sql_cmd.h" // for enum_sql_command 00023 #include "opt_trace_context.h" // Opt_trace_context 00024 00025 struct st_schema_table; 00026 struct TABLE_LIST; 00027 struct TABLE; 00028 class sp_head; 00029 class sp_printable; 00030 class set_var_base; 00031 00045 #ifdef OPTIMIZER_TRACE 00046 00366 class Opt_trace_struct; 00367 class Opt_trace_stmt; // implementation detail local to opt_trace.cc 00368 00369 00373 struct Opt_trace_info 00374 { 00385 const char *trace_ptr; 00386 size_t trace_length; 00387 00388 const char *query_ptr; 00389 size_t query_length; 00390 const CHARSET_INFO *query_charset; 00391 00395 size_t missing_bytes; 00396 bool missing_priv; 00397 }; 00398 00399 00405 class Opt_trace_iterator 00406 { 00407 public: 00411 Opt_trace_iterator(Opt_trace_context *ctx); 00412 00413 void next(); 00414 00424 void get_value(Opt_trace_info *info) const; 00425 00427 bool at_end() const { return cursor == NULL; } 00428 00429 private: 00431 Opt_trace_context *ctx; 00432 const Opt_trace_stmt *cursor; 00433 long row_count; 00434 }; 00435 00436 00446 class Opt_trace_struct 00447 { 00448 protected: 00462 Opt_trace_struct(Opt_trace_context *ctx_arg, bool requires_key_arg, 00463 const char *key, 00464 Opt_trace_context::feature_value feature) : 00465 started(false) 00466 { 00467 // A first inlined test 00468 if (unlikely(ctx_arg->is_started())) 00469 { 00470 // Tracing enabled: must fully initialize the structure. 00471 do_construct(ctx_arg, requires_key_arg, key, feature); 00472 } 00473 /* 00474 Otherwise, just leave "started" to false, it marks that the structure is 00475 dummy. 00476 */ 00477 } 00478 ~Opt_trace_struct() { if (unlikely(started)) do_destruct(); } 00479 00480 public: 00481 00487 void end() { if (unlikely(started)) do_destruct(); } 00488 00521 Opt_trace_struct& add_alnum(const char *key, const char *value) 00522 { 00523 if (likely(!started)) 00524 return *this; 00525 return do_add(key, value, strlen(value), false); 00526 } 00527 00534 Opt_trace_struct& add_alnum(const char *value) 00535 { 00536 if (likely(!started)) 00537 return *this; 00538 return do_add(NULL, value, strlen(value), false); 00539 } 00540 00548 Opt_trace_struct& add_utf8(const char *key, 00549 const char *value, size_t val_length) 00550 { 00551 if (likely(!started)) 00552 return *this; 00553 return do_add(key, value, val_length, true); 00554 } 00555 00557 Opt_trace_struct& add_utf8(const char *value, size_t val_length) 00558 { 00559 if (likely(!started)) 00560 return *this; 00561 return do_add(NULL, value, val_length, true); 00562 } 00563 00565 Opt_trace_struct& add_utf8(const char *key, const char *value) 00566 { 00567 if (likely(!started)) 00568 return *this; 00569 return do_add(key, value, strlen(value), true); 00570 } 00571 00573 Opt_trace_struct& add_utf8(const char *value) 00574 { 00575 if (likely(!started)) 00576 return *this; 00577 return do_add(NULL, value, strlen(value), true); 00578 } 00579 00589 Opt_trace_struct& add(const char *key, Item *item) 00590 { 00591 if (likely(!started)) 00592 return *this; 00593 return do_add(key, item); 00594 } 00595 Opt_trace_struct& add(Item *item) 00596 { 00597 if (likely(!started)) 00598 return *this; 00599 return do_add(NULL, item); 00600 } 00601 public: 00602 Opt_trace_struct& add(const char *key, bool value) 00603 { 00604 if (likely(!started)) 00605 return *this; 00606 return do_add(key, value); 00607 } 00608 Opt_trace_struct& add(bool value) 00609 { 00610 if (likely(!started)) 00611 return *this; 00612 return do_add(NULL, value); 00613 } 00614 Opt_trace_struct& add(const char *key, int value) 00615 { 00616 if (likely(!started)) 00617 return *this; 00618 return do_add(key, static_cast<longlong>(value)); 00619 } 00620 Opt_trace_struct& add(int value) 00621 { 00622 if (likely(!started)) 00623 return *this; 00624 return do_add(NULL, static_cast<longlong>(value)); 00625 } 00626 Opt_trace_struct& add(const char *key, uint value) 00627 { 00628 if (likely(!started)) 00629 return *this; 00630 return do_add(key, static_cast<ulonglong>(value)); 00631 } 00632 Opt_trace_struct& add(uint value) 00633 { 00634 if (likely(!started)) 00635 return *this; 00636 return do_add(NULL, static_cast<ulonglong>(value)); 00637 } 00638 Opt_trace_struct& add(const char *key, ulong value) 00639 { 00640 if (likely(!started)) 00641 return *this; 00642 return do_add(key, static_cast<ulonglong>(value)); 00643 } 00644 Opt_trace_struct& add(ulong value) 00645 { 00646 if (likely(!started)) 00647 return *this; 00648 return do_add(NULL, static_cast<ulonglong>(value)); 00649 } 00650 Opt_trace_struct& add(const char *key, longlong value) 00651 { 00652 if (likely(!started)) 00653 return *this; 00654 return do_add(key, value); 00655 } 00656 Opt_trace_struct& add(longlong value) 00657 { 00658 if (likely(!started)) 00659 return *this; 00660 return do_add(NULL, value); 00661 } 00662 Opt_trace_struct& add(const char *key, ulonglong value) 00663 { 00664 if (likely(!started)) 00665 return *this; 00666 return do_add(key, value); 00667 } 00668 Opt_trace_struct& add(ulonglong value) 00669 { 00670 if (likely(!started)) 00671 return *this; 00672 return do_add(NULL, value); 00673 } 00674 Opt_trace_struct& add(const char *key, double value) 00675 { 00676 if (likely(!started)) 00677 return *this; 00678 return do_add(key, value); 00679 } 00680 Opt_trace_struct& add(double value) 00681 { 00682 if (likely(!started)) 00683 return *this; 00684 return do_add(NULL, value); 00685 } 00687 Opt_trace_struct& add_hex(const char *key, uint64 value) 00688 { 00689 if (likely(!started)) 00690 return *this; 00691 return do_add_hex(key, value); 00692 } 00693 Opt_trace_struct& add_hex(uint64 value) 00694 { 00695 if (likely(!started)) 00696 return *this; 00697 return do_add_hex(NULL, value); 00698 } 00700 Opt_trace_struct& add_null(const char *key) 00701 { 00702 if (likely(!started)) 00703 return *this; 00704 return do_add_null(key); 00705 } 00710 Opt_trace_struct& add_utf8_table(const TABLE *tab) 00711 { 00712 if (likely(!started)) 00713 return *this; 00714 return do_add_utf8_table(tab); 00715 } 00720 Opt_trace_struct& add_select_number(uint select_number) 00721 { 00722 return unlikely(select_number >= INT_MAX) ? 00723 // Clearer than any huge number. 00724 add_alnum("select#", "fake") : 00725 add("select#", select_number); 00726 } 00727 00735 bool set_not_empty() 00736 { 00737 const bool old_empty= empty; 00738 empty= false; 00739 return old_empty; 00740 } 00774 const char *check_key(const char *key); 00775 00776 private: 00778 Opt_trace_struct& add(const char *key, const char* value); 00779 Opt_trace_struct& add(const char *key); 00780 00782 void do_construct(Opt_trace_context *ctx, 00783 bool requires_key, const char *key, 00784 Opt_trace_context::feature_value feature); 00786 void do_destruct(); 00793 Opt_trace_struct& do_add(const char *key, const char *value, 00794 size_t val_length, bool escape); 00795 Opt_trace_struct& do_add(const char *key, Item *item); 00796 Opt_trace_struct& do_add(const char *key, bool value); 00797 Opt_trace_struct& do_add(const char *key, longlong value); 00798 Opt_trace_struct& do_add(const char *key, ulonglong value); 00799 Opt_trace_struct& do_add(const char *key, double value); 00800 Opt_trace_struct& do_add_hex(const char *key, uint64 value); 00801 Opt_trace_struct& do_add_null(const char *key); 00802 Opt_trace_struct& do_add_utf8_table(const TABLE *tab); 00803 00804 Opt_trace_struct(const Opt_trace_struct&); 00805 Opt_trace_struct& operator=(const Opt_trace_struct&); 00806 00807 bool started; 00808 00821 bool requires_key; 00822 00828 bool has_disabled_I_S; 00829 bool empty; 00830 Opt_trace_stmt *stmt; 00831 00832 const char *saved_key; 00833 #ifndef DBUG_OFF 00834 00839 char previous_key[25]; 00840 #endif 00841 }; 00842 00843 00849 class Opt_trace_object: public Opt_trace_struct 00850 { 00851 public: 00859 Opt_trace_object(Opt_trace_context *ctx, const char *key, 00860 Opt_trace_context::feature_value feature= 00861 Opt_trace_context::MISC) 00862 : Opt_trace_struct(ctx, true, key, feature) 00863 {} 00870 Opt_trace_object(Opt_trace_context *ctx, 00871 Opt_trace_context::feature_value feature= 00872 Opt_trace_context::MISC) 00873 : Opt_trace_struct(ctx, true, NULL, feature) 00874 {} 00875 }; 00876 00877 00883 class Opt_trace_array: public Opt_trace_struct 00884 { 00885 public: 00893 Opt_trace_array(Opt_trace_context *ctx, const char *key, 00894 Opt_trace_context::feature_value feature= 00895 Opt_trace_context::MISC) 00896 : Opt_trace_struct(ctx, false, key, feature) 00897 {} 00904 Opt_trace_array(Opt_trace_context *ctx, 00905 Opt_trace_context::feature_value feature= 00906 Opt_trace_context::MISC) 00907 : Opt_trace_struct(ctx, false, NULL, feature) 00908 {} 00909 }; 00910 00911 00919 class Opt_trace_disable_I_S 00920 { 00921 public: 00953 Opt_trace_disable_I_S(Opt_trace_context *ctx_arg, bool disable_arg) 00954 { 00955 if (disable_arg) 00956 { 00957 ctx= ctx_arg; 00958 ctx->disable_I_S_for_this_and_children(); 00959 } 00960 else 00961 ctx= NULL; 00962 } 00963 00965 ~Opt_trace_disable_I_S() 00966 { 00967 if (ctx != NULL) 00968 ctx->restore_I_S(); 00969 } 00970 00971 private: 00973 Opt_trace_context *ctx; 00974 Opt_trace_disable_I_S(const Opt_trace_disable_I_S&); // not defined 00975 Opt_trace_disable_I_S& operator=(const Opt_trace_disable_I_S&);//not defined 00976 }; 00977 00978 00984 01008 class Opt_trace_start 01009 { 01010 public: 01011 Opt_trace_start(THD *thd_arg, TABLE_LIST *tbl, 01012 enum enum_sql_command sql_command, 01013 List<set_var_base> *set_vars, 01014 const char *query, size_t query_length, 01015 sp_printable *instr, 01016 const CHARSET_INFO *query_charset); 01017 ~Opt_trace_start(); 01018 private: 01019 Opt_trace_context * const ctx; 01020 bool error; 01021 }; 01022 01023 01024 class st_select_lex; 01033 void opt_trace_print_expanded_query(THD *thd, 01034 st_select_lex *select_lex, 01035 Opt_trace_object *trace_object); 01036 01072 void opt_trace_disable_if_no_security_context_access(THD *thd); 01073 01089 void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view, 01090 TABLE_LIST *underlying_tables); 01091 01108 void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp); 01109 01115 int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *cond); 01116 01118 01119 #else /* defined (OPTIMIZER_TRACE) */ 01120 01121 /* all empty */ 01122 01124 class Opt_trace_object 01125 { 01126 public: 01127 Opt_trace_object(Opt_trace_context *ctx, const char *key, 01128 Opt_trace_context::feature_value feature= 01129 Opt_trace_context::MISC) 01130 {} 01131 Opt_trace_object(Opt_trace_context *ctx, 01132 Opt_trace_context::feature_value feature= 01133 Opt_trace_context::MISC) 01134 {} 01135 Opt_trace_object& add_alnum(const char *key, const char *value) 01136 { return *this; } 01137 Opt_trace_object& add_utf8(const char *key, 01138 const char *value, size_t val_length) 01139 { return *this; } 01140 Opt_trace_object& add_utf8(const char *key, const char *value) 01141 { return *this; } 01142 Opt_trace_object& add(const char *key, Item *item) { return *this; } 01143 Opt_trace_object& add(const char *key, bool value) { return *this; } 01144 Opt_trace_object& add(const char *key, int value) { return *this; } 01145 Opt_trace_object& add(const char *key, uint value) { return *this; } 01146 Opt_trace_object& add(const char *key, ulong value) { return *this; } 01147 Opt_trace_object& add(const char *key, longlong value) { return *this; } 01148 Opt_trace_object& add(const char *key, ulonglong value) { return *this; } 01149 Opt_trace_object& add(const char *key, double value) { return *this; } 01150 Opt_trace_object& add_hex(const char *key, uint64 value) { return *this; } 01151 Opt_trace_object& add_utf8_table(const TABLE *tab) { return *this; } 01152 Opt_trace_object& add_select_number(uint select_number) { return *this; } 01153 void end() {} 01154 }; 01155 01157 class Opt_trace_array 01158 { 01159 public: 01160 Opt_trace_array(Opt_trace_context *ctx, const char *key, 01161 Opt_trace_context::feature_value feature= 01162 Opt_trace_context::MISC) 01163 {} 01164 Opt_trace_array(Opt_trace_context *ctx, 01165 Opt_trace_context::feature_value feature= 01166 Opt_trace_context::MISC) 01167 {} 01168 Opt_trace_array& add_alnum(const char *value) { return *this; } 01169 Opt_trace_array& add_utf8(const char *value, size_t val_length) 01170 { return *this; } 01171 Opt_trace_array& add_utf8(const char *value) 01172 { return *this; } 01173 Opt_trace_array& add(Item *item) { return *this; } 01174 Opt_trace_array& add(bool value) { return *this; } 01175 Opt_trace_array& add(int value) { return *this; } 01176 Opt_trace_array& add(uint value) { return *this; } 01177 Opt_trace_array& add(longlong value) { return *this; } 01178 Opt_trace_array& add(ulonglong value) { return *this; } 01179 Opt_trace_array& add(double value) { return *this; } 01180 Opt_trace_array& add_hex(uint64 value) { return *this; } 01181 Opt_trace_array& add_utf8_table(TABLE *tab) { return *this; } 01182 Opt_trace_array& add_select_number(uint select_number) { return *this; } 01183 void end() {} 01184 }; 01185 01187 class Opt_trace_disable_I_S 01188 { 01189 public: 01190 Opt_trace_disable_I_S(Opt_trace_context *ctx_arg, bool disable_arg) {} 01191 }; 01192 01193 class Opt_trace_start 01194 { 01195 public: 01196 Opt_trace_start(THD *thd, const TABLE_LIST *tbl, 01197 enum enum_sql_command sql_command, 01198 List<set_var_base> *set_vars, 01199 const char *query, size_t query_length, 01200 sp_printable *instr, 01201 const CHARSET_INFO *query_charset) {} 01202 }; 01203 01204 #define opt_trace_print_expanded_query(thd, select_lex, trace_object) \ 01205 do {} while (0) 01206 #define opt_trace_disable_if_no_view_access(thd, view, underlying_tables) \ 01207 do {} while (0) 01208 #define opt_trace_disable_if_no_stored_proc_func_access(thd, sp) do{} while(0) 01209 #define opt_trace_disable_if_no_security_context_access(thd) do {} while (0) 01210 01211 #endif /* OPTIMIZER_TRACE */ 01212 01231 #define OPT_TRACE_TRANSFORM(trace,object_level0,object_level1, \ 01232 select_number,from,to) \ 01233 Opt_trace_object object_level0(trace); \ 01234 Opt_trace_object object_level1(trace, "transformation"); \ 01235 object_level1.add_select_number(select_number); \ 01236 object_level1.add_alnum("from", from).add_alnum("to", to); 01237 01238 /* 01239 A debug binary without optimizer trace compiled in, will miss some 01240 debugging info, be less useful, so: 01241 */ 01242 #if !defined(DBUG_OFF) && !defined(OPTIMIZER_TRACE) 01243 #error debug binaries must support optimizer trace 01244 #endif 01245 01246 #endif /* OPT_TRACE_INCLUDED */