sp_head.h 20.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* -*- C++ -*- */
/* Copyright (C) 2002 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef _SP_HEAD_H_
#define _SP_HEAD_H_

21
#ifdef USE_PRAGMA_INTERFACE
22 23 24 25 26
#pragma interface			/* gcc class implementation */
#endif

#include <stddef.h>

27 28 29 30
// Values for the type enum. This reflects the order of the enum declaration
// in the CREATE TABLE command.
#define TYPE_ENUM_FUNCTION  1
#define TYPE_ENUM_PROCEDURE 2
31
#define TYPE_ENUM_TRIGGER   3
32

33 34 35
Item_result
sp_map_result_type(enum enum_field_types type);

36 37 38
bool
sp_multi_results_command(enum enum_sql_command cmd);

39
struct sp_label;
40
class sp_instr;
41
struct sp_cond_type;
42
struct sp_pvar;
43

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
class sp_name : public Sql_alloc
{
public:

  LEX_STRING m_db;
  LEX_STRING m_name;
  LEX_STRING m_qname;

  sp_name(LEX_STRING name)
    : m_name(name)
  {
    m_db.str= m_qname.str= 0;
    m_db.length= m_qname.length= 0;
  }

  sp_name(LEX_STRING db, LEX_STRING name)
    : m_db(db), m_name(name)
  {
    m_qname.str= 0;
    m_qname.length= 0;
  }

  // Init. the qualified name from the db and name.
  void init_qname(THD *thd);	// thd for memroot allocation

  ~sp_name()
  {}
};

73 74 75 76
sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name);


