MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sp_rcontext.h
1 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 #ifndef _SP_RCONTEXT_H_
17 #define _SP_RCONTEXT_H_
18 
19 #include "sql_class.h" // select_result_interceptor
20 #include "sp_pcontext.h" // sp_condition_value
21 
23 // sp_rcontext declaration.
25 
26 class sp_cursor;
27 class sp_instr_cpush;
28 class Query_arena;
29 class sp_head;
30 class Item_cache;
31 
32 /*
33  This class is a runtime context of a Stored Routine. It is used in an
34  execution and is intended to contain all dynamic objects (i.e. objects, which
35  can be changed during execution), such as:
36  - stored routine variables;
37  - cursors;
38  - handlers;
39 
40  Runtime context is used with sp_head class. sp_head class is intended to
41  contain all static things, related to the stored routines (code, for example).
42  sp_head instance creates runtime context for the execution of a stored
43  routine.
44 
45  There is a parsing context (an instance of sp_pcontext class), which is used
46  on parsing stage. However, now it contains some necessary for an execution
47  things, such as definition of used stored routine variables. That's why
48  runtime context needs a reference to the parsing context.
49 */
50 
51 class sp_rcontext : public Sql_alloc
52 {
53 public:
64  static sp_rcontext *create(THD *thd,
65  const sp_pcontext *root_parsing_ctx,
66  Field *return_value_fld);
67 
68  ~sp_rcontext();
69 
70 private:
71  sp_rcontext(const sp_pcontext *root_parsing_ctx,
72  Field *return_value_fld,
73  bool in_sub_stmt);
74 
75  // Prevent use of copying constructor and operator.
76  sp_rcontext(const sp_rcontext &);
77  void operator=(sp_rcontext &);
78 
79 private:
82  class sp_handler_entry
83  {
84  public:
86  const sp_handler *handler;
87 
89  uint first_ip;
90 
95  sp_handler_entry(const sp_handler *_handler, uint _first_ip)
96  :handler(_handler), first_ip(_first_ip)
97  { }
98  };
99 
100 public:
117  {
118  public:
120  uint sql_errno;
121 
123  Sql_condition::enum_warning_level level;
124 
126  char sql_state[SQLSTATE_LENGTH + 1];
127 
129  char message[MYSQL_ERRMSG_SIZE];
130 
137  Sql_condition_info(uint _sql_errno,
138  const char *_sql_state,
139  Sql_condition::enum_warning_level _level,
140  const char *_message)
141  :sql_errno(_sql_errno),
142  level(_level)
143  {
144  memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
145  sql_state[SQLSTATE_LENGTH]= '\0';
146 
147  strncpy(message, _message, MYSQL_ERRMSG_SIZE);
148  }
149  };
150 
151 private:
155  class Handler_call_frame
156  {
157  public:
159  const sp_handler *handler;
160 
162  Sql_condition_info sql_condition_info;
163 
166  uint continue_ip;
167 
176  Handler_call_frame(const sp_handler *_handler,
177  uint _sql_errno,
178  const char *_sql_state,
179  Sql_condition::enum_warning_level _level,
180  const char *_message,
181  uint _continue_ip)
182  :handler(_handler),
183  sql_condition_info(_sql_errno, _sql_state, _level, _message),
184  continue_ip(_continue_ip)
185  { }
186  };
187 
188 public:
192  Query_arena *callers_arena;
193 
198 
201 
203  // SP-variables.
205 
206  bool set_variable(THD *thd, uint var_idx, Item **value)
207  { return set_variable(thd, m_var_table->field[var_idx], value); }
208 
209  Item *get_item(uint var_idx) const
210  { return m_var_items[var_idx]; }
211 
212  Item **get_item_addr(uint var_idx) const
213  { return m_var_items.array() + var_idx; }
214 
215  bool set_return_value(THD *thd, Item **return_value_item);
216 
217  bool is_return_value_set() const
218  { return m_return_value_set; }
219 
221  // SQL-handlers.
223 
233  bool push_handler(sp_handler *handler, uint first_ip);
234 
239  void pop_handlers(sp_pcontext *current_scope);
240 
241  const Sql_condition_info *raised_condition() const
242  {
243  return m_activated_handlers.elements() ?
244  &(*m_activated_handlers.back())->sql_condition_info : NULL;
245  }
246 
267  bool handle_sql_condition(THD *thd,
268  uint *ip,
269  const sp_instr *cur_spi);
270 
275  void exit_handler(sp_pcontext *target_scope);
276 
280  {
281  uint ip= (*m_activated_handlers.back())->continue_ip;
282  DBUG_ASSERT(ip != 0);
283 
284  return ip;
285  }
286 
288  // Cursors.
290 
299 
303  void pop_cursors(uint count);
304 
305  void pop_all_cursors()
306  { pop_cursors(m_ccount); }
307 
308  sp_cursor *get_cursor(uint i) const
309  { return m_cstack[i]; }
310 
312  // CASE expressions.
314 
340  bool set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
341 
342  Item *get_case_expr(int case_expr_id) const
343  { return m_case_expr_holders[case_expr_id]; }
344 
345  Item ** get_case_expr_addr(int case_expr_id) const
346  { return (Item**) m_case_expr_holders.array() + case_expr_id; }
347 
348 private:
354  bool alloc_arrays(THD *thd);
355 
363  bool init_var_table(THD *thd);
364 
372  bool init_var_items(THD *thd);
373 
384  Item_cache *create_case_expr_holder(THD *thd, const Item *item) const;
385 
386  bool set_variable(THD *thd, Field *field, Item **value);
387 
388 private:
390  const sp_pcontext *m_root_parsing_ctx;
391 
393  TABLE *m_var_table;
394 
397  Bounds_checked_array<Item *> m_var_items;
398 
401  Field *m_return_value_fld;
402 
405  bool m_return_value_set;
406 
408  bool m_in_sub_stmt;
409 
411  Dynamic_array<sp_handler_entry *> m_visible_handlers;
412 
414  Dynamic_array<Handler_call_frame *> m_activated_handlers;
415 
418 
420  uint m_ccount;
421 
423  Bounds_checked_array<Item_cache *> m_case_expr_holders;
424 }; // class sp_rcontext : public Sql_alloc
425 
427 // sp_cursor declaration.
429 
430 class Server_side_cursor;
431 typedef class st_select_lex_unit SELECT_LEX_UNIT;
432 
433 /* A mediator between stored procedures and server side cursors */
434 
436 {
437 private:
440  class Select_fetch_into_spvars: public select_result_interceptor
441  {
442  List<sp_variable> *spvar_list;
443  uint field_count;
444  public:
445  Select_fetch_into_spvars() {} /* Remove gcc warning */
446  uint get_field_count() { return field_count; }
447  void set_spvar_list(List<sp_variable> *vars) { spvar_list= vars; }
448 
449  virtual bool send_eof() { return FALSE; }
450  virtual bool send_data(List<Item> &items);
451  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
452 };
453 
454 public:
456  :m_server_side_cursor(NULL),
457  m_push_instr(i)
458  { }
459 
460  virtual ~sp_cursor()
461  { destroy(); }
462 
463  bool open(THD *thd);
464 
465  bool close(THD *thd);
466 
467  bool is_open() const
468  { return test(m_server_side_cursor); }
469 
470  bool fetch(THD *thd, List<sp_variable> *vars);
471 
472  sp_instr_cpush *get_push_instr()
473  { return m_push_instr; }
474 
475 private:
476  Select_fetch_into_spvars m_result;
477 
478  Server_side_cursor *m_server_side_cursor;
479  sp_instr_cpush *m_push_instr;
480 
481 private:
482  void destroy();
483 }; // class sp_cursor
484 
485 #endif /* _SP_RCONTEXT_H_ */