1
/*****************************************************************************
3
Copyright (C) 1998, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file eval/eval0proc.c
21
Executes SQL stored procedures and their control structures
23
Created 1/20/1998 Heikki Tuuri
24
*******************************************************/
26
#include "eval0proc.h"
29
#include "eval0proc.ic"
32
/**********************************************************************//**
33
Performs an execution step of an if-statement node.
34
@return query thread to run next or NULL */
39
que_thr_t* thr) /*!< in: query thread */
42
elsif_node_t* elsif_node;
46
node = static_cast<if_node_t *>(thr->run_node);
47
ut_ad(que_node_get_type(node) == QUE_NODE_IF);
49
if (thr->prev_node == que_node_get_parent(node)) {
51
/* Evaluate the condition */
55
if (eval_node_get_ibool_val(node->cond)) {
57
/* The condition evaluated to TRUE: start execution
58
from the first statement in the statement list */
60
thr->run_node = node->stat_list;
62
} else if (node->else_part) {
63
thr->run_node = node->else_part;
65
} else if (node->elsif_list) {
66
elsif_node = node->elsif_list;
69
eval_exp(elsif_node->cond);
71
if (eval_node_get_ibool_val(
74
/* The condition evaluated to TRUE:
75
start execution from the first
76
statement in the statement list */
78
thr->run_node = elsif_node->stat_list;
83
elsif_node = static_cast<elsif_node_t *>(que_node_get_next(elsif_node));
85
if (elsif_node == NULL) {
95
/* Move to the next statement */
96
ut_ad(que_node_get_next(thr->prev_node) == NULL);
101
if (thr->run_node == NULL) {
102
thr->run_node = que_node_get_parent(node);
108
/**********************************************************************//**
109
Performs an execution step of a while-statement node.
110
@return query thread to run next or NULL */
115
que_thr_t* thr) /*!< in: query thread */
121
node = static_cast<while_node_t *>(thr->run_node);
122
ut_ad(que_node_get_type(node) == QUE_NODE_WHILE);
124
ut_ad((thr->prev_node == que_node_get_parent(node))
125
|| (que_node_get_next(thr->prev_node) == NULL));
127
/* Evaluate the condition */
129
eval_exp(node->cond);
131
if (eval_node_get_ibool_val(node->cond)) {
133
/* The condition evaluated to TRUE: start execution
134
from the first statement in the statement list */
136
thr->run_node = node->stat_list;
138
thr->run_node = que_node_get_parent(node);
144
/**********************************************************************//**
145
Performs an execution step of an assignment statement node.
146
@return query thread to run next or NULL */
151
que_thr_t* thr) /*!< in: query thread */
157
node = static_cast<assign_node_t *>(thr->run_node);
158
ut_ad(que_node_get_type(node) == QUE_NODE_ASSIGNMENT);
160
/* Evaluate the value to assign */
164
eval_node_copy_val(node->var->alias, node->val);
166
thr->run_node = que_node_get_parent(node);
171
/**********************************************************************//**
172
Performs an execution step of a for-loop node.
173
@return query thread to run next or NULL */
178
que_thr_t* thr) /*!< in: query thread */
186
node = static_cast<for_node_t *>(thr->run_node);
188
ut_ad(que_node_get_type(node) == QUE_NODE_FOR);
190
parent = que_node_get_parent(node);
192
if (thr->prev_node != parent) {
194
/* Move to the next statement */
195
thr->run_node = que_node_get_next(thr->prev_node);
197
if (thr->run_node != NULL) {
202
/* Increment the value of loop_var */
204
loop_var_value = 1 + eval_node_get_int_val(node->loop_var);
206
/* Initialize the loop */
208
eval_exp(node->loop_start_limit);
209
eval_exp(node->loop_end_limit);
211
loop_var_value = eval_node_get_int_val(node->loop_start_limit);
214
= (int) eval_node_get_int_val(node->loop_end_limit);
217
/* Check if we should do another loop */
219
if (loop_var_value > node->loop_end_value) {
221
/* Enough loops done */
223
thr->run_node = parent;
225
eval_node_set_int_val(node->loop_var, loop_var_value);
227
thr->run_node = node->stat_list;
233
/**********************************************************************//**
234
Performs an execution step of an exit statement node.
235
@return query thread to run next or NULL */
240
que_thr_t* thr) /*!< in: query thread */
243
que_node_t* loop_node;
247
node = static_cast<exit_node_t *>(thr->run_node);
249
ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
251
/* Loops exit by setting thr->run_node as the loop node's parent, so
252
find our containing loop node and get its parent. */
254
loop_node = que_node_get_containing_loop_node(node);
256
/* If someone uses an EXIT statement outside of a loop, this will
260
thr->run_node = que_node_get_parent(loop_node);
265
/**********************************************************************//**
266
Performs an execution step of a return-statement node.
267
@return query thread to run next or NULL */
272
que_thr_t* thr) /*!< in: query thread */
279
node = static_cast<return_node_t *>(thr->run_node);
281
ut_ad(que_node_get_type(node) == QUE_NODE_RETURN);
285
while (que_node_get_type(parent) != QUE_NODE_PROC) {
287
parent = que_node_get_parent(parent);
292
thr->run_node = que_node_get_parent(parent);