MySQL  8.0.21
Source Code Documentation
sp_rcontext.h
Go to the documentation of this file.
1 /* Copyright (c) 2002, 2019, 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, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation. The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef _SP_RCONTEXT_H_
24 #define _SP_RCONTEXT_H_
25 
26 #include <stddef.h>
27 #include <sys/types.h>
28 
29 #include "my_dbug.h"
30 #include "my_inttypes.h"
31 #include "prealloced_array.h" // Prealloced_array
32 #include "sql/item.h"
33 #include "sql/query_result.h" // Query_result_interceptor
34 #include "sql/sql_array.h"
35 #include "sql/sql_error.h"
36 #include "sql/table.h"
37 
38 class Field;
39 class Query_arena;
40 class SELECT_LEX_UNIT;
41 class Server_side_cursor;
42 class THD;
43 class sp_cursor;
44 class sp_handler;
45 class sp_head;
46 class sp_instr;
47 class sp_instr_cpush;
48 class sp_pcontext;
49 class sp_variable;
50 template <class T>
51 class List;
52 
53 ///////////////////////////////////////////////////////////////////////////
54 // sp_rcontext declaration.
55 ///////////////////////////////////////////////////////////////////////////
56 
57 /*
58  This class is a runtime context of a Stored Routine. It is used in an
59  execution and is intended to contain all dynamic objects (i.e. objects, which
60  can be changed during execution), such as:
61  - stored routine variables;
62  - cursors;
63  - handlers;
64 
65  Runtime context is used with sp_head class. sp_head class is intended to
66  contain all static things, related to the stored routines (code, for example).
67  sp_head instance creates runtime context for the execution of a stored
68  routine.
69 
70  There is a parsing context (an instance of sp_pcontext class), which is used
71  on parsing stage. However, now it contains some necessary for an execution
72  things, such as definition of used stored routine variables. That's why
73  runtime context needs a reference to the parsing context.
74 */
75 
76 class sp_rcontext {
77  public:
78  /// Construct and properly initialize a new sp_rcontext instance. The static
79  /// create-function is needed because we need a way to return an error from
80  /// the constructor.
81  ///
82  /// @param thd Thread handle.
83  /// @param root_parsing_ctx Top-level parsing context for this stored program.
84  /// @param return_value_fld Field object to store the return value
85  /// (for stored functions only).
86  ///
87  /// @return valid sp_rcontext object or NULL in case of OOM-error.
88  static sp_rcontext *create(THD *thd, const sp_pcontext *root_parsing_ctx,
89  Field *return_value_fld);
90 
91  ~sp_rcontext();
92 
93  private:
94  sp_rcontext(const sp_pcontext *root_parsing_ctx, Field *return_value_fld,
95  bool in_sub_stmt);
96 
97  // Prevent use of copying constructor and operator.
98  sp_rcontext(const sp_rcontext &);
99  void operator=(sp_rcontext &);
100 
101  private:
102  /// This is an auxillary class to store entering instruction pointer for an
103  /// SQL-handler.
105  public:
106  /// Handler definition (from parsing context).
108 
109  /// Instruction pointer to the first instruction.
111 
112  /// The constructor.
113  ///
114  /// @param _handler sp_handler object.
115  /// @param _first_ip first instruction pointer.
116  sp_handler_entry(const sp_handler *_handler, uint _first_ip)
117  : handler(_handler), first_ip(_first_ip) {}
118  };
119 
120  public:
121  /// This class represents a call frame of SQL-handler (one invocation of a
122  /// handler). Basically, it's needed to store continue instruction pointer for
123  /// CONTINUE SQL-handlers.
125  public:
126  /// Handler definition (from parsing context).
128 
129  /// SQL-condition, triggered handler activation.
131 
132  /// Continue-instruction-pointer for CONTINUE-handlers.
133  /// The attribute contains 0 for EXIT-handlers.
135 
136  /// The Diagnostics Area which will be pushed when the handler activates
137  /// and popped when the handler completes.
139 
140  /// The constructor.
141  ///
142  /// @param _handler SQL-handler
143  /// @param _sql_condition SQL-condition, triggered handler activation.
144  /// @param _continue_ip Continue instruction pointer.
146  Sql_condition *_sql_condition, uint _continue_ip)
147  : handler(_handler),
148  sql_condition(_sql_condition),
149  continue_ip(_continue_ip),
150  handler_da(false) {}
151  };
152 
153  public:
154  /// Arena used to (re) allocate items on. E.g. reallocate INOUT/OUT
155  /// SP-variables when they don't fit into prealloced items. This is common
156  /// situation with String items. It is used mainly in sp_eval_func_item().
158 
159  /// Flag to end an open result set before start executing an SQL-handler
160  /// (if one is found). Otherwise the client will hang due to a violation
161  /// of the client/server protocol.
163 
164  /// The stored program for which this runtime context is created.
166 
167  /////////////////////////////////////////////////////////////////////////
168  // SP-variables.
169  /////////////////////////////////////////////////////////////////////////
170 
171  bool set_variable(THD *thd, uint var_idx, Item **value) {
172  return set_variable(thd, m_var_table->field[var_idx], value);
173  }
174 
175  Item *get_item(uint var_idx) const { return m_var_items[var_idx]; }
176 
177  Item **get_item_addr(uint var_idx) const {
178  return m_var_items.array() + var_idx;
179  }
180 
181  bool set_return_value(THD *thd, Item **return_value_item);
182 
183  bool is_return_value_set() const { return m_return_value_set; }
184 
185  /////////////////////////////////////////////////////////////////////////
186  // SQL-handlers.
187  /////////////////////////////////////////////////////////////////////////
188 
189  /// Create a new sp_handler_entry instance and push it to the handler call
190  /// stack.
191  ///
192  /// @param handler SQL-handler object.
193  /// @param first_ip First instruction pointer of the handler.
194  ///
195  /// @return error flag.
196  /// @retval false on success.
197  /// @retval true on error.
199 
200  /// Pop and delete given number of sp_handler_entry instances from the handler
201  /// call stack.
202  ///
203  /// @param current_scope The current BEGIN..END block.
204  void pop_handlers(sp_pcontext *current_scope);
205 
206  /// Get the Handler_call_frame representing the currently active handler.
208  return m_activated_handlers.size() ? m_activated_handlers.back() : NULL;
209  }
210 
211  /// Handle current SQL condition (if any).
212  ///
213  /// This is the public-interface function to handle SQL conditions in
214  /// stored routines.
215  ///
216  /// @param thd Thread handle.
217  /// @param [out] ip Instruction pointer to the first handler
218  /// instruction.
219  /// @param cur_spi Current SP instruction.
220  ///
221  /// @retval true if an SQL-handler has been activated. That means, all of
222  /// the following conditions are satisfied:
223  /// - the SP-instruction raised SQL-condition(s),
224  /// - and there is an SQL-handler to process at least one of those
225  /// SQL-conditions,
226  /// - and that SQL-handler has been activated.
227  /// Note, that the return value has nothing to do with "error flag"
228  /// semantics.
229  ///
230  /// @retval false otherwise.
231  bool handle_sql_condition(THD *thd, uint *ip, const sp_instr *cur_spi);
232 
233  /// Handle return from SQL-handler.
234  ///
235  /// @param thd Thread handle.
236  /// @param target_scope The BEGIN..END block, containing
237  /// the target (next) instruction.
238  void exit_handler(THD *thd, sp_pcontext *target_scope);
239 
240  /// @return the continue instruction pointer of the last activated CONTINUE
241  /// handler. This function must not be called for the EXIT handlers.
243  uint ip = m_activated_handlers.back()->continue_ip;
244  DBUG_ASSERT(ip != 0);
245 
246  return ip;
247  }
248 
249  /////////////////////////////////////////////////////////////////////////
250  // Cursors.
251  /////////////////////////////////////////////////////////////////////////
252 
253  /// Create a new sp_cursor instance and push it to the cursor stack.
254  ///
255  /// @param i Cursor-push instruction.
256  ///
257  /// @return error flag.
258  /// @retval false on success.
259  /// @retval true on error.
260  bool push_cursor(sp_instr_cpush *i);
261 
262  /// Pop and delete given number of sp_cursor instance from the cursor stack.
263  ///
264  /// @param count Number of cursors to pop & delete.
265  void pop_cursors(uint count);
266 
268 
269  sp_cursor *get_cursor(uint i) const { return m_cstack[i]; }
270 
271  /////////////////////////////////////////////////////////////////////////
272  // CASE expressions.
273  /////////////////////////////////////////////////////////////////////////
274 
275  /// Set CASE expression to the specified value.
276  ///
277  /// @param thd Thread handler.
278  /// @param case_expr_id The CASE expression identifier.
279  /// @param case_expr_item_ptr The CASE expression value
280  ///
281  /// @return error flag.
282  /// @retval false on success.
283  /// @retval true on error.
284  ///
285  /// @note The idea is to reuse Item_cache for the expression of the one
286  /// CASE statement. This optimization takes place when there is CASE
287  /// statement inside of a loop. So, in other words, we will use the same
288  /// object on each iteration instead of creating a new one for each
289  /// iteration.
290  ///
291  /// TODO
292  /// Hypothetically, a type of CASE expression can be different for each
293  /// iteration. For instance, this can happen if the expression contains
294  /// a session variable (something like @@VAR) and its type is changed
295  /// from one iteration to another.
296  ///
297  /// In order to cope with this problem, we check type each time, when we
298  /// use already created object. If the type does not match, we re-create
299  /// Item. This also can (should?) be optimized.
300  bool set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
301 
302  Item *get_case_expr(int case_expr_id) const {
303  return m_case_expr_holders[case_expr_id];
304  }
305 
306  Item **get_case_expr_addr(int case_expr_id) const {
307  return (Item **)m_case_expr_holders.array() + case_expr_id;
308  }
309 
310  private:
311  /// Internal function to allocate memory for arrays.
312  ///
313  /// @param thd Thread handle.
314  ///
315  /// @return error flag: false on success, true in case of failure.
316  bool alloc_arrays(THD *thd);
317 
318  /// Create and initialize a table to store SP-variables.
319  ///
320  /// param thd Thread handle.
321  ///
322  /// @return error flag.
323  /// @retval false on success.
324  /// @retval true on error.
325  bool init_var_table(THD *thd);
326 
327  /// Create and initialize an Item-adapter (Item_field) for each SP-var field.
328  ///
329  /// param thd Thread handle.
330  ///
331  /// @return error flag.
332  /// @retval false on success.
333  /// @retval true on error.
334  bool init_var_items(THD *thd);
335 
336  /// Create an instance of appropriate Item_cache class depending on the
337  /// specified type in the callers arena.
338  ///
339  /// @note We should create cache items in the callers arena, as they are
340  /// used between in several instructions.
341  ///
342  /// @param thd Thread handler.
343  /// @param item Item to get the expression type.
344  ///
345  /// @return Pointer to valid object on success, or NULL in case of error.
346  Item_cache *create_case_expr_holder(THD *thd, const Item *item) const;
347 
348  bool set_variable(THD *thd, Field *field, Item **value);
349 
350  /// Pop the Handler_call_frame on top of the stack of active handlers.
351  /// Also pop the matching Diagnostics Area and transfer conditions.
352  void pop_handler_frame(THD *thd);
353 
354  private:
355  /// Top-level (root) parsing context for this runtime context.
357 
358  /// Virtual table for storing SP-variables.
360 
361  /// Collection of Item_field proxies, each of them points to the
362  /// corresponding field in m_var_table.
364 
365  /// This is a pointer to a field, which should contain return value for
366  /// stored functions (only). For stored procedures, this pointer is NULL.
368 
369  /// Indicates whether the return value (in m_return_value_fld) has been
370  /// set during execution.
372 
373  /// Flag to tell if the runtime context is created for a sub-statement.
375 
376  /// Stack of visible handlers.
378 
379  /// Stack of caught SQL conditions.
381 
382  /// Stack of cursors.
384 
385  /// Current number of cursors in m_cstack.
387 
388  /// Array of CASE expression holders.
390 };
391 
392 ///////////////////////////////////////////////////////////////////////////
393 // sp_cursor declaration.
394 ///////////////////////////////////////////////////////////////////////////
395 
396 /* A mediator between stored procedures and server side cursors */
397 
398 class sp_cursor {
399  private:
400  /**
401  An interceptor of cursor result set used to implement
402  FETCH @<cname@> INTO @<varlist@>.
403  */
407 
408  public:
410  uint get_field_count() { return field_count; }
411  void set_spvar_list(List<sp_variable> *vars) { spvar_list = vars; }
412 
413  virtual bool send_eof(THD *) { return false; }
414  virtual bool send_data(THD *thd, List<Item> &items);
415  virtual bool prepare(THD *thd, List<Item> &list, SELECT_LEX_UNIT *u);
416  };
417 
418  public:
420  : m_result(), m_server_side_cursor(nullptr), m_push_instr(i) {}
421 
422  virtual ~sp_cursor() { destroy(); }
423 
424  bool open(THD *thd);
425 
426  bool close();
427 
428  bool is_open() const { return m_server_side_cursor != nullptr; }
429 
430  bool fetch(List<sp_variable> *vars);
431 
432  sp_instr_cpush *get_push_instr() { return m_push_instr; }
433 
434  private:
436 
439 
440  private:
441  void destroy();
442 }; // class sp_cursor
443 
444 #endif /* _SP_RCONTEXT_H_ */
Definition: sp_rcontext.h:398
bool set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr)
Set CASE expression to the specified value.
Definition: sp_rcontext.cc:422
uint first_ip
Instruction pointer to the first instruction.
Definition: sp_rcontext.h:110
Base class for every SP-instruction.
Definition: sp_instr.h:102
bool m_in_sub_stmt
Flag to tell if the runtime context is created for a sub-statement.
Definition: sp_rcontext.h:374
Server_side_cursor * m_server_side_cursor
Definition: sp_rcontext.h:437
ssize_t count
Definition: memcached.c:386
bool set_variable(THD *thd, uint var_idx, Item **value)
Definition: sp_rcontext.h:171
bool is_open() const
Definition: sp_rcontext.h:428
uint m_ccount
Current number of cursors in m_cstack.
Definition: sp_rcontext.h:386
Handler_call_frame(const sp_handler *_handler, Sql_condition *_sql_condition, uint _continue_ip)
The constructor.
Definition: sp_rcontext.h:145
void pop_handlers(sp_pcontext *current_scope)
Pop and delete given number of sp_handler_entry instances from the handler call stack.
Definition: sp_rcontext.cc:199
Some integer typedefs for easier portability.
An interceptor of cursor result set used to implement FETCH <cname> INTO <varlist>.
Definition: sp_rcontext.h:404
Item * get_case_expr(int case_expr_id) const
Definition: sp_rcontext.h:302
bool init_var_items(THD *thd)
Create and initialize an Item-adapter (Item_field) for each SP-var field.
Definition: sp_rcontext.cc:131
This class represents a call frame of SQL-handler (one invocation of a handler).
Definition: sp_rcontext.h:124
Definition: field.h:694
Diagnostics_area handler_da
The Diagnostics Area which will be pushed when the handler activates and popped when the handler comp...
Definition: sp_rcontext.h:138
Definition: item.h:5995
This class represents &#39;DECLARE HANDLER&#39; statement.
Definition: sp_pcontext.h:191
class udf_list * list
Bounds_checked_array< Item_cache * > m_case_expr_holders
Array of CASE expression holders.
Definition: sp_rcontext.h:389
Field * m_return_value_fld
This is a pointer to a field, which should contain return value for stored functions (only)...
Definition: sp_rcontext.h:367
uint get_field_count()
Definition: sp_rcontext.h:410
const sp_handler * handler
Handler definition (from parsing context).
Definition: sp_rcontext.h:127
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4023
#define close(s)
Definition: win32.h:103
Item ** get_case_expr_addr(int case_expr_id) const
Definition: sp_rcontext.h:306
const sp_pcontext * m_root_parsing_ctx
Top-level (root) parsing context for this runtime context.
Definition: sp_rcontext.h:356
void pop_cursors(uint count)
Pop and delete given number of sp_cursor instance from the cursor stack.
Definition: sp_rcontext.cc:174
virtual ~sp_cursor()
Definition: sp_rcontext.h:422
Definition: table.h:1313
sp_instr_cpush corresponds to DECLARE CURSOR, implements DECLARE CURSOR and OPEN. ...
Definition: sp_instr.h:1214
Server_side_cursor – an interface for materialized implementation of cursors.
Definition: sql_cursor.h:51
Item * get_item(uint var_idx) const
Definition: sp_rcontext.h:175
A typesafe replacement for DYNAMIC_ARRAY.
Definition: prealloced_array.h:66
#define DBUG_ASSERT(A)
Definition: my_dbug.h:199
Element_type * array() const
Definition: sql_array.h:105
TABLE * m_var_table
Virtual table for storing SP-variables.
Definition: sp_rcontext.h:359
List< sp_variable > * spvar_list
Definition: sp_rcontext.h:405
bool push_handler(sp_handler *handler, uint first_ip)
Create a new sp_handler_entry instance and push it to the handler call stack.
Definition: sp_rcontext.cc:180
Definition: sql_class.h:224
Definition: aggregate_check.h:523
uint continue_ip
Continue-instruction-pointer for CONTINUE-handlers.
Definition: sp_rcontext.h:134
sp_handler_entry(const sp_handler *_handler, uint _first_ip)
The constructor.
Definition: sp_rcontext.h:116
uint get_last_handler_continue_ip() const
Definition: sp_rcontext.h:242
The class represents parse-time context, which keeps track of declared variables/parameters, conditions, handlers, cursors and labels.
Definition: sp_pcontext.h:250
Stores status of the currently executed statement.
Definition: sql_error.h:268
sp_instr_cpush * get_push_instr()
Definition: sp_rcontext.h:432
This class represents a stored program variable or a parameter (also referenced as &#39;SP-variable&#39;)...
Definition: sp_pcontext.h:47
Definition: item.h:741
unsigned int uint
Definition: uca-dump.cc:29
bool init_var_table(THD *thd)
Create and initialize a table to store SP-variables.
Definition: sp_rcontext.cc:113
bool alloc_arrays(THD *thd)
Internal function to allocate memory for arrays.
Definition: sp_rcontext.cc:96
sp_head * sp
The stored program for which this runtime context is created.
Definition: sp_rcontext.h:165
void pop_handler_frame(THD *thd)
Pop the Handler_call_frame on top of the stack of active handlers.
Definition: sp_rcontext.cc:210
bool end_partial_result_set
Flag to end an open result set before start executing an SQL-handler (if one is found).
Definition: sp_rcontext.h:162
Prealloced_array< Handler_call_frame *, 16 > m_activated_handlers
Stack of caught SQL conditions.
Definition: sp_rcontext.h:380
Representation of a SQL condition.
Definition: sql_error.h:53
void pop_all_cursors()
Definition: sp_rcontext.h:267
This class represents a query expression (one query block or several query blocks combined with UNION...
Definition: sql_lex.h:590
bool set_return_value(THD *thd, Item **return_value_item)
Definition: sp_rcontext.cc:147
#define NULL
Definition: types.h:54
~sp_rcontext()
Definition: sp_rcontext.cc:66
sp_head represents one instance of a stored program.
Definition: sp_head.h:379
sp_cursor * get_cursor(uint i) const
Definition: sp_rcontext.h:269
bool handle_sql_condition(THD *thd, uint *ip, const sp_instr *cur_spi)
Handle current SQL condition (if any).
Definition: sp_rcontext.cc:253
Definition: query_result.h:190
uint field_count
Definition: sp_rcontext.h:406
virtual bool send_eof(THD *)
Definition: sp_rcontext.h:413
void operator=(sp_rcontext &)
bool m_return_value_set
Indicates whether the return value (in m_return_value_fld) has been set during execution.
Definition: sp_rcontext.h:371
stdx::expected< int, std::error_code > open(const char *fname, int flags, mode_t mode) noexcept
Definition: file_handle.cc:81
sp_rcontext(const sp_pcontext *root_parsing_ctx, Field *return_value_fld, bool in_sub_stmt)
Definition: sp_rcontext.cc:54
Item_cache * create_case_expr_holder(THD *thd, const Item *item) const
Create an instance of appropriate Item_cache class depending on the specified type in the callers are...
Definition: sp_rcontext.cc:408
Bounds_checked_array< sp_cursor * > m_cstack
Stack of cursors.
Definition: sp_rcontext.h:383
void destroy(T *ptr)
Definition: my_alloc.h:381
Query_arena * callers_arena
Arena used to (re) allocate items on.
Definition: sp_rcontext.h:157
Handler_call_frame * current_handler_frame() const
Get the Handler_call_frame representing the currently active handler.
Definition: sp_rcontext.h:207
const sp_handler * handler
Handler definition (from parsing context).
Definition: sp_rcontext.h:107
Sql_condition * sql_condition
SQL-condition, triggered handler activation.
Definition: sp_rcontext.h:130
Bounds_checked_array< Item * > m_var_items
Collection of Item_field proxies, each of them points to the corresponding field in m_var_table...
Definition: sp_rcontext.h:363
static sp_rcontext * create(THD *thd, const sp_pcontext *root_parsing_ctx, Field *return_value_fld)
Construct and properly initialize a new sp_rcontext instance.
Definition: sp_rcontext.cc:80
const string value("\alue\)
bool is_return_value_set() const
Definition: sp_rcontext.h:183
void set_spvar_list(List< sp_variable > *vars)
Definition: sp_rcontext.h:411
This is an auxillary class to store entering instruction pointer for an SQL-handler.
Definition: sp_rcontext.h:104
Query_fetch_into_spvars m_result
Definition: sp_rcontext.h:435
Field ** field
Definition: table.h:1342
void exit_handler(THD *thd, sp_pcontext *target_scope)
Handle return from SQL-handler.
Definition: sp_rcontext.cc:224
Query_fetch_into_spvars()
Definition: sp_rcontext.h:409
Item ** get_item_addr(uint var_idx) const
Definition: sp_rcontext.h:177
sp_instr_cpush * m_push_instr
Definition: sp_rcontext.h:438
bool push_cursor(sp_instr_cpush *i)
Create a new sp_cursor instance and push it to the cursor stack.
Definition: sp_rcontext.cc:155
#define false
Definition: config_static.h:43
Definition: items.h:34
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_class.h:799
Dialog Client Authentication nullptr
Definition: dialog.cc:353
static void prepare(pax_msg *p, pax_op op)
Definition: xcom_base.cc:1304
sp_cursor(sp_instr_cpush *i)
Definition: sp_rcontext.h:419
Definition: sp_rcontext.h:76
Prealloced_array< sp_handler_entry *, 16 > m_visible_handlers
Stack of visible handlers.
Definition: sp_rcontext.h:377