sp_head.h 6.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/* -*- 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_

#ifdef __GNUC__
#pragma interface			/* gcc class implementation */
#endif

#include <stddef.h>

27 28
struct sp_label;

29 30 31 32 33 34 35 36 37
class sp_instr;

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

public:

38
  my_bool m_simple_case;	// TRUE if parsing simple case, FALSE otherwise
39 40
  List<Item_string> m_calls;	// Called procedures.
  List<char *> m_tables;	// Used tables.
41

42 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 73 74 75 76 77 78 79 80
  static void *operator new(size_t size)
  {
    return (void*) sql_alloc((uint) size);
  }

  static void operator delete(void *ptr, size_t size)
  {
    /* Empty */
  }

  sp_head(LEX_STRING *name, LEX* lex);

  int
  create(THD *thd);
  
  int
  execute(THD *thd);

  inline void
  add_instr(sp_instr *i)
  {
    insert_dynamic(&m_instr, (gptr)&i);
  }

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

  // 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);

81
  // Put the instruction on the backpatch list, associated with the label.
82
  void
83
  push_backpatch(sp_instr *, struct sp_label *);
84

85 86
  // Update all instruction with this label in the backpatch list to
  // the current position.
87
  void
88
  backpatch(struct sp_label *);
89

90 91 92 93
private:

  Item_string *m_name;
  Item_string *m_defstr;
94
  LEX *m_call_lex;		// The CALL's own lex
95 96
  LEX m_lex;			// Temp. store for the other lex
  DYNAMIC_ARRAY m_instr;	// The "instructions"
97 98 99 100 101 102
  typedef struct
  {
    struct sp_label *lab;
    sp_instr *instr;
  } bp_t;
  List<bp_t> m_backpatch;	// Instructions needing backpaching
103 104 105 106 107 108 109 110 111 112 113 114 115

  inline sp_instr *
  get_instr(uint i)
  {
    sp_instr *in= NULL;

    get_dynamic(&m_instr, (gptr)&in, i);
    return in;
  }

}; // class sp_head : public Sql_alloc


116 117 118 119
//
// "Instructions"...
//

120 121 122 123 124 125 126 127
class sp_instr : public Sql_alloc
{
  sp_instr(const sp_instr &);	/* Prevent use of these */
  void operator=(sp_instr &);

public:

  // Should give each a name or type code for debugging purposes?
128 129
  sp_instr(uint ip)
    : Sql_alloc(), m_ip(ip)
130 131 132 133 134
  {}

  virtual ~sp_instr()
  {}

135 136 137
  // 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.)
138 139
  // Returns 0 on success, non-zero if some error occured.
  virtual int
140
  execute(THD *thd, uint *nextp)
141
  {				// Default is a no-op.
142
    *nextp = m_ip+1;		// Next instruction
143 144 145
    return 0;
  }

146 147 148 149
protected:

  uint m_ip;			// My index

150 151 152 153 154 155 156 157 158 159 160 161 162
}; // class sp_instr : public Sql_alloc


//
// 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:

163 164
  sp_instr_stmt(uint ip)
    : sp_instr(ip)
165 166 167 168 169
  {}

  virtual ~sp_instr_stmt()
  {}

170
  virtual int execute(THD *thd, uint *nextp);
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

  inline void
  set_lex(LEX *lex)
  {
    memcpy(&m_lex, lex, sizeof(LEX));
  }

  inline LEX *
  get_lex()
  {
    return &m_lex;
  }

private:

  LEX m_lex;			// My own lex

}; // 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:

198 199
  sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
    : sp_instr(ip), m_offset(offset), m_value(val), m_type(type)
200 201 202 203 204
  {}

  virtual ~sp_instr_set()
  {}

205
  virtual int execute(THD *thd, uint *nextp);
206 207 208

private:

209
  uint m_offset;		// Frame offset
210 211 212 213 214
  Item *m_value;
  enum enum_field_types m_type;	// The declared type

}; // class sp_instr_set : public sp_instr

215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

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

public:

  sp_instr_jump(uint ip)
    : sp_instr(ip)
  {}

  sp_instr_jump(uint ip, uint dest)
    : sp_instr(ip), m_dest(dest)
  {}

  virtual ~sp_instr_jump()
  {}

  virtual int execute(THD *thd, uint *nextp)
  {
    *nextp= m_dest;
    return 0;
  }

  virtual void
  set_destination(uint dest)
  {
    m_dest= dest;
  }

246
protected:
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

  int m_dest;			// Where we will go

}; // 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:

  sp_instr_jump_if(uint ip, Item *i)
    : sp_instr_jump(ip), m_expr(i)
  {}

  sp_instr_jump_if(uint ip, Item *i, uint dest)
    : sp_instr_jump(ip, dest), m_expr(i)
  {}

  virtual ~sp_instr_jump_if()
  {}

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

private:

  Item *m_expr;			// The condition

}; // 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:

  sp_instr_jump_if_not(uint ip, Item *i)
    : sp_instr_jump(ip), m_expr(i)
  {}

  sp_instr_jump_if_not(uint ip, Item *i, uint dest)
    : sp_instr_jump(ip, dest), m_expr(i)
  {}

  virtual ~sp_instr_jump_if_not()
  {}

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

private:

  Item *m_expr;			// The condition

}; // class sp_instr_jump_if_not : public sp_instr_jump

306
#endif /* _SP_HEAD_H_ */