~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/sp_pcontext.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- C++ -*- */
 
2
/* Copyright (C) 2002 MySQL AB
 
3
 
 
4
   This program is free software; you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation; version 2 of the License.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
16
 
 
17
#ifndef _SP_PCONTEXT_H_
 
18
#define _SP_PCONTEXT_H_
 
19
 
 
20
#ifdef USE_PRAGMA_INTERFACE
 
21
#pragma interface                       /* gcc class implementation */
 
22
#endif
 
23
 
 
24
typedef enum
 
25
{
 
26
  sp_param_in,
 
27
  sp_param_out,
 
28
  sp_param_inout
 
29
} sp_param_mode_t;
 
30
 
 
31
typedef struct sp_variable
 
32
{
 
33
  LEX_STRING name;
 
34
  enum enum_field_types type;
 
35
  sp_param_mode_t mode;
 
36
  
 
37
  /*
 
38
    offset -- this the index to the variable's value in the runtime frame.
 
39
    This is calculated during parsing and used when creating sp_instr_set
 
40
    instructions and Item_splocal items.
 
41
    I.e. values are set/referred by array indexing in runtime.
 
42
  */
 
43
  uint offset;
 
44
 
 
45
  Item *dflt;
 
46
  Create_field field_def;
 
47
} sp_variable_t;
 
48
 
 
49
 
 
50
#define SP_LAB_IMPL  0          // Implicit label generated by parser
 
51
#define SP_LAB_BEGIN 1          // Label at BEGIN
 
52
#define SP_LAB_ITER  2          // Label at iteration control
 
53
 
 
54
/*
 
55
  An SQL/PSM label. Can refer to the identifier used with the
 
56
  "label_name:" construct which may precede some SQL/PSM statements, or
 
57
  to an implicit implementation-dependent identifier which the parser
 
58
  inserts before a high-level flow control statement such as
 
59
  IF/WHILE/REPEAT/LOOP, when such statement is rewritten into
 
60
  a combination of low-level jump/jump_if instructions and labels.
 
61
*/
 
62
 
 
63
typedef struct sp_label
 
64
{
 
65
  char *name;
 
66
  uint ip;                      // Instruction index
 
67
  int type;                     // begin/iter or ref/free 
 
68
  sp_pcontext *ctx;             // The label's context
 
69
} sp_label_t;
 
70
 
 
71
typedef struct sp_cond_type
 
72
{
 
73
  enum { number, state, warning, notfound, exception } type;
 
74
  char sqlstate[SQLSTATE_LENGTH+1];
 
75
  uint mysqlerr;
 
76
} sp_cond_type_t;
 
77
 
 
78
/*
 
79
  Sanity check for SQLSTATEs. Will not check if it's really an existing
 
80
  state (there are just too many), but will check length bad characters.
 
81
*/
 
82
extern bool
 
83
sp_cond_check(LEX_STRING *sqlstate);
 
84
 
 
85
typedef struct sp_cond
 
86
{
 
87
  LEX_STRING name;
 
88
  sp_cond_type_t *val;
 
89
} sp_cond_t;
 
90
 
 
91
/**
 
92
  The scope of a label in Stored Procedures,
 
93
  for name resolution of labels in a parsing context.
 
94
*/
 
95
enum label_scope_type
 
96
{
 
97
  /**
 
98
    The labels declared in a parent context are in scope.
 
99
  */
 
100
  LABEL_DEFAULT_SCOPE,
 
101
  /**
 
102
    The labels declared in a parent context are not in scope.
 
103
  */
 
104
  LABEL_HANDLER_SCOPE
 
105
};
 
106
 
 
107
/**
 
108
  The parse-time context, used to keep track of declared variables/parameters,
 
109
  conditions, handlers, cursors and labels, during parsing.
 
110
  sp_contexts are organized as a tree, with one object for each begin-end
 
111
  block, one object for each exception handler,
 
112
  plus a root-context for the parameters.
 
113
  This is used during parsing for looking up defined names (e.g. declared
 
114
  variables and visible labels), for error checking, and to calculate offsets
 
115
  to be used at runtime. (During execution variable values, active handlers
 
116
  and cursors, etc, are referred to by an index in a stack.)
 
117
  Parsing contexts for exception handlers limit the visibility of labels.
 
118
  The pcontext tree is also kept during execution and is used for error
 
119
  checking (e.g. correct number of parameters), and in the future, used by
 
120
  the debugger.
 
121
*/
 
122
 
 
123
class sp_pcontext : public Sql_alloc
 
124
{
 
125
public:
 
126
 
 
127
  /**
 
128
    Constructor.
 
129
    Builds a parsing context root node.
 
130
  */
 
131
  sp_pcontext();
 
132
 
 
133
  // Free memory
 
134
  void
 
135
  destroy();
 
136
 
 
137
  /**
 
138
    Create and push a new context in the tree.
 
139
    @param label_scope label scope for the new parsing context
 
140
    @return the node created
 
141
  */
 
142
  sp_pcontext *
 
143
  push_context(label_scope_type label_scope);
 
144
 
 
145
  /**
 
146
    Pop a node from the parsing context tree.
 
147
    @return the parent node
 
148
  */
 
149
  sp_pcontext *
 
150
  pop_context();
 
151
 
 
152
  sp_pcontext *
 
153
  parent_context()
 
154
  {
 
155
    return m_parent;
 
156
  }
 
157
 
 
158
  /*
 
159
    Number of handlers/cursors to pop between this context and 'ctx'.
 
160
    If 'exclusive' is true, don't count the last block we are leaving;
 
161
    this is used for LEAVE where we will jump to the cpop/hpop instructions.
 
162
  */
 
163
  uint
 
164
  diff_handlers(sp_pcontext *ctx, bool exclusive);
 
165
  uint
 
166
  diff_cursors(sp_pcontext *ctx, bool exclusive);
 
167
 
 
168
 
 
169
  //
 
170
  // Parameters and variables
 
171
  //
 
172
 
 
173
  /*
 
174
    The maximum number of variables used in this and all child contexts
 
175
    In the root, this gives us the number of slots needed for variables
 
176
    during execution.
 
177
  */
 
178
  inline uint
 
179
  max_var_index()
 
180
  {
 
181
    return m_max_var_index;
 
182
  }
 
183
 
 
184
  /*
 
185
    The current number of variables used in the parents (from the root),
 
186
    including this context.
 
187
  */
 
188
  inline uint
 
189
  current_var_count()
 
190
  {
 
191
    return m_var_offset + m_vars.elements;
 
192
  }
 
193
 
 
194
  /* The number of variables in this context alone */
 
195
  inline uint
 
196
  context_var_count()
 
197
  {
 
198
    return m_vars.elements;
 
199
  }
 
200
 
 
201
  /* Map index in this pcontext to runtime offset */
 
202
  inline uint
 
203
  var_context2runtime(uint i)
 
204
  {
 
205
    return m_var_offset + i;
 
206
  }
 
207
 
 
208
  /* Set type of variable. 'i' is the offset from the top */
 
209
  inline void
 
210
  set_type(uint i, enum enum_field_types type)
 
211
  {
 
212
    sp_variable_t *p= find_variable(i);
 
213
 
 
214
    if (p)
 
215
      p->type= type;
 
216
  }
 
217
 
 
218
  /* Set default value of variable. 'i' is the offset from the top */
 
219
  inline void
 
220
  set_default(uint i, Item *it)
 
221
  {
 
222
    sp_variable_t *p= find_variable(i);
 
223
 
 
224
    if (p)
 
225
      p->dflt= it;
 
226
  }
 
227
 
 
228
  sp_variable_t *
 
229
  push_variable(LEX_STRING *name, enum enum_field_types type,
 
230
                sp_param_mode_t mode);
 
231
 
 
232
  /*
 
233
    Retrieve definitions of fields from the current context and its
 
234
    children.
 
235
  */
 
236
  void
 
237
  retrieve_field_definitions(List<Create_field> *field_def_lst);
 
238
 
 
239
  // Find by name
 
240
  sp_variable_t *
 
241
  find_variable(LEX_STRING *name, my_bool scoped=0);
 
242
 
 
243
  // Find by offset (from the top)
 
244
  sp_variable_t *
 
245
  find_variable(uint offset);
 
246
 
 
247
  /*
 
248
    Set the current scope boundary (for default values).
 
249
    The argument is the number of variables to skip.   
 
250
  */
 
251
  inline void
 
252
  declare_var_boundary(uint n)
 
253
  {
 
254
    m_pboundary= n;
 
255
  }
 
256
 
 
257
  /*
 
258
    CASE expressions support.
 
259
  */
 
260
 
 
261
  inline int
 
262
  register_case_expr()
 
263
  {
 
264
    return m_num_case_exprs++;
 
265
  }
 
266
 
 
267
  inline int
 
268
  get_num_case_exprs() const
 
269
  {
 
270
    return m_num_case_exprs;
 
271
  }
 
272
 
 
273
  inline bool
 
274
  push_case_expr_id(int case_expr_id)
 
275
  {
 
276
    return insert_dynamic(&m_case_expr_id_lst, (uchar*) &case_expr_id);
 
277
  }
 
278
 
 
279
  inline void
 
280
  pop_case_expr_id()
 
281
  {
 
282
    pop_dynamic(&m_case_expr_id_lst);
 
283
  }
 
284
 
 
285
  inline int
 
286
  get_current_case_expr_id() const
 
287
  {
 
288
    int case_expr_id;
 
289
 
 
290
    get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (uchar*) &case_expr_id,
 
291
                m_case_expr_id_lst.elements - 1);
 
292
 
 
293
    return case_expr_id;
 
294
  }
 
295
 
 
296
  //
 
297
  // Labels
 
298
  //
 
299
 
 
300
  sp_label_t *
 
301
  push_label(char *name, uint ip);
 
302
 
 
303
  sp_label_t *
 
304
  find_label(char *name);
 
305
 
 
306
  inline sp_label_t *
 
307
  last_label()
 
308
  {
 
309
    sp_label_t *lab= m_label.head();
 
310
 
 
311
    if (!lab && m_parent)
 
312
      lab= m_parent->last_label();
 
313
    return lab;
 
314
  }
 
315
 
 
316
  inline sp_label_t *
 
317
  pop_label()
 
318
  {
 
319
    return m_label.pop();
 
320
  }
 
321
 
 
322
  //
 
323
  // Conditions
 
324
  //
 
325
 
 
326
  int
 
327
  push_cond(LEX_STRING *name, sp_cond_type_t *val);
 
328
 
 
329
  inline void
 
330
  pop_cond(uint num)
 
331
  {
 
332
    while (num--)
 
333
      pop_dynamic(&m_conds);
 
334
  }
 
335
 
 
336
  sp_cond_type_t *
 
337
  find_cond(LEX_STRING *name, my_bool scoped=0);
 
338
 
 
339
  //
 
340
  // Handlers
 
341
  //
 
342
 
 
343
  inline void
 
344
  push_handler(sp_cond_type_t *cond)
 
345
  {
 
346
    insert_dynamic(&m_handlers, (uchar*)&cond);
 
347
  }
 
348
 
 
349
  bool
 
350
  find_handler(sp_cond_type *cond);
 
351
 
 
352
  inline uint
 
353
  max_handler_index()
 
354
  {
 
355
    return m_max_handler_index + m_context_handlers;
 
356
  }
 
357
 
 
358
  inline void
 
359
  add_handlers(uint n)
 
360
  {
 
361
    m_context_handlers+= n;
 
362
  }
 
363
 
 
364
  //
 
365
  // Cursors
 
366
  //
 
367
 
 
368
  int
 
369
  push_cursor(LEX_STRING *name);
 
370
 
 
371
  my_bool
 
372
  find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
 
373
 
 
374
  /* Find by offset (for debugging only) */
 
375
  my_bool
 
376
  find_cursor(uint offset, LEX_STRING *n);
 
377
 
 
378
  inline uint
 
379
  max_cursor_index()
 
380
  {
 
381
    return m_max_cursor_index + m_cursors.elements;
 
382
  }
 
383
 
 
384
  inline uint
 
385
  current_cursor_count()
 
386
  {
 
387
    return m_cursor_offset + m_cursors.elements;
 
388
  }
 
389
 
 
390
protected:
 
391
 
 
392
  /**
 
393
    Constructor for a tree node.
 
394
    @param prev the parent parsing context
 
395
    @param label_scope label_scope for this parsing context
 
396
  */
 
397
  sp_pcontext(sp_pcontext *prev, label_scope_type label_scope);
 
398
 
 
399
  /*
 
400
    m_max_var_index -- number of variables (including all types of arguments)
 
401
    in this context including all children contexts.
 
402
    
 
403
    m_max_var_index >= m_vars.elements.
 
404
 
 
405
    m_max_var_index of the root parsing context contains number of all
 
406
    variables (including arguments) in all enclosed contexts.
 
407
  */
 
408
  uint m_max_var_index;         
 
409
 
 
410
  // The maximum sub context's framesizes
 
411
  uint m_max_cursor_index;
 
412
  uint m_max_handler_index;
 
413
  uint m_context_handlers;      // No. of handlers in this context
 
414
 
 
415
private:
 
416
 
 
417
  sp_pcontext *m_parent;        // Parent context
 
418
 
 
419
  /*
 
420
    m_var_offset -- this is an index of the first variable in this
 
421
                    parsing context.
 
422
    
 
423
    m_var_offset is 0 for root context.
 
424
 
 
425
    Since now each variable is stored in separate place, no reuse is done,
 
426
    so m_var_offset is different for all enclosed contexts.
 
427
  */
 
428
  uint m_var_offset;
 
429
 
 
430
  uint m_cursor_offset;         // Cursor offset for this context
 
431
 
 
432
  /*
 
433
    Boundary for finding variables in this context. This is the number
 
434
    of variables currently "invisible" to default clauses.
 
435
    This is normally 0, but will be larger during parsing of
 
436
    DECLARE ... DEFAULT, to get the scope right for DEFAULT values.
 
437
  */
 
438
  uint m_pboundary;
 
439
 
 
440
  int m_num_case_exprs;
 
441
 
 
442
  DYNAMIC_ARRAY m_vars;         // Parameters/variables
 
443
  DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
 
444
  DYNAMIC_ARRAY m_conds;        // Conditions
 
445
  DYNAMIC_ARRAY m_cursors;      // Cursors
 
446
  DYNAMIC_ARRAY m_handlers;     // Handlers, for checking for duplicates
 
447
 
 
448
  List<sp_label_t> m_label;     // The label list
 
449
 
 
450
  List<sp_pcontext> m_children; // Children contexts, used for destruction
 
451
 
 
452
  /**
 
453
    Scope of labels for this parsing context.
 
454
  */
 
455
  label_scope_type m_label_scope;
 
456
 
 
457
private:
 
458
  sp_pcontext(const sp_pcontext &); /* Prevent use of these */
 
459
  void operator=(sp_pcontext &);
 
460
}; // class sp_pcontext : public Sql_alloc
 
461
 
 
462
 
 
463
#endif /* _SP_PCONTEXT_H_ */