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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file eval/eval0eval.c
21
SQL evaluator: evaluates simple data structures, like expressions, in
24
Created 12/29/1997 Heikki Tuuri
25
*******************************************************/
27
#include "eval0eval.h"
30
#include "eval0eval.ic"
33
#include "data0data.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 */
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 */
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) {
77
data = mem_alloc(size);
80
que_node_set_val_buf_size(node, size);
82
dfield_set_data(dfield, data, size);
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. */
93
eval_node_free_val_buf(
94
/*===================*/
95
que_node_t* node) /*!< in: query graph node */
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) {
114
/*****************************************************************//**
115
Evaluates a comparison node.
116
@return the result of the comparison */
121
func_node_t* cmp_node) /*!< in: comparison node */
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));
138
func = cmp_node->func;
144
} else if (func == '<') {
148
} else if (func == PARS_LE_TOKEN) {
152
} else if (func == PARS_NE_TOKEN) {
156
} else if (func == PARS_GE_TOKEN) {
168
eval_node_set_ibool_val(cmp_node, val);
173
/*****************************************************************//**
174
Evaluates a logical operation node. */
179
func_node_t* logical_node) /*!< in: logical operation node */
184
ibool val2 = 0; /* remove warning */
185
ibool val = 0; /* remove warning */
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);
196
val2 = eval_node_get_ibool_val(arg2);
199
func = logical_node->func;
201
if (func == PARS_AND_TOKEN) {
203
} else if (func == PARS_OR_TOKEN) {
205
} else if (func == PARS_NOT_TOKEN) {
211
eval_node_set_ibool_val(logical_node, val);
214
/*****************************************************************//**
215
Evaluates an arithmetic operation node. */
220
func_node_t* arith_node) /*!< in: arithmetic operation node */
225
lint val2 = 0; /* remove warning */
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);
237
val2 = eval_node_get_int_val(arg2);
240
func = arith_node->func;
244
} else if ((func == '-') && arg2) {
246
} else if (func == '-') {
248
} else if (func == '*') {
255
eval_node_set_int_val(arith_node, val);
258
/*****************************************************************//**
259
Evaluates an aggregate operation node. */
264
func_node_t* node) /*!< in: aggregate operation node */
271
ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
273
val = eval_node_get_int_val(node);
277
if (func == PARS_COUNT_TOKEN) {
281
ut_ad(func == PARS_SUM_TOKEN);
284
arg_val = eval_node_get_int_val(arg);
289
eval_node_set_int_val(node, val);
292
/*****************************************************************//**
293
Evaluates a predefined function node where the function is not relevant
299
func_node_t* func_node) /*!< in: predefined function node */
303
que_node_t* arg2 = 0; /* remove warning (??? bug ???) */
311
ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
313
arg1 = func_node->args;
316
arg2 = que_node_get_next(arg1);
319
func = func_node->func;
321
if (func == PARS_PRINTF_TOKEN) {
326
dfield_print(que_node_get_val(arg));
328
arg = que_node_get_next(arg);
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",
340
ut_a(eval_node_get_ibool_val(arg1));
342
/* This function, or more precisely, a debug procedure,
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);
353
int_val = (lint) (len1
354
+ (eval_rnd % (len2 - len1 + 1)));
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);
379
/*****************************************************************//**
380
Evaluates a notfound-function node. */
385
func_node_t* func_node) /*!< in: function node */
390
sel_node_t* sel_node;
393
arg1 = func_node->args;
394
arg2 = que_node_get_next(arg1);
396
ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
400
ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
402
if (cursor->token_type == SYM_LIT) {
404
ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
407
sel_node = cursor->sym_table->query_graph->last_sel_node;
409
sel_node = cursor->alias->cursor_def;
412
if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
418
eval_node_set_ibool_val(func_node, ibool_val);
421
/*****************************************************************//**
422
Evaluates a substr-function node. */
427
func_node_t* func_node) /*!< in: function node */
437
arg1 = func_node->args;
438
arg2 = que_node_get_next(arg1);
440
ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
442
arg3 = que_node_get_next(arg2);
444
str1 = dfield_get_data(que_node_get_val(arg1));
446
len1 = (ulint)eval_node_get_int_val(arg2);
447
len2 = (ulint)eval_node_get_int_val(arg3);
449
dfield = que_node_get_val(func_node);
451
dfield_set_data(dfield, str1 + len1, len2);
454
/*****************************************************************//**
455
Evaluates a replstr-procedure node. */
460
func_node_t* func_node) /*!< in: function node */
471
arg1 = func_node->args;
472
arg2 = que_node_get_next(arg1);
474
ut_ad(que_node_get_type(arg1) == QUE_NODE_SYMBOL);
476
arg3 = que_node_get_next(arg2);
477
arg4 = que_node_get_next(arg3);
479
str1 = dfield_get_data(que_node_get_val(arg1));
480
str2 = dfield_get_data(que_node_get_val(arg2));
482
len1 = (ulint)eval_node_get_int_val(arg3);
483
len2 = (ulint)eval_node_get_int_val(arg4);
485
if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
486
|| (dfield_get_len(que_node_get_val(arg2)) < len2)) {
491
ut_memcpy(str1 + len1, str2, len2);
494
/*****************************************************************//**
495
Evaluates an instr-function node. */
500
func_node_t* func_node) /*!< in: function node */
515
arg1 = func_node->args;
516
arg2 = que_node_get_next(arg1);
518
dfield1 = que_node_get_val(arg1);
519
dfield2 = que_node_get_val(arg2);
521
str1 = dfield_get_data(dfield1);
522
str2 = dfield_get_data(dfield2);
524
len1 = dfield_get_len(dfield1);
525
len2 = dfield_get_len(dfield2);
531
match_char = str2[0];
533
for (i = 0; i < len1; i++) {
534
/* In this outer loop, the number of matched characters is 0 */
536
if (str1[i] == match_char) {
538
if (i + len2 > len1) {
544
/* We have already matched j characters */
552
if (str1[i + j] != str2[j]) {
563
eval_node_set_int_val(func_node, int_val);
566
/*****************************************************************//**
567
Evaluates a predefined function node. */
570
eval_binary_to_number(
571
/*==================*/
572
func_node_t* func_node) /*!< in: function node */
581
arg1 = func_node->args;
583
dfield = que_node_get_val(arg1);
585
str1 = dfield_get_data(dfield);
586
len1 = dfield_get_len(dfield);
596
str2 = (byte*)&int_val;
598
ut_memcpy(str2 + (4 - len1), str1, len1);
601
eval_node_copy_and_alloc_val(func_node, str2, 4);
604
/*****************************************************************//**
605
Evaluates a predefined function node. */
610
func_node_t* func_node) /*!< in: function node */
618
arg = func_node->args;
622
len1 = dfield_get_len(que_node_get_val(arg));
626
arg = que_node_get_next(arg);
629
data = eval_node_ensure_val_buf(func_node, len);
631
arg = func_node->args;
635
dfield = que_node_get_val(arg);
636
len1 = dfield_get_len(dfield);
638
ut_memcpy(data + len, dfield_get_data(dfield), len1);
642
arg = que_node_get_next(arg);
646
/*****************************************************************//**
647
Evaluates a predefined function node. If the first argument is an integer,
648
this function looks at the second argument which is the integer length in
649
bytes, and converts the integer to a VARCHAR.
650
If the first argument is of some other type, this function converts it to
656
func_node_t* func_node) /*!< in: function node */
665
arg1 = func_node->args;
667
str1 = dfield_get_data(que_node_get_val(arg1));
669
if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
671
len = dfield_get_len(que_node_get_val(arg1));
673
dfield = que_node_get_val(func_node);
675
dfield_set_data(dfield, str1, len);
680
arg2 = que_node_get_next(arg1);
682
len1 = (ulint)eval_node_get_int_val(arg2);
689
dfield = que_node_get_val(func_node);
691
dfield_set_data(dfield, str1 + (4 - len1), len1);
694
/*****************************************************************//**
695
Evaluates a predefined function node. */
700
func_node_t* func_node) /*!< in: function node */
707
func = func_node->func;
709
arg1 = func_node->args;
711
if (func == PARS_LENGTH_TOKEN) {
713
int_val = (lint)dfield_get_len(que_node_get_val(arg1));
715
} else if (func == PARS_TO_CHAR_TOKEN) {
717
/* Convert number to character string as a
718
signed decimal integer. */
723
int_val = eval_node_get_int_val(arg1);
725
/* Determine the length of the string. */
728
int_len = 1; /* the number 0 occupies 1 byte */
732
uint_val = ((ulint) -int_val - 1) + 1;
733
int_len++; /* reserve space for minus sign */
735
uint_val = (ulint) int_val;
737
for (; uint_val > 0; int_len++) {
742
/* allocate the string */
743
data = eval_node_ensure_val_buf(func_node, int_len + 1);
745
/* add terminating NUL character */
748
/* convert the number */
755
data[0] = '-'; /* preceding minus sign */
756
uint_val = ((ulint) -int_val - 1) + 1;
758
uint_val = (ulint) int_val;
760
for (tmp = int_len; uint_val > 0; uint_val /= 10) {
762
('0' + (byte)(uint_val % 10));
766
dfield_set_len(que_node_get_val(func_node), int_len);
770
} else if (func == PARS_TO_NUMBER_TOKEN) {
772
int_val = atoi((char*)
773
dfield_get_data(que_node_get_val(arg1)));
775
} else if (func == PARS_SYSDATE_TOKEN) {
776
int_val = (lint)ut_time();
778
eval_predefined_2(func_node);
783
eval_node_set_int_val(func_node, int_val);
786
/*****************************************************************//**
787
Evaluates a function node. */
792
func_node_t* func_node) /*!< in: function node */
798
ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
800
class = func_node->class;
801
func = func_node->func;
803
arg = func_node->args;
805
/* Evaluate first the argument list */
809
/* The functions are not defined for SQL null argument
810
values, except for eval_cmp and notfound */
812
if (dfield_is_null(que_node_get_val(arg))
813
&& (class != PARS_FUNC_CMP)
814
&& (func != PARS_NOTFOUND_TOKEN)
815
&& (func != PARS_PRINTF_TOKEN)) {
819
arg = que_node_get_next(arg);
822
if (class == PARS_FUNC_CMP) {
824
} else if (class == PARS_FUNC_ARITH) {
825
eval_arith(func_node);
826
} else if (class == PARS_FUNC_AGGREGATE) {
827
eval_aggregate(func_node);
828
} else if (class == PARS_FUNC_PREDEFINED) {
830
if (func == PARS_NOTFOUND_TOKEN) {
831
eval_notfound(func_node);
832
} else if (func == PARS_SUBSTR_TOKEN) {
833
eval_substr(func_node);
834
} else if (func == PARS_REPLSTR_TOKEN) {
835
eval_replstr(func_node);
836
} else if (func == PARS_INSTR_TOKEN) {
837
eval_instr(func_node);
838
} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
839
eval_binary_to_number(func_node);
840
} else if (func == PARS_CONCAT_TOKEN) {
841
eval_concat(func_node);
842
} else if (func == PARS_TO_BINARY_TOKEN) {
843
eval_to_binary(func_node);
845
eval_predefined(func_node);
848
ut_ad(class == PARS_FUNC_LOGICAL);
850
eval_logical(func_node);