1 /*****************************************************************************
2
3 Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2019, MariaDB Corporation.
5
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
17
18 *****************************************************************************/
19
20 /**************************************************//**
21 @file eval/eval0eval.cc
22 SQL evaluator: evaluates simple data structures, like expressions, in
23 a query graph
24
25 Created 12/29/1997 Heikki Tuuri
26 *******************************************************/
27
28 #include "eval0eval.h"
29 #include "data0data.h"
30 #include "row0sel.h"
31 #include "rem0cmp.h"
32
33 /** Dummy adress used when we should allocate a buffer of size 0 in
34 eval_node_alloc_val_buf */
35
36 static byte eval_dummy;
37
38 /*************************************************************************
39 Gets the like node from the node */
40 UNIV_INLINE
41 que_node_t*
que_node_get_like_node(que_node_t * node)42 que_node_get_like_node(
43 /*===================*/
44 /* out: next node in a list of nodes */
45 que_node_t* node) /* in: node in a list */
46 {
47 return(((sym_node_t*) node)->like_node);
48 }
49
50 /*****************************************************************//**
51 Allocate a buffer from global dynamic memory for a value of a que_node.
52 NOTE that this memory must be explicitly freed when the query graph is
53 freed. If the node already has an allocated buffer, that buffer is freed
54 here. NOTE that this is the only function where dynamic memory should be
55 allocated for a query node val field.
56 @return pointer to allocated buffer */
57 byte*
eval_node_alloc_val_buf(que_node_t * node,ulint size)58 eval_node_alloc_val_buf(
59 /*====================*/
60 que_node_t* node, /*!< in: query graph node; sets the val field
61 data field to point to the new buffer, and
62 len field equal to size */
63 ulint size) /*!< in: buffer size */
64 {
65 dfield_t* dfield;
66 byte* data;
67
68 ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
69 || que_node_get_type(node) == QUE_NODE_FUNC);
70
71 dfield = que_node_get_val(node);
72
73 data = static_cast<byte*>(dfield_get_data(dfield));
74
75 if (data != &eval_dummy) {
76 ut_free(data);
77 }
78
79 if (size == 0) {
80 data = &eval_dummy;
81 } else {
82 data = static_cast<byte*>(ut_malloc_nokey(size));
83 }
84
85 que_node_set_val_buf_size(node, size);
86
87 dfield_set_data(dfield, data, size);
88
89 return(data);
90 }
91
92 /*****************************************************************//**
93 Free the buffer from global dynamic memory for a value of a que_node,
94 if it has been allocated in the above function. The freeing for pushed
95 column values is done in sel_col_prefetch_buf_free. */
96 void
eval_node_free_val_buf(que_node_t * node)97 eval_node_free_val_buf(
98 /*===================*/
99 que_node_t* node) /*!< in: query graph node */
100 {
101 dfield_t* dfield;
102 byte* data;
103
104 ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
105 || que_node_get_type(node) == QUE_NODE_FUNC);
106
107 dfield = que_node_get_val(node);
108
109 data = static_cast<byte*>(dfield_get_data(dfield));
110
111 if (que_node_get_val_buf_size(node) > 0) {
112 ut_a(data);
113
114 ut_free(data);
115 }
116 }
117
118 /*********************************************************************
119 Evaluates a LIKE comparison node.
120 @return the result of the comparison */
121 UNIV_INLINE
122 ibool
eval_cmp_like(que_node_t * arg1,que_node_t * arg2)123 eval_cmp_like(
124 /*==========*/
125 que_node_t* arg1, /* !< in: left operand */
126 que_node_t* arg2) /* !< in: right operand */
127 {
128 ib_like_t op;
129 que_node_t* arg3;
130 que_node_t* arg4;
131 const dfield_t* dfield;
132
133 arg3 = que_node_get_like_node(arg2);
134
135 /* Get the comparison type operator */
136 ut_a(arg3);
137
138 dfield = que_node_get_val(arg3);
139 ut_ad(dtype_get_mtype(dfield_get_type(dfield)) == DATA_INT);
140 op = static_cast<ib_like_t>(
141 mach_read_from_4(static_cast<const byte*>(
142 dfield_get_data(dfield))));
143
144 switch (op) {
145 case IB_LIKE_PREFIX:
146 arg4 = que_node_get_next(arg3);
147 return(!cmp_dfield_dfield_like_prefix(que_node_get_val(arg1),
148 que_node_get_val(arg4)));
149 case IB_LIKE_EXACT:
150 return(!cmp_dfield_dfield(que_node_get_val(arg1),
151 que_node_get_val(arg2)));
152 }
153
154 ut_error;
155 return(FALSE);
156 }
157
158 /*********************************************************************
159 Evaluates a comparison node.
160 @return the result of the comparison */
161 ibool
eval_cmp(func_node_t * cmp_node)162 eval_cmp(
163 /*=====*/
164 func_node_t* cmp_node) /*!< in: comparison node */
165 {
166 que_node_t* arg1;
167 que_node_t* arg2;
168 int res;
169 ibool val = FALSE; /* remove warning */
170
171 ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
172
173 arg1 = cmp_node->args;
174 arg2 = que_node_get_next(arg1);
175
176 switch (cmp_node->func) {
177 case '<':
178 case '=':
179 case '>':
180 case PARS_LE_TOKEN:
181 case PARS_NE_TOKEN:
182 case PARS_GE_TOKEN:
183 res = cmp_dfield_dfield(
184 que_node_get_val(arg1), que_node_get_val(arg2));
185
186 switch (cmp_node->func) {
187 case '<':
188 val = (res < 0);
189 break;
190 case '=':
191 val = (res == 0);
192 break;
193 case '>':
194 val = (res > 0);
195 break;
196 case PARS_LE_TOKEN:
197 val = (res <= 0);
198 break;
199 case PARS_NE_TOKEN:
200 val = (res != 0);
201 break;
202 case PARS_GE_TOKEN:
203 val = (res >= 0);
204 break;
205 }
206 break;
207 default:
208 val = eval_cmp_like(arg1, arg2);
209 break;
210 }
211
212 eval_node_set_ibool_val(cmp_node, val);
213
214 return(val);
215 }
216
217 /*****************************************************************//**
218 Evaluates a logical operation node. */
219 UNIV_INLINE
220 void
eval_logical(func_node_t * logical_node)221 eval_logical(
222 /*=========*/
223 func_node_t* logical_node) /*!< in: logical operation node */
224 {
225 que_node_t* arg1;
226 que_node_t* arg2;
227 ibool val1;
228 ibool val2 = 0; /* remove warning */
229 ibool val = 0; /* remove warning */
230 int func;
231
232 ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
233
234 arg1 = logical_node->args;
235 arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is 'NOT' */
236
237 val1 = eval_node_get_ibool_val(arg1);
238
239 if (arg2) {
240 val2 = eval_node_get_ibool_val(arg2);
241 }
242
243 func = logical_node->func;
244
245 if (func == PARS_AND_TOKEN) {
246 val = val1 & val2;
247 } else if (func == PARS_OR_TOKEN) {
248 val = val1 | val2;
249 } else if (func == PARS_NOT_TOKEN) {
250 val = TRUE - val1;
251 } else {
252 ut_error;
253 }
254
255 eval_node_set_ibool_val(logical_node, val);
256 }
257
258 /*****************************************************************//**
259 Evaluates an arithmetic operation node. */
260 UNIV_INLINE
261 void
eval_arith(func_node_t * arith_node)262 eval_arith(
263 /*=======*/
264 func_node_t* arith_node) /*!< in: arithmetic operation node */
265 {
266 que_node_t* arg1;
267 que_node_t* arg2;
268 lint val1;
269 lint val2 = 0; /* remove warning */
270 lint val;
271 int func;
272
273 ut_ad(que_node_get_type(arith_node) == QUE_NODE_FUNC);
274
275 arg1 = arith_node->args;
276 arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is unary '-' */
277
278 val1 = eval_node_get_int_val(arg1);
279
280 if (arg2) {
281 val2 = eval_node_get_int_val(arg2);
282 }
283
284 func = arith_node->func;
285
286 if (func == '+') {
287 val = val1 + val2;
288 } else if ((func == '-') && arg2) {
289 val = val1 - val2;
290 } else if (func == '-') {
291 val = -val1;
292 } else if (func == '*') {
293 val = val1 * val2;
294 } else {
295 ut_ad(func == '/');
296 val = val1 / val2;
297 }
298
299 eval_node_set_int_val(arith_node, val);
300 }
301
302 /*****************************************************************//**
303 Evaluates an aggregate operation node. */
304 UNIV_INLINE
305 void
eval_aggregate(func_node_t * node)306 eval_aggregate(
307 /*===========*/
308 func_node_t* node) /*!< in: aggregate operation node */
309 {
310 lint val;
311
312 ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
313
314 val = eval_node_get_int_val(node);
315
316 ut_a(node->func == PARS_COUNT_TOKEN);
317 val = val + 1;
318 eval_node_set_int_val(node, val);
319 }
320
321 /*****************************************************************//**
322 Evaluates a notfound-function node. */
323 UNIV_INLINE
324 void
eval_notfound(func_node_t * func_node)325 eval_notfound(
326 /*==========*/
327 func_node_t* func_node) /*!< in: function node */
328 {
329 sym_node_t* cursor;
330 sel_node_t* sel_node;
331 ibool ibool_val;
332
333 ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
334
335 cursor = static_cast<sym_node_t*>(func_node->args);
336
337 ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
338
339 if (cursor->token_type == SYM_LIT) {
340
341 ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
342 "SQL", 3) == 0);
343
344 sel_node = cursor->sym_table->query_graph->last_sel_node;
345 } else {
346 sel_node = cursor->alias->cursor_def;
347 }
348
349 if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
350 ibool_val = TRUE;
351 } else {
352 ibool_val = FALSE;
353 }
354
355 eval_node_set_ibool_val(func_node, ibool_val);
356 }
357
358 /*****************************************************************//**
359 Evaluates a substr-function node. */
360 UNIV_INLINE
361 void
eval_substr(func_node_t * func_node)362 eval_substr(
363 /*========*/
364 func_node_t* func_node) /*!< in: function node */
365 {
366 que_node_t* arg1;
367 que_node_t* arg2;
368 que_node_t* arg3;
369 dfield_t* dfield;
370 byte* str1;
371 ulint len1;
372 ulint len2;
373
374 arg1 = func_node->args;
375 arg2 = que_node_get_next(arg1);
376
377 ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
378
379 arg3 = que_node_get_next(arg2);
380
381 str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
382
383 len1 = (ulint) eval_node_get_int_val(arg2);
384 len2 = (ulint) eval_node_get_int_val(arg3);
385
386 dfield = que_node_get_val(func_node);
387
388 dfield_set_data(dfield, str1 + len1, len2);
389 }
390
391 /*****************************************************************//**
392 Evaluates an instr-function node. */
393 static
394 void
eval_instr(func_node_t * func_node)395 eval_instr(
396 /*=======*/
397 func_node_t* func_node) /*!< in: function node */
398 {
399 que_node_t* arg1;
400 que_node_t* arg2;
401 dfield_t* dfield1;
402 dfield_t* dfield2;
403 lint int_val;
404 byte* str1;
405 byte* str2;
406 byte match_char;
407 ulint len1;
408 ulint len2;
409 ulint i;
410 ulint j;
411
412 arg1 = func_node->args;
413 arg2 = que_node_get_next(arg1);
414
415 dfield1 = que_node_get_val(arg1);
416 dfield2 = que_node_get_val(arg2);
417
418 str1 = static_cast<byte*>(dfield_get_data(dfield1));
419 str2 = static_cast<byte*>(dfield_get_data(dfield2));
420
421 len1 = dfield_get_len(dfield1);
422 len2 = dfield_get_len(dfield2);
423
424 if (len2 == 0) {
425 ut_error;
426 }
427
428 match_char = str2[0];
429
430 for (i = 0; i < len1; i++) {
431 /* In this outer loop, the number of matched characters is 0 */
432
433 if (str1[i] == match_char) {
434
435 if (i + len2 > len1) {
436
437 break;
438 }
439
440 for (j = 1;; j++) {
441 /* We have already matched j characters */
442
443 if (j == len2) {
444 int_val = lint(i) + 1;
445
446 goto match_found;
447 }
448
449 if (str1[i + j] != str2[j]) {
450
451 break;
452 }
453 }
454 }
455 }
456
457 int_val = 0;
458
459 match_found:
460 eval_node_set_int_val(func_node, int_val);
461 }
462
463 /*****************************************************************//**
464 Evaluates a predefined function node. */
465 static
466 void
eval_concat(func_node_t * func_node)467 eval_concat(
468 /*========*/
469 func_node_t* func_node) /*!< in: function node */
470 {
471 que_node_t* arg;
472 dfield_t* dfield;
473 byte* data;
474 ulint len;
475 ulint len1;
476
477 arg = func_node->args;
478 len = 0;
479
480 while (arg) {
481 len1 = dfield_get_len(que_node_get_val(arg));
482
483 len += len1;
484
485 arg = que_node_get_next(arg);
486 }
487
488 data = eval_node_ensure_val_buf(func_node, len);
489
490 arg = func_node->args;
491 len = 0;
492
493 while (arg) {
494 dfield = que_node_get_val(arg);
495 len1 = dfield_get_len(dfield);
496
497 ut_memcpy(data + len, dfield_get_data(dfield), len1);
498
499 len += len1;
500
501 arg = que_node_get_next(arg);
502 }
503 }
504
505 /*****************************************************************//**
506 Evaluates a predefined function node. If the first argument is an integer,
507 this function looks at the second argument which is the integer length in
508 bytes, and converts the integer to a VARCHAR.
509 If the first argument is of some other type, this function converts it to
510 BINARY. */
511 UNIV_INLINE
512 void
eval_to_binary(func_node_t * func_node)513 eval_to_binary(
514 /*===========*/
515 func_node_t* func_node) /*!< in: function node */
516 {
517 que_node_t* arg1;
518 que_node_t* arg2;
519 dfield_t* dfield;
520 byte* str1;
521 ulint len;
522 ulint len1;
523
524 arg1 = func_node->args;
525
526 str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
527
528 if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
529
530 len = dfield_get_len(que_node_get_val(arg1));
531
532 dfield = que_node_get_val(func_node);
533
534 dfield_set_data(dfield, str1, len);
535
536 return;
537 }
538
539 arg2 = que_node_get_next(arg1);
540
541 len1 = (ulint) eval_node_get_int_val(arg2);
542
543 if (len1 > 4) {
544
545 ut_error;
546 }
547
548 dfield = que_node_get_val(func_node);
549
550 dfield_set_data(dfield, str1 + (4 - len1), len1);
551 }
552
553 /*****************************************************************//**
554 Evaluate LENGTH(). */
eval_length(func_node_t * func_node)555 inline void eval_length(func_node_t* func_node)
556 {
557 eval_node_set_int_val(func_node,
558 dfield_get_len(que_node_get_val
559 (func_node->args)));
560 }
561
562 /*****************************************************************//**
563 Evaluates a function node. */
564 void
eval_func(func_node_t * func_node)565 eval_func(
566 /*======*/
567 func_node_t* func_node) /*!< in: function node */
568 {
569 que_node_t* arg;
570 ulint fclass;
571
572 ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
573
574 fclass = func_node->fclass;
575 const int func = func_node->func;
576
577 arg = func_node->args;
578
579 /* Evaluate first the argument list */
580 while (arg) {
581 eval_exp(arg);
582
583 /* The functions are not defined for SQL null argument
584 values, except for eval_cmp and notfound */
585
586 if (dfield_is_null(que_node_get_val(arg))
587 && (fclass != PARS_FUNC_CMP)
588 && (func != PARS_NOTFOUND_TOKEN)) {
589 ut_error;
590 }
591
592 arg = que_node_get_next(arg);
593 }
594
595 switch (fclass) {
596 case PARS_FUNC_CMP:
597 eval_cmp(func_node);
598 return;
599 case PARS_FUNC_ARITH:
600 eval_arith(func_node);
601 return;
602 case PARS_FUNC_AGGREGATE:
603 eval_aggregate(func_node);
604 return;
605 case PARS_FUNC_PREDEFINED:
606 switch (func) {
607 case PARS_NOTFOUND_TOKEN:
608 eval_notfound(func_node);
609 return;
610 case PARS_SUBSTR_TOKEN:
611 eval_substr(func_node);
612 return;
613 case PARS_INSTR_TOKEN:
614 eval_instr(func_node);
615 return;
616 case PARS_CONCAT_TOKEN:
617 eval_concat(func_node);
618 return;
619 case PARS_TO_BINARY_TOKEN:
620 eval_to_binary(func_node);
621 return;
622 case PARS_LENGTH_TOKEN:
623 eval_length(func_node);
624 return;
625 default:
626 ut_error;
627 }
628 case PARS_FUNC_LOGICAL:
629 eval_logical(func_node);
630 return;
631 }
632
633 ut_error;
634 }
635