serg@serg.mylan's avatar
serg@serg.mylan committed
77
class sp_head :private Query_arena
78 79 80 81
{
  sp_head(const sp_head &);	/* Prevent use of these */
  void operator=(sp_head &);

82
  MEM_ROOT main_mem_root;
83 84
public:

85 86
  int m_type;			// TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
  enum enum_field_types m_returns; // For FUNCTIONs only
87
  CHARSET_INFO *m_returns_cs;	// For FUNCTIONs only
88 89 90
  TYPELIB *m_returns_typelib;	// For FUNCTIONs only
  uint m_returns_len;		// For FUNCTIONs only
  uint m_returns_pack;		// For FUNCTIONs only
91
  my_bool m_has_return;		// For FUNCTIONs only
92
  my_bool m_simple_case;	// TRUE if parsing simple case, FALSE otherwise
93
  my_bool m_multi_results;	// TRUE if a procedure with SELECT(s)
94
  my_bool m_in_handler;		// TRUE if parser in a handler body
95
  uchar *m_tmp_query;		// Temporary pointer to sub query string
96
  uint m_old_cmq;		// Old CLIENT_MULTI_QUERIES value
97
  st_sp_chistics *m_chistics;
98
  ulong m_sql_mode;		// For SHOW CREATE
99 100
  LEX_STRING m_qname;		// db.name
  LEX_STRING m_db;
101 102 103 104
  LEX_STRING m_name;
  LEX_STRING m_params;
  LEX_STRING m_body;
  LEX_STRING m_defstr;
105 106
  LEX_STRING m_definer_user;
  LEX_STRING m_definer_host;
107 108
  longlong m_created;
  longlong m_modified;
109 110 111 112 113 114 115 116
  /*
    Sets containing names of SP and SF used by this routine.

    TODO Probably we should combine these two hashes in one. It will
    decrease memory overhead ans simplify algorithms using them. The
    same applies to similar hashes in LEX.
  */
  HASH m_spfuns, m_spprocs;
117
  // Pointers set during parsing
118
  uchar *m_param_begin, *m_param_end, *m_body_begin;
119

120 121 122
  static void *
  operator new(size_t size);

123
  static void
124 125
  operator delete(void *ptr, size_t size);

126 127 128 129
  sp_head();

  // Initialize after we have reset mem_root
  void
130 131 132 133
  init(LEX *lex);

  // Initialize strings after parsing header
  void
134
  init_strings(THD *thd, LEX *lex, sp_name *name);
135

136 137 138
  TYPELIB *
  create_typelib(List<String> *src);

139 140
  int
  create(THD *thd);
141

142 143
  virtual ~sp_head();

144 145 146 147
  // Free memory
  void
  destroy();

148
  int
149 150 151 152
  execute_function(THD *thd, Item **args, uint argcount, Item **resp);

  int
  execute_procedure(THD *thd, List<Item> *args);
153

154 155 156 157 158 159
  int
  show_create_procedure(THD *thd);

  int
  show_create_function(THD *thd);

160 161
  void
  add_instr(sp_instr *instr);
162 163 164 165 166 167 168

  inline uint
  instructions()
  {
    return m_instr.elements;
  }

169 170 171 172 173 174 175 176 177
  inline sp_instr *
  last_instruction()
  {
    sp_instr *i;

    get_dynamic(&m_instr, (gptr)&i, m_instr.elements-1);
    return i;
  }

178 179 180 181 182 183 184 185 186
  // Resets lex in 'thd' and keeps a copy of the old one.
  void
  reset_lex(THD *thd);

  // Restores lex in 'thd' from our copy, but keeps some status from the
  // one in 'thd', like ptr, tables, fields, etc.
  void
  restore_lex(THD *thd);

187
  // Put the instruction on the backpatch list, associated with the label.
188
  void
189
  push_backpatch(sp_instr *, struct sp_label *);
190

191 192
  // Update all instruction with this label in the backpatch list to
  // the current position.
193
  void
194
  backpatch(struct sp_label *);
195

196 197 198 199 200 201 202
  // Check that no unresolved references exist.
  // If none found, 0 is returned, otherwise errors have been issued
  // and -1 is returned.
  // This is called by the parser at the end of a create procedure/function.
  int
  check_backpatch(THD *thd);

203 204 205
  char *name(uint *lenp = 0) const
  {
    if (lenp)
206 207
      *lenp= m_name.length;
    return m_name.str;
208 209
  }

210 211
  char *create_string(THD *thd, ulong *lenp);

212
  Field *make_field(uint max_length, const char *name, TABLE *dummy);
213

214
  void set_info(char *definer, uint definerlen,
215
		longlong created, longlong modified,
216
		st_sp_chistics *chistics, ulong sql_mode);
217

218 219 220
  void reset_thd_mem_root(THD *thd);

  void restore_thd_mem_root(THD *thd);
221

222 223 224 225 226 227 228 229 230 231 232 233 234 235
  void optimize();
  void opt_mark(uint ip);

  inline sp_instr *
  get_instr(uint i)
  {
    sp_instr *ip;

    if (i < m_instr.elements)
      get_dynamic(&m_instr, (gptr)&ip, i);
    else
      ip= NULL;
    return ip;
  }
236

237 238 239 240
  /* Add tables used by routine to the table list. */
  bool add_used_tables_to_table_list(THD *thd,
                                     TABLE_LIST ***query_tables_last_ptr);

241 242
private:

monty@mysql.com's avatar
monty@mysql.com committed
243
  MEM_ROOT *m_thd_root;		// Temp. store for thd's mem_root
244
  THD *m_thd;			// Set if we have reset mem_root
245
  char *m_thd_db;		// Original thd->db pointer
246

247
  sp_pcontext *m_pcont;		// Parse context
248
  List<LEX> m_lex;		// Temp. store for the other lex
249
  DYNAMIC_ARRAY m_instr;	// The "instructions"
250 251 252 253 254
  typedef struct
  {
    struct sp_label *lab;
    sp_instr *instr;
  } bp_t;
255
  List<bp_t> m_backpatch;	// Instructions needing backpatching
256 257 258 259 260
  /*
    Multi-set representing optimized list of tables to be locked by this
    routine. Does not include tables which are used by invoked routines.
  */
  HASH m_sptabs;
261

262 263 264
  /* Used for tracking of routine invocations and preventing recursion. */
  bool m_is_invoked;

265 266 267
  int
  execute(THD *thd);

268 269 270 271 272
  /*
    Merge the list of tables used by query into the multi-set of tables used
    by routine.
  */
  bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check);
273 274 275
}; // class sp_head : public Sql_alloc


276 277 278 279
//
// "Instructions"...
//

280
class sp_instr :public Query_arena, public Sql_alloc
281 282 283 284 285 286
{
  sp_instr(const sp_instr &);	/* Prevent use of these */
  void operator=(sp_instr &);

public:

287 288
  uint marked;
  uint m_ip;			// My index
289
  sp_pcontext *m_ctx;		// My parse context
290

291
  // Should give each a name or type code for debugging purposes?
292
  sp_instr(uint ip, sp_pcontext *ctx)
293
    :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
294 295 296
  {}

  virtual ~sp_instr()
297
  { free_items(); }
298

299 300 301
  // Execute this instrution. '*nextp' will be set to the index of the next
  // instruction to execute. (For most instruction this will be the
  // instruction following this one.)
302
  // Returns 0 on success, non-zero if some error occured.
303 304
  virtual int execute(THD *thd, uint *nextp) = 0;

305 306 307 308 309 310 311 312 313 314 315
  /*
    Execute core function of instruction after all preparations (e.g.
    setting of proper LEX, saving part of the thread context have been
    done).

    Should be implemented for instructions using expressions or whole
    statements (thus having to have own LEX). Used in concert with
    sp_lex_keeper class and its descendants.
  */
  virtual int exec_core(THD *thd, uint *nextp);

316
  virtual void print(String *str) = 0;
317

318
  virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
319
  {}
320

321 322 323 324 325 326
  virtual uint opt_mark(sp_head *sp)
  {
    marked= 1;
    return m_ip+1;
  }

327
  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
328 329 330 331 332 333 334 335
  {
    return m_ip;
  }

  virtual void opt_move(uint dst, List<sp_instr> *ibp)
  {
    m_ip= dst;
  }
336

337 338 339
}; // class sp_instr : public Sql_alloc


340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
/*
  Auxilary class to which instructions delegate responsibility
  for handling LEX and preparations before executing statement
  or calculating complex expression.

  Exist mainly to avoid having double hierarchy between instruction
  classes.

  TODO: Add ability to not store LEX and do any preparations if
        expression used is simple.
*/

class sp_lex_keeper
{
  /* Prevent use of these */
  sp_lex_keeper(const sp_lex_keeper &);
  void operator=(sp_lex_keeper &);
public:

  sp_lex_keeper(LEX *lex, bool lex_resp)
    : m_lex(lex), m_lex_resp(lex_resp)
  {
    lex->sp_lex_in_use= TRUE;
  }
  virtual ~sp_lex_keeper()
  {
    if (m_lex_resp)
      delete m_lex;
  }

  /*
    Prepare execution of instruction using LEX, if requested check whenever
    we have read access to tables used and open/lock them, call instruction's
    exec_core() method, perform cleanup afterwards.
  */
  int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
                              sp_instr* instr);

  inline uint sql_command() const
  {
    return (uint)m_lex->sql_command;
  }

383 384 385 386
  void disable_query_cache()
  {
    m_lex->safe_to_cache_query= 0;
  }
387 388 389 390 391 392 393 394 395 396 397
private:

  LEX *m_lex;
  /*
    Indicates whenever this sp_lex_keeper instance responsible
    for LEX deletion.
  */
  bool m_lex_resp;
};


398 399 400 401 402 403 404 405 406 407
//
// Call out to some prepared SQL statement.
//
class sp_instr_stmt : public sp_instr
{
  sp_instr_stmt(const sp_instr_stmt &);	/* Prevent use of these */
  void operator=(sp_instr_stmt &);

public:

408 409
  LEX_STRING m_query;		// For thd->query

410 411
  sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
    : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
412 413 414 415
  {
    m_query.str= 0;
    m_query.length= 0;
  }
416

417 418
  virtual ~sp_instr_stmt()
  {};
419

420
  virtual int execute(THD *thd, uint *nextp);
421

422
  virtual int exec_core(THD *thd, uint *nextp);
423

424
  virtual void print(String *str);
425

426 427
private:

428
  sp_lex_keeper m_lex_keeper;
429 430 431 432 433 434 435 436 437 438 439

}; // class sp_instr_stmt : public sp_instr


class sp_instr_set : public sp_instr
{
  sp_instr_set(const sp_instr_set &);	/* Prevent use of these */
  void operator=(sp_instr_set &);

public:

440
  sp_instr_set(uint ip, sp_pcontext *ctx,
441 442 443 444
	       uint offset, Item *val, enum enum_field_types type,
               LEX *lex, bool lex_resp)
    : sp_instr(ip, ctx), m_offset(offset), m_value(val), m_type(type),
      m_lex_keeper(lex, lex_resp)
445 446 447 448 449
  {}

