~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/******************************************************
2
Executes SQL stored procedures and their control structures
3
4
(c) 1998 Innobase Oy
5
6
Created 1/20/1998 Heikki Tuuri
7
*******************************************************/
8
9
#include "eval0proc.h"
10
11
#ifdef UNIV_NONINL
12
#include "eval0proc.ic"
13
#endif
14
15
/**************************************************************************
16
Performs an execution step of an if-statement node. */
17
18
que_thr_t*
19
if_step(
20
/*====*/
21
				/* out: query thread to run next or NULL */
22
	que_thr_t*	thr)	/* in: query thread */
23
{
24
	if_node_t*	node;
25
	elsif_node_t*	elsif_node;
26
27
	ut_ad(thr);
28
29
	node = thr->run_node;
30
	ut_ad(que_node_get_type(node) == QUE_NODE_IF);
31
32
	if (thr->prev_node == que_node_get_parent(node)) {
33
34
		/* Evaluate the condition */
35
36
		eval_exp(node->cond);
37
38
		if (eval_node_get_ibool_val(node->cond)) {
39
40
			/* The condition evaluated to TRUE: start execution
41
			from the first statement in the statement list */
42
43
			thr->run_node = node->stat_list;
44
45
		} else if (node->else_part) {
46
			thr->run_node = node->else_part;
47
48
		} else if (node->elsif_list) {
49
			elsif_node = node->elsif_list;
50
51
			for (;;) {
52
				eval_exp(elsif_node->cond);
53
54
				if (eval_node_get_ibool_val(
55
					    elsif_node->cond)) {
56
57
					/* The condition evaluated to TRUE:
58
					start execution from the first
59
					statement in the statement list */
60
61
					thr->run_node = elsif_node->stat_list;
62
63
					break;
64
				}
65
66
				elsif_node = que_node_get_next(elsif_node);
67
68
				if (elsif_node == NULL) {
69
					thr->run_node = NULL;
70
71
					break;
72
				}
73
			}
74
		} else {
75
			thr->run_node = NULL;
76
		}
77
	} else {
78
		/* Move to the next statement */
79
		ut_ad(que_node_get_next(thr->prev_node) == NULL);
80
81
		thr->run_node = NULL;
82
	}
83
84
	if (thr->run_node == NULL) {
85
		thr->run_node = que_node_get_parent(node);
86
	}
87
88
	return(thr);
89
}
90
91
/**************************************************************************
92
Performs an execution step of a while-statement node. */
93
94
que_thr_t*
95
while_step(
96
/*=======*/
97
				/* out: query thread to run next or NULL */
98
	que_thr_t*	thr)	/* in: query thread */
99
{
100
	while_node_t*	node;
101
102
	ut_ad(thr);
103
104
	node = thr->run_node;
105
	ut_ad(que_node_get_type(node) == QUE_NODE_WHILE);
106
107
	ut_ad((thr->prev_node == que_node_get_parent(node))
108
	      || (que_node_get_next(thr->prev_node) == NULL));
109
110
	/* Evaluate the condition */
111
112
	eval_exp(node->cond);
113
114
	if (eval_node_get_ibool_val(node->cond)) {
115
116
		/* The condition evaluated to TRUE: start execution
117
		from the first statement in the statement list */
118
119
		thr->run_node = node->stat_list;
120
	} else {
121
		thr->run_node = que_node_get_parent(node);
122
	}
123
124
	return(thr);
125
}
126
127
/**************************************************************************
128
Performs an execution step of an assignment statement node. */
129
130
que_thr_t*
131
assign_step(
132
/*========*/
133
				/* out: query thread to run next or NULL */
134
	que_thr_t*	thr)	/* in: query thread */
135
{
136
	assign_node_t*	node;
137
138
	ut_ad(thr);
139
140
	node = thr->run_node;
141
	ut_ad(que_node_get_type(node) == QUE_NODE_ASSIGNMENT);
142
143
	/* Evaluate the value to assign */
144
145
	eval_exp(node->val);
146
147
	eval_node_copy_val(node->var->alias, node->val);
148
149
	thr->run_node = que_node_get_parent(node);
150
151
	return(thr);
152
}
153
154
/**************************************************************************
155
Performs an execution step of a for-loop node. */
156
157
que_thr_t*
158
for_step(
159
/*=====*/
160
				/* out: query thread to run next or NULL */
161
	que_thr_t*	thr)	/* in: query thread */
162
{
163
	for_node_t*	node;
164
	que_node_t*	parent;
165
	lint		loop_var_value;
166
167
	ut_ad(thr);
168
169
	node = thr->run_node;
170
171
	ut_ad(que_node_get_type(node) == QUE_NODE_FOR);
172
173
	parent = que_node_get_parent(node);
174
175
	if (thr->prev_node != parent) {
176
177
		/* Move to the next statement */
178
		thr->run_node = que_node_get_next(thr->prev_node);
179
180
		if (thr->run_node != NULL) {
181
182
			return(thr);
183
		}
184
185
		/* Increment the value of loop_var */
186
187
		loop_var_value = 1 + eval_node_get_int_val(node->loop_var);
188
	} else {
189
		/* Initialize the loop */
190
191
		eval_exp(node->loop_start_limit);
192
		eval_exp(node->loop_end_limit);
193
194
		loop_var_value = eval_node_get_int_val(node->loop_start_limit);
195
196
		node->loop_end_value
197
                  = (int) eval_node_get_int_val(node->loop_end_limit);
198
	}
199
200
	/* Check if we should do another loop */
201
202
	if (loop_var_value > node->loop_end_value) {
203
204
		/* Enough loops done */
205
206
		thr->run_node = parent;
207
	} else {
208
		eval_node_set_int_val(node->loop_var, loop_var_value);
209
210
		thr->run_node = node->stat_list;
211
	}
212
213
	return(thr);
214
}
215
216
/**************************************************************************
217
Performs an execution step of an exit statement node. */
218
219
que_thr_t*
220
exit_step(
221
/*======*/
222
				/* out: query thread to run next or NULL */
223
	que_thr_t*	thr)	/* in: query thread */
224
{
225
	exit_node_t*	node;
226
	que_node_t*	loop_node;
227
228
	ut_ad(thr);
229
230
	node = thr->run_node;
231
232
	ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
233
234
	/* Loops exit by setting thr->run_node as the loop node's parent, so
235
	find our containing loop node and get its parent. */
236
237
	loop_node = que_node_get_containing_loop_node(node);
238
239
	/* If someone uses an EXIT statement outside of a loop, this will
240
	trigger. */
241
	ut_a(loop_node);
242
243
	thr->run_node = que_node_get_parent(loop_node);
244
245
	return(thr);
246
}
247
248
/**************************************************************************
249
Performs an execution step of a return-statement node. */
250
251
que_thr_t*
252
return_step(
253
/*========*/
254
				/* out: query thread to run next or NULL */
255
	que_thr_t*	thr)	/* in: query thread */
256
{
257
	return_node_t*	node;
258
	que_node_t*	parent;
259
260
	ut_ad(thr);
261
262
	node = thr->run_node;
263
264
	ut_ad(que_node_get_type(node) == QUE_NODE_RETURN);
265
266
	parent = node;
267
268
	while (que_node_get_type(parent) != QUE_NODE_PROC) {
269
270
		parent = que_node_get_parent(parent);
271
	}
272
273
	ut_a(parent);
274
275
	thr->run_node = que_node_get_parent(parent);
276
277
	return(thr);
278
}