00001 /* -*- C++ -*- */ 00002 /* Copyright (C) 2002 MySQL AB 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00017 00018 #ifndef _SP_RCONTEXT_H_ 00019 #define _SP_RCONTEXT_H_ 00020 00021 #ifdef USE_PRAGMA_INTERFACE 00022 #pragma interface /* gcc class implementation */ 00023 #endif 00024 00025 struct sp_cond_type; 00026 class sp_cursor; 00027 struct sp_variable; 00028 class sp_lex_keeper; 00029 class sp_instr_cpush; 00030 00031 #define SP_HANDLER_NONE 0 00032 #define SP_HANDLER_EXIT 1 00033 #define SP_HANDLER_CONTINUE 2 00034 #define SP_HANDLER_UNDO 3 00035 00036 typedef struct 00037 { 00038 struct sp_cond_type *cond; 00039 uint handler; // Location of handler 00040 int type; 00041 uint foffset; // Frame offset for the handlers declare level 00042 } sp_handler_t; 00043 00044 00045 /* 00046 This class is a runtime context of a Stored Routine. It is used in an 00047 execution and is intended to contain all dynamic objects (i.e. objects, which 00048 can be changed during execution), such as: 00049 - stored routine variables; 00050 - cursors; 00051 - handlers; 00052 00053 Runtime context is used with sp_head class. sp_head class is intended to 00054 contain all static things, related to the stored routines (code, for example). 00055 sp_head instance creates runtime context for the execution of a stored 00056 routine. 00057 00058 There is a parsing context (an instance of sp_pcontext class), which is used 00059 on parsing stage. However, now it contains some necessary for an execution 00060 things, such as definition of used stored routine variables. That's why 00061 runtime context needs a reference to the parsing context. 00062 */ 00063 00064 class sp_rcontext : public Sql_alloc 00065 { 00066 sp_rcontext(const sp_rcontext &); /* Prevent use of these */ 00067 void operator=(sp_rcontext &); 00068 00069 public: 00070 00071 /* 00072 Arena used to (re) allocate items on . E.g. reallocate INOUT/OUT 00073 SP parameters when they don't fit into prealloced items. This 00074 is common situation with String items. It is used mainly in 00075 sp_eval_func_item(). 00076 */ 00077 Query_arena *callers_arena; 00078 00079 #ifndef DBUG_OFF 00080 /* 00081 The routine for which this runtime context is created. Used for checking 00082 if correct runtime context is used for variable handling. 00083 */ 00084 sp_head *sp; 00085 #endif 00086 00087 sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld, 00088 sp_rcontext *prev_runtime_ctx); 00089 bool init(THD *thd); 00090 00091 ~sp_rcontext(); 00092 00093 int 00094 set_variable(THD *thd, uint var_idx, Item **value); 00095 00096 Item * 00097 get_item(uint var_idx); 00098 00099 Item ** 00100 get_item_addr(uint var_idx); 00101 00102 bool 00103 set_return_value(THD *thd, Item **return_value_item); 00104 00105 inline bool 00106 is_return_value_set() const 00107 { 00108 return m_return_value_set; 00109 } 00110 00111 inline void 00112 push_handler(struct sp_cond_type *cond, uint h, int type, uint f) 00113 { 00114 m_handler[m_hcount].cond= cond; 00115 m_handler[m_hcount].handler= h; 00116 m_handler[m_hcount].type= type; 00117 m_handler[m_hcount].foffset= f; 00118 m_hcount+= 1; 00119 } 00120 00121 inline void 00122 pop_handlers(uint count) 00123 { 00124 m_hcount-= count; 00125 } 00126 00127 // Returns 1 if a handler was found, 0 otherwise. 00128 bool 00129 find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level); 00130 00131 // Returns handler type and sets *ip to location if one was found 00132 inline int 00133 found_handler(uint *ip, uint *fp) 00134 { 00135 if (m_hfound < 0) 00136 return SP_HANDLER_NONE; 00137 *ip= m_handler[m_hfound].handler; 00138 *fp= m_handler[m_hfound].foffset; 00139 return m_handler[m_hfound].type; 00140 } 00141 00142 // Returns true if we found a handler in this context 00143 inline bool 00144 found_handler_here() 00145 { 00146 return (m_hfound >= 0); 00147 } 00148 00149 // Clears the handler find state 00150 inline void 00151 clear_handler() 00152 { 00153 m_hfound= -1; 00154 } 00155 00156 inline void 00157 push_hstack(uint h) 00158 { 00159 m_hstack[m_hsp++]= h; 00160 } 00161 00162 inline uint 00163 pop_hstack() 00164 { 00165 return m_hstack[--m_hsp]; 00166 } 00167 00168 inline void 00169 enter_handler(int hid) 00170 { 00171 m_in_handler[m_ihsp++]= hid; 00172 } 00173 00174 inline void 00175 exit_handler() 00176 { 00177 m_ihsp-= 1; 00178 } 00179 00180 void 00181 push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); 00182 00183 void 00184 pop_cursors(uint count); 00185 00186 void 00187 pop_all_cursors() 00188 { 00189 pop_cursors(m_ccount); 00190 } 00191 00192 inline sp_cursor * 00193 get_cursor(uint i) 00194 { 00195 return m_cstack[i]; 00196 } 00197 00198 /* 00199 CASE expressions support. 00200 */ 00201 00202 int 00203 set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr); 00204 00205 Item * 00206 get_case_expr(int case_expr_id); 00207 00208 Item ** 00209 get_case_expr_addr(int case_expr_id); 00210 00211 private: 00212 sp_pcontext *m_root_parsing_ctx; 00213 00214 /* Virtual table for storing variables. */ 00215 TABLE *m_var_table; 00216 00217 /* 00218 Collection of Item_field proxies, each of them points to the corresponding 00219 field in m_var_table. 00220 */ 00221 Item **m_var_items; 00222 00223 /* 00224 This is a pointer to a field, which should contain return value for stored 00225 functions (only). For stored procedures, this pointer is NULL. 00226 */ 00227 Field *m_return_value_fld; 00228 00229 /* 00230 Indicates whether the return value (in m_return_value_fld) has been set 00231 during execution. 00232 */ 00233 bool m_return_value_set; 00234 00235 sp_handler_t *m_handler; // Visible handlers 00236 uint m_hcount; // Stack pointer for m_handler 00237 uint *m_hstack; // Return stack for continue handlers 00238 uint m_hsp; // Stack pointer for m_hstack 00239 uint *m_in_handler; // Active handler, for recursion check 00240 uint m_ihsp; // Stack pointer for m_in_handler 00241 int m_hfound; // Set by find_handler; -1 if not found 00242 00243 sp_cursor **m_cstack; 00244 uint m_ccount; 00245 00246 Item_cache **m_case_expr_holders; 00247 00248 /* Previous runtime context (NULL if none) */ 00249 sp_rcontext *m_prev_runtime_ctx; 00250 00251 private: 00252 bool init_var_table(THD *thd); 00253 bool init_var_items(); 00254 00255 Item_cache *create_case_expr_holder(THD *thd, Item_result result_type); 00256 00257 int set_variable(THD *thd, Field *field, Item **value); 00258 }; // class sp_rcontext : public Sql_alloc 00259 00260 00261 /* 00262 An interceptor of cursor result set used to implement 00263 FETCH <cname> INTO <varlist>. 00264 */ 00265 00266 class Select_fetch_into_spvars: public select_result_interceptor 00267 { 00268 List<struct sp_variable> *spvar_list; 00269 uint field_count; 00270 public: 00271 Select_fetch_into_spvars() {} /* Remove gcc warning */ 00272 uint get_field_count() { return field_count; } 00273 void set_spvar_list(List<struct sp_variable> *vars) { spvar_list= vars; } 00274 00275 virtual bool send_eof() { return FALSE; } 00276 virtual bool send_data(List<Item> &items); 00277 virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u); 00278 }; 00279 00280 00281 /* A mediator between stored procedures and server side cursors */ 00282 00283 class sp_cursor : public Sql_alloc 00284 { 00285 public: 00286 00287 sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); 00288 00289 virtual ~sp_cursor() 00290 { 00291 destroy(); 00292 } 00293 00294 sp_lex_keeper * 00295 get_lex_keeper() { return m_lex_keeper; } 00296 00297 int 00298 open(THD *thd); 00299 00300 int 00301 close(THD *thd); 00302 00303 inline my_bool 00304 is_open() 00305 { 00306 return test(server_side_cursor); 00307 } 00308 00309 int 00310 fetch(THD *, List<struct sp_variable> *vars); 00311 00312 inline sp_instr_cpush * 00313 get_instr() 00314 { 00315 return m_i; 00316 } 00317 00318 private: 00319 00320 Select_fetch_into_spvars result; 00321 sp_lex_keeper *m_lex_keeper; 00322 Server_side_cursor *server_side_cursor; 00323 sp_instr_cpush *m_i; // My push instruction 00324 void 00325 destroy(); 00326 00327 }; // class sp_cursor : public Sql_alloc 00328 00329 #endif /* _SP_RCONTEXT_H_ */
1.4.7

