You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

423 lines
9.4 KiB

  1. /* -*- C++ -*- */
  2. /* Copyright (C) 2002 MySQL AB
  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; either version 2 of the License, or
  6. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  14. #ifndef _SP_PCONTEXT_H_
  15. #define _SP_PCONTEXT_H_
  16. #ifdef USE_PRAGMA_INTERFACE
  17. #pragma interface /* gcc class implementation */
  18. #endif
  19. typedef enum
  20. {
  21. sp_param_in,
  22. sp_param_out,
  23. sp_param_inout
  24. } sp_param_mode_t;
  25. typedef struct sp_variable
  26. {
  27. LEX_STRING name;
  28. enum enum_field_types type;
  29. sp_param_mode_t mode;
  30. /*
  31. offset -- this the index to the variable's value in the runtime frame.
  32. This is calculated during parsing and used when creating sp_instr_set
  33. instructions and Item_splocal items.
  34. I.e. values are set/referred by array indexing in runtime.
  35. */
  36. uint offset;
  37. Item *dflt;
  38. create_field field_def;
  39. } sp_variable_t;
  40. #define SP_LAB_IMPL 0 // Implicit label generated by parser
  41. #define SP_LAB_BEGIN 1 // Label at BEGIN
  42. #define SP_LAB_ITER 2 // Label at iteration control
  43. /*
  44. An SQL/PSM label. Can refer to the identifier used with the
  45. "label_name:" construct which may precede some SQL/PSM statements, or
  46. to an implicit implementation-dependent identifier which the parser
  47. inserts before a high-level flow control statement such as
  48. IF/WHILE/REPEAT/LOOP, when such statement is rewritten into
  49. a combination of low-level jump/jump_if instructions and labels.
  50. */
  51. typedef struct sp_label
  52. {
  53. char *name;
  54. uint ip; // Instruction index
  55. int type; // begin/iter or ref/free
  56. sp_pcontext *ctx; // The label's context
  57. } sp_label_t;
  58. typedef struct sp_cond_type
  59. {
  60. enum { number, state, warning, notfound, exception } type;
  61. char sqlstate[6];
  62. uint mysqlerr;
  63. } sp_cond_type_t;
  64. /*
  65. Sanity check for SQLSTATEs. Will not check if it's really an existing
  66. state (there are just too many), but will check length bad characters.
  67. */
  68. extern bool
  69. sp_cond_check(LEX_STRING *sqlstate);
  70. typedef struct sp_cond
  71. {
  72. LEX_STRING name;
  73. sp_cond_type_t *val;
  74. } sp_cond_t;
  75. /*
  76. The parse-time context, used to keep track on declared variables/parameters,
  77. conditions, handlers, cursors and labels, during parsing.
  78. sp_contexts are organized as a tree, with one object for each begin-end
  79. block, plus a root-context for the parameters.
  80. This is used during parsing for looking up defined names (e.g. declared
  81. variables and visible labels), for error checking, and to calculate offsets
  82. to be used at runtime. (During execution variable values, active handlers
  83. and cursors, etc, are referred to by an index in a stack.)
  84. The pcontext tree is also kept during execution and is used for error
  85. checking (e.g. correct number of parameters), and in the future, used by
  86. the debugger.
  87. */
  88. class sp_pcontext : public Sql_alloc
  89. {
  90. sp_pcontext(const sp_pcontext &); /* Prevent use of these */
  91. void operator=(sp_pcontext &);
  92. public:
  93. sp_pcontext(sp_pcontext *prev);
  94. // Free memory
  95. void
  96. destroy();
  97. sp_pcontext *
  98. push_context();
  99. // Returns the previous context, not the one we pop
  100. sp_pcontext *
  101. pop_context();
  102. sp_pcontext *
  103. parent_context()
  104. {
  105. return m_parent;
  106. }
  107. /*
  108. Number of handlers/cursors to pop between this context and 'ctx'.
  109. If 'exclusive' is true, don't count the last block we are leaving;
  110. this is used for LEAVE where we will jump to the cpop/hpop instructions.
  111. */
  112. uint
  113. diff_handlers(sp_pcontext *ctx, bool exclusive);
  114. uint
  115. diff_cursors(sp_pcontext *ctx, bool exclusive);
  116. //
  117. // Parameters and variables
  118. //
  119. /*
  120. The maximum number of variables used in this and all child contexts
  121. In the root, this gives us the number of slots needed for variables
  122. during execution.
  123. */
  124. inline uint
  125. max_var_index()
  126. {
  127. return m_max_var_index;
  128. }
  129. /*
  130. The current number of variables used in the parents (from the root),
  131. including this context.
  132. */
  133. inline uint
  134. current_var_count()
  135. {
  136. return m_var_offset + m_vars.elements;
  137. }
  138. /* The number of variables in this context alone */
  139. inline uint
  140. context_var_count()
  141. {
  142. return m_vars.elements;
  143. }
  144. /* Map index in this pcontext to runtime offset */
  145. inline uint
  146. var_context2runtime(uint i)
  147. {
  148. return m_var_offset + i;
  149. }
  150. /* Set type of variable. 'i' is the offset from the top */
  151. inline void
  152. set_type(uint i, enum enum_field_types type)
  153. {
  154. sp_variable_t *p= find_variable(i);
  155. if (p)
  156. p->type= type;
  157. }
  158. /* Set default value of variable. 'i' is the offset from the top */
  159. inline void
  160. set_default(uint i, Item *it)
  161. {
  162. sp_variable_t *p= find_variable(i);
  163. if (p)
  164. p->dflt= it;
  165. }
  166. sp_variable_t *
  167. push_variable(LEX_STRING *name, enum enum_field_types type,
  168. sp_param_mode_t mode);
  169. /*
  170. Retrieve definitions of fields from the current context and its
  171. children.
  172. */
  173. void
  174. retrieve_field_definitions(List<create_field> *field_def_lst);
  175. // Find by name
  176. sp_variable_t *
  177. find_variable(LEX_STRING *name, my_bool scoped=0);
  178. // Find by offset (from the top)
  179. sp_variable_t *
  180. find_variable(uint offset);
  181. /*
  182. Set the current scope boundary (for default values).
  183. The argument is the number of variables to skip.
  184. */
  185. inline void
  186. declare_var_boundary(uint n)
  187. {
  188. m_pboundary= n;
  189. }
  190. /*
  191. CASE expressions support.
  192. */
  193. inline int
  194. register_case_expr()
  195. {
  196. return m_num_case_exprs++;
  197. }
  198. inline int
  199. get_num_case_exprs() const
  200. {
  201. return m_num_case_exprs;
  202. }
  203. inline bool
  204. push_case_expr_id(int case_expr_id)
  205. {
  206. return insert_dynamic(&m_case_expr_id_lst, (gptr) &case_expr_id);
  207. }
  208. inline void
  209. pop_case_expr_id()
  210. {
  211. pop_dynamic(&m_case_expr_id_lst);
  212. }
  213. inline int
  214. get_current_case_expr_id() const
  215. {
  216. int case_expr_id;
  217. get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (gptr) &case_expr_id,
  218. m_case_expr_id_lst.elements - 1);
  219. return case_expr_id;
  220. }
  221. //
  222. // Labels
  223. //
  224. sp_label_t *
  225. push_label(char *name, uint ip);
  226. sp_label_t *
  227. find_label(char *name);
  228. inline sp_label_t *
  229. last_label()
  230. {
  231. sp_label_t *lab= m_label.head();
  232. if (!lab && m_parent)
  233. lab= m_parent->last_label();
  234. return lab;
  235. }
  236. inline sp_label_t *
  237. pop_label()
  238. {
  239. return m_label.pop();
  240. }
  241. //
  242. // Conditions
  243. //
  244. void
  245. push_cond(LEX_STRING *name, sp_cond_type_t *val);
  246. inline void
  247. pop_cond(uint num)
  248. {
  249. while (num--)
  250. pop_dynamic(&m_conds);
  251. }
  252. sp_cond_type_t *
  253. find_cond(LEX_STRING *name, my_bool scoped=0);
  254. //
  255. // Handlers
  256. //
  257. inline void
  258. push_handler(sp_cond_type_t *cond)
  259. {
  260. insert_dynamic(&m_handlers, (gptr)&cond);
  261. }
  262. bool
  263. find_handler(sp_cond_type *cond);
  264. inline uint
  265. max_handler_index()
  266. {
  267. return m_max_handler_index + m_context_handlers;
  268. }
  269. inline void
  270. add_handlers(uint n)
  271. {
  272. m_context_handlers+= n;
  273. }
  274. //
  275. // Cursors
  276. //
  277. void
  278. push_cursor(LEX_STRING *name);
  279. my_bool
  280. find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
  281. /* Find by offset (for debugging only) */
  282. my_bool
  283. find_cursor(uint offset, LEX_STRING *n);
  284. inline uint
  285. max_cursor_index()
  286. {
  287. return m_max_cursor_index + m_cursors.elements;
  288. }
  289. inline uint
  290. current_cursor_count()
  291. {
  292. return m_cursor_offset + m_cursors.elements;
  293. }
  294. protected:
  295. /*
  296. m_max_var_index -- number of variables (including all types of arguments)
  297. in this context including all children contexts.
  298. m_max_var_index >= m_vars.elements.
  299. m_max_var_index of the root parsing context contains number of all
  300. variables (including arguments) in all enclosed contexts.
  301. */
  302. uint m_max_var_index;
  303. // The maximum sub context's framesizes
  304. uint m_max_cursor_index;
  305. uint m_max_handler_index;
  306. uint m_context_handlers; // No. of handlers in this context
  307. private:
  308. sp_pcontext *m_parent; // Parent context
  309. /*
  310. m_var_offset -- this is an index of the first variable in this
  311. parsing context.
  312. m_var_offset is 0 for root context.
  313. Since now each variable is stored in separate place, no reuse is done,
  314. so m_var_offset is different for all enclosed contexts.
  315. */
  316. uint m_var_offset;
  317. uint m_cursor_offset; // Cursor offset for this context
  318. /*
  319. Boundary for finding variables in this context. This is the number
  320. of variables currently "invisible" to default clauses.
  321. This is normally 0, but will be larger during parsing of
  322. DECLARE ... DEFAULT, to get the scope right for DEFAULT values.
  323. */
  324. uint m_pboundary;
  325. int m_num_case_exprs;
  326. DYNAMIC_ARRAY m_vars; // Parameters/variables
  327. DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
  328. DYNAMIC_ARRAY m_conds; // Conditions
  329. DYNAMIC_ARRAY m_cursors; // Cursors
  330. DYNAMIC_ARRAY m_handlers; // Handlers, for checking for duplicates
  331. List<sp_label_t> m_label; // The label list
  332. List<sp_pcontext> m_children; // Children contexts, used for destruction
  333. }; // class sp_pcontext : public Sql_alloc
  334. #endif /* _SP_PCONTEXT_H_ */