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