My Project
sp_rcontext.h
00001 /* Copyright (c) 2002, 2013, 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 #ifndef _SP_RCONTEXT_H_
00017 #define _SP_RCONTEXT_H_
00018 
00019 #include "sql_class.h"                    // select_result_interceptor
00020 #include "sp_pcontext.h"                  // sp_condition_value
00021 
00023 // sp_rcontext declaration.
00025 
00026 class sp_cursor;
00027 class sp_instr_cpush;
00028 class Query_arena;
00029 class sp_head;
00030 class Item_cache;
00031 
00032 /*
00033   This class is a runtime context of a Stored Routine. It is used in an
00034   execution and is intended to contain all dynamic objects (i.e.  objects, which
00035   can be changed during execution), such as:
00036     - stored routine variables;
00037     - cursors;
00038     - handlers;
00039 
00040   Runtime context is used with sp_head class. sp_head class is intended to
00041   contain all static things, related to the stored routines (code, for example).
00042   sp_head instance creates runtime context for the execution of a stored
00043   routine.
00044 
00045   There is a parsing context (an instance of sp_pcontext class), which is used
00046   on parsing stage. However, now it contains some necessary for an execution
00047   things, such as definition of used stored routine variables. That's why
00048   runtime context needs a reference to the parsing context.
00049 */
00050 
00051 class sp_rcontext : public Sql_alloc
00052 {
00053 public:
00064   static sp_rcontext *create(THD *thd,
00065                              const sp_pcontext *root_parsing_ctx,
00066                              Field *return_value_fld);
00067 
00068   ~sp_rcontext();
00069 
00070 private:
00071   sp_rcontext(const sp_pcontext *root_parsing_ctx,
00072               Field *return_value_fld,
00073               bool in_sub_stmt);
00074 
00075   // Prevent use of copying constructor and operator.
00076   sp_rcontext(const sp_rcontext &);
00077   void operator=(sp_rcontext &);
00078 
00079 private:
00082   class sp_handler_entry
00083   {
00084   public:
00086     const sp_handler *handler;
00087 
00089     uint first_ip;
00090 
00095     sp_handler_entry(const sp_handler *_handler, uint _first_ip)
00096      :handler(_handler), first_ip(_first_ip)
00097     { }
00098   };
00099 
00100 public:
00116   class Sql_condition_info
00117   {
00118   public:
00120     uint sql_errno;
00121 
00123     Sql_condition::enum_warning_level level;
00124 
00126     char sql_state[SQLSTATE_LENGTH + 1];
00127 
00129     char message[MYSQL_ERRMSG_SIZE];
00130 
00137     Sql_condition_info(uint _sql_errno,
00138                        const char *_sql_state,
00139                        Sql_condition::enum_warning_level _level,
00140                        const char *_message)
00141      :sql_errno(_sql_errno),
00142       level(_level)
00143     {
00144       memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
00145       sql_state[SQLSTATE_LENGTH]= '\0';
00146 
00147       strncpy(message, _message, MYSQL_ERRMSG_SIZE - 1);
00148       message[MYSQL_ERRMSG_SIZE - 1]= '\0';
00149     }
00150   };
00151 
00152 private:
00156   class Handler_call_frame
00157   {
00158   public:
00160     const sp_handler *handler;
00161 
00163     Sql_condition_info sql_condition_info;
00164 
00167     uint continue_ip;
00168 
00177     Handler_call_frame(const sp_handler *_handler,
00178                        uint _sql_errno,
00179                        const char *_sql_state,
00180                        Sql_condition::enum_warning_level _level,
00181                        const char *_message,
00182                        uint _continue_ip)
00183      :handler(_handler),
00184       sql_condition_info(_sql_errno, _sql_state, _level, _message),
00185       continue_ip(_continue_ip)
00186     { }
00187  };
00188 
00189 public:
00193   Query_arena *callers_arena;
00194 
00198   bool end_partial_result_set;
00199 
00201   sp_head *sp;
00202 
00204   // SP-variables.
00206 
00207   bool set_variable(THD *thd, uint var_idx, Item **value)
00208   { return set_variable(thd, m_var_table->field[var_idx], value); }
00209 
00210   Item *get_item(uint var_idx) const
00211   { return m_var_items[var_idx]; }
00212 
00213   Item **get_item_addr(uint var_idx) const
00214   { return m_var_items.array() + var_idx; }
00215 
00216   bool set_return_value(THD *thd, Item **return_value_item);
00217 
00218   bool is_return_value_set() const
00219   { return m_return_value_set; }
00220 
00222   // SQL-handlers.
00224 
00234   bool push_handler(sp_handler *handler, uint first_ip);
00235 
00240   void pop_handlers(sp_pcontext *current_scope);
00241 
00242   const Sql_condition_info *raised_condition() const
00243   {
00244     return m_activated_handlers.elements() ?
00245       &(*m_activated_handlers.back())->sql_condition_info : NULL;
00246   }
00247 
00268   bool handle_sql_condition(THD *thd,
00269                             uint *ip,
00270                             const sp_instr *cur_spi);
00271 
00276   void exit_handler(sp_pcontext *target_scope);
00277 
00280   uint get_last_handler_continue_ip() const
00281   {
00282     uint ip= (*m_activated_handlers.back())->continue_ip;
00283     DBUG_ASSERT(ip != 0);
00284 
00285     return ip;
00286   }
00287 
00289   // Cursors.
00291 
00299   bool push_cursor(sp_instr_cpush *i);
00300 
00304   void pop_cursors(uint count);
00305 
00306   void pop_all_cursors()
00307   { pop_cursors(m_ccount); }
00308 
00309   sp_cursor *get_cursor(uint i) const
00310   { return m_cstack[i]; }
00311 
00313   // CASE expressions.
00315 
00341   bool set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
00342 
00343   Item *get_case_expr(int case_expr_id) const
00344   { return m_case_expr_holders[case_expr_id]; }
00345 
00346   Item ** get_case_expr_addr(int case_expr_id) const
00347   { return (Item**) m_case_expr_holders.array() + case_expr_id; }
00348 
00349 private:
00355   bool alloc_arrays(THD *thd);
00356 
00364   bool init_var_table(THD *thd);
00365 
00373   bool init_var_items(THD *thd);
00374 
00385   Item_cache *create_case_expr_holder(THD *thd, const Item *item) const;
00386 
00387   bool set_variable(THD *thd, Field *field, Item **value);
00388 
00389 private:
00391   const sp_pcontext *m_root_parsing_ctx;
00392 
00394   TABLE *m_var_table;
00395 
00398   Bounds_checked_array<Item *> m_var_items;
00399 
00402   Field *m_return_value_fld;
00403 
00406   bool m_return_value_set;
00407 
00409   bool m_in_sub_stmt;
00410 
00412   Dynamic_array<sp_handler_entry *> m_visible_handlers;
00413 
00415   Dynamic_array<Handler_call_frame *> m_activated_handlers;
00416 
00418   Bounds_checked_array<sp_cursor *> m_cstack;
00419 
00421   uint m_ccount;
00422 
00424   Bounds_checked_array<Item_cache *> m_case_expr_holders;
00425 }; // class sp_rcontext : public Sql_alloc
00426 
00428 // sp_cursor declaration.
00430 
00431 class Server_side_cursor;
00432 typedef class st_select_lex_unit SELECT_LEX_UNIT;
00433 
00434 /* A mediator between stored procedures and server side cursors */
00435 
00436 class sp_cursor
00437 {
00438 private:
00441   class Select_fetch_into_spvars: public select_result_interceptor
00442   {
00443     List<sp_variable> *spvar_list;
00444     uint field_count;
00445   public:
00446     Select_fetch_into_spvars() {}               /* Remove gcc warning */
00447     uint get_field_count() { return field_count; }
00448     void set_spvar_list(List<sp_variable> *vars) { spvar_list= vars; }
00449 
00450     virtual bool send_eof() { return FALSE; }
00451     virtual bool send_data(List<Item> &items);
00452     virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
00453 };
00454 
00455 public:
00456   sp_cursor(sp_instr_cpush *i)
00457    :m_server_side_cursor(NULL),
00458     m_push_instr(i)
00459   { }
00460 
00461   virtual ~sp_cursor()
00462   { destroy(); }
00463 
00464   bool open(THD *thd);
00465 
00466   bool close(THD *thd);
00467 
00468   bool is_open() const
00469   { return MY_TEST(m_server_side_cursor); }
00470 
00471   bool fetch(THD *thd, List<sp_variable> *vars);
00472 
00473   sp_instr_cpush *get_push_instr()
00474   { return m_push_instr; }
00475 
00476 private:
00477   Select_fetch_into_spvars m_result;
00478 
00479   Server_side_cursor *m_server_side_cursor;
00480   sp_instr_cpush *m_push_instr;
00481 
00482 private:
00483   void destroy();
00484 }; // class sp_cursor
00485 
00486 #endif /* _SP_RCONTEXT_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines