My Project
|
00001 /* Copyright (c) 2012, 2014, 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 _SP_INSTR_H_ 00017 #define _SP_INSTR_H_ 00018 00019 #include "my_global.h" // NO_EMBEDDED_ACCESS_CHECKS 00020 #include "sp_pcontext.h" // sp_pcontext 00021 #include "sql_class.h" // THD 00022 #include "sp_head.h" // sp_printable 00023 00025 // This file contains SP-instruction classes. 00027 00032 class sp_branch_instr 00033 { 00034 public: 00041 virtual void set_destination(uint old_dest, uint new_dest) = 0; 00042 00049 virtual void backpatch(uint dest) = 0; 00050 00051 virtual ~sp_branch_instr() 00052 { } 00053 }; 00054 00056 00061 class sp_instr : public Query_arena, 00062 public Sql_alloc, 00063 public sp_printable 00064 { 00065 public: 00066 sp_instr(uint ip, sp_pcontext *ctx) 00067 :Query_arena(0, STMT_INITIALIZED_FOR_SP), 00068 m_marked(false), 00069 m_ip(ip), 00070 m_parsing_ctx(ctx) 00071 { } 00072 00073 virtual ~sp_instr() 00074 { free_items(); } 00075 00088 virtual bool execute(THD *thd, uint *nextp) = 0; 00089 00090 uint get_ip() const 00091 { return m_ip; } 00092 00098 virtual uint get_cont_dest() const 00099 { return get_ip() + 1; } 00100 00101 sp_pcontext *get_parsing_ctx() const 00102 { return m_parsing_ctx; } 00103 00105 // The following operations are used solely for SP-code-optimizer. 00107 00113 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads) 00114 { 00115 m_marked= true; 00116 return get_ip() + 1; 00117 } 00118 00125 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 00126 { return get_ip(); } 00127 00134 virtual void opt_move(uint dst, List<sp_branch_instr> *ibp) 00135 { m_ip= dst; } 00136 00137 bool opt_is_marked() const 00138 { return m_marked; } 00139 00140 virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list() 00141 { return NULL; } 00142 00143 protected: 00146 bool m_marked; 00147 00149 uint m_ip; 00150 00152 sp_pcontext *m_parsing_ctx; 00153 00154 private: 00155 // Prevent use of copy constructor and assignment operator. 00156 sp_instr(const sp_instr &); 00157 void operator= (sp_instr &); 00158 }; 00159 00161 00171 class sp_lex_instr : public sp_instr 00172 { 00173 public: 00174 sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner) 00175 :sp_instr(ip, ctx), 00176 m_lex(NULL), 00177 m_is_lex_owner(false), 00178 m_first_execution(true), 00179 m_prelocking_tables(NULL), 00180 m_lex_query_tables_own_last(NULL) 00181 { 00182 set_lex(lex, is_lex_owner); 00183 memset(&m_lex_mem_root, 0, sizeof (MEM_ROOT)); 00184 } 00185 00186 virtual ~sp_lex_instr() 00187 { 00188 free_lex(); 00189 /* 00190 If the instruction is reparsed, m_lex_mem_root was used to allocate 00191 the items, then freeing the memroot, frees the items. Also free the 00192 items allocated on heap as well. 00193 */ 00194 if (alloc_root_inited(&m_lex_mem_root)) 00195 free_items(); 00196 free_root(&m_lex_mem_root, MYF(0)); 00197 } 00198 00218 bool validate_lex_and_execute_core(THD *thd, uint *nextp, bool open_tables); 00219 00220 virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list() 00221 { return &m_trig_field_list; } 00222 00223 private: 00242 bool reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables); 00243 00253 LEX *parse_expr(THD *thd, sp_head *sp); 00254 00265 void set_lex(LEX *lex, bool is_lex_owner); 00266 00270 void free_lex(); 00271 00272 public: 00274 // sp_instr implementation. 00276 00277 virtual bool execute(THD *thd, uint *nextp) 00278 { return validate_lex_and_execute_core(thd, nextp, true); } 00279 00280 protected: 00282 // Interface (virtual) methods. 00284 00294 virtual bool exec_core(THD *thd, uint *nextp) = 0; 00295 00304 virtual bool is_invalid() const = 0; 00305 00309 virtual void invalidate() = 0; 00310 00317 virtual void get_query(String *sql_query) const; 00318 00329 virtual LEX_STRING get_expr_query() const 00330 { return EMPTY_STR; } 00331 00342 virtual bool on_after_expr_parsing(THD *thd) 00343 { return false; } 00344 00351 virtual void cleanup_before_parsing(THD *thd); 00352 00353 private: 00359 MEM_ROOT m_lex_mem_root; 00360 00362 LEX *m_lex; 00363 00368 bool m_is_lex_owner; 00369 00374 bool m_first_execution; 00375 00376 /***************************************************************************** 00377 Support for being able to execute this statement in two modes: 00378 a) inside prelocked mode set by the calling procedure or its ancestor. 00379 b) outside of prelocked mode, when this statement enters/leaves 00380 prelocked mode itself. 00381 *****************************************************************************/ 00382 00387 TABLE_LIST *m_prelocking_tables; 00388 00393 TABLE_LIST **m_lex_query_tables_own_last; 00394 00398 SQL_I_List<Item_trigger_field> m_trig_field_list; 00399 }; 00400 00402 00410 class sp_instr_stmt : public sp_lex_instr 00411 { 00412 public: 00413 sp_instr_stmt(uint ip, 00414 LEX *lex, 00415 LEX_STRING query) 00416 :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true), 00417 m_query(query), 00418 m_valid(true) 00419 { } 00420 00422 // sp_instr implementation. 00424 00425 virtual bool execute(THD *thd, uint *nextp); 00426 00428 // sp_printable implementation. 00430 00431 virtual void print(String *str); 00432 00434 // sp_lex_instr implementation. 00436 00437 virtual bool exec_core(THD *thd, uint *nextp); 00438 00439 virtual bool is_invalid() const 00440 { return !m_valid; } 00441 00442 virtual void invalidate() 00443 { m_valid= false; } 00444 00445 virtual void get_query(String *sql_query) const 00446 { sql_query->append(m_query.str, m_query.length); } 00447 00448 virtual bool on_after_expr_parsing(THD *thd) 00449 { 00450 m_valid= true; 00451 return false; 00452 } 00453 00454 private: 00456 LEX_STRING m_query; 00457 00459 bool m_valid; 00460 }; 00461 00463 00467 class sp_instr_set : public sp_lex_instr 00468 { 00469 public: 00470 sp_instr_set(uint ip, 00471 LEX *lex, 00472 uint offset, 00473 Item *value_item, 00474 LEX_STRING value_query, 00475 bool is_lex_owner) 00476 :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, is_lex_owner), 00477 m_offset(offset), 00478 m_value_item(value_item), 00479 m_value_query(value_query) 00480 { } 00481 00483 // sp_printable implementation. 00485 00486 virtual void print(String *str); 00487 00489 // sp_lex_instr implementation. 00491 00492 virtual bool exec_core(THD *thd, uint *nextp); 00493 00494 virtual bool is_invalid() const 00495 { return m_value_item == NULL; } 00496 00497 virtual void invalidate() 00498 { m_value_item= NULL; } 00499 00500 virtual bool on_after_expr_parsing(THD *thd) 00501 { 00502 DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1); 00503 00504 m_value_item= thd->lex->select_lex.item_list.head(); 00505 00506 return false; 00507 } 00508 00509 virtual LEX_STRING get_expr_query() const 00510 { return m_value_query; } 00511 00512 private: 00514 uint m_offset; 00515 00517 Item *m_value_item; 00518 00520 LEX_STRING m_value_query; 00521 }; 00522 00524 00529 class sp_instr_set_trigger_field : public sp_lex_instr 00530 { 00531 public: 00532 sp_instr_set_trigger_field(uint ip, 00533 LEX *lex, 00534 LEX_STRING trigger_field_name, 00535 Item_trigger_field *trigger_field, 00536 Item *value_item, 00537 LEX_STRING value_query) 00538 :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true), 00539 m_trigger_field_name(trigger_field_name), 00540 m_trigger_field(trigger_field), 00541 m_value_item(value_item), 00542 m_value_query(value_query) 00543 { } 00544 00546 // sp_printable implementation. 00548 00549 virtual void print(String *str); 00550 00552 // sp_lex_instr implementation. 00554 00555 virtual bool exec_core(THD *thd, uint *nextp); 00556 00557 virtual bool is_invalid() const 00558 { return m_value_item == NULL; } 00559 00560 virtual void invalidate() 00561 { m_value_item= NULL; } 00562 00563 virtual bool on_after_expr_parsing(THD *thd); 00564 00565 virtual void cleanup_before_parsing(THD *thd); 00566 00567 virtual LEX_STRING get_expr_query() const 00568 { return m_value_query; } 00569 00570 private: 00572 LEX_STRING m_trigger_field_name; 00573 00575 Item_trigger_field *m_trigger_field; 00576 00578 Item *m_value_item; 00579 00581 LEX_STRING m_value_query; 00582 }; 00583 00585 00589 class sp_instr_freturn : public sp_lex_instr 00590 { 00591 public: 00592 sp_instr_freturn(uint ip, 00593 LEX *lex, 00594 Item *expr_item, 00595 LEX_STRING expr_query, 00596 enum enum_field_types return_field_type) 00597 :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true), 00598 m_expr_item(expr_item), 00599 m_expr_query(expr_query), 00600 m_return_field_type(return_field_type) 00601 { } 00602 00604 // sp_printable implementation. 00606 00607 virtual void print(String *str); 00608 00610 // sp_instr implementation. 00612 00613 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads) 00614 { 00615 m_marked= true; 00616 return UINT_MAX; 00617 } 00618 00620 // sp_lex_instr implementation. 00622 00623 virtual bool exec_core(THD *thd, uint *nextp); 00624 00625 virtual bool is_invalid() const 00626 { return m_expr_item == NULL; } 00627 00628 virtual void invalidate() 00629 { 00630 // it's already deleted. 00631 m_expr_item= NULL; 00632 } 00633 00634 virtual bool on_after_expr_parsing(THD *thd) 00635 { 00636 DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1); 00637 00638 m_expr_item= thd->lex->select_lex.item_list.head(); 00639 00640 return false; 00641 } 00642 00643 virtual LEX_STRING get_expr_query() const 00644 { return m_expr_query; } 00645 00646 private: 00648 Item *m_expr_item; 00649 00651 LEX_STRING m_expr_query; 00652 00654 enum enum_field_types m_return_field_type; 00655 }; 00656 00658 00669 class sp_instr_jump : public sp_instr, 00670 public sp_branch_instr 00671 { 00672 public: 00673 sp_instr_jump(uint ip, sp_pcontext *ctx) 00674 :sp_instr(ip, ctx), 00675 m_dest(0), 00676 m_optdest(NULL) 00677 { } 00678 00679 sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest) 00680 :sp_instr(ip, ctx), 00681 m_dest(dest), 00682 m_optdest(NULL) 00683 { } 00684 00686 // sp_printable implementation. 00688 00689 virtual void print(String *str); 00690 00692 // sp_instr implementation. 00694 00695 virtual bool execute(THD *thd, uint *nextp) 00696 { 00697 *nextp= m_dest; 00698 return false; 00699 } 00700 00701 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); 00702 00703 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start); 00704 00705 virtual void opt_move(uint dst, List<sp_branch_instr> *ibp); 00706 00708 // sp_branch_instr implementation. 00710 00711 virtual void set_destination(uint old_dest, uint new_dest) 00712 { 00713 if (m_dest == old_dest) 00714 m_dest= new_dest; 00715 } 00716 00717 virtual void backpatch(uint dest) 00718 { 00719 /* Calling backpatch twice is a logic flaw in jump resolution. */ 00720 DBUG_ASSERT(m_dest == 0); 00721 m_dest= dest; 00722 } 00723 00724 protected: 00726 uint m_dest; 00727 00728 // The following attribute is used by SP-optimizer. 00729 sp_instr *m_optdest; 00730 }; 00731 00733 00738 class sp_lex_branch_instr : public sp_lex_instr, 00739 public sp_branch_instr 00740 { 00741 protected: 00742 sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex, 00743 Item *expr_item, LEX_STRING expr_query) 00744 :sp_lex_instr(ip, ctx, lex, true), 00745 m_dest(0), 00746 m_cont_dest(0), 00747 m_optdest(NULL), 00748 m_cont_optdest(NULL), 00749 m_expr_item(expr_item), 00750 m_expr_query(expr_query) 00751 { } 00752 00753 sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex, 00754 Item *expr_item, LEX_STRING expr_query, 00755 uint dest) 00756 :sp_lex_instr(ip, ctx, lex, true), 00757 m_dest(dest), 00758 m_cont_dest(0), 00759 m_optdest(NULL), 00760 m_cont_optdest(NULL), 00761 m_expr_item(expr_item), 00762 m_expr_query(expr_query) 00763 { } 00764 00765 public: 00766 void set_cont_dest(uint cont_dest) 00767 { m_cont_dest= cont_dest; } 00768 00770 // sp_instr implementation. 00772 00773 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); 00774 00775 virtual void opt_move(uint dst, List<sp_branch_instr> *ibp); 00776 00777 virtual uint get_cont_dest() const 00778 { return m_cont_dest; } 00779 00781 // sp_lex_instr implementation. 00783 00784 virtual bool is_invalid() const 00785 { return m_expr_item == NULL; } 00786 00787 virtual void invalidate() 00788 { m_expr_item= NULL; /* it's already deleted. */ } 00789 00790 virtual LEX_STRING get_expr_query() const 00791 { return m_expr_query; } 00792 00794 // sp_branch_instr implementation. 00796 00797 virtual void set_destination(uint old_dest, uint new_dest) 00798 { 00799 if (m_dest == old_dest) 00800 m_dest= new_dest; 00801 00802 if (m_cont_dest == old_dest) 00803 m_cont_dest= new_dest; 00804 } 00805 00806 virtual void backpatch(uint dest) 00807 { 00808 /* Calling backpatch twice is a logic flaw in jump resolution. */ 00809 DBUG_ASSERT(m_dest == 0); 00810 m_dest= dest; 00811 } 00812 00813 protected: 00815 uint m_dest; 00816 00818 uint m_cont_dest; 00819 00820 // The following attributes are used by SP-optimizer. 00821 sp_instr *m_optdest; 00822 sp_instr *m_cont_optdest; 00823 00825 Item *m_expr_item; 00826 00828 LEX_STRING m_expr_query; 00829 }; 00830 00832 00837 class sp_instr_jump_if_not : public sp_lex_branch_instr 00838 { 00839 public: 00840 sp_instr_jump_if_not(uint ip, 00841 LEX *lex, 00842 Item *expr_item, 00843 LEX_STRING expr_query) 00844 :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex, 00845 expr_item, expr_query) 00846 { } 00847 00848 sp_instr_jump_if_not(uint ip, 00849 LEX *lex, 00850 Item *expr_item, 00851 LEX_STRING expr_query, 00852 uint dest) 00853 :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex, 00854 expr_item, expr_query, dest) 00855 { } 00856 00858 // sp_printable implementation. 00860 00861 virtual void print(String *str); 00862 00864 // sp_lex_instr implementation. 00866 00867 virtual bool exec_core(THD *thd, uint *nextp); 00868 00869 virtual bool on_after_expr_parsing(THD *thd) 00870 { 00871 DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1); 00872 00873 m_expr_item= thd->lex->select_lex.item_list.head(); 00874 00875 return false; 00876 } 00877 }; 00878 00880 // Instructions used for the "simple CASE" implementation. 00882 00887 class sp_instr_set_case_expr : public sp_lex_branch_instr 00888 { 00889 public: 00890 sp_instr_set_case_expr(uint ip, 00891 LEX *lex, 00892 uint case_expr_id, 00893 Item *case_expr_item, 00894 LEX_STRING case_expr_query) 00895 :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex, 00896 case_expr_item, case_expr_query), 00897 m_case_expr_id(case_expr_id) 00898 { } 00899 00901 // sp_printable implementation. 00903 00904 virtual void print(String *str); 00905 00907 // sp_instr implementation. 00909 00910 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); 00911 00912 virtual void opt_move(uint dst, List<sp_branch_instr> *ibp); 00913 00915 // sp_branch_instr implementation. 00917 00918 /* 00919 NOTE: set_destination() and backpatch() are overriden here just because the 00920 m_dest attribute is not used by this class, so there is no need to do 00921 anything about it. 00922 00923 @todo These operations probably should be left as they are (i.e. do not 00924 override them here). The m_dest attribute would be set and not used, but 00925 that should not be a big deal. 00926 00927 @todo This also indicates deficiency of the current SP-istruction class 00928 hierarchy. 00929 */ 00930 00931 virtual void set_destination(uint old_dest, uint new_dest) 00932 { 00933 if (m_cont_dest == old_dest) 00934 m_cont_dest= new_dest; 00935 } 00936 00937 virtual void backpatch(uint dest) 00938 { } 00939 00941 // sp_lex_instr implementation. 00943 00944 virtual bool exec_core(THD *thd, uint *nextp); 00945 00946 virtual bool on_after_expr_parsing(THD *thd) 00947 { 00948 DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1); 00949 00950 m_expr_item= thd->lex->select_lex.item_list.head(); 00951 00952 return false; 00953 } 00954 00955 private: 00957 uint m_case_expr_id; 00958 }; 00959 00961 00969 class sp_instr_jump_case_when : public sp_lex_branch_instr 00970 { 00971 public: 00972 sp_instr_jump_case_when(uint ip, 00973 LEX *lex, 00974 int case_expr_id, 00975 Item *when_expr_item, 00976 LEX_STRING when_expr_query) 00977 :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex, 00978 when_expr_item, when_expr_query), 00979 m_case_expr_id(case_expr_id) 00980 { } 00981 00983 // sp_printable implementation. 00985 00986 virtual void print(String *str); 00987 00989 // sp_lex_instr implementation. 00991 00992 virtual bool exec_core(THD *thd, uint *nextp); 00993 00994 virtual void invalidate() 00995 { 00996 // Items should be already deleted in lex-keeper. 00997 m_case_expr_item= NULL; 00998 m_eq_item= NULL; 00999 m_expr_item= NULL; // it's a WHEN-expression. 01000 } 01001 01002 virtual bool on_after_expr_parsing(THD *thd) 01003 { return build_expr_items(thd); } 01004 01005 private: 01026 bool build_expr_items(THD *thd); 01027 01028 private: 01030 int m_case_expr_id; 01031 01033 Item_case_expr *m_case_expr_item; 01034 01040 Item *m_eq_item; 01041 }; 01042 01044 // SQL-condition handler instructions. 01046 01047 class sp_instr_hpush_jump : public sp_instr_jump 01048 { 01049 public: 01050 sp_instr_hpush_jump(uint ip, 01051 sp_pcontext *ctx, 01052 sp_handler *handler) 01053 :sp_instr_jump(ip, ctx), 01054 m_handler(handler), 01055 m_opt_hpop(0), 01056 m_frame(ctx->current_var_count()) 01057 { 01058 DBUG_ASSERT(m_handler->condition_values.elements == 0); 01059 } 01060 01061 virtual ~sp_instr_hpush_jump() 01062 { 01063 m_handler->condition_values.empty(); 01064 m_handler= NULL; 01065 } 01066 01067 void add_condition(sp_condition_value *condition_value) 01068 { m_handler->condition_values.push_back(condition_value); } 01069 01070 sp_handler *get_handler() 01071 { return m_handler; } 01072 01074 // sp_printable implementation. 01076 01077 virtual void print(String *str); 01078 01080 // sp_instr implementation. 01082 01083 virtual bool execute(THD *thd, uint *nextp); 01084 01085 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); 01086 01088 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 01089 { return get_ip(); } 01090 01092 // sp_branch_instr implementation. 01094 01095 virtual void backpatch(uint dest) 01096 { 01097 DBUG_ASSERT(!m_dest || !m_opt_hpop); 01098 if (!m_dest) 01099 m_dest= dest; 01100 else 01101 m_opt_hpop= dest; 01102 } 01103 01104 private: 01106 sp_handler *m_handler; 01107 01109 uint m_opt_hpop; 01110 01111 // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in 01112 // debug version only). It's used in print(). 01113 uint m_frame; 01114 }; 01115 01117 01118 class sp_instr_hpop : public sp_instr 01119 { 01120 public: 01121 sp_instr_hpop(uint ip, sp_pcontext *ctx) 01122 : sp_instr(ip, ctx) 01123 { } 01124 01126 // sp_printable implementation. 01128 01129 virtual void print(String *str) 01130 { str->append(STRING_WITH_LEN("hpop")); } 01131 01133 // sp_instr implementation. 01135 01136 virtual bool execute(THD *thd, uint *nextp); 01137 }; 01138 01140 01141 class sp_instr_hreturn : public sp_instr_jump 01142 { 01143 public: 01144 sp_instr_hreturn(uint ip, sp_pcontext *ctx) 01145 :sp_instr_jump(ip, ctx), 01146 m_frame(ctx->current_var_count()) 01147 { } 01148 01150 // sp_printable implementation. 01152 01153 virtual void print(String *str); 01154 01156 // sp_instr implementation. 01158 01159 virtual bool execute(THD *thd, uint *nextp); 01160 01162 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 01163 { return get_ip(); } 01164 01165 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); 01166 01167 private: 01168 // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in 01169 // debug version only). It's used in print(). 01170 uint m_frame; 01171 }; 01172 01174 // Cursor implementation. 01176 01194 class sp_instr_cpush : public sp_lex_instr 01195 { 01196 public: 01197 sp_instr_cpush(uint ip, 01198 sp_pcontext *ctx, 01199 LEX *cursor_lex, 01200 LEX_STRING cursor_query, 01201 int cursor_idx) 01202 :sp_lex_instr(ip, ctx, cursor_lex, true), 01203 m_cursor_query(cursor_query), 01204 m_valid(true), 01205 m_cursor_idx(cursor_idx) 01206 { 01207 // Cursor can't be stored in Query Cache, so we should prevent opening QC 01208 // for try to write results which are absent. 01209 01210 cursor_lex->safe_to_cache_query= false; 01211 } 01212 01214 // sp_printable implementation. 01216 01217 virtual void print(String *str); 01218 01220 // Query_arena implementation. 01222 01228 virtual void cleanup_stmt() 01229 { /* no op */ } 01230 01232 // sp_instr implementation. 01234 01235 virtual bool execute(THD *thd, uint *nextp); 01236 01238 // sp_lex_instr implementation. 01240 01241 virtual bool exec_core(THD *thd, uint *nextp); 01242 01243 virtual bool is_invalid() const 01244 { return !m_valid; } 01245 01246 virtual void invalidate() 01247 { m_valid= false; } 01248 01249 virtual void get_query(String *sql_query) const 01250 { sql_query->append(m_cursor_query.str, m_cursor_query.length); } 01251 01252 virtual bool on_after_expr_parsing(THD *thd) 01253 { 01254 m_valid= true; 01255 return false; 01256 } 01257 01258 private: 01260 LEX_STRING m_cursor_query; 01261 01264 bool m_valid; 01265 01267 int m_cursor_idx; 01268 }; 01269 01271 01276 class sp_instr_cpop : public sp_instr 01277 { 01278 public: 01279 sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count) 01280 :sp_instr(ip, ctx), 01281 m_count(count) 01282 { } 01283 01285 // sp_printable implementation. 01287 01288 virtual void print(String *str); 01289 01291 // sp_instr implementation. 01293 01294 virtual bool execute(THD *thd, uint *nextp); 01295 01296 private: 01297 uint m_count; 01298 }; 01299 01301 01306 class sp_instr_copen : public sp_instr 01307 { 01308 public: 01309 sp_instr_copen(uint ip, sp_pcontext *ctx, int cursor_idx) 01310 :sp_instr(ip, ctx), 01311 m_cursor_idx(cursor_idx) 01312 { } 01313 01315 // sp_printable implementation. 01317 01318 virtual void print(String *str); 01319 01321 // sp_instr implementation. 01323 01324 virtual bool execute(THD *thd, uint *nextp); 01325 01326 private: 01328 int m_cursor_idx; 01329 }; 01330 01332 01338 class sp_instr_cclose : public sp_instr 01339 { 01340 public: 01341 sp_instr_cclose(uint ip, sp_pcontext *ctx, int cursor_idx) 01342 :sp_instr(ip, ctx), 01343 m_cursor_idx(cursor_idx) 01344 { } 01345 01347 // sp_printable implementation. 01349 01350 virtual void print(String *str); 01351 01353 // sp_instr implementation. 01355 01356 virtual bool execute(THD *thd, uint *nextp); 01357 01358 private: 01360 int m_cursor_idx; 01361 }; 01362 01364 01370 class sp_instr_cfetch : public sp_instr 01371 { 01372 public: 01373 sp_instr_cfetch(uint ip, sp_pcontext *ctx, int cursor_idx) 01374 :sp_instr(ip, ctx), 01375 m_cursor_idx(cursor_idx) 01376 { } 01377 01379 // sp_printable implementation. 01381 01382 virtual void print(String *str); 01383 01385 // sp_instr implementation. 01387 01388 virtual bool execute(THD *thd, uint *nextp); 01389 01390 void add_to_varlist(sp_variable *var) 01391 { m_varlist.push_back(var); } 01392 01393 private: 01395 List<sp_variable> m_varlist; 01396 01398 int m_cursor_idx; 01399 }; 01400 01403 01409 class sp_instr_error : public sp_instr 01410 { 01411 public: 01412 sp_instr_error(uint ip, sp_pcontext *ctx, int errcode) 01413 :sp_instr(ip, ctx), 01414 m_errcode(errcode) 01415 { } 01416 01418 // sp_printable implementation. 01420 01421 virtual void print(String *str); 01422 01424 // sp_instr implementation. 01426 01427 virtual bool execute(THD *thd, uint *nextp) 01428 { 01429 my_message(m_errcode, ER(m_errcode), MYF(0)); 01430 *nextp= get_ip() + 1; 01431 return true; 01432 } 01433 01434 virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads) 01435 { 01436 m_marked= true; 01437 return UINT_MAX; 01438 } 01439 01440 private: 01442 int m_errcode; 01443 }; 01444 01446 01447 #endif // _SP_INSTR_H_