My Project
sp_instr.h
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines