~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
4
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.
8
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.
12
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
16
17
*****************************************************************************/
18
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
19
/******************************************************
20
SQL evaluator: evaluates simple data structures, like expressions, in
21
a query graph
22
23
Created 12/29/1997 Heikki Tuuri
24
*******************************************************/
25
26
#include "eval0eval.h"
27
28
#ifdef UNIV_NONINL
29
#include "eval0eval.ic"
30
#endif
31
32
#include "data0data.h"
33
#include "row0sel.h"
34
35
/* The RND function seed */
36
static ulint	eval_rnd	= 128367121;
37
38
/* Dummy adress used when we should allocate a buffer of size 0 in
39
the function below */
40
41
static byte	eval_dummy;
42
43
/*********************************************************************
44
Allocate a buffer from global dynamic memory for a value of a que_node.
45
NOTE that this memory must be explicitly freed when the query graph is
46
freed. If the node already has an allocated buffer, that buffer is freed
47
here. NOTE that this is the only function where dynamic memory should be
48
allocated for a query node val field. */
49
UNIV_INTERN
50
byte*
51
eval_node_alloc_val_buf(
52
/*====================*/
53
				/* out: pointer to allocated buffer */
54
	que_node_t*	node,	/* in: query graph node; sets the val field
55
				data field to point to the new buffer, and
56
				len field equal to size */
57
	ulint		size)	/* in: buffer size */
58
{
59
	dfield_t*	dfield;
60
	byte*		data;
61
62
	ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
63
	      || que_node_get_type(node) == QUE_NODE_FUNC);
64
65
	dfield = que_node_get_val(node);
66
67
	data = dfield_get_data(dfield);
68
69
	if (data && data != &eval_dummy) {
70
		mem_free(data);
71
	}
72
73
	if (size == 0) {
74
		data = &eval_dummy;
75
	} else {
76
		data = mem_alloc(size);
77
	}
78
79
	que_node_set_val_buf_size(node, size);
80
81
	dfield_set_data(dfield, data, size);
82
83
	return(data);
84
}
85
86
/*********************************************************************
87
Free the buffer from global dynamic memory for a value of a que_node,
88
if it has been allocated in the above function. The freeing for pushed
89
column values is done in sel_col_prefetch_buf_free. */
90
UNIV_INTERN
91
void
92
eval_node_free_val_buf(
93
/*===================*/
94
	que_node_t*	node)	/* in: query graph node */
95
{
96
	dfield_t*	dfield;
97
	byte*		data;
98
99
	ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
100
	      || que_node_get_type(node) == QUE_NODE_FUNC);
101
102
	dfield = que_node_get_val(node);
103
104
	data = dfield_get_data(dfield);
105
106
	if (que_node_get_val_buf_size(node) > 0) {
107
		ut_a(data);
108
109
		mem_free(data);
110
	}
111
}
112
113
/*********************************************************************
114
Evaluates a comparison node. */
115
UNIV_INTERN
116
ibool
117
eval_cmp(
118
/*=====*/
119
					/* out: the result of the comparison */
120
	func_node_t*	cmp_node)	/* in: comparison node */
121
{
122
	que_node_t*	arg1;
123
	que_node_t*	arg2;
124
	int		res;
125
	ibool		val;
126
	int		func;
127
128
	ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
129
130
	arg1 = cmp_node->args;
131
	arg2 = que_node_get_next(arg1);
132
133
	res = cmp_dfield_dfield(que_node_get_val(arg1),
134
				que_node_get_val(arg2));
135
	val = TRUE;
136
137
	func = cmp_node->func;
138
139
	if (func == '=') {
140
		if (res != 0) {
141
			val = FALSE;
142
		}
143
	} else if (func == '<') {
144
		if (res != -1) {
145
			val = FALSE;
146
		}
147
	} else if (func == PARS_LE_TOKEN) {
148
		if (res == 1) {
149
			val = FALSE;
150
		}
151
	} else if (func == PARS_NE_TOKEN) {
152
		if (res == 0) {
153
			val = FALSE;
154
		}
155
	} else if (func == PARS_GE_TOKEN) {
156
		if (res == -1) {
157
			val = FALSE;
158
		}
159
	} else {
160
		ut_ad(func == '>');
161
162
		if (res != 1) {
163
			val = FALSE;
164
		}
165
	}
166
167
	eval_node_set_ibool_val(cmp_node, val);
168
169
	return(val);
170
}
171
172
/*********************************************************************
173
Evaluates a logical operation node. */
174
UNIV_INLINE
175
void
176
eval_logical(
177
/*=========*/
178
	func_node_t*	logical_node)	/* in: logical operation node */
179
{
180
	que_node_t*	arg1;
181
	que_node_t*	arg2;
182
	ibool		val1;
183
	ibool		val2 = 0; /* remove warning */
184
	ibool		val = 0;  /* remove warning */
185
	int		func;
186
187
	ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
188
189
	arg1 = logical_node->args;
190
	arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is 'NOT' */
191
192
	val1 = eval_node_get_ibool_val(arg1);
193
194
	if (arg2) {
195
		val2 = eval_node_get_ibool_val(arg2);
196
	}
197
198
	func = logical_node->func;
199
200
	if (func == PARS_AND_TOKEN) {
201
		val = val1 & val2;
202
	} else if (func == PARS_OR_TOKEN) {
203
		val = val1 | val2;
204
	} else if (func == PARS_NOT_TOKEN) {
205
		val = TRUE - val1;
206
	} else {
207
		ut_error;
208
	}
209
210
	eval_node_set_ibool_val(logical_node, val);
211
}
212
213
/*********************************************************************
214
Evaluates an arithmetic operation node. */
215
UNIV_INLINE
216
void
217
eval_arith(
218
/*=======*/
219
	func_node_t*	arith_node)	/* in: arithmetic operation node */
220
{
221
	que_node_t*	arg1;
222
	que_node_t*	arg2;
223
	lint		val1;
224
	lint		val2 = 0; /* remove warning */
225
	lint		val;
226
	int		func;
227
228
	ut_ad(que_node_get_type(arith_node) == QUE_NODE_FUNC);
229
230
	arg1 = arith_node->args;
231
	arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is unary '-' */
232
233
	val1 = eval_node_get_int_val(arg1);
234
235
	if (arg2) {
236
		val2 = eval_node_get_int_val(arg2);
237
	}
238
239
	func = arith_node->func;
240
241
	if (func == '+') {
242
		val = val1 + val2;
243
	} else if ((func == '-') && arg2) {
244
		val = val1 - val2;
245
	} else if (func == '-') {
246
		val = -val1;
247
	} else if (func == '*') {
248
		val = val1 * val2;
249
	} else {
250
		ut_ad(func == '/');
251
		val = val1 / val2;
252
	}
253
254
	eval_node_set_int_val(arith_node, val);
255
}
256
257
/*********************************************************************
258
Evaluates an aggregate operation node. */
259
UNIV_INLINE
260
void
261
eval_aggregate(
262
/*===========*/
263
	func_node_t*	node)	/* in: aggregate operation node */
264
{
265
	que_node_t*	arg;
266
	lint		val;
267
	lint		arg_val;
268
	int		func;
269
270
	ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
271
272
	val = eval_node_get_int_val(node);
273
274
	func = node->func;
275
276
	if (func == PARS_COUNT_TOKEN) {
277
278
		val = val + 1;
279
	} else {
280
		ut_ad(func == PARS_SUM_TOKEN);
281
282
		arg = node->args;
283
		arg_val = eval_node_get_int_val(arg);
284
285
		val = val + arg_val;
286
	}
287
288
	eval_node_set_int_val(node, val);
289
}
290
291
/*********************************************************************
292
Evaluates a predefined function node where the function is not relevant
293
in benchmarks. */
294
static
295
void
296
eval_predefined_2(
297
/*==============*/
298
	func_node_t*	func_node)	/* in: predefined function node */
299
{
300
	que_node_t*	arg;
301
	que_node_t*	arg1;
302
	que_node_t*	arg2 = 0; /* remove warning (??? bug ???) */
303
	lint		int_val;
304
	byte*		data;
305
	ulint		len1;
306
	ulint		len2;
307
	int		func;
308
	ulint		i;
309
310
	ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
311
312
	arg1 = func_node->args;
313
314
	if (arg1) {
315
		arg2 = que_node_get_next(arg1);
316
	}
317
318
	func = func_node->func;
319
320
	if (func == PARS_PRINTF_TOKEN) {
321
322
		arg = arg1;
323
324
		while (arg) {
325
			dfield_print(que_node_get_val(arg));
326
327
			arg = que_node_get_next(arg);
328
		}
329
330
		putc('\n', stderr);
331
332
	} else if (func == PARS_ASSERT_TOKEN) {
333
334
		if (!eval_node_get_ibool_val(arg1)) {
335
			fputs("SQL assertion fails in a stored procedure!\n",
336
			      stderr);
337
		}
338
339
		ut_a(eval_node_get_ibool_val(arg1));
340
341
		/* This function, or more precisely, a debug procedure,
342
		returns no value */
343
344
	} else if (func == PARS_RND_TOKEN) {
345
346
		len1 = (ulint)eval_node_get_int_val(arg1);
347
		len2 = (ulint)eval_node_get_int_val(arg2);
348
349
		ut_ad(len2 >= len1);
350
351
		if (len2 > len1) {
352
			int_val = (lint) (len1
353
					  + (eval_rnd % (len2 - len1 + 1)));
354
		} else {
355
			int_val = (lint) len1;
356
		}
357
358
		eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
359
360
		eval_node_set_int_val(func_node, int_val);
361
362
	} else if (func == PARS_RND_STR_TOKEN) {
363
364
		len1 = (ulint)eval_node_get_int_val(arg1);
365
366
		data = eval_node_ensure_val_buf(func_node, len1);
367
368
		for (i = 0; i < len1; i++) {
369
			data[i] = (byte)(97 + (eval_rnd % 3));
370
371
			eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
372
		}
373
	} else {
374
		ut_error;
375
	}
376
}
377
378
/*********************************************************************
379
Evaluates a notfound-function node. */
380
UNIV_INLINE
381
void
382
eval_notfound(
383
/*==========*/
384
	func_node_t*	func_node)	/* in: function node */
385
{
386
	que_node_t*	arg1;
387
	que_node_t*	arg2;
388
	sym_node_t*	cursor;
389
	sel_node_t*	sel_node;
390
	ibool		ibool_val;
391
392
	arg1 = func_node->args;
393
	arg2 = que_node_get_next(arg1);
394
395
	ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
396
397
	cursor = arg1;
398
399
	ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
400
401
	if (cursor->token_type == SYM_LIT) {
402
403
		ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
404
				"SQL", 3) == 0);
405
406
		sel_node = cursor->sym_table->query_graph->last_sel_node;
407
	} else {
408
		sel_node = cursor->alias->cursor_def;
409
	}
410
411
	if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
412
		ibool_val = TRUE;
413
	} else {
414
		ibool_val = FALSE;
415
	}
416
417
	eval_node_set_ibool_val(func_node, ibool_val);
418
}
419
420
/*********************************************************************
421
Evaluates a substr-function node. */
422
UNIV_INLINE
423
void
424
eval_substr(
425
/*========*/
426
	func_node_t*	func_node)	/* in: function node */
427
{
428
	que_node_t*	arg1;
429
	que_node_t*	arg2;
430
	que_node_t*	arg3;
431
	dfield_t*	dfield;
432
	byte*		str1;
433
	ulint		len1;
434
	ulint		len2;
435
436
	arg1 = func_node->args;
437
	arg2 = que_node_get_next(arg1);
438
439
	ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
440
441
	arg3 = que_node_get_next(arg2);
442
443
	str1 = dfield_get_data(que_node_get_val(arg1));
444
445
	len1 = (ulint)eval_node_get_int_val(arg2);
446
	len2 = (ulint)eval_node_get_int_val(arg3);
447
448
	dfield = que_node_get_val(func_node);
449
450
	dfield_set_data(dfield, str1 + len1, len2);
451
}
452
453
/*********************************************************************
454
Evaluates a replstr-procedure node. */
455
static
456
void
457
eval_replstr(
458
/*=========*/
459
	func_node_t*	func_node)	/* in: function node */
460
{
461
	que_node_t*	arg1;
462
	que_node_t*	arg2;
463
	que_node_t*	arg3;
464
	que_node_t*	arg4;
465
	byte*		str1;
466
	byte*		str2;
467
	ulint		len1;
468
	ulint		len2;
469
470
	arg1 = func_node->args;
471
	arg2 = que_node_get_next(arg1);
472
473
	ut_ad(que_node_get_type(arg1) == QUE_NODE_SYMBOL);
474
475
	arg3 = que_node_get_next(arg2);
476
	arg4 = que_node_get_next(arg3);
477
478
	str1 = dfield_get_data(que_node_get_val(arg1));
479
	str2 = dfield_get_data(que_node_get_val(arg2));
480
481
	len1 = (ulint)eval_node_get_int_val(arg3);
482
	len2 = (ulint)eval_node_get_int_val(arg4);
483
484
	if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
485
	    || (dfield_get_len(que_node_get_val(arg2)) < len2)) {
486
487
		ut_error;
488
	}
489
490
	ut_memcpy(str1 + len1, str2, len2);
491
}
492
493
/*********************************************************************
494
Evaluates an instr-function node. */
495
static
496
void
497
eval_instr(
498
/*=======*/
499
	func_node_t*	func_node)	/* in: function node */
500
{
501
	que_node_t*	arg1;
502
	que_node_t*	arg2;
503
	dfield_t*	dfield1;
504
	dfield_t*	dfield2;
505
	lint		int_val;
506
	byte*		str1;
507
	byte*		str2;
508
	byte		match_char;
509
	ulint		len1;
510
	ulint		len2;
511
	ulint		i;
512
	ulint		j;
513
514
	arg1 = func_node->args;
515
	arg2 = que_node_get_next(arg1);
516
517
	dfield1 = que_node_get_val(arg1);
518
	dfield2 = que_node_get_val(arg2);
519
520
	str1 = dfield_get_data(dfield1);
521
	str2 = dfield_get_data(dfield2);
522
523
	len1 = dfield_get_len(dfield1);
524
	len2 = dfield_get_len(dfield2);
525
526
	if (len2 == 0) {
527
		ut_error;
528
	}
529
530
	match_char = str2[0];
531
532
	for (i = 0; i < len1; i++) {
533
		/* In this outer loop, the number of matched characters is 0 */
534
535
		if (str1[i] == match_char) {
536
537
			if (i + len2 > len1) {
538
539
				break;
540
			}
541
542
			for (j = 1;; j++) {
543
				/* We have already matched j characters */
544
545
				if (j == len2) {
546
					int_val = i + 1;
547
548
					goto match_found;
549
				}
550
551
				if (str1[i + j] != str2[j]) {
552
553
					break;
554
				}
555
			}
556
		}
557
	}
558
559
	int_val = 0;
560
561
match_found:
562
	eval_node_set_int_val(func_node, int_val);
563
}
564
565
/*********************************************************************
566
Evaluates a predefined function node. */
567
UNIV_INLINE
568
void
569
eval_binary_to_number(
570
/*==================*/
571
	func_node_t*	func_node)	/* in: function node */
572
{
573
	que_node_t*	arg1;
574
	dfield_t*	dfield;
575
	byte*		str1;
576
	byte*		str2;
577
	ulint		len1;
578
	ulint		int_val;
579
580
	arg1 = func_node->args;
581
582
	dfield = que_node_get_val(arg1);
583
584
	str1 = dfield_get_data(dfield);
585
	len1 = dfield_get_len(dfield);
586
587
	if (len1 > 4) {
588
		ut_error;
589
	}
590
591
	if (len1 == 4) {
592
		str2 = str1;
593
	} else {
594
		int_val = 0;
595
		str2 = (byte*)&int_val;
596
597
		ut_memcpy(str2 + (4 - len1), str1, len1);
598
	}
599
600
	eval_node_copy_and_alloc_val(func_node, str2, 4);
601
}
602
603
/*********************************************************************
604
Evaluates a predefined function node. */
605
static
606
void
607
eval_concat(
608
/*========*/
609
	func_node_t*	func_node)	/* in: function node */
610
{
611
	que_node_t*	arg;
612
	dfield_t*	dfield;
613
	byte*		data;
614
	ulint		len;
615
	ulint		len1;
616
617
	arg = func_node->args;
618
	len = 0;
619
620
	while (arg) {
621
		len1 = dfield_get_len(que_node_get_val(arg));
622
623
		len += len1;
624
625
		arg = que_node_get_next(arg);
626
	}
627
628
	data = eval_node_ensure_val_buf(func_node, len);
629
630
	arg = func_node->args;
631
	len = 0;
632
633
	while (arg) {
634
		dfield = que_node_get_val(arg);
635
		len1 = dfield_get_len(dfield);
636
637
		ut_memcpy(data + len, dfield_get_data(dfield), len1);
638
639
		len += len1;
640
641
		arg = que_node_get_next(arg);
642
	}
643
}
644
645
/*********************************************************************
646
Evaluates a predefined function node. If the first argument is an integer,
647
this function looks at the second argument which is the integer length in
648
bytes, and converts the integer to a VARCHAR.
649
If the first argument is of some other type, this function converts it to
650
BINARY. */
651
UNIV_INLINE
652
void
653
eval_to_binary(
654
/*===========*/
655
	func_node_t*	func_node)	/* in: function node */
656
{
657
	que_node_t*	arg1;
658
	que_node_t*	arg2;
659
	dfield_t*	dfield;
660
	byte*		str1;
661
	ulint		len;
662
	ulint		len1;
663
664
	arg1 = func_node->args;
665
666
	str1 = dfield_get_data(que_node_get_val(arg1));
667
668
	if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
669
670
		len = dfield_get_len(que_node_get_val(arg1));
671
672
		dfield = que_node_get_val(func_node);
673
674
		dfield_set_data(dfield, str1, len);
675
676
		return;
677
	}
678
679
	arg2 = que_node_get_next(arg1);
680
681
	len1 = (ulint)eval_node_get_int_val(arg2);
682
683
	if (len1 > 4) {
684
685
		ut_error;
686
	}
687
688
	dfield = que_node_get_val(func_node);
689
690
	dfield_set_data(dfield, str1 + (4 - len1), len1);
691
}
692
693
/*********************************************************************
694
Evaluates a predefined function node. */
695
UNIV_INLINE
696
void
697
eval_predefined(
698
/*============*/
699
	func_node_t*	func_node)	/* in: function node */
700
{
701
	que_node_t*	arg1;
702
	lint		int_val;
703
	byte*		data;
704
	int		func;
705
706
	func = func_node->func;
707
708
	arg1 = func_node->args;
709
710
	if (func == PARS_LENGTH_TOKEN) {
711
712
		int_val = (lint)dfield_get_len(que_node_get_val(arg1));
713
714
	} else if (func == PARS_TO_CHAR_TOKEN) {
715
716
		/* Convert number to character string as a
717
		signed decimal integer. */
718
719
		ulint	uint_val;
720
		int	int_len;
721
722
		int_val = eval_node_get_int_val(arg1);
723
724
		/* Determine the length of the string. */
725
726
		if (int_val == 0) {
727
			int_len = 1; /* the number 0 occupies 1 byte */
728
		} else {
729
			int_len = 0;
730
			if (int_val < 0) {
731
				uint_val = ((ulint) -int_val - 1) + 1;
732
				int_len++; /* reserve space for minus sign */
733
			} else {
734
				uint_val = (ulint) int_val;
735
			}
736
			for (; uint_val > 0; int_len++) {
737
				uint_val /= 10;
738
			}
739
		}
740
741
		/* allocate the string */
742
		data = eval_node_ensure_val_buf(func_node, int_len + 1);
743
744
		/* add terminating NUL character */
745
		data[int_len] = 0;
746
747
		/* convert the number */
748
749
		if (int_val == 0) {
750
			data[0] = '0';
751
		} else {
752
			int tmp;
753
			if (int_val < 0) {
754
				data[0] = '-'; /* preceding minus sign */
755
				uint_val = ((ulint) -int_val - 1) + 1;
756
			} else {
757
				uint_val = (ulint) int_val;
758
			}
759
			for (tmp = int_len; uint_val > 0; uint_val /= 10) {
760
				data[--tmp] = (byte)
761
					('0' + (byte)(uint_val % 10));
762
			}
763
		}
764
765
		dfield_set_len(que_node_get_val(func_node), int_len);
766
767
		return;
768
769
	} else if (func == PARS_TO_NUMBER_TOKEN) {
770
771
		int_val = atoi((char*)
772
			       dfield_get_data(que_node_get_val(arg1)));
773
774
	} else if (func == PARS_SYSDATE_TOKEN) {
775
		int_val = (lint)ut_time();
776
	} else {
777
		eval_predefined_2(func_node);
778
779
		return;
780
	}
781
782
	eval_node_set_int_val(func_node, int_val);
783
}
784
785
/*********************************************************************
786
Evaluates a function node. */
787
UNIV_INTERN
788
void
789
eval_func(
790
/*======*/
791
	func_node_t*	func_node)	/* in: function node */
792
{
793
	que_node_t*	arg;
794
	ulint		class;
795
	ulint		func;
796
797
	ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
798
799
	class = func_node->class;
800
	func = func_node->func;
801
802
	arg = func_node->args;
803
804
	/* Evaluate first the argument list */
805
	while (arg) {
806
		eval_exp(arg);
807
808
		/* The functions are not defined for SQL null argument
809
		values, except for eval_cmp and notfound */
810
811
		if (dfield_is_null(que_node_get_val(arg))
812
		    && (class != PARS_FUNC_CMP)
813
		    && (func != PARS_NOTFOUND_TOKEN)
814
		    && (func != PARS_PRINTF_TOKEN)) {
815
			ut_error;
816
		}
817
818
		arg = que_node_get_next(arg);
819
	}
820
821
	if (class == PARS_FUNC_CMP) {
822
		eval_cmp(func_node);
823
	} else if (class == PARS_FUNC_ARITH) {
824
		eval_arith(func_node);
825
	} else if (class == PARS_FUNC_AGGREGATE) {
826
		eval_aggregate(func_node);
827
	} else if (class == PARS_FUNC_PREDEFINED) {
828
829
		if (func == PARS_NOTFOUND_TOKEN) {
830
			eval_notfound(func_node);
831
		} else if (func == PARS_SUBSTR_TOKEN) {
832
			eval_substr(func_node);
833
		} else if (func == PARS_REPLSTR_TOKEN) {
834
			eval_replstr(func_node);
835
		} else if (func == PARS_INSTR_TOKEN) {
836
			eval_instr(func_node);
837
		} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
838
			eval_binary_to_number(func_node);
839
		} else if (func == PARS_CONCAT_TOKEN) {
840
			eval_concat(func_node);
841
		} else if (func == PARS_TO_BINARY_TOKEN) {
842
			eval_to_binary(func_node);
843
		} else {
844
			eval_predefined(func_node);
845
		}
846
	} else {
847
		ut_ad(class == PARS_FUNC_LOGICAL);
848
849
		eval_logical(func_node);
850
	}
851
}