My Project
|
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_ */