  virtual ~sp_instr_set()
  {}

450
  virtual int execute(THD *thd, uint *nextp);
451

452 453
  virtual int exec_core(THD *thd, uint *nextp);

454 455
  virtual void print(String *str);

456 457
private:

458
  uint m_offset;		// Frame offset
459 460
  Item *m_value;
  enum enum_field_types m_type;	// The declared type
461
  sp_lex_keeper m_lex_keeper;
462 463 464

}; // class sp_instr_set : public sp_instr

465

466 467 468 469 470 471 472 473 474 475
/*
  Set NEW/OLD row field value instruction. Used in triggers.
*/
class sp_instr_set_trigger_field : public sp_instr
{
  sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
  void operator=(sp_instr_set_trigger_field &);

public:

476
  sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
477
                             Item_trigger_field *trg_fld, Item *val)
478
    : sp_instr(ip, ctx),
479
      trigger_field(trg_fld),
480 481 482 483 484 485 486 487 488 489
      value(val)
  {}

  virtual ~sp_instr_set_trigger_field()
  {}

  virtual int execute(THD *thd, uint *nextp);

  virtual void print(String *str);

490
private:
491
  Item_trigger_field *trigger_field;
492 493 494 495
  Item *value;
}; // class sp_instr_trigger_field : public sp_instr


496 497 498 499 500 501 502
class sp_instr_jump : public sp_instr
{
  sp_instr_jump(const sp_instr_jump &);	/* Prevent use of these */
  void operator=(sp_instr_jump &);

public:

503 504
  uint m_dest;			// Where we will go

505 506
  sp_instr_jump(uint ip, sp_pcontext *ctx)
    : sp_instr(ip, ctx), m_dest(0), m_optdest(0)
507 508
  {}

509 510
  sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
    : sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
511 512 513 514 515
  {}

  virtual ~sp_instr_jump()
  {}

516
  virtual int execute(THD *thd, uint *nextp);
517

518 519
  virtual void print(String *str);

520 521
  virtual uint opt_mark(sp_head *sp);

522
  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
523 524 525

  virtual void opt_move(uint dst, List<sp_instr> *ibp);

526
  virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
527
  {
528 529
    if (m_dest == 0)		// Don't reset
      m_dest= dest;
530 531
  }

532
protected:
533

534
  sp_instr *m_optdest;		// Used during optimization
535 536 537 538 539 540 541 542 543 544 545

}; // class sp_instr_jump : public sp_instr


class sp_instr_jump_if : public sp_instr_jump
{
  sp_instr_jump_if(const sp_instr_jump_if &); /* Prevent use of these */
  void operator=(sp_instr_jump_if &);

public:

546 547
  sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
    : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
548 549
  {}

550 551
  sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
    : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
552 553 554 555 556 557 558
  {}

  virtual ~sp_instr_jump_if()
  {}

  virtual int execute(THD *thd, uint *nextp);

559 560
  virtual int exec_core(THD *thd, uint *nextp);

561 562
  virtual void print(String *str);

563 564
  virtual uint opt_mark(sp_head *sp);

565
  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
566 567 568 569
  {
    return m_ip;
  }

570 571 572
private:

  Item *m_expr;			// The condition
573
  sp_lex_keeper m_lex_keeper;
574 575 576 577 578 579 580 581 582 583 584

}; // class sp_instr_jump_if : public sp_instr_jump


class sp_instr_jump_if_not : public sp_instr_jump
{
  sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */
  void operator=(sp_instr_jump_if_not &);

public:

585 586
  sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
    : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
587 588
  {}

589 590
  sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
    : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
591 592 593 594 595 596 597
  {}

  virtual ~sp_instr_jump_if_not()
  {}

  virtual int execute(THD *thd, uint *nextp);

598 599
  virtual int exec_core(THD *thd, uint *nextp);

600 601
  virtual void print(String *str);

602 603
  virtual uint opt_mark(sp_head *sp);

604
  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
605 606 607 608
  {
    return m_ip;
  }

609 610 611
private:

  Item *m_expr;			// The condition
612
  sp_lex_keeper m_lex_keeper;
613 614 615

}; // class sp_instr_jump_if_not : public sp_instr_jump

616

