mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innodb_plugin / eval / eval0eval.c
blobfc34ce83a0f2fde0114de31f05620a339a7083d6
1 /*****************************************************************************
3 Copyright (c) 1997, 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.,
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *****************************************************************************/
19 /**************************************************//**
20 @file eval/eval0eval.c
21 SQL evaluator: evaluates simple data structures, like expressions, in
22 a query graph
24 Created 12/29/1997 Heikki Tuuri
25 *******************************************************/
27 #include "eval0eval.h"
29 #ifdef UNIV_NONINL
30 #include "eval0eval.ic"
31 #endif
33 #include "data0data.h"
34 #include "row0sel.h"
36 /** The RND function seed */
37 static ulint eval_rnd = 128367121;
39 /** Dummy adress used when we should allocate a buffer of size 0 in
40 eval_node_alloc_val_buf */
42 static byte eval_dummy;
44 /*****************************************************************//**
45 Allocate a buffer from global dynamic memory for a value of a que_node.
46 NOTE that this memory must be explicitly freed when the query graph is
47 freed. If the node already has an allocated buffer, that buffer is freed
48 here. NOTE that this is the only function where dynamic memory should be
49 allocated for a query node val field.
50 @return pointer to allocated buffer */
51 UNIV_INTERN
52 byte*
53 eval_node_alloc_val_buf(
54 /*====================*/
55 que_node_t* node, /*!< in: query graph node; sets the val field
56 data field to point to the new buffer, and
57 len field equal to size */
58 ulint size) /*!< in: buffer size */
60 dfield_t* dfield;
61 byte* data;
63 ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
64 || que_node_get_type(node) == QUE_NODE_FUNC);
66 dfield = que_node_get_val(node);
68 data = dfield_get_data(dfield);
70 if (data && data != &eval_dummy) {
71 mem_free(data);
74 if (size == 0) {
75 data = &eval_dummy;
76 } else {
77 data = mem_alloc(size);
80 que_node_set_val_buf_size(node, size);
82 dfield_set_data(dfield, data, size);
84 return(data);
87 /*****************************************************************//**
88 Free the buffer from global dynamic memory for a value of a que_node,
89 if it has been allocated in the above function. The freeing for pushed
90 column values is done in sel_col_prefetch_buf_free. */
91 UNIV_INTERN
92 void
93 eval_node_free_val_buf(
94 /*===================*/
95 que_node_t* node) /*!< in: query graph node */
97 dfield_t* dfield;
98 byte* data;
100 ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
101 || que_node_get_type(node) == QUE_NODE_FUNC);
103 dfield = que_node_get_val(node);
105 data = dfield_get_data(dfield);
107 if (que_node_get_val_buf_size(node) > 0) {
108 ut_a(data);
110 mem_free(data);
114 /*****************************************************************//**
115 Evaluates a comparison node.
116 @return the result of the comparison */
117 UNIV_INTERN
118 ibool
119 eval_cmp(
120 /*=====*/
121 func_node_t* cmp_node) /*!< in: comparison node */
123 que_node_t* arg1;
124 que_node_t* arg2;
125 int res;
126 ibool val;
127 int func;
129 ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
131 arg1 = cmp_node->args;
132 arg2 = que_node_get_next(arg1);
134 res = cmp_dfield_dfield(que_node_get_val(arg1),
135 que_node_get_val(arg2));
136 val = TRUE;
138 func = cmp_node->func;
140 if (func == '=') {
141 if (res != 0) {
142 val = FALSE;
144 } else if (func == '<') {
145 if (res != -1) {
146 val = FALSE;
148 } else if (func == PARS_LE_TOKEN) {
149 if (res == 1) {
150 val = FALSE;
152 } else if (func == PARS_NE_TOKEN) {
153 if (res == 0) {
154 val = FALSE;
156 } else if (func == PARS_GE_TOKEN) {
157 if (res == -1) {
158 val = FALSE;
160 } else {
161 ut_ad(func == '>');
163 if (res != 1) {
164 val = FALSE;
168 eval_node_set_ibool_val(cmp_node, val);
170 return(val);
173 /*****************************************************************//**
174 Evaluates a logical operation node. */
175 UNIV_INLINE
176 void
177 eval_logical(
178 /*=========*/
179 func_node_t* logical_node) /*!< in: logical operation node */
181 que_node_t* arg1;
182 que_node_t* arg2;
183 ibool val1;
184 ibool val2 = 0; /* remove warning */
185 ibool val = 0; /* remove warning */
186 int func;
188 ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
190 arg1 = logical_node->args;
191 arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is 'NOT' */
193 val1 = eval_node_get_ibool_val(arg1);
195 if (arg2) {
196 val2 = eval_node_get_ibool_val(arg2);
199 func = logical_node->func;
201 if (func == PARS_AND_TOKEN) {
202 val = val1 & val2;
203 } else if (func == PARS_OR_TOKEN) {
204 val = val1 | val2;
205 } else if (func == PARS_NOT_TOKEN) {
206 val = TRUE - val1;
207 } else {
208 ut_error;
211 eval_node_set_ibool_val(logical_node, val);
214 /*****************************************************************//**
215 Evaluates an arithmetic operation node. */
216 UNIV_INLINE
217 void
218 eval_arith(
219 /*=======*/
220 func_node_t* arith_node) /*!< in: arithmetic operation node */
222 que_node_t* arg1;
223 que_node_t* arg2;
224 lint val1;
225 lint val2 = 0; /* remove warning */
226 lint val;
227 int func;
229 ut_ad(que_node_get_type(arith_node) == QUE_NODE_FUNC);
231 arg1 = arith_node->args;
232 arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is unary '-' */
234 val1 = eval_node_get_int_val(arg1);
236 if (arg2) {
237 val2 = eval_node_get_int_val(arg2);
240 func = arith_node->func;
242 if (func == '+') {
243 val = val1 + val2;
244 } else if ((func == '-') && arg2) {
245 val = val1 - val2;
246 } else if (func == '-') {
247 val = -val1;
248 } else if (func == '*') {
249 val = val1 * val2;
250 } else {
251 ut_ad(func == '/');
252 val = val1 / val2;
255 eval_node_set_int_val(arith_node, val);
258 /*****************************************************************//**
259 Evaluates an aggregate operation node. */
260 UNIV_INLINE
261 void
262 eval_aggregate(
263 /*===========*/
264 func_node_t* node) /*!< in: aggregate operation node */
266 que_node_t* arg;
267 lint val;
268 lint arg_val;
269 int func;
271 ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
273 val = eval_node_get_int_val(node);
275 func = node->func;
277 if (func == PARS_COUNT_TOKEN) {
279 val = val + 1;
280 } else {
281 ut_ad(func == PARS_SUM_TOKEN);
283 arg = node->args;
284 arg_val = eval_node_get_int_val(arg);
286 val = val + arg_val;
289 eval_node_set_int_val(node, val);
292 /*****************************************************************//**
293 Evaluates a predefined function node where the function is not relevant
294 in benchmarks. */
295 static
296 void
297 eval_predefined_2(
298 /*==============*/
299 func_node_t* func_node) /*!< in: predefined function node */
301 que_node_t* arg;
302 que_node_t* arg1;
303 que_node_t* arg2 = 0; /* remove warning (??? bug ???) */
304 lint int_val;
305 byte* data;
306 ulint len1;
307 ulint len2;
308 int func;
309 ulint i;
311 ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
313 arg1 = func_node->args;
315 if (arg1) {
316 arg2 = que_node_get_next(arg1);
319 func = func_node->func;
321 if (func == PARS_PRINTF_TOKEN) {
323 arg = arg1;
325 while (arg) {
326 dfield_print(que_node_get_val(arg));
328 arg = que_node_get_next(arg);
331 putc('\n', stderr);
333 } else if (func == PARS_ASSERT_TOKEN) {
335 if (!eval_node_get_ibool_val(arg1)) {
336 fputs("SQL assertion fails in a stored procedure!\n",
337 stderr);
340 ut_a(eval_node_get_ibool_val(arg1));
342 /* This function, or more precisely, a debug procedure,
343 returns no value */
345 } else if (func == PARS_RND_TOKEN) {
347 len1 = (ulint)eval_node_get_int_val(arg1);
348 len2 = (ulint)eval_node_get_int_val(arg2);
350 ut_ad(len2 >= len1);
352 if (len2 > len1) {
353 int_val = (lint) (len1
354 + (eval_rnd % (len2 - len1 + 1)));
355 } else {
356 int_val = (lint) len1;
359 eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
361 eval_node_set_int_val(func_node, int_val);
363 } else if (func == PARS_RND_STR_TOKEN) {
365 len1 = (ulint)eval_node_get_int_val(arg1);
367 data = eval_node_ensure_val_buf(func_node, len1);
369 for (i = 0; i < len1; i++) {
370 data[i] = (byte)(97 + (eval_rnd % 3));
372 eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
374 } else {
375 ut_error;
379 /*****************************************************************//**
380 Evaluates a notfound-function node. */
381 UNIV_INLINE
382 void
383 eval_notfound(
384 /*==========*/
385 func_node_t* func_node) /*!< in: function node */
387 sym_node_t* cursor;
388 sel_node_t* sel_node;
389 ibool ibool_val;
391 ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
393 cursor = func_node->args;
395 ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
397 if (cursor->token_type == SYM_LIT) {
399 ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
400 "SQL", 3) == 0);
402 sel_node = cursor->sym_table->query_graph->last_sel_node;
403 } else {
404 sel_node = cursor->alias->cursor_def;
407 if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
408 ibool_val = TRUE;
409 } else {
410 ibool_val = FALSE;
413 eval_node_set_ibool_val(func_node, ibool_val);
416 /*****************************************************************//**
417 Evaluates a substr-function node. */
418 UNIV_INLINE
419 void
420 eval_substr(
421 /*========*/
422 func_node_t* func_node) /*!< in: function node */
424 que_node_t* arg1;
425 que_node_t* arg2;
426 que_node_t* arg3;
427 dfield_t* dfield;
428 byte* str1;
429 ulint len1;
430 ulint len2;
432 arg1 = func_node->args;
433 arg2 = que_node_get_next(arg1);
435 ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
437 arg3 = que_node_get_next(arg2);
439 str1 = dfield_get_data(que_node_get_val(arg1));
441 len1 = (ulint)eval_node_get_int_val(arg2);
442 len2 = (ulint)eval_node_get_int_val(arg3);
444 dfield = que_node_get_val(func_node);
446 dfield_set_data(dfield, str1 + len1, len2);
449 /*****************************************************************//**
450 Evaluates a replstr-procedure node. */
451 static
452 void
453 eval_replstr(
454 /*=========*/
455 func_node_t* func_node) /*!< in: function node */
457 que_node_t* arg1;
458 que_node_t* arg2;
459 que_node_t* arg3;
460 que_node_t* arg4;
461 byte* str1;
462 byte* str2;
463 ulint len1;
464 ulint len2;
466 arg1 = func_node->args;
467 arg2 = que_node_get_next(arg1);
469 ut_ad(que_node_get_type(arg1) == QUE_NODE_SYMBOL);
471 arg3 = que_node_get_next(arg2);
472 arg4 = que_node_get_next(arg3);
474 str1 = dfield_get_data(que_node_get_val(arg1));
475 str2 = dfield_get_data(que_node_get_val(arg2));
477 len1 = (ulint)eval_node_get_int_val(arg3);
478 len2 = (ulint)eval_node_get_int_val(arg4);
480 if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
481 || (dfield_get_len(que_node_get_val(arg2)) < len2)) {
483 ut_error;
486 ut_memcpy(str1 + len1, str2, len2);
489 /*****************************************************************//**
490 Evaluates an instr-function node. */
491 static
492 void
493 eval_instr(
494 /*=======*/
495 func_node_t* func_node) /*!< in: function node */
497 que_node_t* arg1;
498 que_node_t* arg2;
499 dfield_t* dfield1;
500 dfield_t* dfield2;
501 lint int_val;
502 byte* str1;
503 byte* str2;
504 byte match_char;
505 ulint len1;
506 ulint len2;
507 ulint i;
508 ulint j;
510 arg1 = func_node->args;
511 arg2 = que_node_get_next(arg1);
513 dfield1 = que_node_get_val(arg1);
514 dfield2 = que_node_get_val(arg2);
516 str1 = dfield_get_data(dfield1);
517 str2 = dfield_get_data(dfield2);
519 len1 = dfield_get_len(dfield1);
520 len2 = dfield_get_len(dfield2);
522 if (len2 == 0) {
523 ut_error;
526 match_char = str2[0];
528 for (i = 0; i < len1; i++) {
529 /* In this outer loop, the number of matched characters is 0 */
531 if (str1[i] == match_char) {
533 if (i + len2 > len1) {
535 break;
538 for (j = 1;; j++) {
539 /* We have already matched j characters */
541 if (j == len2) {
542 int_val = i + 1;
544 goto match_found;
547 if (str1[i + j] != str2[j]) {
549 break;
555 int_val = 0;
557 match_found:
558 eval_node_set_int_val(func_node, int_val);
561 /*****************************************************************//**
562 Evaluates a predefined function node. */
563 UNIV_INLINE
564 void
565 eval_binary_to_number(
566 /*==================*/
567 func_node_t* func_node) /*!< in: function node */
569 que_node_t* arg1;
570 dfield_t* dfield;
571 byte* str1;
572 byte* str2;
573 ulint len1;
574 ulint int_val;
576 arg1 = func_node->args;
578 dfield = que_node_get_val(arg1);
580 str1 = dfield_get_data(dfield);
581 len1 = dfield_get_len(dfield);
583 if (len1 > 4) {
584 ut_error;
587 if (len1 == 4) {
588 str2 = str1;
589 } else {
590 int_val = 0;
591 str2 = (byte*)&int_val;
593 ut_memcpy(str2 + (4 - len1), str1, len1);
596 eval_node_copy_and_alloc_val(func_node, str2, 4);
599 /*****************************************************************//**
600 Evaluates a predefined function node. */
601 static
602 void
603 eval_concat(
604 /*========*/
605 func_node_t* func_node) /*!< in: function node */
607 que_node_t* arg;
608 dfield_t* dfield;
609 byte* data;
610 ulint len;
611 ulint len1;
613 arg = func_node->args;
614 len = 0;
616 while (arg) {
617 len1 = dfield_get_len(que_node_get_val(arg));
619 len += len1;
621 arg = que_node_get_next(arg);
624 data = eval_node_ensure_val_buf(func_node, len);
626 arg = func_node->args;
627 len = 0;
629 while (arg) {
630 dfield = que_node_get_val(arg);
631 len1 = dfield_get_len(dfield);
633 ut_memcpy(data + len, dfield_get_data(dfield), len1);
635 len += len1;
637 arg = que_node_get_next(arg);
641 /*****************************************************************//**
642 Evaluates a predefined function node. If the first argument is an integer,
643 this function looks at the second argument which is the integer length in
644 bytes, and converts the integer to a VARCHAR.
645 If the first argument is of some other type, this function converts it to
646 BINARY. */
647 UNIV_INLINE
648 void
649 eval_to_binary(
650 /*===========*/
651 func_node_t* func_node) /*!< in: function node */
653 que_node_t* arg1;
654 que_node_t* arg2;
655 dfield_t* dfield;
656 byte* str1;
657 ulint len;
658 ulint len1;
660 arg1 = func_node->args;
662 str1 = dfield_get_data(que_node_get_val(arg1));
664 if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
666 len = dfield_get_len(que_node_get_val(arg1));
668 dfield = que_node_get_val(func_node);
670 dfield_set_data(dfield, str1, len);
672 return;
675 arg2 = que_node_get_next(arg1);
677 len1 = (ulint)eval_node_get_int_val(arg2);
679 if (len1 > 4) {
681 ut_error;
684 dfield = que_node_get_val(func_node);
686 dfield_set_data(dfield, str1 + (4 - len1), len1);
689 /*****************************************************************//**
690 Evaluates a predefined function node. */
691 UNIV_INLINE
692 void
693 eval_predefined(
694 /*============*/
695 func_node_t* func_node) /*!< in: function node */
697 que_node_t* arg1;
698 lint int_val;
699 byte* data;
700 int func;
702 func = func_node->func;
704 arg1 = func_node->args;
706 if (func == PARS_LENGTH_TOKEN) {
708 int_val = (lint)dfield_get_len(que_node_get_val(arg1));
710 } else if (func == PARS_TO_CHAR_TOKEN) {
712 /* Convert number to character string as a
713 signed decimal integer. */
715 ulint uint_val;
716 int int_len;
718 int_val = eval_node_get_int_val(arg1);
720 /* Determine the length of the string. */
722 if (int_val == 0) {
723 int_len = 1; /* the number 0 occupies 1 byte */
724 } else {
725 int_len = 0;
726 if (int_val < 0) {
727 uint_val = ((ulint) -int_val - 1) + 1;
728 int_len++; /* reserve space for minus sign */
729 } else {
730 uint_val = (ulint) int_val;
732 for (; uint_val > 0; int_len++) {
733 uint_val /= 10;
737 /* allocate the string */
738 data = eval_node_ensure_val_buf(func_node, int_len + 1);
740 /* add terminating NUL character */
741 data[int_len] = 0;
743 /* convert the number */
745 if (int_val == 0) {
746 data[0] = '0';
747 } else {
748 int tmp;
749 if (int_val < 0) {
750 data[0] = '-'; /* preceding minus sign */
751 uint_val = ((ulint) -int_val - 1) + 1;
752 } else {
753 uint_val = (ulint) int_val;
755 for (tmp = int_len; uint_val > 0; uint_val /= 10) {
756 data[--tmp] = (byte)
757 ('0' + (byte)(uint_val % 10));
761 dfield_set_len(que_node_get_val(func_node), int_len);
763 return;
765 } else if (func == PARS_TO_NUMBER_TOKEN) {
767 int_val = atoi((char*)
768 dfield_get_data(que_node_get_val(arg1)));
770 } else if (func == PARS_SYSDATE_TOKEN) {
771 int_val = (lint)ut_time();
772 } else {
773 eval_predefined_2(func_node);
775 return;
778 eval_node_set_int_val(func_node, int_val);
781 /*****************************************************************//**
782 Evaluates a function node. */
783 UNIV_INTERN
784 void
785 eval_func(
786 /*======*/
787 func_node_t* func_node) /*!< in: function node */
789 que_node_t* arg;
790 ulint class;
791 ulint func;
793 ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
795 class = func_node->class;
796 func = func_node->func;
798 arg = func_node->args;
800 /* Evaluate first the argument list */
801 while (arg) {
802 eval_exp(arg);
804 /* The functions are not defined for SQL null argument
805 values, except for eval_cmp and notfound */
807 if (dfield_is_null(que_node_get_val(arg))
808 && (class != PARS_FUNC_CMP)
809 && (func != PARS_NOTFOUND_TOKEN)
810 && (func != PARS_PRINTF_TOKEN)) {
811 ut_error;
814 arg = que_node_get_next(arg);
817 if (class == PARS_FUNC_CMP) {
818 eval_cmp(func_node);
819 } else if (class == PARS_FUNC_ARITH) {
820 eval_arith(func_node);
821 } else if (class == PARS_FUNC_AGGREGATE) {
822 eval_aggregate(func_node);
823 } else if (class == PARS_FUNC_PREDEFINED) {
825 if (func == PARS_NOTFOUND_TOKEN) {
826 eval_notfound(func_node);
827 } else if (func == PARS_SUBSTR_TOKEN) {
828 eval_substr(func_node);
829 } else if (func == PARS_REPLSTR_TOKEN) {
830 eval_replstr(func_node);
831 } else if (func == PARS_INSTR_TOKEN) {
832 eval_instr(func_node);
833 } else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
834 eval_binary_to_number(func_node);
835 } else if (func == PARS_CONCAT_TOKEN) {
836 eval_concat(func_node);
837 } else if (func == PARS_TO_BINARY_TOKEN) {
838 eval_to_binary(func_node);
839 } else {
840 eval_predefined(func_node);
842 } else {
843 ut_ad(class == PARS_FUNC_LOGICAL);
845 eval_logical(func_node);