MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sp_instr.h
1 /* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #ifndef _SP_INSTR_H_
17 #define _SP_INSTR_H_
18 
19 #include "my_global.h" // NO_EMBEDDED_ACCESS_CHECKS
20 #include "sp_pcontext.h" // sp_pcontext
21 #include "sql_class.h" // THD
22 #include "sp_head.h" // sp_printable
23 
25 // This file contains SP-instruction classes.
27 
33 {
34 public:
41  virtual void set_destination(uint old_dest, uint new_dest) = 0;
42 
49  virtual void backpatch(uint dest) = 0;
50 
51  virtual ~sp_branch_instr()
52  { }
53 };
54 
56 
61 class sp_instr : public Query_arena,
62  public Sql_alloc,
63  public sp_printable
64 {
65 public:
66  sp_instr(uint ip, sp_pcontext *ctx)
67  :Query_arena(0, STMT_INITIALIZED_FOR_SP),
68  m_marked(false),
69  m_ip(ip),
70  m_parsing_ctx(ctx)
71  { }
72 
73  virtual ~sp_instr()
74  { free_items(); }
75 
88  virtual bool execute(THD *thd, uint *nextp) = 0;
89 
90  uint get_ip() const
91  { return m_ip; }
92 
98  virtual uint get_cont_dest() const
99  { return get_ip() + 1; }
100 
101  sp_pcontext *get_parsing_ctx() const
102  { return m_parsing_ctx; }
103 
105  // The following operations are used solely for SP-code-optimizer.
107 
113  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
114  {
115  m_marked= true;
116  return get_ip() + 1;
117  }
118 
125  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
126  { return get_ip(); }
127 
134  virtual void opt_move(uint dst, List<sp_branch_instr> *ibp)
135  { m_ip= dst; }
136 
137  bool opt_is_marked() const
138  { return m_marked; }
139 
140 protected:
143  bool m_marked;
144 
146  uint m_ip;
147 
150 
151 private:
152  // Prevent use of copy constructor and assignment operator.
153  sp_instr(const sp_instr &);
154  void operator= (sp_instr &);
155 };
156 
158 
168 class sp_lex_instr : public sp_instr
169 {
170 public:
171  sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner)
172  :sp_instr(ip, ctx),
173  m_lex(NULL),
174  m_is_lex_owner(false),
175  m_first_execution(true),
176  m_prelocking_tables(NULL),
177  m_lex_query_tables_own_last(NULL)
178  {
179  set_lex(lex, is_lex_owner);
180  memset(&m_lex_mem_root, 0, sizeof (MEM_ROOT));
181  }
182 
183  virtual ~sp_lex_instr()
184  {
185  free_lex();
186  /*
187  If the instruction is reparsed, m_lex_mem_root was used to allocate the
188  items, then freeing the memroot, frees the items. Hence set the free_list
189  pointer to NULL.
190  */
191  if (alloc_root_inited(&m_lex_mem_root))
192  free_list= NULL;
193  free_root(&m_lex_mem_root, MYF(0));
194  }
195 
215  bool validate_lex_and_execute_core(THD *thd, uint *nextp, bool open_tables);
216 
217 private:
236  bool reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables);
237 
247  LEX *parse_expr(THD *thd, sp_head *sp);
248 
259  void set_lex(LEX *lex, bool is_lex_owner);
260 
264  void free_lex();
265 
266 public:
268  // sp_instr implementation.
270 
271  virtual bool execute(THD *thd, uint *nextp)
272  { return validate_lex_and_execute_core(thd, nextp, true); }
273 
274 protected:
276  // Interface (virtual) methods.
278 
288  virtual bool exec_core(THD *thd, uint *nextp) = 0;
289 
298  virtual bool is_invalid() const = 0;
299 
303  virtual void invalidate() = 0;
304 
311  virtual void get_query(String *sql_query) const;
312 
323  virtual LEX_STRING get_expr_query() const
324  { return EMPTY_STR; }
325 
336  virtual bool on_after_expr_parsing(THD *thd)
337  { return false; }
338 
345  virtual void cleanup_before_parsing(THD *thd);
346 
347 private:
353  MEM_ROOT m_lex_mem_root;
354 
356  LEX *m_lex;
357 
362  bool m_is_lex_owner;
363 
368  bool m_first_execution;
369 
370  /*****************************************************************************
371  Support for being able to execute this statement in two modes:
372  a) inside prelocked mode set by the calling procedure or its ancestor.
373  b) outside of prelocked mode, when this statement enters/leaves
374  prelocked mode itself.
375  *****************************************************************************/
376 
381  TABLE_LIST *m_prelocking_tables;
382 
387  TABLE_LIST **m_lex_query_tables_own_last;
388 };
389 
391 
400 {
401 public:
402  sp_instr_stmt(uint ip,
403  LEX *lex,
405  :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
406  m_query(query),
407  m_valid(true)
408  { }
409 
411  // sp_instr implementation.
413 
414  virtual bool execute(THD *thd, uint *nextp);
415 
417  // sp_printable implementation.
419 
420  virtual void print(String *str);
421 
423  // sp_lex_instr implementation.
425 
426  virtual bool exec_core(THD *thd, uint *nextp);
427 
428  virtual bool is_invalid() const
429  { return !m_valid; }
430 
431  virtual void invalidate()
432  { m_valid= false; }
433 
434  virtual void get_query(String *sql_query) const
435  { sql_query->append(m_query.str, m_query.length); }
436 
437  virtual bool on_after_expr_parsing(THD *thd)
438  {
439  m_valid= true;
440  return false;
441  }
442 
443 private:
445  LEX_STRING m_query;
446 
448  bool m_valid;
449 };
450 
452 
457 {
458 public:
459  sp_instr_set(uint ip,
460  LEX *lex,
461  uint offset,
462  Item *value_item,
463  LEX_STRING value_query,
464  bool is_lex_owner)
465  :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, is_lex_owner),
466  m_offset(offset),
467  m_value_item(value_item),
468  m_value_query(value_query)
469  { }
470 
472  // sp_printable implementation.
474 
475  virtual void print(String *str);
476 
478  // sp_lex_instr implementation.
480 
481  virtual bool exec_core(THD *thd, uint *nextp);
482 
483  virtual bool is_invalid() const
484  { return m_value_item == NULL; }
485 
486  virtual void invalidate()
487  { m_value_item= NULL; }
488 
489  virtual bool on_after_expr_parsing(THD *thd)
490  {
491  DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
492 
493  m_value_item= thd->lex->select_lex.item_list.head();
494 
495  return false;
496  }
497 
498  virtual LEX_STRING get_expr_query() const
499  { return m_value_query; }
500 
501 private:
503  uint m_offset;
504 
506  Item *m_value_item;
507 
509  LEX_STRING m_value_query;
510 };
511 
513 
519 {
520 public:
522  LEX *lex,
523  LEX_STRING trigger_field_name,
524  Item_trigger_field *trigger_field,
525  Item *value_item,
526  LEX_STRING value_query)
527  :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
528  m_trigger_field_name(trigger_field_name),
529  m_trigger_field(trigger_field),
530  m_value_item(value_item),
531  m_value_query(value_query)
532  { }
533 
535  // sp_printable implementation.
537 
538  virtual void print(String *str);
539 
541  // sp_lex_instr implementation.
543 
544  virtual bool exec_core(THD *thd, uint *nextp);
545 
546  virtual bool is_invalid() const
547  { return m_value_item == NULL; }
548 
549  virtual void invalidate()
550  { m_value_item= NULL; }
551 
552  virtual bool on_after_expr_parsing(THD *thd);
553 
554  virtual void cleanup_before_parsing(THD *thd);
555 
556  virtual LEX_STRING get_expr_query() const
557  { return m_value_query; }
558 
559 private:
561  LEX_STRING m_trigger_field_name;
562 
564  Item_trigger_field *m_trigger_field;
565 
567  Item *m_value_item;
568 
570  LEX_STRING m_value_query;
571 };
572 
574 
579 {
580 public:
581  sp_instr_freturn(uint ip,
582  LEX *lex,
583  Item *expr_item,
584  LEX_STRING expr_query,
585  enum enum_field_types return_field_type)
586  :sp_lex_instr(ip, lex->get_sp_current_parsing_ctx(), lex, true),
587  m_expr_item(expr_item),
588  m_expr_query(expr_query),
589  m_return_field_type(return_field_type)
590  { }
591 
593  // sp_printable implementation.
595 
596  virtual void print(String *str);
597 
599  // sp_instr implementation.
601 
602  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
603  {
604  m_marked= true;
605  return UINT_MAX;
606  }
607 
609  // sp_lex_instr implementation.
611 
612  virtual bool exec_core(THD *thd, uint *nextp);
613 
614  virtual bool is_invalid() const
615  { return m_expr_item == NULL; }
616 
617  virtual void invalidate()
618  {
619  // it's already deleted.
620  m_expr_item= NULL;
621  }
622 
623  virtual bool on_after_expr_parsing(THD *thd)
624  {
625  DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
626 
627  m_expr_item= thd->lex->select_lex.item_list.head();
628 
629  return false;
630  }
631 
632  virtual LEX_STRING get_expr_query() const
633  { return m_expr_query; }
634 
635 private:
637  Item *m_expr_item;
638 
640  LEX_STRING m_expr_query;
641 
643  enum enum_field_types m_return_field_type;
644 };
645 
647 
658 class sp_instr_jump : public sp_instr,
659  public sp_branch_instr
660 {
661 public:
662  sp_instr_jump(uint ip, sp_pcontext *ctx)
663  :sp_instr(ip, ctx),
664  m_dest(0),
665  m_optdest(NULL)
666  { }
667 
668  sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
669  :sp_instr(ip, ctx),
670  m_dest(dest),
671  m_optdest(NULL)
672  { }
673 
675  // sp_printable implementation.
677 
678  virtual void print(String *str);
679 
681  // sp_instr implementation.
683 
684  virtual bool execute(THD *thd, uint *nextp)
685  {
686  *nextp= m_dest;
687  return false;
688  }
689 
690  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
691 
692  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
693 
694  virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
695 
697  // sp_branch_instr implementation.
699 
700  virtual void set_destination(uint old_dest, uint new_dest)
701  {
702  if (m_dest == old_dest)
703  m_dest= new_dest;
704  }
705 
706  virtual void backpatch(uint dest)
707  {
708  /* Calling backpatch twice is a logic flaw in jump resolution. */
709  DBUG_ASSERT(m_dest == 0);
710  m_dest= dest;
711  }
712 
713 protected:
715  uint m_dest;
716 
717  // The following attribute is used by SP-optimizer.
718  sp_instr *m_optdest;
719 };
720 
722 
728  public sp_branch_instr
729 {
730 protected:
731  sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex,
732  Item *expr_item, LEX_STRING expr_query)
733  :sp_lex_instr(ip, ctx, lex, true),
734  m_dest(0),
735  m_cont_dest(0),
736  m_optdest(NULL),
737  m_cont_optdest(NULL),
738  m_expr_item(expr_item),
739  m_expr_query(expr_query)
740  { }
741 
742  sp_lex_branch_instr(uint ip, sp_pcontext *ctx, LEX *lex,
743  Item *expr_item, LEX_STRING expr_query,
744  uint dest)
745  :sp_lex_instr(ip, ctx, lex, true),
746  m_dest(dest),
747  m_cont_dest(0),
748  m_optdest(NULL),
749  m_cont_optdest(NULL),
750  m_expr_item(expr_item),
751  m_expr_query(expr_query)
752  { }
753 
754 public:
755  void set_cont_dest(uint cont_dest)
756  { m_cont_dest= cont_dest; }
757 
759  // sp_instr implementation.
761 
762  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
763 
764  virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
765 
766  virtual uint get_cont_dest() const
767  { return m_cont_dest; }
768 
770  // sp_lex_instr implementation.
772 
773  virtual bool is_invalid() const
774  { return m_expr_item == NULL; }
775 
776  virtual void invalidate()
777  { m_expr_item= NULL; /* it's already deleted. */ }
778 
779  virtual LEX_STRING get_expr_query() const
780  { return m_expr_query; }
781 
783  // sp_branch_instr implementation.
785 
786  virtual void set_destination(uint old_dest, uint new_dest)
787  {
788  if (m_dest == old_dest)
789  m_dest= new_dest;
790 
791  if (m_cont_dest == old_dest)
792  m_cont_dest= new_dest;
793  }
794 
795  virtual void backpatch(uint dest)
796  {
797  /* Calling backpatch twice is a logic flaw in jump resolution. */
798  DBUG_ASSERT(m_dest == 0);
799  m_dest= dest;
800  }
801 
802 protected:
804  uint m_dest;
805 
808 
809  // The following attributes are used by SP-optimizer.
810  sp_instr *m_optdest;
811  sp_instr *m_cont_optdest;
812 
815 
818 };
819 
821 
827 {
828 public:
829  sp_instr_jump_if_not(uint ip,
830  LEX *lex,
831  Item *expr_item,
832  LEX_STRING expr_query)
833  :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
834  expr_item, expr_query)
835  { }
836 
837  sp_instr_jump_if_not(uint ip,
838  LEX *lex,
839  Item *expr_item,
840  LEX_STRING expr_query,
841  uint dest)
842  :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
843  expr_item, expr_query, dest)
844  { }
845 
847  // sp_printable implementation.
849 
850  virtual void print(String *str);
851 
853  // sp_lex_instr implementation.
855 
856  virtual bool exec_core(THD *thd, uint *nextp);
857 
858  virtual bool on_after_expr_parsing(THD *thd)
859  {
860  DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
861 
862  m_expr_item= thd->lex->select_lex.item_list.head();
863 
864  return false;
865  }
866 };
867 
869 // Instructions used for the "simple CASE" implementation.
871 
877 {
878 public:
879  sp_instr_set_case_expr(uint ip,
880  LEX *lex,
881  uint case_expr_id,
882  Item *case_expr_item,
883  LEX_STRING case_expr_query)
884  :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
885  case_expr_item, case_expr_query),
886  m_case_expr_id(case_expr_id)
887  { }
888 
890  // sp_printable implementation.
892 
893  virtual void print(String *str);
894 
896  // sp_instr implementation.
898 
899  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
900 
901  virtual void opt_move(uint dst, List<sp_branch_instr> *ibp);
902 
904  // sp_branch_instr implementation.
906 
907  /*
908  NOTE: set_destination() and backpatch() are overriden here just because the
909  m_dest attribute is not used by this class, so there is no need to do
910  anything about it.
911 
912  @todo These operations probably should be left as they are (i.e. do not
913  override them here). The m_dest attribute would be set and not used, but
914  that should not be a big deal.
915 
916  @todo This also indicates deficiency of the current SP-istruction class
917  hierarchy.
918  */
919 
920  virtual void set_destination(uint old_dest, uint new_dest)
921  {
922  if (m_cont_dest == old_dest)
923  m_cont_dest= new_dest;
924  }
925 
926  virtual void backpatch(uint dest)
927  { }
928 
930  // sp_lex_instr implementation.
932 
933  virtual bool exec_core(THD *thd, uint *nextp);
934 
935  virtual bool on_after_expr_parsing(THD *thd)
936  {
937  DBUG_ASSERT(thd->lex->select_lex.item_list.elements == 1);
938 
939  m_expr_item= thd->lex->select_lex.item_list.head();
940 
941  return false;
942  }
943 
944 private:
946  uint m_case_expr_id;
947 };
948 
950 
959 {
960 public:
961  sp_instr_jump_case_when(uint ip,
962  LEX *lex,
963  int case_expr_id,
964  Item *when_expr_item,
965  LEX_STRING when_expr_query)
966  :sp_lex_branch_instr(ip, lex->get_sp_current_parsing_ctx(), lex,
967  when_expr_item, when_expr_query),
968  m_case_expr_id(case_expr_id)
969  { }
970 
972  // sp_printable implementation.
974 
975  virtual void print(String *str);
976 
978  // sp_lex_instr implementation.
980 
981  virtual bool exec_core(THD *thd, uint *nextp);
982 
983  virtual void invalidate()
984  {
985  // Items should be already deleted in lex-keeper.
986  m_case_expr_item= NULL;
987  m_eq_item= NULL;
988  m_expr_item= NULL; // it's a WHEN-expression.
989  }
990 
991  virtual bool on_after_expr_parsing(THD *thd)
992  { return build_expr_items(thd); }
993 
994 private:
1015  bool build_expr_items(THD *thd);
1016 
1017 private:
1019  int m_case_expr_id;
1020 
1022  Item_case_expr *m_case_expr_item;
1023 
1029  Item *m_eq_item;
1030 };
1031 
1033 // SQL-condition handler instructions.
1035 
1037 {
1038 public:
1039  sp_instr_hpush_jump(uint ip,
1040  sp_pcontext *ctx,
1042  :sp_instr_jump(ip, ctx),
1043  m_handler(handler),
1044  m_opt_hpop(0),
1045  m_frame(ctx->current_var_count())
1046  {
1047  DBUG_ASSERT(m_handler->condition_values.elements == 0);
1048  }
1049 
1050  virtual ~sp_instr_hpush_jump()
1051  {
1052  m_handler->condition_values.empty();
1053  m_handler= NULL;
1054  }
1055 
1056  void add_condition(sp_condition_value *condition_value)
1057  { m_handler->condition_values.push_back(condition_value); }
1058 
1059  sp_handler *get_handler()
1060  { return m_handler; }
1061 
1063  // sp_printable implementation.
1065 
1066  virtual void print(String *str);
1067 
1069  // sp_instr implementation.
1071 
1072  virtual bool execute(THD *thd, uint *nextp);
1073 
1074  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
1075 
1077  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
1078  { return get_ip(); }
1079 
1081  // sp_branch_instr implementation.
1083 
1084  virtual void backpatch(uint dest)
1085  {
1086  DBUG_ASSERT(!m_dest || !m_opt_hpop);
1087  if (!m_dest)
1088  m_dest= dest;
1089  else
1090  m_opt_hpop= dest;
1091  }
1092 
1093 private:
1095  sp_handler *m_handler;
1096 
1098  uint m_opt_hpop;
1099 
1100  // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
1101  // debug version only). It's used in print().
1102  uint m_frame;
1103 };
1104 
1106 
1107 class sp_instr_hpop : public sp_instr
1108 {
1109 public:
1110  sp_instr_hpop(uint ip, sp_pcontext *ctx)
1111  : sp_instr(ip, ctx)
1112  { }
1113 
1115  // sp_printable implementation.
1117 
1118  virtual void print(String *str)
1119  { str->append(STRING_WITH_LEN("hpop")); }
1120 
1122  // sp_instr implementation.
1124 
1125  virtual bool execute(THD *thd, uint *nextp);
1126 };
1127 
1129 
1131 {
1132 public:
1133  sp_instr_hreturn(uint ip, sp_pcontext *ctx)
1134  :sp_instr_jump(ip, ctx),
1135  m_frame(ctx->current_var_count())
1136  { }
1137 
1139  // sp_printable implementation.
1141 
1142  virtual void print(String *str);
1143 
1145  // sp_instr implementation.
1147 
1148  virtual bool execute(THD *thd, uint *nextp);
1149 
1151  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
1152  { return get_ip(); }
1153 
1154  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
1155 
1156 private:
1157  // This attribute is needed for SHOW PROCEDURE CODE only (i.e. it's needed in
1158  // debug version only). It's used in print().
1159  uint m_frame;
1160 };
1161 
1163 // Cursor implementation.
1165 
1184 {
1185 public:
1186  sp_instr_cpush(uint ip,
1187  sp_pcontext *ctx,
1188  LEX *cursor_lex,
1189  LEX_STRING cursor_query,
1190  int cursor_idx)
1191  :sp_lex_instr(ip, ctx, cursor_lex, true),
1192  m_cursor_query(cursor_query),
1193  m_valid(true),
1194  m_cursor_idx(cursor_idx)
1195  {
1196  // Cursor can't be stored in Query Cache, so we should prevent opening QC
1197  // for try to write results which are absent.
1198 
1199  cursor_lex->safe_to_cache_query= false;
1200  }
1201 
1203  // sp_printable implementation.
1205 
1206  virtual void print(String *str);
1207 
1209  // Query_arena implementation.
1211 
1217  virtual void cleanup_stmt()
1218  { /* no op */ }
1219 
1221  // sp_instr implementation.
1223 
1224  virtual bool execute(THD *thd, uint *nextp);
1225 
1227  // sp_lex_instr implementation.
1229 
1230  virtual bool exec_core(THD *thd, uint *nextp);
1231 
1232  virtual bool is_invalid() const
1233  { return !m_valid; }
1234 
1235  virtual void invalidate()
1236  { m_valid= false; }
1237 
1238  virtual void get_query(String *sql_query) const
1239  { sql_query->append(m_cursor_query.str, m_cursor_query.length); }
1240 
1241  virtual bool on_after_expr_parsing(THD *thd)
1242  {
1243  m_valid= true;
1244  return false;
1245  }
1246 
1247 private:
1249  LEX_STRING m_cursor_query;
1250 
1253  bool m_valid;
1254 
1256  int m_cursor_idx;
1257 };
1258 
1260 
1265 class sp_instr_cpop : public sp_instr
1266 {
1267 public:
1268  sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
1269  :sp_instr(ip, ctx),
1270  m_count(count)
1271  { }
1272 
1274  // sp_printable implementation.
1276 
1277  virtual void print(String *str);
1278 
1280  // sp_instr implementation.
1282 
1283  virtual bool execute(THD *thd, uint *nextp);
1284 
1285 private:
1286  uint m_count;
1287 };
1288 
1290 
1295 class sp_instr_copen : public sp_instr
1296 {
1297 public:
1298  sp_instr_copen(uint ip, sp_pcontext *ctx, int cursor_idx)
1299  :sp_instr(ip, ctx),
1300  m_cursor_idx(cursor_idx)
1301  { }
1302 
1304  // sp_printable implementation.
1306 
1307  virtual void print(String *str);
1308 
1310  // sp_instr implementation.
1312 
1313  virtual bool execute(THD *thd, uint *nextp);
1314 
1315 private:
1317  int m_cursor_idx;
1318 };
1319 
1321 
1328 {
1329 public:
1330  sp_instr_cclose(uint ip, sp_pcontext *ctx, int cursor_idx)
1331  :sp_instr(ip, ctx),
1332  m_cursor_idx(cursor_idx)
1333  { }
1334 
1336  // sp_printable implementation.
1338 
1339  virtual void print(String *str);
1340 
1342  // sp_instr implementation.
1344 
1345  virtual bool execute(THD *thd, uint *nextp);
1346 
1347 private:
1349  int m_cursor_idx;
1350 };
1351 
1353 
1360 {
1361 public:
1362  sp_instr_cfetch(uint ip, sp_pcontext *ctx, int cursor_idx)
1363  :sp_instr(ip, ctx),
1364  m_cursor_idx(cursor_idx)
1365  { }
1366 
1368  // sp_printable implementation.
1370 
1371  virtual void print(String *str);
1372 
1374  // sp_instr implementation.
1376 
1377  virtual bool execute(THD *thd, uint *nextp);
1378 
1379  void add_to_varlist(sp_variable *var)
1380  { m_varlist.push_back(var); }
1381 
1382 private:
1384  List<sp_variable> m_varlist;
1385 
1387  int m_cursor_idx;
1388 };
1389 
1392 
1398 class sp_instr_error : public sp_instr
1399 {
1400 public:
1401  sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
1402  :sp_instr(ip, ctx),
1403  m_errcode(errcode)
1404  { }
1405 
1407  // sp_printable implementation.
1409 
1410  virtual void print(String *str);
1411 
1413  // sp_instr implementation.
1415 
1416  virtual bool execute(THD *thd, uint *nextp)
1417  {
1418  my_message(m_errcode, ER(m_errcode), MYF(0));
1419  *nextp= get_ip() + 1;
1420  return true;
1421  }
1422 
1423  virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
1424  {
1425  m_marked= true;
1426  return UINT_MAX;
1427  }
1428 
1429 private:
1431  int m_errcode;
1432 };
1433 
1435 
1436 #endif // _SP_INSTR_H_