617
class sp_instr_freturn : public sp_instr
618
{
619 620
  sp_instr_freturn(const sp_instr_freturn &);	/* Prevent use of these */
  void operator=(sp_instr_freturn &);
621 622 623

public:

624
  sp_instr_freturn(uint ip, sp_pcontext *ctx,
625 626
		   Item *val, enum enum_field_types type, LEX *lex)
    : sp_instr(ip, ctx), m_value(val), m_type(type), m_lex_keeper(lex, TRUE)
627 628
  {}

629
  virtual ~sp_instr_freturn()
630 631 632 633
  {}

  virtual int execute(THD *thd, uint *nextp);

634 635
  virtual int exec_core(THD *thd, uint *nextp);

636 637
  virtual void print(String *str);

638 639 640 641 642 643
  virtual uint opt_mark(sp_head *sp)
  {
    marked= 1;
    return UINT_MAX;
  }

644 645 646 647
protected:

  Item *m_value;
  enum enum_field_types m_type;
648
  sp_lex_keeper m_lex_keeper;
649

650 651 652 653 654 655 656 657 658 659
}; // class sp_instr_freturn : public sp_instr


class sp_instr_hpush_jump : public sp_instr_jump
{
  sp_instr_hpush_jump(const sp_instr_hpush_jump &); /* Prevent use of these */
  void operator=(sp_instr_hpush_jump &);

public:

660 661
  sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
    : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp)
662 663 664 665 666 667 668 669 670 671 672 673
  {
    m_handler= ip+1;
    m_cond.empty();
  }

  virtual ~sp_instr_hpush_jump()
  {
    m_cond.empty();
  }

  virtual int execute(THD *thd, uint *nextp);

674 675
  virtual void print(String *str);

676 677
  virtual uint opt_mark(sp_head *sp);

678
  virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
679 680 681 682
  {
    return m_ip;
  }

683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
  inline void add_condition(struct sp_cond_type *cond)
  {
    m_cond.push_front(cond);
  }

private:

  int m_type;			// Handler type
  uint m_frame;
  uint m_handler;		// Location of handler
  List<struct sp_cond_type> m_cond;

}; // class sp_instr_hpush_jump : public sp_instr_jump


class sp_instr_hpop : public sp_instr
{
  sp_instr_hpop(const sp_instr_hpop &);	/* Prevent use of these */
  void operator=(sp_instr_hpop &);

public:

705 706
  sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
    : sp_instr(ip, ctx), m_count(count)
707 708 709 710 711 712 713
  {}

  virtual ~sp_instr_hpop()
  {}

  virtual int execute(THD *thd, uint *nextp);

714 715
  virtual void print(String *str);

716
  virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
717 718 719 720 721 722 723 724

  virtual uint opt_mark(sp_head *sp)
  {
    if (m_count)
      marked= 1;
    return m_ip+1;
  }

725 726 727 728 729 730 731
private:

  uint m_count;

}; // class sp_instr_hpop : public sp_instr


732
class sp_instr_hreturn : public sp_instr_jump
733 734 735 736 737 738
{
  sp_instr_hreturn(const sp_instr_hreturn &);	/* Prevent use of these */
  void operator=(sp_instr_hreturn &);

public:

739
  sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
740
    : sp_instr_jump(ip, ctx), m_frame(fp)
741 742 743 744 745 746 747
  {}

  virtual ~sp_instr_hreturn()
  {}

  virtual int execute(THD *thd, uint *nextp);

748 749
  virtual void print(String *str);

750
  virtual uint opt_mark(sp_head *sp);
751

752 753 754 755 756 757
private:

  uint m_frame;

}; // class sp_instr_hreturn : public sp_instr

758

759 760 761 762 763 764 765
class sp_instr_cpush : public sp_instr
{
  sp_instr_cpush(const sp_instr_cpush &); /* Prevent use of these */
  void operator=(sp_instr_cpush &);

public:

766
  sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
767
    : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
768 769
  {}

770 771
  virtual ~sp_instr_cpush()
  {}
772 773 774

  virtual int execute(THD *thd, uint *nextp);

775 776
  virtual void print(String *str);

777 778
private:

779
  sp_lex_keeper m_lex_keeper;
780 781 782 783 784 785 786 787 788 789 790

}; // class sp_instr_cpush : public sp_instr


class sp_instr_cpop : public sp_instr
{
  sp_instr_cpop(const sp_instr_cpop &); /* Prevent use of these */
  void operator=(sp_instr_cpop &);

public:

791 792
  sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
    : sp_instr(ip, ctx), m_count(count)
793 794 795 796 797 798 799
  {}

