~drizzle-trunk/drizzle/development

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