1 /* Copyright (c) 2012, 2015, 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_INSTR_H_
24 #define _SP_INSTR_H_
25 
26 #include "my_global.h"    // NO_EMBEDDED_ACCESS_CHECKS
27 #include "sp_pcontext.h"  // sp_pcontext
28 #include "sql_class.h"    // THD
29 #include "sp_head.h"      // sp_printable
30 
31 ///////////////////////////////////////////////////////////////////////////
32 // This file contains SP-instruction classes.
33 ///////////////////////////////////////////////////////////////////////////
34 
35 /**
36   An interface for all SP-instructions with destinations that
37   need to be updated by the SP-optimizer.
38 */
39 class sp_branch_instr
40 {
41 public:
42   /**
43     Update the destination; used by the SP-instruction-optimizer.
44 
45     @param old_dest current (old) destination (instruction pointer).
46     @param new_dest new destination (instruction pointer).
47   */
48   virtual void set_destination(uint old_dest, uint new_dest) = 0;
49 
50   /**
51     Update all instruction with the given label in the backpatch list to
52     the specified instruction pointer.
53 
54     @param dest     destination instruction pointer.
55   */
56   virtual void backpatch(uint dest) = 0;
57 
~sp_branch_instr()58   virtual ~sp_branch_instr()
59   { }
60 };
61 
62 ///////////////////////////////////////////////////////////////////////////
63 
64 /**
65   Base class for every SP-instruction. sp_instr defines interface and provides
66   base implementation.
67 */
68 class sp_instr : public Query_arena,
69                  public Sql_alloc,
70                  public sp_printable
71 {
72 public:
sp_instr(uint ip,sp_pcontext * ctx)73   sp_instr(uint ip, sp_pcontext *ctx)
74    :Query_arena(0, STMT_INITIALIZED_FOR_SP),
75     m_marked(false),
76     m_ip(ip),
77     m_parsing_ctx(ctx)
78   { }
79 
~sp_instr()80   virtual ~sp_instr()
81   { free_items(); }
82 
83   /**
84     Execute this instruction
85 
86     @param thd         Thread context
87     @param[out] nextp  index of the next instruction to execute. (For most
88                        instructions this will be the instruction following this
89                        one). Note that this parameter is undefined in case of
90                        errors, use get_cont_dest() to find the continuation
91                        instruction for CONTINUE error handlers.
92 
93     @return Error status.
94   */
95   virtual bool execute(THD *thd, uint *nextp) = 0;
96 
get_ip()97   uint get_ip() const
98   { return m_ip; }
99 
100   /**
101     Get the continuation destination (instruction pointer for the CONTINUE
102     HANDLER) of this instruction.
103     @return the continuation destination
104   */
get_cont_dest()105   virtual uint get_cont_dest() const
106   { return get_ip() + 1; }
107 
get_parsing_ctx()108   sp_pcontext *get_parsing_ctx() const
109   { return m_parsing_ctx; }
110 
111   ///////////////////////////////////////////////////////////////////////////
112   // The following operations are used solely for SP-code-optimizer.
113   ///////////////////////////////////////////////////////////////////////////
114 
115   /**
116     Mark this instruction as reachable during optimization and return the
117     index to the next instruction. Jump instruction will add their
118     destination to the leads list.
119   */
opt_mark(sp_head * sp,List<sp_instr> * leads)120   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
121   {
122     m_marked= true;
123     return get_ip() + 1;
124   }
125 
126   /**
127     Short-cut jumps to jumps during optimization. This is used by the
128     jump instructions' opt_mark() methods. 'start' is the starting point,
129     used to prevent the mark sweep from looping for ever. Return the
130     end destination.
131   */
opt_shortcut_jump(sp_head * sp,sp_instr * start)132   virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
133   { return get_ip(); }
134 
135   /**
136     Inform the instruction that it has been moved during optimization.
137     Most instructions will simply update its index, but jump instructions
138     must also take care of their destination pointers. Forward jumps get
139     pushed to the backpatch list 'ibp'.
140   */
opt_move(uint dst,List<sp_branch_instr> * ibp)141   virtual void opt_move(uint dst, List<sp_branch_instr> *ibp)
142   { m_ip= dst; }
143 
opt_is_marked()144   bool opt_is_marked() const
145   { return m_marked; }
146 
get_instr_trig_field_list()147   virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list()
148   { return NULL; }
149 
150 protected:
151   /// Show if this instruction is reachable within the SP
152   /// (used by SP-optimizer).
153   bool m_marked;
154 
155   /// Instruction pointer.
156   uint m_ip;
157 
158   /// Instruction parsing context.
159   sp_pcontext *m_parsing_ctx;
160 
161 private:
162   // Prevent use of copy constructor and assignment operator.
163   sp_instr(const sp_instr &);
164   void operator= (sp_instr &);
165 };
166 
167 ///////////////////////////////////////////////////////////////////////////
168 
169 /**
170   sp_lex_instr is a class providing the interface and base implementation
171   for SP-instructions, whose execution is based on expression evaluation.
172 
173   sp_lex_instr keeps LEX-object to be able to evaluate the expression.
174 
175   sp_lex_instr also provides possibility to re-parse the original query
176   string if for some reason the LEX-object is not valid any longer.
177 */
178 class sp_lex_instr : public sp_instr
179 {
180 public:
sp_lex_instr(uint ip,sp_pcontext * ctx,LEX * lex,bool is_lex_owner)181   sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner)
182    :sp_instr(ip, ctx),
183     m_lex(NULL),
184     m_is_lex_owner(false),
185     m_first_execution(true),
186     m_prelocking_tables(NULL),
187     m_lex_query_tables_own_last(NULL)
188   {
189     set_lex(lex, is_lex_owner);
190     memset(&m_lex_mem_root, 0, sizeof (MEM_ROOT));
191   }
192 
~sp_lex_instr()193   virtual ~sp_lex_instr()
194   {
195     free_lex();
196     /*
197       If the instruction is reparsed, m_lex_mem_root was used to allocate
198       the items, then freeing the memroot, frees the items. Also free the
199       items allocated on heap as well.
200     */
201     if (alloc_root_inited(&m_lex_mem_root))
202       free_items();
203     free_root(&m_lex_mem_root, MYF(0));
204   }
205 
206   /**
207     Make a few attempts to execute the instruction.
208 
209     Basically, this operation does the following things:
210       - install Reprepare_observer to catch metadata changes (if any);
211       - calls reset_lex_and_exec_core() to execute the instruction;
212       - if the execution fails due to a change in metadata, re-parse the
213         instruction's SQL-statement and repeat execution.
214 
215     @param      thd           Thread context.
216     @param[out] nextp         Next instruction pointer
217     @param      open_tables   Flag to specify if the function should check read
218                               access to tables in LEX's table list and open and
219                               lock them (used in instructions which need to
220                               calculate some expression and don't execute
221                               complete statement).
222 
223     @return Error status.
224   */
225   bool validate_lex_and_execute_core(THD *thd, uint *nextp, bool open_tables);
226 
get_instr_trig_field_list()227   virtual SQL_I_List<Item_trigger_field>* get_instr_trig_field_list()
228   { return &m_trig_field_list; }
229 
230 private:
231   /**
232     Prepare LEX and thread for execution of instruction, if requested open
233     and lock LEX's tables, execute instruction's core function, perform
234     cleanup afterwards.
235 
236     @param thd           thread context
237     @param nextp[out]    next instruction pointer
238     @param open_tables   if TRUE then check read access to tables in LEX's table
239                          list and open and lock them (used in instructions which
240                          need to calculate some expression and don't execute
241                          complete statement).
242 
243     @note
244       We are not saving/restoring some parts of THD which may need this because
245       we do this once for whole routine execution in sp_head::execute().
246 
247     @return Error status.
248   */
249   bool reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables);
250 
251   /**
252     (Re-)parse the query corresponding to this instruction and return a new
253     LEX-object.
254 
255     @param thd  Thread context.
256     @param sp   The stored program.
257 
258     @return new LEX-object or NULL in case of failure.
259   */
260   LEX *parse_expr(THD *thd, sp_head *sp);
261 
262   /**
263      Set LEX-object.
264 
265      Previously assigned LEX-object (if any) will be properly cleaned up
266      and destroyed.
267 
268      @param lex          LEX-object to be used by this instance of sp_lex_instr.
269      @param is_lex_owner the flag specifying if this instance sp_lex_instr
270                          owns (and thus deletes when needed) passed LEX-object.
271   */
272   void set_lex(LEX *lex, bool is_lex_owner);
273 
274   /**
275      Cleanup and destroy assigned LEX-object if needed.
276   */
277   void free_lex();
278 
279 public:
280   /////////////////////////////////////////////////////////////////////////
281   // sp_instr implementation.
282   /////////////////////////////////////////////////////////////////////////
283 
execute(THD * thd,uint * nextp)284   virtual bool execute(THD *thd, uint *nextp)
285   { return validate_lex_and_execute_core(thd, nextp, true); }
286 
287 protected:
288   /////////////////////////////////////////////////////////////////////////
289   // Interface (virtual) methods.
290   /////////////////////////////////////////////////////////////////////////
291 
292   /**
293     Execute core function of instruction after all preparations
294     (e.g. setting of proper LEX, saving part of the thread context).
295 
296     @param thd  Thread context.
297     @param nextp[out]    next instruction pointer
298 
299     @return Error flag.
300   */
301   virtual bool exec_core(THD *thd, uint *nextp) = 0;
302 
303   /**
304     @retval false if the object (i.e. LEX-object) is valid and exec_core() can be
305     just called.
306 
307     @retval true if the object is not valid any longer, exec_core() can not be
308     called. The original query string should be re-parsed and a new LEX-object
309     should be used.
310   */
311   virtual bool is_invalid() const = 0;
312 
313   /**
314     Invalidate the object.
315   */
316   virtual void invalidate() = 0;
317 
318   /**
319     Return the query string, which can be passed to the parser. I.e. the
320     operation should return a valid SQL-statement query string.
321 
322     @param[out] sql_query SQL-statement query string.
323   */
324   virtual void get_query(String *sql_query) const;
325 
326   /**
327     @return the expression query string. This string can not be passed directly
328     to the parser as it is most likely not a valid SQL-statement.
329 
330     @note as it can be seen in the get_query() implementation, get_expr_query()
331     might return EMPTY_STR. EMPTY_STR means that no query-expression is
332     available. That happens when class provides different implementation of
333     get_query(). Strictly speaking, this is a drawback of the current class
334     hierarchy.
335   */
get_expr_query()336   virtual LEX_STRING get_expr_query() const
337   { return EMPTY_STR; }
338 
339   /**
340     Callback function which is called after the statement query string is
341     successfully parsed, and the thread context has not been switched to the
342     outer context. The thread context contains new LEX-object corresponding to
343     the parsed query string.
344 
345     @param thd  Thread context.
346 
347     @return Error flag.
348   */
on_after_expr_parsing(THD * thd)349   virtual bool on_after_expr_parsing(THD *thd)
350   { return false; }
351 
352   /**
353     Destroy items in the free list before re-parsing the statement query
354     string (and thus, creating new items).
355 
356     @param thd  Thread context.
357   */
358   virtual void cleanup_before_parsing(THD *thd);
359 
360   /// LEX-object.
361   LEX *m_lex;
362 private:
363   /**
364     Mem-root for storing the LEX-tree during reparse. This
365     mem-root is freed when a reparse is triggered or the stored
366     routine is dropped.
367   */
368   MEM_ROOT m_lex_mem_root;
369 
370 
371   /**
372     Indicates whether this sp_lex_instr instance is responsible for
373     LEX-object deletion.
374   */
375   bool m_is_lex_owner;
376 
377   /**
378     Indicates whether exec_core() has not been already called on the current
379     LEX-object.
380   */
381   bool m_first_execution;
382 
383   /*****************************************************************************
384     Support for being able to execute this statement in two modes:
385     a) inside prelocked mode set by the calling procedure or its ancestor.
386     b) outside of prelocked mode, when this statement enters/leaves
387        prelocked mode itself.
388   *****************************************************************************/
389 
390   /**
391     List of additional tables this statement needs to lock when it
392     enters/leaves prelocked mode on its own.
393   */
394   TABLE_LIST *m_prelocking_tables;
395 
396   /**
397     The value m_lex->query_tables_own_last should be set to this when the
398     statement enters/leaves prelocked mode on its own.
399   */
400   TABLE_LIST **m_lex_query_tables_own_last;
401 
402   /**
403     List of all the Item_trigger_field's of instruction.
404   */
405   SQL_I_List<Item_trigger_field> m_trig_field_list;
406 };
407 
408 ///////////////////////////////////////////////////////////////////////////
409 
410 /**
411   sp_instr_stmt represents almost all conventional SQL-statements, which are
412   supported outside stored programs.
413 
414   SET-statements, which deal with SP-variable or NEW/OLD trigger pseudo-rows are
415   not represented by this instruction.
416 */
417 class sp_instr_stmt : public sp_lex_instr
418 {
419 public:
sp_instr_stmt(uint ip,LEX * lex,LEX_STRING query)420   sp_instr_stmt(uint ip,
421                 LEX *lex,
422                 LEX_STRING query)
423    :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
424     m_query(query),
425     m_valid(true)
426   { }
427 
428   /////////////////////////////////////////////////////////////////////////
429   // sp_instr implementation.
430   /////////////////////////////////////////////////////////////////////////
431 
432   virtual bool execute(THD *thd, uint *nextp);
433 
434   /////////////////////////////////////////////////////////////////////////
435   // sp_printable implementation.
436   /////////////////////////////////////////////////////////////////////////
437 
438   virtual void print(String *str);
439 
440   /////////////////////////////////////////////////////////////////////////
441   // sp_lex_instr implementation.
442   /////////////////////////////////////////////////////////////////////////
443 
444   virtual bool exec_core(THD *thd, uint *nextp);
445 
is_invalid()446   virtual bool is_invalid() const
447   { return !m_valid; }
448 
invalidate()449   virtual void invalidate()
450   { m_valid= false; }
451 
get_query(String * sql_query)452   virtual void get_query(String *sql_query) const
453   { sql_query->append(m_query.str, m_query.length); }
454 
on_after_expr_parsing(THD * thd)455   virtual bool on_after_expr_parsing(THD *thd)
456   {
457     m_valid= true;
458     return false;
459   }
460 
461 private:
462   /// Complete query of the SQL-statement.
463   LEX_STRING m_query;
464 
465   /// Specify if the stored LEX-object is up-to-date.
466   bool m_valid;
467 };
468 
469 ///////////////////////////////////////////////////////////////////////////
470 
471 /**
472   sp_instr_set represents SET-statememnts, which deal with SP-variables.
473 */
474 class sp_instr_set : public sp_lex_instr
475 {
476 public:
sp_instr_set(uint ip,LEX * lex,uint offset,Item * value_item,LEX_STRING value_query,bool is_lex_owner)477   sp_instr_set(uint ip,
478                LEX *lex,
479 	       uint offset,
480                Item *value_item,
481                LEX_STRING value_query,
482                bool is_lex_owner)
483    :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, is_lex_owner),
484     m_offset(offset),
485     m_value_item(value_item),
486     m_value_query(value_query)
487   { }
488 
489   /////////////////////////////////////////////////////////////////////////
490   // sp_printable implementation.
491   /////////////////////////////////////////////////////////////////////////
492 
493   virtual void print(String *str);
494 
495   /////////////////////////////////////////////////////////////////////////
496   // sp_lex_instr implementation.
497   /////////////////////////////////////////////////////////////////////////
498 
499   virtual bool exec_core(THD *thd, uint *nextp);
500 
is_invalid()501   virtual bool is_invalid() const
502   { return m_value_item == NULL; }
503 
invalidate()504   virtual void invalidate()
505   { m_value_item= NULL; }
506 
on_after_expr_parsing(THD * thd)507   virtual bool on_after_expr_parsing(THD *thd)
508   {
509     DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
510 
511     m_value_item= thd->lex->select_lex.item_list.head();
512 
513     return false;
514   }
515 
get_expr_query()516   virtual LEX_STRING get_expr_query() const
517   { return m_value_query; }
518 
519 private:
520   /// Frame offset.
521   uint m_offset;
522 
523   /// Value expression item of the SET-statement.
524   Item *m_value_item;
525 
526   /// SQL-query corresponding to the value expression.
527   LEX_STRING m_value_query;
528 };
529 
530 ///////////////////////////////////////////////////////////////////////////
531 
532 /**
533   sp_instr_set_trigger_field represents SET-statements, which deal with NEW/OLD
534   trigger pseudo-rows.
535 */
536 class sp_instr_set_trigger_field : public sp_lex_instr
537 {
538 public:
sp_instr_set_trigger_field(uint ip,LEX * lex,LEX_STRING trigger_field_name,Item_trigger_field * trigger_field,Item * value_item,LEX_STRING value_query)539   sp_instr_set_trigger_field(uint ip,
540                              LEX *lex,
541                              LEX_STRING trigger_field_name,
542                              Item_trigger_field *trigger_field,
543                              Item *value_item,
544                              LEX_STRING value_query)
545    :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
546     m_trigger_field_name(trigger_field_name),
547     m_trigger_field(trigger_field),
548     m_value_item(value_item),
549     m_value_query(value_query)
550   { }
551 
552   /////////////////////////////////////////////////////////////////////////
553   // sp_printable implementation.
554   /////////////////////////////////////////////////////////////////////////
555 
556   virtual void print(String *str);
557 
558   /////////////////////////////////////////////////////////////////////////
559   // sp_lex_instr implementation.
560   /////////////////////////////////////////////////////////////////////////
561 
562   virtual bool exec_core(THD *thd, uint *nextp);
563 
is_invalid()564   virtual bool is_invalid() const
565   { return m_value_item == NULL; }
566 
invalidate()567   virtual void invalidate()
568   { m_value_item= NULL; }
569 
570   virtual bool on_after_expr_parsing(THD *thd);
571 
572   virtual void cleanup_before_parsing(THD *thd);
573 
get_expr_query()574   virtual LEX_STRING get_expr_query() const
575   { return m_value_query; }
576 
577 private:
578   /// Trigger field name ("field_name" of the "NEW.field_name").
579   LEX_STRING m_trigger_field_name;
580 
581   /// Item corresponding to the NEW/OLD trigger field.
582   Item_trigger_field *m_trigger_field;
583 
584   /// Value expression item of the SET-statement.
585   Item *m_value_item;
586 
587   /// SQL-query corresponding to the value expression.
588   LEX_STRING m_value_query;
589 };
590 
591 ///////////////////////////////////////////////////////////////////////////
592 
593 /**
594   sp_instr_freturn represents RETURN statement in stored functions.
595 */
596 class sp_instr_freturn : public sp_lex_instr
597 {
598 public:
sp_instr_freturn(uint ip,LEX * lex,Item * expr_item,LEX_STRING expr_query,enum enum_field_types return_field_type)599   sp_instr_freturn(uint ip,
600                    LEX *lex,
601 		   Item *expr_item,
602                    LEX_STRING expr_query,
603                    enum enum_field_types return_field_type)
604    :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
605     m_expr_item(expr_item),
606     m_expr_query(expr_query),
607     m_return_field_type(return_field_type)
608   { }
609 
610   /////////////////////////////////////////////////////////////////////////
611   // sp_printable implementation.
612   /////////////////////////////////////////////////////////////////////////
613 
614   virtual void print(String *str);
615 
616   /////////////////////////////////////////////////////////////////////////
617   // sp_instr implementation.
618   /////////////////////////////////////////////////////////////////////////
619 
opt_mark(sp_head * sp,List<sp_instr> * leads)620   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
621   {
622     m_marked= true;
623     return UINT_MAX;
624   }
625 
626   /////////////////////////////////////////////////////////////////////////
627   // sp_lex_instr implementation.
628   /////////////////////////////////////////////////////////////////////////
629 
630   virtual bool exec_core(THD *thd, uint *nextp);
631 
is_invalid()632   virtual bool is_invalid() const
633   { return m_expr_item == NULL; }
634 
invalidate()635   virtual void invalidate()
636   {
637     // it's already deleted.
638     m_expr_item= NULL;
639   }
640 
on_after_expr_parsing(THD * thd)641   virtual bool on_after_expr_parsing(THD *thd)
642   {
643     DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
644 
645     m_expr_item= thd->lex->select_lex.item_list.head();
646 
647     return false;
648   }
649 
get_expr_query()650   virtual LEX_STRING get_expr_query() const
651   { return m_expr_query; }
652 
653 private:
654   /// RETURN-expression item.
655   Item *m_expr_item;
656 
657   /// SQL-query corresponding to the RETURN-expression.
658   LEX_STRING m_expr_query;
659 
660   /// RETURN-field type code.
661   enum enum_field_types m_return_field_type;
662 };
663 
664 ///////////////////////////////////////////////////////////////////////////
665 
666 /**
667   This is base class for all kinds of jump instructions.
668 
669   @note this is the only class, we directly construct instances of, that has
670   subclasses. We also redefine sp_instr_jump behavior in those subclasses.
671 
672   @todo later we will consider introducing a new class, which will be the base
673   for sp_instr_jump, sp_instr_set_case_expr and sp_instr_jump_case_when.
674   Something like sp_regular_branch_instr (similar to sp_lex_branch_instr).
675 */
676 class sp_instr_jump : public sp_instr,
677                       public sp_branch_instr
678 {
679 public:
sp_instr_jump(uint ip,sp_pcontext * ctx)680   sp_instr_jump(uint ip, sp_pcontext *ctx)
681    :sp_instr(ip, ctx),
682     m_dest(0),
683     m_optdest(NULL)
684   { }
685 
sp_instr_jump(uint ip,sp_pcontext * ctx,uint dest)686   sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
687    :sp_instr(ip, ctx),
688     m_dest(dest),
689     m_optdest(NULL)
690   { }
691 
692   /////////////////////////////////////////////////////////////////////////
693   // sp_printable implementation.
694   /////////////////////////////////////////////////////////////////////////
695 
696   virtual void print(String *str);
697 
698   /////////////////////////////////////////////////////////////////////////
699   // sp_instr implementation.
700   /////////////////////////////////////////////////////////////////////////
701 
execute(THD * thd,uint * nextp)702   virtual bool execute(THD *thd, uint *nextp)
703   {
704     *nextp= m_dest;
705     return false;
706   }
707 
708   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
709 
710   virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
711 
712   virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
713 
714   /////////////////////////////////////////////////////////////////////////
715   // sp_branch_instr implementation.
716   /////////////////////////////////////////////////////////////////////////
717 
set_destination(uint old_dest,uint new_dest)718   virtual void set_destination(uint old_dest, uint new_dest)
719   {
720     if (m_dest == old_dest)
721       m_dest= new_dest;
722   }
723 
backpatch(uint dest)724   virtual void backpatch(uint dest)
725   {
726     /* Calling backpatch twice is a logic flaw in jump resolution. */
727     DBUG_ASSERT(m_dest == 0);
728     m_dest= dest;
729   }
730 
731 protected:
732   /// Where we will go.
733   uint m_dest;
734 
735   // The following attribute is used by SP-optimizer.
736   sp_instr *m_optdest;
737 };
738 
739 ///////////////////////////////////////////////////////////////////////////
740 
741 /**
742   sp_lex_branch_instr is a base class for SP-instructions, which might perform
743   conditional jump depending on the value of an SQL-expression.
744 */
745 class sp_lex_branch_instr : public sp_lex_instr,
746                             public sp_branch_instr
747 {
748 protected:
sp_lex_branch_instr(uint ip,sp_pcontext * ctx,LEX * lex,Item * expr_item,LEX_STRING expr_query)749   sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex,
750                       Item *expr_item, LEX_STRING expr_query)
751    :sp_lex_instr(ip, ctx, lex, true),
752     m_dest(0),
753     m_cont_dest(0),
754     m_optdest(NULL),
755     m_cont_optdest(NULL),
756     m_expr_item(expr_item),
757     m_expr_query(expr_query)
758   { }
759 
sp_lex_branch_instr(uint ip,sp_pcontext * ctx,LEX * lex,Item * expr_item,LEX_STRING expr_query,uint dest)760   sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex,
761                       Item *expr_item, LEX_STRING expr_query,
762                       uint dest)
763    :sp_lex_instr(ip, ctx, lex, true),
764     m_dest(dest),
765     m_cont_dest(0),
766     m_optdest(NULL),
767     m_cont_optdest(NULL),
768     m_expr_item(expr_item),
769     m_expr_query(expr_query)
770   { }
771 
772 public:
set_cont_dest(uint cont_dest)773   void set_cont_dest(uint cont_dest)
774   { m_cont_dest= cont_dest; }
775 
776   /////////////////////////////////////////////////////////////////////////
777   // sp_instr implementation.
778   /////////////////////////////////////////////////////////////////////////
779 
780   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
781 
782   virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
783 
get_cont_dest()784   virtual uint get_cont_dest() const
785   { return m_cont_dest; }
786 
787   /////////////////////////////////////////////////////////////////////////
788   // sp_lex_instr implementation.
789   /////////////////////////////////////////////////////////////////////////
790 
is_invalid()791   virtual bool is_invalid() const
792   { return m_expr_item == NULL; }
793 
invalidate()794   virtual void invalidate()
795   { m_expr_item= NULL; /* it's already deleted. */ }
796 
get_expr_query()797   virtual LEX_STRING get_expr_query() const
798   { return m_expr_query; }
799 
800   /////////////////////////////////////////////////////////////////////////
801   // sp_branch_instr implementation.
802   /////////////////////////////////////////////////////////////////////////
803 
set_destination(uint old_dest,uint new_dest)804   virtual void set_destination(uint old_dest, uint new_dest)
805   {
806     if (m_dest == old_dest)
807       m_dest= new_dest;
808 
809     if (m_cont_dest == old_dest)
810       m_cont_dest= new_dest;
811   }
812 
backpatch(uint dest)813   virtual void backpatch(uint dest)
814   {
815     /* Calling backpatch twice is a logic flaw in jump resolution. */
816     DBUG_ASSERT(m_dest == 0);
817     m_dest= dest;
818   }
819 
820 protected:
821   /// Where we will go.
822   uint m_dest;
823 
824   /// Where continue handlers will go.
825   uint m_cont_dest;
826 
827   // The following attributes are used by SP-optimizer.
828   sp_instr *m_optdest;
829   sp_instr *m_cont_optdest;
830 
831   /// Expression item.
832   Item *m_expr_item;
833 
834   /// SQL-query corresponding to the expression.
835   LEX_STRING m_expr_query;
836 };
837 
838 ///////////////////////////////////////////////////////////////////////////
839 
840 /**
841   sp_instr_jump_if_not implements SP-instruction, which does the jump if its
842   SQL-expression is false.
843 */
844 class sp_instr_jump_if_not : public sp_lex_branch_instr
845 {
846 public:
sp_instr_jump_if_not(uint ip,LEX * lex,Item * expr_item,LEX_STRING expr_query)847   sp_instr_jump_if_not(uint ip,
848                        LEX *lex,
849                        Item *expr_item,
850                        LEX_STRING expr_query)
851    :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
852                         expr_item, expr_query)
853   { }
854 
sp_instr_jump_if_not(uint ip,LEX * lex,Item * expr_item,LEX_STRING expr_query,uint dest)855   sp_instr_jump_if_not(uint ip,
856                        LEX *lex,
857                        Item *expr_item,
858                        LEX_STRING expr_query,
859                        uint dest)
860    :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
861                         expr_item, expr_query, dest)
862   { }
863 
864   /////////////////////////////////////////////////////////////////////////
865   // sp_printable implementation.
866   /////////////////////////////////////////////////////////////////////////
867 
868   virtual void print(String *str);
869 
870   /////////////////////////////////////////////////////////////////////////
871   // sp_lex_instr implementation.
872   /////////////////////////////////////////////////////////////////////////
873 
874   virtual bool exec_core(THD *thd, uint *nextp);
875 
on_after_expr_parsing(THD * thd)876   virtual bool on_after_expr_parsing(THD *thd)
877   {
878     DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
879 
880     m_expr_item= thd->lex->select_lex.item_list.head();
881 
882     return false;
883   }
884 };
885 
886 ///////////////////////////////////////////////////////////////////////////
887 // Instructions used for the "simple CASE" implementation.
888 ///////////////////////////////////////////////////////////////////////////
889 
890 /**
891   sp_instr_set_case_expr is used in the "simple CASE" implementation to evaluate
892   and store the CASE-expression in the runtime context.
893 */
894 class sp_instr_set_case_expr : public sp_lex_branch_instr
895 {
896 public:
sp_instr_set_case_expr(uint ip,LEX * lex,uint case_expr_id,Item * case_expr_item,LEX_STRING case_expr_query)897   sp_instr_set_case_expr(uint ip,
898                          LEX *lex,
899                          uint case_expr_id,
900                          Item *case_expr_item,
901                          LEX_STRING case_expr_query)
902    :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
903                         case_expr_item, case_expr_query),
904     m_case_expr_id(case_expr_id)
905   { }
906 
907   /////////////////////////////////////////////////////////////////////////
908   // sp_printable implementation.
909   /////////////////////////////////////////////////////////////////////////
910 
911   virtual void print(String *str);
912 
913   /////////////////////////////////////////////////////////////////////////
914   // sp_instr implementation.
915   /////////////////////////////////////////////////////////////////////////
916 
917   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
918 
919   virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
920 
921   /////////////////////////////////////////////////////////////////////////
922   // sp_branch_instr implementation.
923   /////////////////////////////////////////////////////////////////////////
924 
925   /*
926     NOTE: set_destination() and backpatch() are overriden here just because the
927     m_dest attribute is not used by this class, so there is no need to do
928     anything about it.
929 
930     @todo These operations probably should be left as they are (i.e. do not
931     override them here). The m_dest attribute would be set and not used, but
932     that should not be a big deal.
933 
934     @todo This also indicates deficiency of the current SP-istruction class
935     hierarchy.
936   */
937 
set_destination(uint old_dest,uint new_dest)938   virtual void set_destination(uint old_dest, uint new_dest)
939   {
940     if (m_cont_dest == old_dest)
941       m_cont_dest= new_dest;
942   }
943 
backpatch(uint dest)944   virtual void backpatch(uint dest)
945   { }
946 
947   /////////////////////////////////////////////////////////////////////////
948   // sp_lex_instr implementation.
949   /////////////////////////////////////////////////////////////////////////
950 
951   virtual bool exec_core(THD *thd, uint *nextp);
952 
on_after_expr_parsing(THD * thd)953   virtual bool on_after_expr_parsing(THD *thd)
954   {
955     DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
956 
957     m_expr_item= thd->lex->select_lex.item_list.head();
958 
959     return false;
960   }
961 
962 private:
963   /// Identifier (index) of the CASE-expression in the runtime context.
964   uint m_case_expr_id;
965 };
966 
967 ///////////////////////////////////////////////////////////////////////////
968 
969 /**
970   sp_instr_jump_case_when instruction is used in the "simple CASE"
971   implementation. It's a jump instruction with the following condition:
972     (CASE-expression = WHEN-expression)
973   CASE-expression is retrieved from sp_rcontext;
974   WHEN-expression is kept by this instruction.
975 */
976 class sp_instr_jump_case_when : public sp_lex_branch_instr
977 {
978 public:
sp_instr_jump_case_when(uint ip,LEX * lex,int case_expr_id,Item * when_expr_item,LEX_STRING when_expr_query)979   sp_instr_jump_case_when(uint ip,
980                           LEX *lex,
981                           int case_expr_id,
982                           Item *when_expr_item,
983                           LEX_STRING when_expr_query)
984    :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
985                         when_expr_item, when_expr_query),
986     m_case_expr_id(case_expr_id)
987   { }
988 
989   /////////////////////////////////////////////////////////////////////////
990   // sp_printable implementation.
991   /////////////////////////////////////////////////////////////////////////
992 
993   virtual void print(String *str);
994 
995   /////////////////////////////////////////////////////////////////////////
996   // sp_lex_instr implementation.
997   /////////////////////////////////////////////////////////////////////////
998 
999   virtual bool exec_core(THD *thd, uint *nextp);
1000 
invalidate()1001   virtual void invalidate()
1002   {
1003     // Items should be already deleted in lex-keeper.
1004     m_case_expr_item= NULL;
1005     m_eq_item= NULL;
1006     m_expr_item= NULL; // it's a WHEN-expression.
1007   }
1008 
on_after_expr_parsing(THD * thd)1009   virtual bool on_after_expr_parsing(THD *thd)
1010   { return build_expr_items(thd); }
1011 
1012 private:
1013   /**
1014     Build CASE-expression item tree:
1015       Item_func_eq(case-expression, when-i-expression)
1016 
1017     This function is used for the following form of CASE statement:
1018       CASE case-expression
1019         WHEN when-1-expression THEN ...
1020         WHEN when-2-expression THEN ...
1021         ...
1022         WHEN when-n-expression THEN ...
1023       END CASE
1024 
1025     The thing is that after the parsing we have an item (item tree) for the
1026     case-expression and for each when-expression. Here we build jump
1027     conditions: expressions like (case-expression = when-i-expression).
1028 
1029     @param thd  Thread context.
1030 
1031     @return Error flag.
1032   */
1033   bool build_expr_items(THD *thd);
1034 
1035 private:
1036   /// Identifier (index) of the CASE-expression in the runtime context.
1037   int m_case_expr_id;
1038 
1039   /// Item representing the CASE-expression.
1040   Item_case_expr *m_case_expr_item;
1041 
1042   /**
1043     Item corresponding to the main item of the jump-condition-expression:
1044     it's the equal function (=) in the (case-expression = when-i-expression)
1045     expression.
1046   */
1047   Item *m_eq_item;
1048 };
1049 
1050 ///////////////////////////////////////////////////////////////////////////
1051 // SQL-condition handler instructions.
1052 ///////////////////////////////////////////////////////////////////////////
1053 
1054 class sp_instr_hpush_jump : public sp_instr_jump
1055 {
1056 public:
sp_instr_hpush_jump(uint ip,sp_pcontext * ctx,sp_handler * handler)1057   sp_instr_hpush_jump(uint ip,
1058                       sp_pcontext *ctx,
1059                       sp_handler *handler)
1060    :sp_instr_jump(ip, ctx),
1061     m_handler(handler),
1062     m_opt_hpop(0),
1063     m_frame(ctx->current_var_count())
1064   {
1065     DBUG_ASSERT(m_handler->condition_values.elements == 0);
1066   }
1067 
~sp_instr_hpush_jump()1068   virtual ~sp_instr_hpush_jump()
1069   {
1070     m_handler->condition_values.empty();
1071     m_handler= NULL;
1072   }
1073 
add_condition(sp_condition_value * condition_value)1074   void add_condition(sp_condition_value *condition_value)
1075   { m_handler->condition_values.push_back(condition_value); }
1076 
get_handler()1077   sp_handler *get_handler()
1078   { return m_handler; }
1079 
1080   /////////////////////////////////////////////////////////////////////////
1081   // sp_printable implementation.
1082   /////////////////////////////////////////////////////////////////////////
1083 
1084   virtual void print(String *str);
1085 
1086   /////////////////////////////////////////////////////////////////////////
1087   // sp_instr implementation.
1088   /////////////////////////////////////////////////////////////////////////
1089 
1090   virtual bool execute(THD *thd, uint *nextp);
1091 
1092   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
1093 
1094   /** Override sp_instr_jump's shortcut; we stop here. */
opt_shortcut_jump(sp_head * sp,sp_instr * start)1095   virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
1096   { return get_ip(); }
1097 
1098   /////////////////////////////////////////////////////////////////////////
1099   // sp_branch_instr implementation.
1100   /////////////////////////////////////////////////////////////////////////
1101 
backpatch(uint dest)1102   virtual void backpatch(uint dest)
1103   {
1104     DBUG_ASSERT(!m_dest || !m_opt_hpop);
1105     if (!m_dest)
1106       m_dest= dest;
1107     else
1108       m_opt_hpop= dest;
1109   }
1110 
1111 private:
1112   /// Handler.
1113   sp_handler *m_handler;
1114 
1115   /// hpop marking end of handler scope.
1116   uint m_opt_hpop;
1117 
1118   // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
1119   // debug version only). It's used in print().
1120   uint m_frame;
1121 };
1122 
1123 ///////////////////////////////////////////////////////////////////////////
1124 
1125 class sp_instr_hpop : public sp_instr
1126 {
1127 public:
sp_instr_hpop(uint ip,sp_pcontext * ctx)1128   sp_instr_hpop(uint ip, sp_pcontext *ctx)
1129     : sp_instr(ip, ctx)
1130   { }
1131 
1132   /////////////////////////////////////////////////////////////////////////
1133   // sp_printable implementation.
1134   /////////////////////////////////////////////////////////////////////////
1135 
print(String * str)1136   virtual void print(String *str)
1137   { str->append(STRING_WITH_LEN("hpop")); }
1138 
1139   /////////////////////////////////////////////////////////////////////////
1140   // sp_instr implementation.
1141   /////////////////////////////////////////////////////////////////////////
1142 
1143   virtual bool execute(THD *thd, uint *nextp);
1144 };
1145 
1146 ///////////////////////////////////////////////////////////////////////////
1147 
1148 class sp_instr_hreturn : public sp_instr_jump
1149 {
1150 public:
sp_instr_hreturn(uint ip,sp_pcontext * ctx)1151   sp_instr_hreturn(uint ip, sp_pcontext *ctx)
1152    :sp_instr_jump(ip, ctx),
1153     m_frame(ctx->current_var_count())
1154   { }
1155 
1156   /////////////////////////////////////////////////////////////////////////
1157   // sp_printable implementation.
1158   /////////////////////////////////////////////////////////////////////////
1159 
1160   virtual void print(String *str);
1161 
1162   /////////////////////////////////////////////////////////////////////////
1163   // sp_instr implementation.
1164   /////////////////////////////////////////////////////////////////////////
1165 
1166   virtual bool execute(THD *thd, uint *nextp);
1167 
1168   /** Override sp_instr_jump's shortcut; we stop here. */
opt_shortcut_jump(sp_head * sp,sp_instr * start)1169   virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
1170   { return get_ip(); }
1171 
1172   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
1173 
1174 private:
1175   // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
1176   // debug version only). It's used in print().
1177   uint m_frame;
1178 };
1179 
1180 ///////////////////////////////////////////////////////////////////////////
1181 // Cursor implementation.
1182 ///////////////////////////////////////////////////////////////////////////
1183 
1184 /**
1185   sp_instr_cpush corresponds to DECLARE CURSOR, implements DECLARE CURSOR and
1186   OPEN.
1187 
1188   This is the most important instruction in cursor implementation. It is created
1189   and added to sp_head when DECLARE CURSOR is being parsed. The arena of this
1190   instruction contains LEX-object for the cursor's SELECT-statement.
1191 
1192   This instruction is actually used to open the cursor.
1193 
1194   execute() operation "implements" DECLARE CURSOR statement -- it merely pushes
1195   a new cursor object into the stack in sp_rcontext object.
1196 
1197   exec_core() operation implements OPEN statement. It is important to implement
1198   OPEN statement in this instruction, because OPEN may lead to re-parsing of the
1199   SELECT-statement. So, the original Arena and parsing context must be used.
1200 */
1201 class sp_instr_cpush : public sp_lex_instr
1202 {
1203 public:
sp_instr_cpush(uint ip,sp_pcontext * ctx,LEX * cursor_lex,LEX_STRING cursor_query,int cursor_idx)1204   sp_instr_cpush(uint ip,
1205                  sp_pcontext *ctx,
1206                  LEX *cursor_lex,
1207                  LEX_STRING cursor_query,
1208                  int cursor_idx)
1209    :sp_lex_instr(ip, ctx, cursor_lex, true),
1210     m_cursor_query(cursor_query),
1211     m_valid(true),
1212     m_cursor_idx(cursor_idx)
1213   {
1214     // Cursor can't be stored in Query Cache, so we should prevent opening QC
1215     // for try to write results which are absent.
1216 
1217     cursor_lex->safe_to_cache_query= false;
1218   }
1219 
1220   /////////////////////////////////////////////////////////////////////////
1221   // sp_printable implementation.
1222   /////////////////////////////////////////////////////////////////////////
1223 
1224   virtual void print(String *str);
1225 
1226   /////////////////////////////////////////////////////////////////////////
1227   // Query_arena implementation.
1228   /////////////////////////////////////////////////////////////////////////
1229 
1230   /**
1231     This call is used to cleanup the instruction when a sensitive
1232     cursor is closed. For now stored procedures always use materialized
1233     cursors and the call is not used.
1234   */
cleanup_stmt()1235   virtual void cleanup_stmt()
1236   { /* no op */ }
1237 
1238   /////////////////////////////////////////////////////////////////////////
1239   // sp_instr implementation.
1240   /////////////////////////////////////////////////////////////////////////
1241 
1242   virtual bool execute(THD *thd, uint *nextp);
1243 
1244   /////////////////////////////////////////////////////////////////////////
1245   // sp_lex_instr implementation.
1246   /////////////////////////////////////////////////////////////////////////
1247 
1248   virtual bool exec_core(THD *thd, uint *nextp);
1249 
is_invalid()1250   virtual bool is_invalid() const
1251   { return !m_valid; }
1252 
invalidate()1253   virtual void invalidate()
1254   { m_valid= false; }
1255 
get_query(String * sql_query)1256   virtual void get_query(String *sql_query) const
1257   { sql_query->append(m_cursor_query.str, m_cursor_query.length); }
1258 
on_after_expr_parsing(THD * thd)1259   virtual bool on_after_expr_parsing(THD *thd)
1260   {
1261     m_valid= true;
1262     return false;
1263   }
1264 
1265 private:
1266   /// This attribute keeps the cursor SELECT statement.
1267   LEX_STRING m_cursor_query;
1268 
1269   /// Flag if the LEX-object of this instruction is valid or not.
1270   /// The LEX-object is not valid when metadata have changed.
1271   bool m_valid;
1272 
1273   /// Used to identify the cursor in the sp_rcontext.
1274   int m_cursor_idx;
1275 };
1276 
1277 ///////////////////////////////////////////////////////////////////////////
1278 
1279 /**
1280   sp_instr_cpop instruction is added at the end of BEGIN..END block.
1281   It's used to remove declared cursors so that they are not visible any longer.
1282 */
1283 class sp_instr_cpop : public sp_instr
1284 {
1285 public:
sp_instr_cpop(uint ip,sp_pcontext * ctx,uint count)1286   sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
1287    :sp_instr(ip, ctx),
1288     m_count(count)
1289   { }
1290 
1291   /////////////////////////////////////////////////////////////////////////
1292   // sp_printable implementation.
1293   /////////////////////////////////////////////////////////////////////////
1294 
1295   virtual void print(String *str);
1296 
1297   /////////////////////////////////////////////////////////////////////////
1298   // sp_instr implementation.
1299   /////////////////////////////////////////////////////////////////////////
1300 
1301   virtual bool execute(THD *thd, uint *nextp);
1302 
1303 private:
1304   uint m_count;
1305 };
1306 
1307 ///////////////////////////////////////////////////////////////////////////
1308 
1309 /**
1310   sp_instr_copen represents OPEN statement (opens the cursor).
1311   However, the actual implementation is in sp_instr_cpush::exec_core().
1312 */
1313 class sp_instr_copen : public sp_instr
1314 {
1315 public:
sp_instr_copen(uint ip,sp_pcontext * ctx,int cursor_idx)1316   sp_instr_copen(uint ip, sp_pcontext *ctx, int cursor_idx)
1317    :sp_instr(ip, ctx),
1318     m_cursor_idx(cursor_idx)
1319   { }
1320 
1321   /////////////////////////////////////////////////////////////////////////
1322   // sp_printable implementation.
1323   /////////////////////////////////////////////////////////////////////////
1324 
1325   virtual void print(String *str);
1326 
1327   /////////////////////////////////////////////////////////////////////////
1328   // sp_instr implementation.
1329   /////////////////////////////////////////////////////////////////////////
1330 
1331   virtual bool execute(THD *thd, uint *nextp);
1332 
1333 private:
1334   /// Used to identify the cursor in the sp_rcontext.
1335   int m_cursor_idx;
1336 };
1337 
1338 ///////////////////////////////////////////////////////////////////////////
1339 
1340 /**
1341   The instruction corresponds to the CLOSE statement.
1342   It just forwards the close-call to the appropriate sp_cursor object in the
1343   sp_rcontext.
1344 */
1345 class sp_instr_cclose : public sp_instr
1346 {
1347 public:
sp_instr_cclose(uint ip,sp_pcontext * ctx,int cursor_idx)1348   sp_instr_cclose(uint ip, sp_pcontext *ctx, int cursor_idx)
1349    :sp_instr(ip, ctx),
1350     m_cursor_idx(cursor_idx)
1351   { }
1352 
1353   /////////////////////////////////////////////////////////////////////////
1354   // sp_printable implementation.
1355   /////////////////////////////////////////////////////////////////////////
1356 
1357   virtual void print(String *str);
1358 
1359   /////////////////////////////////////////////////////////////////////////
1360   // sp_instr implementation.
1361   /////////////////////////////////////////////////////////////////////////
1362 
1363   virtual bool execute(THD *thd, uint *nextp);
1364 
1365 private:
1366   /// Used to identify the cursor in the sp_rcontext.
1367   int m_cursor_idx;
1368 };
1369 
1370 ///////////////////////////////////////////////////////////////////////////
1371 
1372 /**
1373   The instruction corresponds to the FETCH statement.
1374   It just forwards the close-call to the appropriate sp_cursor object in the
1375   sp_rcontext.
1376 */
1377 class sp_instr_cfetch : public sp_instr
1378 {
1379 public:
sp_instr_cfetch(uint ip,sp_pcontext * ctx,int cursor_idx)1380   sp_instr_cfetch(uint ip, sp_pcontext *ctx, int cursor_idx)
1381    :sp_instr(ip, ctx),
1382     m_cursor_idx(cursor_idx)
1383   { }
1384 
1385   /////////////////////////////////////////////////////////////////////////
1386   // sp_printable implementation.
1387   /////////////////////////////////////////////////////////////////////////
1388 
1389   virtual void print(String *str);
1390 
1391   /////////////////////////////////////////////////////////////////////////
1392   // sp_instr implementation.
1393   /////////////////////////////////////////////////////////////////////////
1394 
1395   virtual bool execute(THD *thd, uint *nextp);
1396 
add_to_varlist(sp_variable * var)1397   void add_to_varlist(sp_variable *var)
1398   { m_varlist.push_back(var); }
1399 
1400 private:
1401   /// List of SP-variables to store fetched values.
1402   List<sp_variable> m_varlist;
1403 
1404   /// Used to identify the cursor in the sp_rcontext.
1405   int m_cursor_idx;
1406 };
1407 
1408 ///////////////////////////////////////////////////////////////////////////
1409 ///////////////////////////////////////////////////////////////////////////
1410 
1411 /**
1412   sp_instr_error just throws an SQL-condition if the execution flow comes to it.
1413   It's used in the CASE implementation to perform runtime-check that the
1414   CASE-expression is handled by some WHEN/ELSE clause.
1415 */
1416 class sp_instr_error : public sp_instr
1417 {
1418 public:
sp_instr_error(uint ip,sp_pcontext * ctx,int errcode)1419   sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
1420    :sp_instr(ip, ctx),
1421     m_errcode(errcode)
1422   { }
1423 
1424   /////////////////////////////////////////////////////////////////////////
1425   // sp_printable implementation.
1426   /////////////////////////////////////////////////////////////////////////
1427 
1428   virtual void print(String *str);
1429 
1430   /////////////////////////////////////////////////////////////////////////
1431   // sp_instr implementation.
1432   /////////////////////////////////////////////////////////////////////////
1433 
execute(THD * thd,uint * nextp)1434   virtual bool execute(THD *thd, uint *nextp)
1435   {
1436     my_message(m_errcode, ER(m_errcode), MYF(0));
1437     *nextp= get_ip() + 1;
1438     return true;
1439   }
1440 
opt_mark(sp_head * sp,List<sp_instr> * leads)1441   virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
1442   {
1443     m_marked= true;
1444     return UINT_MAX;
1445   }
1446 
1447 private:
1448   /// The error code, which should be raised by this instruction.
1449   int m_errcode;
1450 };
1451 
1452 ///////////////////////////////////////////////////////////////////////////
1453 
1454 #endif // _SP_INSTR_H_
1455