~ubuntu-branches/ubuntu/precise/mysql-5.5/precise-201203300109

« back to all changes in this revision

Viewing changes to storage/innobase/eval/eval0eval.c

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2011-11-08 11:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20111108113113-3ulw01fvi4vn8m25
Tags: upstream-5.5.17
ImportĀ upstreamĀ versionĀ 5.5.17

Show diffs side-by-side

added added

removed removed

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