1 /* -*- C++ -*- */
2 /* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software Foundation,
22    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23 
24 #ifndef _SP_PCONTEXT_H_
25 #define _SP_PCONTEXT_H_
26 
27 #include "my_global.h"
28 #include "mysql/mysql_lex_string.h"             // LEX_STRING
29 #include "mysql_com.h"                          // enum_field_types
30 #include "field.h"                              // Create_field
31 #include "mem_root_array.h"                     // Mem_root_array
32 
33 
34 /// This class represents a stored program variable or a parameter
35 /// (also referenced as 'SP-variable').
36 
37 class sp_variable : public Sql_alloc
38 {
39 public:
40   enum enum_mode
41   {
42     MODE_IN,
43     MODE_OUT,
44     MODE_INOUT
45   };
46 
47   /// Name of the SP-variable.
48   LEX_STRING name;
49 
50   /// Field-type of the SP-variable.
51   enum enum_field_types type;
52 
53   /// Mode of the SP-variable.
54   enum_mode mode;
55 
56   /// The index to the variable's value in the runtime frame.
57   ///
58   /// It is calculated during parsing and used when creating sp_instr_set
59   /// instructions and Item_splocal items. I.e. values are set/referred by
60   /// array indexing in runtime.
61   uint offset;
62 
63   /// Default value of the SP-variable (if any).
64   Item *default_value;
65 
66   /// Full type information (field meta-data) of the SP-variable.
67   Create_field field_def;
68 
69 public:
sp_variable(LEX_STRING _name,enum_field_types _type,enum_mode _mode,uint _offset)70   sp_variable(LEX_STRING _name, enum_field_types _type, enum_mode _mode,
71               uint _offset)
72    :Sql_alloc(),
73     name(_name),
74     type(_type),
75     mode(_mode),
76     offset(_offset),
77     default_value(NULL)
78   { }
79 };
80 
81 ///////////////////////////////////////////////////////////////////////////
82 
83 /// This class represents an SQL/PSM label. Can refer to the identifier
84 /// used with the "label_name:" construct which may precede some SQL/PSM
85 /// statements, or to an implicit implementation-dependent identifier which
86 /// the parser inserts before a high-level flow control statement such as
87 /// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a
88 /// combination of low-level jump/jump_if instructions and labels.
89 
90 class sp_label : public Sql_alloc
91 {
92 public:
93   enum enum_type
94   {
95     /// Implicit label generated by parser.
96     IMPLICIT,
97 
98     /// Label at BEGIN.
99     BEGIN,
100 
101     /// Label at iteration control
102     ITERATION
103   };
104 
105   /// Name of the label.
106   LEX_STRING name;
107 
108   /// Instruction pointer of the label.
109   uint ip;
110 
111   /// Type of the label.
112   enum_type type;
113 
114   /// Scope of the label.
115   class sp_pcontext *ctx;
116 
117 public:
sp_label(LEX_STRING _name,uint _ip,enum_type _type,sp_pcontext * _ctx)118   sp_label(LEX_STRING _name, uint _ip, enum_type _type, sp_pcontext *_ctx)
119    :Sql_alloc(),
120     name(_name),
121     ip(_ip),
122     type(_type),
123     ctx(_ctx)
124   { }
125 };
126 
127 ///////////////////////////////////////////////////////////////////////////
128 
129 /// This class represents condition-value term in DECLARE CONDITION or
130 /// DECLARE HANDLER statements. sp_condition_value has little to do with
131 /// SQL-conditions.
132 ///
133 /// In some sense, this class is a union -- a set of filled attributes
134 /// depends on the sp_condition_value::type value.
135 
136 class sp_condition_value : public Sql_alloc
137 {
138 public:
139   enum enum_type
140   {
141     ERROR_CODE,
142     SQLSTATE,
143     WARNING,
144     NOT_FOUND,
145     EXCEPTION
146   };
147 
148   /// Type of the condition value.
149   enum_type type;
150 
151   /// SQLSTATE of the condition value.
152   char sql_state[SQLSTATE_LENGTH+1];
153 
154   /// MySQL error code of the condition value.
155   uint mysqlerr;
156 
157 public:
sp_condition_value(uint _mysqlerr)158   sp_condition_value(uint _mysqlerr)
159    :Sql_alloc(),
160     type(ERROR_CODE),
161     mysqlerr(_mysqlerr)
162   { }
163 
sp_condition_value(const char * _sql_state)164   sp_condition_value(const char *_sql_state)
165    :Sql_alloc(),
166     type(SQLSTATE)
167   {
168     memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
169     sql_state[SQLSTATE_LENGTH]= 0;
170   }
171 
sp_condition_value(enum_type _type)172   sp_condition_value(enum_type _type)
173    :Sql_alloc(),
174     type(_type)
175   {
176     assert(type != ERROR_CODE && type != SQLSTATE);
177   }
178 
179   /// Print a condition_value in human-readable form.
180   ///
181   /// @param str The variable to print to.
182   void print(String *str) const;
183 
184   /// Check if two instances of sp_condition_value are equal or not.
185   ///
186   /// @param cv another instance of sp_condition_value to check.
187   ///
188   /// @return true if the instances are equal, false otherwise.
189   bool equals(const sp_condition_value *cv) const;
190 };
191 
192 ///////////////////////////////////////////////////////////////////////////
193 
194 /// This class represents 'DECLARE CONDITION' statement.
195 /// sp_condition has little to do with SQL-conditions.
196 
197 class sp_condition : public Sql_alloc
198 {
199 public:
200   /// Name of the condition.
201   LEX_STRING name;
202 
203   /// Value of the condition.
204   sp_condition_value *value;
205 
206 public:
sp_condition(LEX_STRING _name,sp_condition_value * _value)207   sp_condition(LEX_STRING _name, sp_condition_value *_value)
208    :Sql_alloc(),
209     name(_name),
210     value(_value)
211   { }
212 };
213 
214 ///////////////////////////////////////////////////////////////////////////
215 
216 /// This class represents 'DECLARE HANDLER' statement.
217 
218 class sp_handler : public Sql_alloc
219 {
220 public:
221   /// Enumeration of possible handler types.
222   /// Note: UNDO handlers are not (and have never been) supported.
223   enum enum_type
224   {
225     EXIT,
226     CONTINUE
227   };
228 
229   /// Handler type.
230   enum_type type;
231 
232   /// BEGIN..END block of the handler.
233   sp_pcontext *scope;
234 
235   /// Conditions caught by this handler.
236   List<const sp_condition_value> condition_values;
237 
238 public:
239   /// The constructor.
240   ///
241   /// @param _type    SQL-handler type.
242   /// @param _scope   Handler scope.
sp_handler(enum_type _type,sp_pcontext * _scope)243   sp_handler(enum_type _type, sp_pcontext *_scope)
244    :Sql_alloc(),
245     type(_type),
246     scope(_scope)
247   { }
248 
249   /// Print all conditions of a handler in human-readable form.
250   ///
251   /// @param str The variable to print to.
252   void print_conditions(String *str) const;
253 
254   /// Print type and conditions (but not body) of a handler.
255   ///
256   /// @param str The variable to print to.
257   void print(String *str) const;
258 };
259 
260 ///////////////////////////////////////////////////////////////////////////
261 
262 /// The class represents parse-time context, which keeps track of declared
263 /// variables/parameters, conditions, handlers, cursors and labels.
264 ///
265 /// sp_context objects are organized in a tree according to the following
266 /// rules:
267 ///   - one sp_pcontext object corresponds for for each BEGIN..END block;
268 ///   - one sp_pcontext object corresponds for each exception handler;
269 ///   - one additional sp_pcontext object is created to contain
270 ///     Stored Program parameters.
271 ///
272 /// sp_pcontext objects are used both at parse-time and at runtime.
273 ///
274 /// During the parsing stage sp_pcontext objects are used:
275 ///   - to look up defined names (e.g. declared variables and visible
276 ///     labels);
277 ///   - to check for duplicates;
278 ///   - for error checking;
279 ///   - to calculate offsets to be used at runtime.
280 ///
281 /// During the runtime phase, a tree of sp_pcontext objects is used:
282 ///   - for error checking (e.g. to check correct number of parameters);
283 ///   - to resolve SQL-handlers.
284 
285 class sp_pcontext : public Sql_alloc
286 {
287 public:
288   enum enum_scope
289   {
290     /// REGULAR_SCOPE designates regular BEGIN ... END blocks.
291     REGULAR_SCOPE,
292 
293     /// HANDLER_SCOPE designates SQL-handler blocks.
294     HANDLER_SCOPE
295   };
296 
297 public:
298   sp_pcontext(THD *thd);
299   ~sp_pcontext();
300 
301 
302   /// Create and push a new context in the tree.
303 
304   /// @param thd   thread context.
305   /// @param scope scope of the new parsing context.
306   /// @return the node created.
307   sp_pcontext *push_context(THD *thd, enum_scope scope);
308 
309   /// Pop a node from the parsing context tree.
310   /// @return the parent node.
311   sp_pcontext *pop_context();
312 
parent_context()313   sp_pcontext *parent_context() const
314   { return m_parent; }
315 
get_level()316   int get_level() const
317   { return m_level; }
318 
319   /// Calculate and return the number of handlers to pop between the given
320   /// context and this one.
321   ///
322   /// @param ctx       the other parsing context.
323   /// @param exclusive specifies if the last scope should be excluded.
324   ///
325   /// @return the number of handlers to pop between the given context and
326   /// this one.  If 'exclusive' is true, don't count the last scope we are
327   /// leaving; this is used for LEAVE where we will jump to the hpop
328   /// instructions.
329   size_t diff_handlers(const sp_pcontext *ctx, bool exclusive) const;
330 
331   /// Calculate and return the number of cursors to pop between the given
332   /// context and this one.
333   ///
334   /// @param ctx       the other parsing context.
335   /// @param exclusive specifies if the last scope should be excluded.
336   ///
337   /// @return the number of cursors to pop between the given context and
338   /// this one.  If 'exclusive' is true, don't count the last scope we are
339   /// leaving; this is used for LEAVE where we will jump to the cpop
340   /// instructions.
341   size_t diff_cursors(const sp_pcontext *ctx, bool exclusive) const;
342 
343   /////////////////////////////////////////////////////////////////////////
344   // SP-variables (parameters and variables).
345   /////////////////////////////////////////////////////////////////////////
346 
347   /// @return the maximum number of variables used in this and all child
348   /// contexts. For the root parsing context, this gives us the number of
349   /// slots needed for variables during the runtime phase.
max_var_index()350   uint max_var_index() const
351   { return m_max_var_index; }
352 
353   /// @return the current number of variables used in the parent contexts
354   /// (from the root), including this context.
current_var_count()355   uint current_var_count() const
356   { return m_var_offset + static_cast<uint>(m_vars.size()); }
357 
358   /// @return the number of variables in this context alone.
context_var_count()359   uint context_var_count() const
360   { return static_cast<uint>(m_vars.size()); }
361 
362   /// @return map index in this parsing context to runtime offset.
var_context2runtime(uint i)363   uint var_context2runtime(uint i) const
364   { return m_var_offset + i; }
365 
366   /// Add SP-variable to the parsing context.
367   ///
368   /// @param thd  Thread context.
369   /// @param name Name of the SP-variable.
370   /// @param type Type of the SP-variable.
371   /// @param mode Mode of the SP-variable.
372   ///
373   /// @return instance of newly added SP-variable.
374   sp_variable *add_variable(THD *thd,
375                             LEX_STRING name,
376                             enum enum_field_types type,
377                             sp_variable::enum_mode mode);
378 
379   /// Retrieve full type information about SP-variables in this parsing
380   /// context and its children.
381   ///
382   /// @param field_def_lst[out] Container to store type information.
383   void retrieve_field_definitions(List<Create_field> *field_def_lst) const;
384 
385   /// Find SP-variable by name.
386   ///
387   /// The function does a linear search (from newer to older variables,
388   /// in case we have shadowed names).
389   ///
390   /// The function is called only at parsing time.
391   ///
392   /// @param name               Variable name.
393   /// @param current_scope_only A flag if we search only in current scope.
394   ///
395   /// @return instance of found SP-variable, or NULL if not found.
396   sp_variable *find_variable(LEX_STRING name, bool current_scope_only) const;
397 
398   /// Find SP-variable by the offset in the root parsing context.
399   ///
400   /// The function is used for two things:
401   /// - When evaluating parameters at the beginning, and setting out parameters
402   ///   at the end, of invocation. (Top frame only, so no recursion then.)
403   /// - For printing of sp_instr_set. (Debug mode only.)
404   ///
405   /// @param offset Variable offset in the root parsing context.
406   ///
407   /// @return instance of found SP-variable, or NULL if not found.
408   sp_variable *find_variable(uint offset) const;
409 
410   /// Set the current scope boundary (for default values).
411   ///
412   /// @param n The number of variables to skip.
declare_var_boundary(uint n)413   void declare_var_boundary(uint n)
414   { m_pboundary= n; }
415 
416   /////////////////////////////////////////////////////////////////////////
417   // CASE expressions.
418   /////////////////////////////////////////////////////////////////////////
419 
get_num_case_exprs()420   int get_num_case_exprs() const
421   { return m_num_case_exprs; }
422 
push_case_expr_id()423   int push_case_expr_id()
424   {
425     if (m_case_expr_ids.push_back(m_num_case_exprs))
426       return -1;
427 
428     return m_num_case_exprs++;
429   }
430 
pop_case_expr_id()431   void pop_case_expr_id()
432   { m_case_expr_ids.pop_back(); }
433 
get_current_case_expr_id()434   int get_current_case_expr_id() const
435   { return m_case_expr_ids.back(); }
436 
437   /////////////////////////////////////////////////////////////////////////
438   // Labels.
439   /////////////////////////////////////////////////////////////////////////
440 
441   sp_label *push_label(THD *thd, LEX_STRING name, uint ip);
442 
443   sp_label *find_label(LEX_STRING name);
444 
last_label()445   sp_label *last_label()
446   {
447     sp_label *label= m_labels.head();
448 
449     if (!label && m_parent)
450       label= m_parent->last_label();
451 
452     return label;
453   }
454 
pop_label()455   sp_label *pop_label()
456   { return m_labels.pop(); }
457 
458   /////////////////////////////////////////////////////////////////////////
459   // Conditions.
460   /////////////////////////////////////////////////////////////////////////
461 
462   bool add_condition(THD *thd, LEX_STRING name, sp_condition_value *value);
463 
464   /// See comment for find_variable() above.
465   sp_condition_value *find_condition(LEX_STRING name,
466                                      bool current_scope_only) const;
467 
468   /////////////////////////////////////////////////////////////////////////
469   // Handlers.
470   /////////////////////////////////////////////////////////////////////////
471 
472   sp_handler *add_handler(THD* thd, sp_handler::enum_type type);
473 
474   /// This is an auxilary parsing-time function to check if an SQL-handler
475   /// exists in the current parsing context (current scope) for the given
476   /// SQL-condition. This function is used to check for duplicates during
477   /// the parsing phase.
478   ///
479   /// This function can not be used during the runtime phase to check
480   /// SQL-handler existence because it searches for the SQL-handler in the
481   /// current scope only (during runtime, current and parent scopes
482   /// should be checked according to the SQL-handler resolution rules).
483   ///
484   /// @param condition_value the handler condition value
485   ///                        (not SQL-condition!).
486   ///
487   /// @retval true if such SQL-handler exists.
488   /// @retval false otherwise.
489   bool check_duplicate_handler(const sp_condition_value *cond_value) const;
490 
491   /// Find an SQL handler for the given SQL condition according to the
492   /// SQL-handler resolution rules. This function is used at runtime.
493   ///
494   /// @param sql_state        The SQL condition state
495   /// @param sql_errno        The error code
496   /// @param severity         The SQL condition severity level
497   ///
498   /// @return a pointer to the found SQL-handler or NULL.
499   sp_handler *find_handler(const char *sql_state,
500                            uint sql_errno,
501                            Sql_condition::enum_severity_level severity) const;
502 
503   /////////////////////////////////////////////////////////////////////////
504   // Cursors.
505   /////////////////////////////////////////////////////////////////////////
506 
507   bool add_cursor(LEX_STRING name);
508 
509   /// See comment for find_variable() above.
510   bool find_cursor(LEX_STRING name, uint *poff, bool current_scope_only) const;
511 
512   /// Find cursor by offset (for debugging only).
513   const LEX_STRING *find_cursor(uint offset) const;
514 
max_cursor_index()515   uint max_cursor_index() const
516   { return m_max_cursor_index + static_cast<uint>(m_cursors.size()); }
517 
current_cursor_count()518   uint current_cursor_count() const
519   { return m_cursor_offset + static_cast<uint>(m_cursors.size()); }
520 
521 private:
522   /// Constructor for a tree node.
523   /// @param thd  thread context
524   /// @param prev the parent parsing context
525   /// @param scope scope of this parsing context
526   sp_pcontext(THD *thd, sp_pcontext *prev, enum_scope scope);
527 
528   void init(uint var_offset, uint cursor_offset, int num_case_expressions);
529 
530   /* Prevent use of these */
531   sp_pcontext(const sp_pcontext &);
532   void operator=(sp_pcontext &);
533 
534 private:
535   /// Level of the corresponding BEGIN..END block (0 means the topmost block).
536   int m_level;
537 
538   /// m_max_var_index -- number of variables (including all types of arguments)
539   /// in this context including all children contexts.
540   ///
541   /// m_max_var_index >= m_vars.size().
542   ///
543   /// m_max_var_index of the root parsing context contains number of all
544   /// variables (including arguments) in all enclosed contexts.
545   uint m_max_var_index;
546 
547   /// The maximum sub context's framesizes.
548   uint m_max_cursor_index;
549 
550   /// Parent context.
551   sp_pcontext *m_parent;
552 
553   /// An index of the first SP-variable in this parsing context. The index
554   /// belongs to a runtime table of SP-variables.
555   ///
556   /// Note:
557   ///   - m_var_offset is 0 for root parsing context;
558   ///   - m_var_offset is different for all nested parsing contexts.
559   uint m_var_offset;
560 
561   /// Cursor offset for this context.
562   uint m_cursor_offset;
563 
564   /// Boundary for finding variables in this context. This is the number of
565   /// variables currently "invisible" to default clauses. This is normally 0,
566   /// but will be larger during parsing of DECLARE ... DEFAULT, to get the
567   /// scope right for DEFAULT values.
568   uint m_pboundary;
569 
570   int m_num_case_exprs;
571 
572   /// SP parameters/variables.
573   Mem_root_array<sp_variable *, true> m_vars;
574 
575   /// Stack of CASE expression ids.
576   Mem_root_array<int, true> m_case_expr_ids;
577 
578   /// Stack of SQL-conditions.
579   Mem_root_array<sp_condition *, true> m_conditions;
580 
581   /// Stack of cursors.
582   Mem_root_array<LEX_STRING, true> m_cursors;
583 
584   /// Stack of SQL-handlers.
585   Mem_root_array<sp_handler *, true> m_handlers;
586 
587   /// List of labels.
588   List<sp_label> m_labels;
589 
590   /// Children contexts, used for destruction.
591   Mem_root_array<sp_pcontext *, true> m_children;
592 
593   /// Scope of this parsing context.
594   enum_scope m_scope;
595 }; // class sp_pcontext : public Sql_alloc
596 
597 
598 #endif /* _SP_PCONTEXT_H_ */
599