  virtual ~sp_instr_cpop()
  {}

  virtual int execute(THD *thd, uint *nextp);

800 801
  virtual void print(String *str);

802
  virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
803 804 805 806 807 808 809 810

  virtual uint opt_mark(sp_head *sp)
  {
    if (m_count)
      marked= 1;
    return m_ip+1;
  }

811 812 813 814 815 816 817
private:

  uint m_count;

}; // class sp_instr_cpop : public sp_instr


818
class sp_instr_copen : public sp_instr
819 820 821 822 823 824
{
  sp_instr_copen(const sp_instr_copen &); /* Prevent use of these */
  void operator=(sp_instr_copen &);

public:

825
  sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
826
    : sp_instr(ip, ctx), m_cursor(c)
827 828 829 830 831 832 833
  {}

  virtual ~sp_instr_copen()
  {}

  virtual int execute(THD *thd, uint *nextp);

834 835
  virtual int exec_core(THD *thd, uint *nextp);

836 837
  virtual void print(String *str);

838 839 840 841 842 843 844 845 846 847 848 849 850 851
private:

  uint m_cursor;		// Stack index

}; // class sp_instr_copen : public sp_instr_stmt


class sp_instr_cclose : public sp_instr
{
  sp_instr_cclose(const sp_instr_cclose &); /* Prevent use of these */
  void operator=(sp_instr_cclose &);

public:

852 853
  sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
    : sp_instr(ip, ctx), m_cursor(c)
854 855 856 857 858 859 860
  {}

  virtual ~sp_instr_cclose()
  {}

  virtual int execute(THD *thd, uint *nextp);

861 862
  virtual void print(String *str);

863 864 865 866 867 868 869 870 871 872 873 874 875 876
private:

  uint m_cursor;

}; // class sp_instr_cclose : public sp_instr


class sp_instr_cfetch : public sp_instr
{
  sp_instr_cfetch(const sp_instr_cfetch &); /* Prevent use of these */
  void operator=(sp_instr_cfetch &);

public:

877 878
  sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c)
    : sp_instr(ip, ctx), m_cursor(c)
879 880 881 882 883 884 885 886 887
  {
    m_varlist.empty();
  }

  virtual ~sp_instr_cfetch()
  {}

  virtual int execute(THD *thd, uint *nextp);

888 889
  virtual void print(String *str);

890 891 892 893 894 895 896 897 898 899 900 901 902
  void add_to_varlist(struct sp_pvar *var)
  {
    m_varlist.push_back(var);
  }

private:

  uint m_cursor;
  List<struct sp_pvar> m_varlist;

}; // class sp_instr_cfetch : public sp_instr


903 904 905 906 907 908 909
class sp_instr_error : public sp_instr
{
  sp_instr_error(const sp_instr_error &); /* Prevent use of these */
  void operator=(sp_instr_error &);

public:

910 911
  sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
    : sp_instr(ip, ctx), m_errcode(errcode)
912 913 914 915 916 917 918 919 920
  {}

  virtual ~sp_instr_error()
  {}

  virtual int execute(THD *thd, uint *nextp);

  virtual void print(String *str);

921 922 923 924 925 926
  virtual uint opt_mark(sp_head *sp)
  {
    marked= 1;
    return UINT_MAX;
  }

927 928 929 930 931 932 933
private:

  int m_errcode;

}; // class sp_instr_error : public sp_instr


934 935 936 937 938 939 940 941 942 943 944 945
struct st_sp_security_context
{
  bool changed;
  uint master_access;
  uint db_access;
  char *priv_user;
  char priv_host[MAX_HOSTNAME];
  char *user;
  char *host;
  char *ip;
};

946
#ifndef NO_EMBEDDED_ACCESS_CHECKS
947 948 949 950
void
sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp);
void
sp_restore_security_context(THD *thd, sp_head *sp,st_sp_security_context *ctxp);
951
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
952

953 954 955 956
TABLE_LIST *
sp_add_to_query_tables(THD *thd, LEX *lex,
		       const char *db, const char *name,
		       thr_lock_type locktype);
957 958
bool
sp_add_sp_tables_to_table_list(THD *thd, LEX *lex, LEX *func_lex);
959

960
#endif /* _SP_HEAD_H_ */