1/*****************************************************************************
2
3Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
16Fifth Floor, Boston, MA 02110-1301 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file pars/pars0pars.c
22SQL parser
23
24Created 11/19/1996 Heikki Tuuri
25*******************************************************/
26
27/* Historical note: Innobase executed its first SQL string (CREATE TABLE)
28on 1/27/1998 */
29
30#include "ha_prototypes.h"
31
32#include "pars0pars.h"
33#include "row0sel.h"
34#include "row0ins.h"
35#include "row0upd.h"
36#include "dict0dict.h"
37#include "dict0mem.h"
38#include "dict0crea.h"
39#include "que0que.h"
40#include "pars0grm.h"
41#include "pars0opt.h"
42#include "data0data.h"
43#include "data0type.h"
44#include "trx0trx.h"
45#include "trx0roll.h"
46#include "lock0lock.h"
47#include "eval0eval.h"
48
49/* Global variable used while parsing a single procedure or query : the code is
50NOT re-entrant */
51sym_tab_t* pars_sym_tab_global;
52
53/* Global variables used to denote certain reserved words, used in
54constructing the parsing tree */
55
56pars_res_word_t pars_to_char_token = {PARS_TO_CHAR_TOKEN};
57pars_res_word_t pars_to_number_token = {PARS_TO_NUMBER_TOKEN};
58pars_res_word_t pars_to_binary_token = {PARS_TO_BINARY_TOKEN};
59pars_res_word_t pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};
60pars_res_word_t pars_substr_token = {PARS_SUBSTR_TOKEN};
61pars_res_word_t pars_replstr_token = {PARS_REPLSTR_TOKEN};
62pars_res_word_t pars_concat_token = {PARS_CONCAT_TOKEN};
63pars_res_word_t pars_instr_token = {PARS_INSTR_TOKEN};
64pars_res_word_t pars_length_token = {PARS_LENGTH_TOKEN};
65pars_res_word_t pars_sysdate_token = {PARS_SYSDATE_TOKEN};
66pars_res_word_t pars_printf_token = {PARS_PRINTF_TOKEN};
67pars_res_word_t pars_assert_token = {PARS_ASSERT_TOKEN};
68pars_res_word_t pars_rnd_token = {PARS_RND_TOKEN};
69pars_res_word_t pars_rnd_str_token = {PARS_RND_STR_TOKEN};
70pars_res_word_t pars_count_token = {PARS_COUNT_TOKEN};
71pars_res_word_t pars_sum_token = {PARS_SUM_TOKEN};
72pars_res_word_t pars_distinct_token = {PARS_DISTINCT_TOKEN};
73pars_res_word_t pars_binary_token = {PARS_BINARY_TOKEN};
74pars_res_word_t pars_blob_token = {PARS_BLOB_TOKEN};
75pars_res_word_t pars_int_token = {PARS_INT_TOKEN};
76pars_res_word_t pars_bigint_token = {PARS_BIGINT_TOKEN};
77pars_res_word_t pars_char_token = {PARS_CHAR_TOKEN};
78pars_res_word_t pars_float_token = {PARS_FLOAT_TOKEN};
79pars_res_word_t pars_update_token = {PARS_UPDATE_TOKEN};
80pars_res_word_t pars_asc_token = {PARS_ASC_TOKEN};
81pars_res_word_t pars_desc_token = {PARS_DESC_TOKEN};
82pars_res_word_t pars_open_token = {PARS_OPEN_TOKEN};
83pars_res_word_t pars_close_token = {PARS_CLOSE_TOKEN};
84pars_res_word_t pars_share_token = {PARS_SHARE_TOKEN};
85pars_res_word_t pars_unique_token = {PARS_UNIQUE_TOKEN};
86pars_res_word_t pars_clustered_token = {PARS_CLUSTERED_TOKEN};
87
88/** Global variable used to denote the '*' in SELECT * FROM.. */
89ulint pars_star_denoter = 12345678;
90
91/********************************************************************
92Get user function with the given name.*/
93UNIV_INLINE
94pars_user_func_t*
95pars_info_lookup_user_func(
96/*=======================*/
97 /* out: user func, or NULL if not
98 found */
99 pars_info_t* info, /* in: info struct */
100 const char* name) /* in: function name to find*/
101{
102 if (info && info->funcs) {
103 ulint i;
104 ib_vector_t* vec = info->funcs;
105
106 for (i = 0; i < ib_vector_size(vec); i++) {
107 pars_user_func_t* puf;
108
109 puf = static_cast<pars_user_func_t*>(
110 ib_vector_get(vec, i));
111
112 if (strcmp(puf->name, name) == 0) {
113 return(puf);
114 }
115 }
116 }
117
118 return(NULL);
119}
120
121/********************************************************************
122Get bound identifier with the given name.*/
123UNIV_INLINE
124pars_bound_id_t*
125pars_info_lookup_bound_id(
126/*======================*/
127 /* out: bound literal, or NULL if
128 not found */
129 pars_info_t* info, /* in: info struct */
130 const char* name) /* in: bound literal name to find */
131{
132 if (info && info->bound_ids) {
133 ulint i;
134 ib_vector_t* vec = info->bound_ids;
135
136 for (i = 0; i < ib_vector_size(vec); i++) {
137 pars_bound_id_t* bid;
138
139 bid = static_cast<pars_bound_id_t*>(
140 ib_vector_get(vec, i));
141
142 if (strcmp(bid->name, name) == 0) {
143 return(bid);
144 }
145 }
146 }
147
148 return(NULL);
149}
150
151/********************************************************************
152Get bound literal with the given name.*/
153UNIV_INLINE
154pars_bound_lit_t*
155pars_info_lookup_bound_lit(
156/*=======================*/
157 /* out: bound literal, or NULL if
158 not found */
159 pars_info_t* info, /* in: info struct */
160 const char* name) /* in: bound literal name to find */
161{
162 if (info && info->bound_lits) {
163 ulint i;
164 ib_vector_t* vec = info->bound_lits;
165
166 for (i = 0; i < ib_vector_size(vec); i++) {
167 pars_bound_lit_t* pbl;
168
169 pbl = static_cast<pars_bound_lit_t*>(
170 ib_vector_get(vec, i));
171
172 if (strcmp(pbl->name, name) == 0) {
173 return(pbl);
174 }
175 }
176 }
177
178 return(NULL);
179}
180
181/*********************************************************************//**
182Determines the class of a function code.
183@return function class: PARS_FUNC_ARITH, ... */
184static
185ulint
186pars_func_get_class(
187/*================*/
188 int func) /*!< in: function code: '=', PARS_GE_TOKEN, ... */
189{
190 switch (func) {
191 case '+': case '-': case '*': case '/':
192 return(PARS_FUNC_ARITH);
193
194 case '=': case '<': case '>':
195 case PARS_GE_TOKEN: case PARS_LE_TOKEN: case PARS_NE_TOKEN:
196 return(PARS_FUNC_CMP);
197
198 case PARS_AND_TOKEN: case PARS_OR_TOKEN: case PARS_NOT_TOKEN:
199 return(PARS_FUNC_LOGICAL);
200
201 case PARS_COUNT_TOKEN: case PARS_SUM_TOKEN:
202 return(PARS_FUNC_AGGREGATE);
203
204 case PARS_TO_CHAR_TOKEN:
205 case PARS_TO_NUMBER_TOKEN:
206 case PARS_TO_BINARY_TOKEN:
207 case PARS_BINARY_TO_NUMBER_TOKEN:
208 case PARS_SUBSTR_TOKEN:
209 case PARS_CONCAT_TOKEN:
210 case PARS_LENGTH_TOKEN:
211 case PARS_INSTR_TOKEN:
212 case PARS_SYSDATE_TOKEN:
213 case PARS_NOTFOUND_TOKEN:
214 case PARS_PRINTF_TOKEN:
215 case PARS_ASSERT_TOKEN:
216 case PARS_RND_TOKEN:
217 case PARS_RND_STR_TOKEN:
218 case PARS_REPLSTR_TOKEN:
219 return(PARS_FUNC_PREDEFINED);
220
221 default:
222 return(PARS_FUNC_OTHER);
223 }
224}
225
226/*********************************************************************//**
227Parses an operator or predefined function expression.
228@return own: function node in a query tree */
229static
230func_node_t*
231pars_func_low(
232/*==========*/
233 int func, /*!< in: function token code */
234 que_node_t* arg) /*!< in: first argument in the argument list */
235{
236 func_node_t* node;
237
238 node = static_cast<func_node_t*>(
239 mem_heap_alloc(pars_sym_tab_global->heap, sizeof(func_node_t)));
240
241 node->common.type = QUE_NODE_FUNC;
242 dfield_set_data(&(node->common.val), NULL, 0);
243 node->common.val_buf_size = 0;
244
245 node->func = func;
246
247 node->fclass = pars_func_get_class(func);
248
249 node->args = arg;
250
251 UT_LIST_ADD_LAST(pars_sym_tab_global->func_node_list, node);
252
253 return(node);
254}
255
256/*********************************************************************//**
257Parses a function expression.
258@return own: function node in a query tree */
259func_node_t*
260pars_func(
261/*======*/
262 que_node_t* res_word,/*!< in: function name reserved word */
263 que_node_t* arg) /*!< in: first argument in the argument list */
264{
265 return(pars_func_low(((pars_res_word_t*) res_word)->code, arg));
266}
267
268/*************************************************************************
269Rebind a LIKE search string. NOTE: We ignore any '%' characters embedded
270within the search string.*/
271int
272pars_like_rebind(
273/*=============*/
274 /* out, own: function node in a query tree */
275 sym_node_t* node, /* in: The search string node.*/
276 const byte* ptr, /* in: literal to (re) bind */
277 ulint ptr_len)/* in: length of literal to (re) bind*/
278{
279 dtype_t* dtype;
280 dfield_t* dfield;
281 ib_like_t op_check;
282 sym_node_t* like_node;
283 sym_node_t* str_node = NULL;
284 ib_like_t op = IB_LIKE_EXACT;
285 int func = PARS_LIKE_TOKEN_EXACT;
286
287 /* Is this a STRING% ? */
288 if (ptr[ptr_len - 1] == '%') {
289 op = IB_LIKE_PREFIX;
290 }
291
292 /* Is this a '%STRING' or %STRING% ?*/
293 ut_ad(*ptr != '%');
294
295 if (node->like_node == NULL) {
296 /* Add the LIKE operator info node to the node list.
297 This will be used during the comparison phase to determine
298 how to match.*/
299 like_node = sym_tab_add_int_lit(node->sym_table, op);
300 que_node_list_add_last(NULL, like_node);
301 node->like_node = like_node;
302 str_node = sym_tab_add_str_lit(node->sym_table, ptr, ptr_len);
303 que_node_list_add_last(like_node, str_node);
304 } else {
305 like_node = node->like_node;
306
307 /* Change the value of the string in the existing
308 string node of like node */
309 str_node = static_cast<sym_node_t*>(
310 que_node_list_get_last(like_node));
311
312 /* Must find the string node */
313 ut_a(str_node);
314 ut_a(str_node != like_node);
315 ut_a(str_node->token_type == SYM_LIT);
316
317 dfield = que_node_get_val(str_node);
318 dfield_set_data(dfield, ptr, ptr_len);
319 }
320
321 dfield = que_node_get_val(like_node);
322 dtype = dfield_get_type(dfield);
323
324 ut_a(dtype_get_mtype(dtype) == DATA_INT);
325 op_check = static_cast<ib_like_t>(
326 mach_read_from_4(static_cast<byte*>(dfield_get_data(dfield))));
327
328 switch (op_check) {
329 case IB_LIKE_PREFIX:
330 case IB_LIKE_EXACT:
331 break;
332
333 default:
334 ut_error;
335 }
336
337 mach_write_to_4(static_cast<byte*>(dfield_get_data(dfield)), op);
338
339 dfield = que_node_get_val(node);
340
341 /* Adjust the length of the search value so the '%' is not
342 visible. Then create and add a search string node to the
343 search value node. Searching for %SUFFIX and %SUBSTR% requires
344 a full table scan and so we set the search value to ''.
345 For PREFIX% we simply remove the trailing '%'.*/
346
347 switch (op) {
348 case IB_LIKE_EXACT:
349 dfield = que_node_get_val(str_node);
350 dtype = dfield_get_type(dfield);
351
352 ut_a(dtype_get_mtype(dtype) == DATA_VARCHAR);
353
354 dfield_set_data(dfield, ptr, ptr_len);
355 break;
356
357 case IB_LIKE_PREFIX:
358 func = PARS_LIKE_TOKEN_PREFIX;
359
360 /* Modify the original node */
361 dfield_set_len(dfield, ptr_len - 1);
362
363 dfield = que_node_get_val(str_node);
364 dtype = dfield_get_type(dfield);
365
366 ut_a(dtype_get_mtype(dtype) == DATA_VARCHAR);
367
368 dfield_set_data(dfield, ptr, ptr_len - 1);
369 break;
370
371 default:
372 ut_error;
373 }
374
375 return(func);
376}
377
378/*************************************************************************
379Parses a LIKE operator expression. */
380static
381int
382pars_like_op(
383/*=========*/
384 /* out, own: function node in a query tree */
385 que_node_t* arg) /* in: LIKE comparison string.*/
386{
387 char* ptr;
388 ulint ptr_len;
389 int func = PARS_LIKE_TOKEN_EXACT;
390 dfield_t* dfield = que_node_get_val(arg);
391 dtype_t* dtype = dfield_get_type(dfield);
392
393 ut_a(dtype_get_mtype(dtype) == DATA_CHAR
394 || dtype_get_mtype(dtype) == DATA_VARCHAR);
395
396 ptr = static_cast<char*>(dfield_get_data(dfield));
397 ptr_len = strlen(ptr);
398
399 if (ptr_len) {
400
401 func = pars_like_rebind(
402 static_cast<sym_node_t*>(arg), (byte*) ptr, ptr_len);
403 }
404
405 return(func);
406}
407/*********************************************************************//**
408Parses an operator expression.
409@return own: function node in a query tree */
410func_node_t*
411pars_op(
412/*====*/
413 int func, /*!< in: operator token code */
414 que_node_t* arg1, /*!< in: first argument */
415 que_node_t* arg2) /*!< in: second argument or NULL for an unary
416 operator */
417{
418 que_node_list_add_last(NULL, arg1);
419
420 if (arg2) {
421 que_node_list_add_last(arg1, arg2);
422 }
423
424 /* We need to parse the string and determine whether it's a
425 PREFIX, SUFFIX or SUBSTRING comparison */
426 if (func == PARS_LIKE_TOKEN) {
427
428 ut_a(que_node_get_type(arg2) == QUE_NODE_SYMBOL);
429
430 func = pars_like_op(arg2);
431
432 ut_a(func == PARS_LIKE_TOKEN_EXACT
433 || func == PARS_LIKE_TOKEN_PREFIX
434 || func == PARS_LIKE_TOKEN_SUFFIX
435 || func == PARS_LIKE_TOKEN_SUBSTR);
436 }
437
438 return(pars_func_low(func, arg1));
439}
440
441/*********************************************************************//**
442Parses an ORDER BY clause. Order by a single column only is supported.
443@return own: order-by node in a query tree */
444order_node_t*
445pars_order_by(
446/*==========*/
447 sym_node_t* column, /*!< in: column name */
448 pars_res_word_t* asc) /*!< in: &pars_asc_token or pars_desc_token */
449{
450 order_node_t* node;
451
452 node = static_cast<order_node_t*>(
453 mem_heap_alloc(
454 pars_sym_tab_global->heap, sizeof(order_node_t)));
455
456 node->common.type = QUE_NODE_ORDER;
457
458 node->column = column;
459
460 if (asc == &pars_asc_token) {
461 node->asc = TRUE;
462 } else {
463 ut_a(asc == &pars_desc_token);
464 node->asc = FALSE;
465 }
466
467 return(node);
468}
469
470/*********************************************************************//**
471Determine if a data type is a built-in string data type of the InnoDB
472SQL parser.
473@return TRUE if string data type */
474static
475ibool
476pars_is_string_type(
477/*================*/
478 ulint mtype) /*!< in: main data type */
479{
480 switch (mtype) {
481 case DATA_VARCHAR: case DATA_CHAR:
482 case DATA_FIXBINARY: case DATA_BINARY:
483 return(TRUE);
484 }
485
486 return(FALSE);
487}
488
489/*********************************************************************//**
490Resolves the data type of a function in an expression. The argument data
491types must already be resolved. */
492static
493void
494pars_resolve_func_data_type(
495/*========================*/
496 func_node_t* node) /*!< in: function node */
497{
498 que_node_t* arg;
499
500 ut_a(que_node_get_type(node) == QUE_NODE_FUNC);
501
502 arg = node->args;
503
504 switch (node->func) {
505 case PARS_SUM_TOKEN:
506 case '+': case '-': case '*': case '/':
507 /* Inherit the data type from the first argument (which must
508 not be the SQL null literal whose type is DATA_ERROR) */
509
510 dtype_copy(que_node_get_data_type(node),
511 que_node_get_data_type(arg));
512
513 ut_a(dtype_get_mtype(que_node_get_data_type(node))
514 == DATA_INT);
515 break;
516
517 case PARS_COUNT_TOKEN:
518 ut_a(arg);
519 dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
520 break;
521
522 case PARS_TO_CHAR_TOKEN:
523 case PARS_RND_STR_TOKEN:
524 ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
525 dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
526 DATA_ENGLISH, 0);
527 break;
528
529 case PARS_TO_BINARY_TOKEN:
530 if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
531 dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
532 DATA_ENGLISH, 0);
533 } else {
534 dtype_set(que_node_get_data_type(node), DATA_BINARY,
535 0, 0);
536 }
537 break;
538
539 case PARS_TO_NUMBER_TOKEN:
540 case PARS_BINARY_TO_NUMBER_TOKEN:
541 case PARS_LENGTH_TOKEN:
542 case PARS_INSTR_TOKEN:
543 ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
544 dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
545 break;
546
547 case PARS_SYSDATE_TOKEN:
548 ut_a(arg == NULL);
549 dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
550 break;
551
552 case PARS_SUBSTR_TOKEN:
553 case PARS_CONCAT_TOKEN:
554 ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
555 dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
556 DATA_ENGLISH, 0);
557 break;
558
559 case '>': case '<': case '=':
560 case PARS_GE_TOKEN:
561 case PARS_LE_TOKEN:
562 case PARS_NE_TOKEN:
563 case PARS_AND_TOKEN:
564 case PARS_OR_TOKEN:
565 case PARS_NOT_TOKEN:
566 case PARS_NOTFOUND_TOKEN:
567
568 /* We currently have no iboolean type: use integer type */
569 dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
570 break;
571
572 case PARS_RND_TOKEN:
573 ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
574 dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
575 break;
576
577 case PARS_LIKE_TOKEN_EXACT:
578 case PARS_LIKE_TOKEN_PREFIX:
579 case PARS_LIKE_TOKEN_SUFFIX:
580 case PARS_LIKE_TOKEN_SUBSTR:
581 dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
582 DATA_ENGLISH, 0);
583 break;
584
585 default:
586 ut_error;
587 }
588}
589
590/*********************************************************************//**
591Resolves the meaning of variables in an expression and the data types of
592functions. It is an error if some identifier cannot be resolved here. */
593static
594void
595pars_resolve_exp_variables_and_types(
596/*=================================*/
597 sel_node_t* select_node, /*!< in: select node or NULL; if
598 this is not NULL then the variable
599 sym nodes are added to the
600 copy_variables list of select_node */
601 que_node_t* exp_node) /*!< in: expression */
602{
603 func_node_t* func_node;
604 que_node_t* arg;
605 sym_node_t* sym_node;
606 sym_node_t* node;
607
608 ut_a(exp_node);
609
610 if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
611 func_node = static_cast<func_node_t*>(exp_node);
612
613 arg = func_node->args;
614
615 while (arg) {
616 pars_resolve_exp_variables_and_types(select_node, arg);
617
618 arg = que_node_get_next(arg);
619 }
620
621 pars_resolve_func_data_type(func_node);
622
623 return;
624 }
625
626 ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);
627
628 sym_node = static_cast<sym_node_t*>(exp_node);
629
630 if (sym_node->resolved) {
631
632 return;
633 }
634
635 /* Not resolved yet: look in the symbol table for a variable
636 or a cursor or a function with the same name */
637
638 node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
639
640 while (node) {
641 if (node->resolved
642 && ((node->token_type == SYM_VAR)
643 || (node->token_type == SYM_CURSOR)
644 || (node->token_type == SYM_FUNCTION))
645 && node->name
646 && (sym_node->name_len == node->name_len)
647 && (ut_memcmp(sym_node->name, node->name,
648 node->name_len) == 0)) {
649
650 /* Found a variable or a cursor declared with
651 the same name */
652
653 break;
654 }
655
656 node = UT_LIST_GET_NEXT(sym_list, node);
657 }
658
659 if (!node) {
660 fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n",
661 sym_node->name);
662 }
663
664 ut_a(node);
665
666 sym_node->resolved = TRUE;
667 sym_node->token_type = SYM_IMPLICIT_VAR;
668 sym_node->alias = node;
669 sym_node->indirection = node;
670
671 if (select_node) {
672 UT_LIST_ADD_LAST(select_node->copy_variables, sym_node);
673 }
674
675 dfield_set_type(que_node_get_val(sym_node),
676 que_node_get_data_type(node));
677}
678
679/*********************************************************************//**
680Resolves the meaning of variables in an expression list. It is an error if
681some identifier cannot be resolved here. Resolves also the data types of
682functions. */
683static
684void
685pars_resolve_exp_list_variables_and_types(
686/*======================================*/
687 sel_node_t* select_node, /*!< in: select node or NULL */
688 que_node_t* exp_node) /*!< in: expression list first node, or
689 NULL */
690{
691 while (exp_node) {
692 pars_resolve_exp_variables_and_types(select_node, exp_node);
693
694 exp_node = que_node_get_next(exp_node);
695 }
696}
697
698/*********************************************************************//**
699Resolves the columns in an expression. */
700static
701void
702pars_resolve_exp_columns(
703/*=====================*/
704 sym_node_t* table_node, /*!< in: first node in a table list */
705 que_node_t* exp_node) /*!< in: expression */
706{
707 func_node_t* func_node;
708 que_node_t* arg;
709 sym_node_t* sym_node;
710 dict_table_t* table;
711 sym_node_t* t_node;
712 ulint n_cols;
713 ulint i;
714
715 ut_a(exp_node);
716
717 if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
718 func_node = static_cast<func_node_t*>(exp_node);
719
720 arg = func_node->args;
721
722 while (arg) {
723 pars_resolve_exp_columns(table_node, arg);
724
725 arg = que_node_get_next(arg);
726 }
727
728 return;
729 }
730
731 ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);
732
733 sym_node = static_cast<sym_node_t*>(exp_node);
734
735 if (sym_node->resolved) {
736
737 return;
738 }
739
740 /* Not resolved yet: look in the table list for a column with the
741 same name */
742
743 t_node = table_node;
744
745 while (t_node) {
746 table = t_node->table;
747
748 n_cols = dict_table_get_n_cols(table);
749
750 for (i = 0; i < n_cols; i++) {
751 const dict_col_t* col
752 = dict_table_get_nth_col(table, i);
753 const char* col_name
754 = dict_table_get_col_name(table, i);
755
756 if ((sym_node->name_len == ut_strlen(col_name))
757 && (0 == ut_memcmp(sym_node->name, col_name,
758 sym_node->name_len))) {
759 /* Found */
760 sym_node->resolved = TRUE;
761 sym_node->token_type = SYM_COLUMN;
762 sym_node->table = table;
763 sym_node->col_no = i;
764 sym_node->prefetch_buf = NULL;
765
766 dict_col_copy_type(
767 col,
768 dfield_get_type(&sym_node
769 ->common.val));
770
771 return;
772 }
773 }
774
775 t_node = static_cast<sym_node_t*>(que_node_get_next(t_node));
776 }
777}
778
779/*********************************************************************//**
780Resolves the meaning of columns in an expression list. */
781static
782void
783pars_resolve_exp_list_columns(
784/*==========================*/
785 sym_node_t* table_node, /*!< in: first node in a table list */
786 que_node_t* exp_node) /*!< in: expression list first node, or
787 NULL */
788{
789 while (exp_node) {
790 pars_resolve_exp_columns(table_node, exp_node);
791
792 exp_node = que_node_get_next(exp_node);
793 }
794}
795
796/*********************************************************************//**
797Retrieves the table definition for a table name id. */
798static
799void
800pars_retrieve_table_def(
801/*====================*/
802 sym_node_t* sym_node) /*!< in: table node */
803{
804 ut_a(sym_node);
805 ut_a(que_node_get_type(sym_node) == QUE_NODE_SYMBOL);
806
807 /* Open the table only if it is not already opened. */
808 if (sym_node->token_type != SYM_TABLE_REF_COUNTED) {
809
810 ut_a(sym_node->table == NULL);
811
812 sym_node->resolved = TRUE;
813 sym_node->token_type = SYM_TABLE_REF_COUNTED;
814
815 sym_node->table = dict_table_open_on_name(
816 sym_node->name, TRUE, FALSE, DICT_ERR_IGNORE_NONE);
817
818 ut_a(sym_node->table != NULL);
819 }
820}
821
822/*********************************************************************//**
823Retrieves the table definitions for a list of table name ids.
824@return number of tables */
825static
826ulint
827pars_retrieve_table_list_defs(
828/*==========================*/
829 sym_node_t* sym_node) /*!< in: first table node in list */
830{
831 ulint count = 0;
832
833 if (sym_node == NULL) {
834
835 return(count);
836 }
837
838 while (sym_node) {
839 pars_retrieve_table_def(sym_node);
840
841 count++;
842
843 sym_node = static_cast<sym_node_t*>(
844 que_node_get_next(sym_node));
845 }
846
847 return(count);
848}
849
850/*********************************************************************//**
851Adds all columns to the select list if the query is SELECT * FROM ... */
852static
853void
854pars_select_all_columns(
855/*====================*/
856 sel_node_t* select_node) /*!< in: select node already containing
857 the table list */
858{
859 sym_node_t* col_node;
860 sym_node_t* table_node;
861 dict_table_t* table;
862 ulint i;
863
864 select_node->select_list = NULL;
865
866 table_node = select_node->table_list;
867
868 while (table_node) {
869 table = table_node->table;
870
871 for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
872 const char* col_name = dict_table_get_col_name(
873 table, i);
874
875 col_node = sym_tab_add_id(pars_sym_tab_global,
876 (byte*) col_name,
877 ut_strlen(col_name));
878
879 select_node->select_list = que_node_list_add_last(
880 select_node->select_list, col_node);
881 }
882
883 table_node = static_cast<sym_node_t*>(
884 que_node_get_next(table_node));
885 }
886}
887
888/*********************************************************************//**
889Parses a select list; creates a query graph node for the whole SELECT
890statement.
891@return own: select node in a query tree */
892sel_node_t*
893pars_select_list(
894/*=============*/
895 que_node_t* select_list, /*!< in: select list */
896 sym_node_t* into_list) /*!< in: variables list or NULL */
897{
898 sel_node_t* node;
899
900 node = sel_node_create(pars_sym_tab_global->heap);
901
902 node->select_list = select_list;
903 node->into_list = into_list;
904
905 pars_resolve_exp_list_variables_and_types(NULL, into_list);
906
907 return(node);
908}
909
910/*********************************************************************//**
911Checks if the query is an aggregate query, in which case the selct list must
912contain only aggregate function items. */
913static
914void
915pars_check_aggregate(
916/*=================*/
917 sel_node_t* select_node) /*!< in: select node already containing
918 the select list */
919{
920 que_node_t* exp_node;
921 func_node_t* func_node;
922 ulint n_nodes = 0;
923 ulint n_aggregate_nodes = 0;
924
925 exp_node = select_node->select_list;
926
927 while (exp_node) {
928
929 n_nodes++;
930
931 if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
932
933 func_node = static_cast<func_node_t*>(exp_node);
934
935 if (func_node->fclass == PARS_FUNC_AGGREGATE) {
936
937 n_aggregate_nodes++;
938 }
939 }
940
941 exp_node = que_node_get_next(exp_node);
942 }
943
944 if (n_aggregate_nodes > 0) {
945 ut_a(n_nodes == n_aggregate_nodes);
946
947 select_node->is_aggregate = TRUE;
948 } else {
949 select_node->is_aggregate = FALSE;
950 }
951}
952
953/*********************************************************************//**
954Parses a select statement.
955@return own: select node in a query tree */
956sel_node_t*
957pars_select_statement(
958/*==================*/
959 sel_node_t* select_node, /*!< in: select node already containing
960 the select list */
961 sym_node_t* table_list, /*!< in: table list */
962 que_node_t* search_cond, /*!< in: search condition or NULL */
963 pars_res_word_t* for_update, /*!< in: NULL or &pars_update_token */
964 pars_res_word_t* lock_shared, /*!< in: NULL or &pars_share_token */
965 order_node_t* order_by) /*!< in: NULL or an order-by node */
966{
967 select_node->state = SEL_NODE_OPEN;
968
969 select_node->table_list = table_list;
970 select_node->n_tables = pars_retrieve_table_list_defs(table_list);
971
972 if (select_node->select_list == &pars_star_denoter) {
973
974 /* SELECT * FROM ... */
975 pars_select_all_columns(select_node);
976 }
977
978 if (select_node->into_list) {
979 ut_a(que_node_list_get_len(select_node->into_list)
980 == que_node_list_get_len(select_node->select_list));
981 }
982
983 UT_LIST_INIT(select_node->copy_variables, &sym_node_t::col_var_list);
984
985 pars_resolve_exp_list_columns(table_list, select_node->select_list);
986 pars_resolve_exp_list_variables_and_types(select_node,
987 select_node->select_list);
988 pars_check_aggregate(select_node);
989
990 select_node->search_cond = search_cond;
991
992 if (search_cond) {
993 pars_resolve_exp_columns(table_list, search_cond);
994 pars_resolve_exp_variables_and_types(select_node, search_cond);
995 }
996
997 if (for_update) {
998 ut_a(!lock_shared);
999
1000 select_node->set_x_locks = TRUE;
1001 select_node->row_lock_mode = LOCK_X;
1002
1003 select_node->consistent_read = FALSE;
1004 select_node->read_view = NULL;
1005 } else if (lock_shared){
1006 select_node->set_x_locks = FALSE;
1007 select_node->row_lock_mode = LOCK_S;
1008
1009 select_node->consistent_read = FALSE;
1010 select_node->read_view = NULL;
1011 } else {
1012 select_node->set_x_locks = FALSE;
1013 select_node->row_lock_mode = LOCK_S;
1014
1015 select_node->consistent_read = TRUE;
1016 }
1017
1018 select_node->order_by = order_by;
1019
1020 if (order_by) {
1021 pars_resolve_exp_columns(table_list, order_by->column);
1022 }
1023
1024 /* The final value of the following fields depend on the environment
1025 where the select statement appears: */
1026
1027 select_node->can_get_updated = FALSE;
1028 select_node->explicit_cursor = NULL;
1029
1030 opt_search_plan(select_node);
1031
1032 return(select_node);
1033}
1034
1035/*********************************************************************//**
1036Parses a cursor declaration.
1037@return sym_node */
1038que_node_t*
1039pars_cursor_declaration(
1040/*====================*/
1041 sym_node_t* sym_node, /*!< in: cursor id node in the symbol
1042 table */
1043 sel_node_t* select_node) /*!< in: select node */
1044{
1045 sym_node->resolved = TRUE;
1046 sym_node->token_type = SYM_CURSOR;
1047 sym_node->cursor_def = select_node;
1048
1049 select_node->state = SEL_NODE_CLOSED;
1050 select_node->explicit_cursor = sym_node;
1051
1052 return(sym_node);
1053}
1054
1055/*********************************************************************//**
1056Parses a function declaration.
1057@return sym_node */
1058que_node_t*
1059pars_function_declaration(
1060/*======================*/
1061 sym_node_t* sym_node) /*!< in: function id node in the symbol
1062 table */
1063{
1064 sym_node->resolved = TRUE;
1065 sym_node->token_type = SYM_FUNCTION;
1066
1067 /* Check that the function exists. */
1068 ut_a(pars_info_lookup_user_func(
1069 pars_sym_tab_global->info, sym_node->name));
1070
1071 return(sym_node);
1072}
1073
1074/*********************************************************************//**
1075Parses a delete or update statement start.
1076@return own: update node in a query tree */
1077upd_node_t*
1078pars_update_statement_start(
1079/*========================*/
1080 ibool is_delete, /*!< in: TRUE if delete */
1081 sym_node_t* table_sym, /*!< in: table name node */
1082 col_assign_node_t* col_assign_list)/*!< in: column assignment list, NULL
1083 if delete */
1084{
1085 upd_node_t* node;
1086
1087 node = upd_node_create(pars_sym_tab_global->heap);
1088
1089 node->is_delete = is_delete ? PLAIN_DELETE : NO_DELETE;
1090
1091 node->table_sym = table_sym;
1092 node->col_assign_list = col_assign_list;
1093
1094 return(node);
1095}
1096
1097/*********************************************************************//**
1098Parses a column assignment in an update.
1099@return column assignment node */
1100col_assign_node_t*
1101pars_column_assignment(
1102/*===================*/
1103 sym_node_t* column, /*!< in: column to assign */
1104 que_node_t* exp) /*!< in: value to assign */
1105{
1106 col_assign_node_t* node;
1107
1108 node = static_cast<col_assign_node_t*>(
1109 mem_heap_alloc(pars_sym_tab_global->heap,
1110 sizeof(col_assign_node_t)));
1111 node->common.type = QUE_NODE_COL_ASSIGNMENT;
1112
1113 node->col = column;
1114 node->val = exp;
1115
1116 return(node);
1117}
1118
1119/*********************************************************************//**
1120Processes an update node assignment list. */
1121static
1122void
1123pars_process_assign_list(
1124/*=====================*/
1125 upd_node_t* node) /*!< in: update node */
1126{
1127 col_assign_node_t* col_assign_list;
1128 sym_node_t* table_sym;
1129 col_assign_node_t* assign_node;
1130 upd_field_t* upd_field;
1131 dict_index_t* clust_index;
1132 sym_node_t* col_sym;
1133 ulint changes_ord_field;
1134 ulint changes_field_size;
1135 ulint n_assigns;
1136 ulint i;
1137
1138 table_sym = node->table_sym;
1139 col_assign_list = static_cast<col_assign_node_t*>(
1140 node->col_assign_list);
1141 clust_index = dict_table_get_first_index(node->table);
1142
1143 assign_node = col_assign_list;
1144 n_assigns = 0;
1145
1146 while (assign_node) {
1147 pars_resolve_exp_columns(table_sym, assign_node->col);
1148 pars_resolve_exp_columns(table_sym, assign_node->val);
1149 pars_resolve_exp_variables_and_types(NULL, assign_node->val);
1150#if 0
1151 ut_a(dtype_get_mtype(
1152 dfield_get_type(que_node_get_val(
1153 assign_node->col)))
1154 == dtype_get_mtype(
1155 dfield_get_type(que_node_get_val(
1156 assign_node->val))));
1157#endif
1158
1159 /* Add to the update node all the columns found in assignment
1160 values as columns to copy: therefore, TRUE */
1161
1162 opt_find_all_cols(TRUE, clust_index, &(node->columns), NULL,
1163 assign_node->val);
1164 n_assigns++;
1165
1166 assign_node = static_cast<col_assign_node_t*>(
1167 que_node_get_next(assign_node));
1168 }
1169
1170 node->update = upd_create(n_assigns, pars_sym_tab_global->heap);
1171
1172 assign_node = col_assign_list;
1173
1174 changes_field_size = UPD_NODE_NO_SIZE_CHANGE;
1175
1176 for (i = 0; i < n_assigns; i++) {
1177 upd_field = upd_get_nth_field(node->update, i);
1178
1179 col_sym = assign_node->col;
1180
1181 upd_field_set_field_no(upd_field, dict_index_get_nth_col_pos(
1182 clust_index, col_sym->col_no,
1183 NULL),
1184 clust_index);
1185 upd_field->exp = assign_node->val;
1186
1187 if (!dict_col_get_fixed_size(
1188 dict_index_get_nth_col(clust_index,
1189 upd_field->field_no),
1190 dict_table_is_comp(node->table))) {
1191 changes_field_size = 0;
1192 }
1193
1194 assign_node = static_cast<col_assign_node_t*>(
1195 que_node_get_next(assign_node));
1196 }
1197
1198 /* Find out if the update can modify an ordering field in any index */
1199
1200 changes_ord_field = UPD_NODE_NO_ORD_CHANGE;
1201
1202 if (row_upd_changes_some_index_ord_field_binary(node->table,
1203 node->update)) {
1204 changes_ord_field = 0;
1205 }
1206
1207 node->cmpl_info = changes_ord_field | changes_field_size;
1208}
1209
1210/*********************************************************************//**
1211Parses an update or delete statement.
1212@return own: update node in a query tree */
1213upd_node_t*
1214pars_update_statement(
1215/*==================*/
1216 upd_node_t* node, /*!< in: update node */
1217 sym_node_t* cursor_sym, /*!< in: pointer to a cursor entry in
1218 the symbol table or NULL */
1219 que_node_t* search_cond) /*!< in: search condition or NULL */
1220{
1221 sym_node_t* table_sym;
1222 sel_node_t* sel_node;
1223 plan_t* plan;
1224
1225 table_sym = node->table_sym;
1226
1227 pars_retrieve_table_def(table_sym);
1228 node->table = table_sym->table;
1229
1230 UT_LIST_INIT(node->columns, &sym_node_t::col_var_list);
1231
1232 /* Make the single table node into a list of table nodes of length 1 */
1233
1234 que_node_list_add_last(NULL, table_sym);
1235
1236 if (cursor_sym) {
1237 pars_resolve_exp_variables_and_types(NULL, cursor_sym);
1238
1239 sel_node = cursor_sym->alias->cursor_def;
1240
1241 node->searched_update = FALSE;
1242 } else {
1243 sel_node = pars_select_list(NULL, NULL);
1244
1245 pars_select_statement(sel_node, table_sym, search_cond, NULL,
1246 &pars_share_token, NULL);
1247 node->searched_update = TRUE;
1248 sel_node->common.parent = node;
1249 }
1250
1251 node->select = sel_node;
1252
1253 ut_a(!node->is_delete || (node->col_assign_list == NULL));
1254 ut_a(node->is_delete == PLAIN_DELETE || node->col_assign_list != NULL);
1255
1256 if (node->is_delete == PLAIN_DELETE) {
1257 node->cmpl_info = 0;
1258 } else {
1259 pars_process_assign_list(node);
1260 }
1261
1262 if (node->searched_update) {
1263 node->has_clust_rec_x_lock = TRUE;
1264 sel_node->set_x_locks = TRUE;
1265 sel_node->row_lock_mode = LOCK_X;
1266 } else {
1267 node->has_clust_rec_x_lock = sel_node->set_x_locks;
1268 }
1269
1270 ut_a(sel_node->n_tables == 1);
1271 ut_a(sel_node->consistent_read == FALSE);
1272 ut_a(sel_node->order_by == NULL);
1273 ut_a(sel_node->is_aggregate == FALSE);
1274
1275 sel_node->can_get_updated = TRUE;
1276
1277 node->state = UPD_NODE_UPDATE_CLUSTERED;
1278
1279 plan = sel_node_get_nth_plan(sel_node, 0);
1280
1281 plan->no_prefetch = TRUE;
1282
1283 if (!dict_index_is_clust(plan->index)) {
1284
1285 plan->must_get_clust = TRUE;
1286
1287 node->pcur = &(plan->clust_pcur);
1288 } else {
1289 node->pcur = &(plan->pcur);
1290 }
1291
1292 return(node);
1293}
1294
1295/*********************************************************************//**
1296Parses an insert statement.
1297@return own: update node in a query tree */
1298ins_node_t*
1299pars_insert_statement(
1300/*==================*/
1301 sym_node_t* table_sym, /*!< in: table name node */
1302 que_node_t* values_list, /*!< in: value expression list or NULL */
1303 sel_node_t* select) /*!< in: select condition or NULL */
1304{
1305 ins_node_t* node;
1306 dtuple_t* row;
1307 ulint ins_type;
1308
1309 ut_a(values_list || select);
1310 ut_a(!values_list || !select);
1311
1312 if (values_list) {
1313 ins_type = INS_VALUES;
1314 } else {
1315 ins_type = INS_SEARCHED;
1316 }
1317
1318 pars_retrieve_table_def(table_sym);
1319
1320 node = ins_node_create(ins_type, table_sym->table,
1321 pars_sym_tab_global->heap);
1322
1323 row = dtuple_create(pars_sym_tab_global->heap,
1324 dict_table_get_n_cols(node->table));
1325
1326 dict_table_copy_types(row, table_sym->table);
1327
1328 ins_node_set_new_row(node, row);
1329
1330 node->select = select;
1331
1332 if (select) {
1333 select->common.parent = node;
1334
1335 ut_a(que_node_list_get_len(select->select_list)
1336 == dict_table_get_n_user_cols(table_sym->table));
1337 }
1338
1339 node->values_list = values_list;
1340
1341 if (node->values_list) {
1342 pars_resolve_exp_list_variables_and_types(NULL, values_list);
1343
1344 ut_a(que_node_list_get_len(values_list)
1345 == dict_table_get_n_user_cols(table_sym->table));
1346 }
1347
1348 return(node);
1349}
1350
1351/*********************************************************************//**
1352Set the type of a dfield. */
1353static
1354void
1355pars_set_dfield_type(
1356/*=================*/
1357 dfield_t* dfield, /*!< in: dfield */
1358 pars_res_word_t* type, /*!< in: pointer to a type
1359 token */
1360 ulint len, /*!< in: length, or 0 */
1361 ibool is_unsigned, /*!< in: if TRUE, column is
1362 UNSIGNED. */
1363 ibool is_not_null) /*!< in: if TRUE, column is
1364 NOT NULL. */
1365{
1366 ulint flags = 0;
1367
1368 if (is_not_null) {
1369 flags |= DATA_NOT_NULL;
1370 }
1371
1372 if (is_unsigned) {
1373 flags |= DATA_UNSIGNED;
1374 }
1375
1376 if (type == &pars_bigint_token) {
1377 ut_a(len == 0);
1378
1379 dtype_set(dfield_get_type(dfield), DATA_INT, flags, 8);
1380 } else if (type == &pars_int_token) {
1381 ut_a(len == 0);
1382
1383 dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4);
1384
1385 } else if (type == &pars_char_token) {
1386 //ut_a(len == 0);
1387
1388 dtype_set(dfield_get_type(dfield), DATA_VARCHAR,
1389 DATA_ENGLISH | flags, len);
1390 } else if (type == &pars_binary_token) {
1391 ut_a(len != 0);
1392
1393 dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
1394 DATA_BINARY_TYPE | flags, len);
1395 } else if (type == &pars_blob_token) {
1396 ut_a(len == 0);
1397
1398 dtype_set(dfield_get_type(dfield), DATA_BLOB,
1399 DATA_BINARY_TYPE | flags, 0);
1400 } else {
1401 ut_error;
1402 }
1403}
1404
1405/*********************************************************************//**
1406Parses a variable declaration.
1407@return own: symbol table node of type SYM_VAR */
1408sym_node_t*
1409pars_variable_declaration(
1410/*======================*/
1411 sym_node_t* node, /*!< in: symbol table node allocated for the
1412 id of the variable */
1413 pars_res_word_t* type) /*!< in: pointer to a type token */
1414{
1415 node->resolved = TRUE;
1416 node->token_type = SYM_VAR;
1417
1418 node->param_type = PARS_NOT_PARAM;
1419
1420 pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE, FALSE);
1421
1422 return(node);
1423}
1424
1425/*********************************************************************//**
1426Parses a procedure parameter declaration.
1427@return own: symbol table node of type SYM_VAR */
1428sym_node_t*
1429pars_parameter_declaration(
1430/*=======================*/
1431 sym_node_t* node, /*!< in: symbol table node allocated for the
1432 id of the parameter */
1433 ulint param_type,
1434 /*!< in: PARS_INPUT or PARS_OUTPUT */
1435 pars_res_word_t* type) /*!< in: pointer to a type token */
1436{
1437 ut_a((param_type == PARS_INPUT) || (param_type == PARS_OUTPUT));
1438
1439 pars_variable_declaration(node, type);
1440
1441 node->param_type = param_type;
1442
1443 return(node);
1444}
1445
1446/*********************************************************************//**
1447Sets the parent field in a query node list. */
1448static
1449void
1450pars_set_parent_in_list(
1451/*====================*/
1452 que_node_t* node_list, /*!< in: first node in a list */
1453 que_node_t* parent) /*!< in: parent value to set in all
1454 nodes of the list */
1455{
1456 que_common_t* common;
1457
1458 common = static_cast<que_common_t*>(node_list);
1459
1460 while (common) {
1461 common->parent = parent;
1462
1463 common = static_cast<que_common_t*>(que_node_get_next(common));
1464 }
1465}
1466
1467/*********************************************************************//**
1468Parses an elsif element.
1469@return elsif node */
1470elsif_node_t*
1471pars_elsif_element(
1472/*===============*/
1473 que_node_t* cond, /*!< in: if-condition */
1474 que_node_t* stat_list) /*!< in: statement list */
1475{
1476 elsif_node_t* node;
1477
1478 node = static_cast<elsif_node_t*>(
1479 mem_heap_alloc(
1480 pars_sym_tab_global->heap, sizeof(elsif_node_t)));
1481
1482 node->common.type = QUE_NODE_ELSIF;
1483
1484 node->cond = cond;
1485
1486 pars_resolve_exp_variables_and_types(NULL, cond);
1487
1488 node->stat_list = stat_list;
1489
1490 return(node);
1491}
1492
1493/*********************************************************************//**
1494Parses an if-statement.
1495@return if-statement node */
1496if_node_t*
1497pars_if_statement(
1498/*==============*/
1499 que_node_t* cond, /*!< in: if-condition */
1500 que_node_t* stat_list, /*!< in: statement list */
1501 que_node_t* else_part) /*!< in: else-part statement list
1502 or elsif element list */
1503{
1504 if_node_t* node;
1505 elsif_node_t* elsif_node;
1506
1507 node = static_cast<if_node_t*>(
1508 mem_heap_alloc(
1509 pars_sym_tab_global->heap, sizeof(if_node_t)));
1510
1511 node->common.type = QUE_NODE_IF;
1512
1513 node->cond = cond;
1514
1515 pars_resolve_exp_variables_and_types(NULL, cond);
1516
1517 node->stat_list = stat_list;
1518
1519 if (else_part && (que_node_get_type(else_part) == QUE_NODE_ELSIF)) {
1520
1521 /* There is a list of elsif conditions */
1522
1523 node->else_part = NULL;
1524 node->elsif_list = static_cast<elsif_node_t*>(else_part);
1525
1526 elsif_node = static_cast<elsif_node_t*>(else_part);
1527
1528 while (elsif_node) {
1529 pars_set_parent_in_list(elsif_node->stat_list, node);
1530
1531 elsif_node = static_cast<elsif_node_t*>(
1532 que_node_get_next(elsif_node));
1533 }
1534 } else {
1535 node->else_part = else_part;
1536 node->elsif_list = NULL;
1537
1538 pars_set_parent_in_list(else_part, node);
1539 }
1540
1541 pars_set_parent_in_list(stat_list, node);
1542
1543 return(node);
1544}
1545
1546/*********************************************************************//**
1547Parses a while-statement.
1548@return while-statement node */
1549while_node_t*
1550pars_while_statement(
1551/*=================*/
1552 que_node_t* cond, /*!< in: while-condition */
1553 que_node_t* stat_list) /*!< in: statement list */
1554{
1555 while_node_t* node;
1556
1557 node = static_cast<while_node_t*>(
1558 mem_heap_alloc(
1559 pars_sym_tab_global->heap, sizeof(while_node_t)));
1560
1561 node->common.type = QUE_NODE_WHILE;
1562
1563 node->cond = cond;
1564
1565 pars_resolve_exp_variables_and_types(NULL, cond);
1566
1567 node->stat_list = stat_list;
1568
1569 pars_set_parent_in_list(stat_list, node);
1570
1571 return(node);
1572}
1573
1574/*********************************************************************//**
1575Parses a for-loop-statement.
1576@return for-statement node */
1577for_node_t*
1578pars_for_statement(
1579/*===============*/
1580 sym_node_t* loop_var, /*!< in: loop variable */
1581 que_node_t* loop_start_limit,/*!< in: loop start expression */
1582 que_node_t* loop_end_limit, /*!< in: loop end expression */
1583 que_node_t* stat_list) /*!< in: statement list */
1584{
1585 for_node_t* node;
1586
1587 node = static_cast<for_node_t*>(
1588 mem_heap_alloc(pars_sym_tab_global->heap, sizeof(for_node_t)));
1589
1590 node->common.type = QUE_NODE_FOR;
1591
1592 pars_resolve_exp_variables_and_types(NULL, loop_var);
1593 pars_resolve_exp_variables_and_types(NULL, loop_start_limit);
1594 pars_resolve_exp_variables_and_types(NULL, loop_end_limit);
1595
1596 node->loop_var = loop_var->indirection;
1597
1598 ut_a(loop_var->indirection);
1599
1600 node->loop_start_limit = loop_start_limit;
1601 node->loop_end_limit = loop_end_limit;
1602
1603 node->stat_list = stat_list;
1604
1605 pars_set_parent_in_list(stat_list, node);
1606
1607 return(node);
1608}
1609
1610/*********************************************************************//**
1611Parses an exit statement.
1612@return exit statement node */
1613exit_node_t*
1614pars_exit_statement(void)
1615/*=====================*/
1616{
1617 exit_node_t* node;
1618
1619 node = static_cast<exit_node_t*>(
1620 mem_heap_alloc(pars_sym_tab_global->heap, sizeof(exit_node_t)));
1621 node->common.type = QUE_NODE_EXIT;
1622
1623 return(node);
1624}
1625
1626/*********************************************************************//**
1627Parses a return-statement.
1628@return return-statement node */
1629return_node_t*
1630pars_return_statement(void)
1631/*=======================*/
1632{
1633 return_node_t* node;
1634
1635 node = static_cast<return_node_t*>(
1636 mem_heap_alloc(
1637 pars_sym_tab_global->heap, sizeof(return_node_t)));
1638 node->common.type = QUE_NODE_RETURN;
1639
1640 return(node);
1641}
1642
1643/*********************************************************************//**
1644Parses an assignment statement.
1645@return assignment statement node */
1646assign_node_t*
1647pars_assignment_statement(
1648/*======================*/
1649 sym_node_t* var, /*!< in: variable to assign */
1650 que_node_t* val) /*!< in: value to assign */
1651{
1652 assign_node_t* node;
1653
1654 node = static_cast<assign_node_t*>(
1655 mem_heap_alloc(
1656 pars_sym_tab_global->heap, sizeof(assign_node_t)));
1657 node->common.type = QUE_NODE_ASSIGNMENT;
1658
1659 node->var = var;
1660 node->val = val;
1661
1662 pars_resolve_exp_variables_and_types(NULL, var);
1663 pars_resolve_exp_variables_and_types(NULL, val);
1664
1665 ut_a(dtype_get_mtype(dfield_get_type(que_node_get_val(var)))
1666 == dtype_get_mtype(dfield_get_type(que_node_get_val(val))));
1667
1668 return(node);
1669}
1670
1671/*********************************************************************//**
1672Parses a procedure call.
1673@return function node */
1674func_node_t*
1675pars_procedure_call(
1676/*================*/
1677 que_node_t* res_word,/*!< in: procedure name reserved word */
1678 que_node_t* args) /*!< in: argument list */
1679{
1680 func_node_t* node;
1681
1682 node = pars_func(res_word, args);
1683
1684 pars_resolve_exp_list_variables_and_types(NULL, args);
1685
1686 return(node);
1687}
1688
1689/*********************************************************************//**
1690Parses a fetch statement. into_list or user_func (but not both) must be
1691non-NULL.
1692@return fetch statement node */
1693fetch_node_t*
1694pars_fetch_statement(
1695/*=================*/
1696 sym_node_t* cursor, /*!< in: cursor node */
1697 sym_node_t* into_list, /*!< in: variables to set, or NULL */
1698 sym_node_t* user_func) /*!< in: user function name, or NULL */
1699{
1700 sym_node_t* cursor_decl;
1701 fetch_node_t* node;
1702
1703 /* Logical XOR. */
1704 ut_a(!into_list != !user_func);
1705
1706 node = static_cast<fetch_node_t*>(
1707 mem_heap_alloc(
1708 pars_sym_tab_global->heap, sizeof(fetch_node_t)));
1709
1710 node->common.type = QUE_NODE_FETCH;
1711
1712 pars_resolve_exp_variables_and_types(NULL, cursor);
1713
1714 if (into_list) {
1715 pars_resolve_exp_list_variables_and_types(NULL, into_list);
1716 node->into_list = into_list;
1717 node->func = NULL;
1718 } else {
1719 pars_resolve_exp_variables_and_types(NULL, user_func);
1720
1721 node->func = pars_info_lookup_user_func(
1722 pars_sym_tab_global->info, user_func->name);
1723
1724 ut_a(node->func);
1725
1726 node->into_list = NULL;
1727 }
1728
1729 cursor_decl = cursor->alias;
1730
1731 ut_a(cursor_decl->token_type == SYM_CURSOR);
1732
1733 node->cursor_def = cursor_decl->cursor_def;
1734
1735 if (into_list) {
1736 ut_a(que_node_list_get_len(into_list)
1737 == que_node_list_get_len(node->cursor_def->select_list));
1738 }
1739
1740 return(node);
1741}
1742
1743/*********************************************************************//**
1744Parses an open or close cursor statement.
1745@return fetch statement node */
1746open_node_t*
1747pars_open_statement(
1748/*================*/
1749 ulint type, /*!< in: ROW_SEL_OPEN_CURSOR
1750 or ROW_SEL_CLOSE_CURSOR */
1751 sym_node_t* cursor) /*!< in: cursor node */
1752{
1753 sym_node_t* cursor_decl;
1754 open_node_t* node;
1755
1756 node = static_cast<open_node_t*>(
1757 mem_heap_alloc(
1758 pars_sym_tab_global->heap, sizeof(open_node_t)));
1759
1760 node->common.type = QUE_NODE_OPEN;
1761
1762 pars_resolve_exp_variables_and_types(NULL, cursor);
1763
1764 cursor_decl = cursor->alias;
1765
1766 ut_a(cursor_decl->token_type == SYM_CURSOR);
1767
1768 node->op_type = static_cast<open_node_op>(type);
1769 node->cursor_def = cursor_decl->cursor_def;
1770
1771 return(node);
1772}
1773
1774/*********************************************************************//**
1775Parses a row_printf-statement.
1776@return row_printf-statement node */
1777row_printf_node_t*
1778pars_row_printf_statement(
1779/*======================*/
1780 sel_node_t* sel_node) /*!< in: select node */
1781{
1782 row_printf_node_t* node;
1783
1784 node = static_cast<row_printf_node_t*>(
1785 mem_heap_alloc(
1786 pars_sym_tab_global->heap, sizeof(row_printf_node_t)));
1787 node->common.type = QUE_NODE_ROW_PRINTF;
1788
1789 node->sel_node = sel_node;
1790
1791 sel_node->common.parent = node;
1792
1793 return(node);
1794}
1795
1796/*********************************************************************//**
1797Parses a commit statement.
1798@return own: commit node struct */
1799commit_node_t*
1800pars_commit_statement(void)
1801/*=======================*/
1802{
1803 return(trx_commit_node_create(pars_sym_tab_global->heap));
1804}
1805
1806/*********************************************************************//**
1807Parses a rollback statement.
1808@return own: rollback node struct */
1809roll_node_t*
1810pars_rollback_statement(void)
1811/*=========================*/
1812{
1813 return(roll_node_create(pars_sym_tab_global->heap));
1814}
1815
1816/*********************************************************************//**
1817Parses a column definition at a table creation.
1818@return column sym table node */
1819sym_node_t*
1820pars_column_def(
1821/*============*/
1822 sym_node_t* sym_node, /*!< in: column node in the
1823 symbol table */
1824 pars_res_word_t* type, /*!< in: data type */
1825 sym_node_t* len, /*!< in: length of column, or
1826 NULL */
1827 void* is_unsigned, /*!< in: if not NULL, column
1828 is of type UNSIGNED. */
1829 void* is_not_null) /*!< in: if not NULL, column
1830 is of type NOT NULL. */
1831{
1832 ulint len2;
1833
1834 if (len) {
1835 len2 = ulint(eval_node_get_int_val(len));
1836 } else {
1837 len2 = 0;
1838 }
1839
1840 pars_set_dfield_type(que_node_get_val(sym_node), type, len2,
1841 is_unsigned != NULL, is_not_null != NULL);
1842
1843 return(sym_node);
1844}
1845
1846/*********************************************************************//**
1847Parses a table creation operation.
1848@return table create subgraph */
1849tab_node_t*
1850pars_create_table(
1851/*==============*/
1852 sym_node_t* table_sym, /*!< in: table name node in the symbol
1853 table */
1854 sym_node_t* column_defs, /*!< in: list of column names */
1855 sym_node_t* compact, /* in: non-NULL if COMPACT table. */
1856 sym_node_t* block_size) /* in: block size (can be NULL) */
1857{
1858 dict_table_t* table;
1859 sym_node_t* column;
1860 tab_node_t* node;
1861 const dtype_t* dtype;
1862 ulint n_cols;
1863 ulint flags = 0;
1864 ulint flags2 = 0;
1865
1866 if (compact != NULL) {
1867
1868 /* System tables currently only use the REDUNDANT row
1869 format therefore the check for srv_file_per_table should be
1870 safe for now. */
1871
1872 flags |= DICT_TF_COMPACT;
1873
1874 /* FIXME: Ideally this should be part of the SQL syntax
1875 or use some other mechanism. We want to reduce dependency
1876 on global variables. There is an inherent race here but
1877 that has always existed around this variable. */
1878 if (srv_file_per_table) {
1879 flags2 |= DICT_TF2_USE_FILE_PER_TABLE;
1880 }
1881 }
1882
1883 if (block_size != NULL) {
1884 ulint size;
1885 dfield_t* dfield;
1886
1887 dfield = que_node_get_val(block_size);
1888
1889 ut_a(dfield_get_len(dfield) == 4);
1890 size = mach_read_from_4(static_cast<byte*>(
1891 dfield_get_data(dfield)));
1892
1893
1894 switch (size) {
1895 case 0:
1896 break;
1897
1898 case 1: case 2: case 4: case 8: case 16:
1899 flags |= DICT_TF_COMPACT;
1900 /* FTS-FIXME: needs the zip changes */
1901 /* flags |= size << DICT_TF_COMPRESSED_SHIFT; */
1902 break;
1903
1904 default:
1905 ut_error;
1906 }
1907 }
1908
1909 /* Set the flags2 when create table or alter tables */
1910 flags2 |= DICT_TF2_FTS_AUX_HEX_NAME;
1911 DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
1912 flags2 &= ~DICT_TF2_FTS_AUX_HEX_NAME;);
1913
1914
1915 n_cols = que_node_list_get_len(column_defs);
1916
1917 table = dict_mem_table_create(
1918 table_sym->name, NULL, n_cols, 0, flags, flags2);
1919
1920 mem_heap_t* heap = pars_sym_tab_global->heap;
1921 column = column_defs;
1922
1923 while (column) {
1924 dtype = dfield_get_type(que_node_get_val(column));
1925
1926 dict_mem_table_add_col(table, heap,
1927 column->name, dtype->mtype,
1928 dtype->prtype, dtype->len);
1929 column->resolved = TRUE;
1930 column->token_type = SYM_COLUMN;
1931
1932 column = static_cast<sym_node_t*>(que_node_get_next(column));
1933 }
1934
1935 dict_table_add_system_columns(table, heap);
1936 node = tab_create_graph_create(table, heap,
1937 FIL_ENCRYPTION_DEFAULT,
1938 FIL_DEFAULT_ENCRYPTION_KEY);
1939
1940 table_sym->resolved = TRUE;
1941 table_sym->token_type = SYM_TABLE;
1942
1943 return(node);
1944}
1945
1946/*********************************************************************//**
1947Parses an index creation operation.
1948@return index create subgraph */
1949ind_node_t*
1950pars_create_index(
1951/*==============*/
1952 pars_res_word_t* unique_def, /*!< in: not NULL if a unique index */
1953 pars_res_word_t* clustered_def, /*!< in: not NULL if a clustered index */
1954 sym_node_t* index_sym, /*!< in: index name node in the symbol
1955 table */
1956 sym_node_t* table_sym, /*!< in: table name node in the symbol
1957 table */
1958 sym_node_t* column_list) /*!< in: list of column names */
1959{
1960 dict_index_t* index;
1961 sym_node_t* column;
1962 ind_node_t* node;
1963 ulint n_fields;
1964 ulint ind_type;
1965
1966 n_fields = que_node_list_get_len(column_list);
1967
1968 ind_type = 0;
1969
1970 if (unique_def) {
1971 ind_type = ind_type | DICT_UNIQUE;
1972 }
1973
1974 if (clustered_def) {
1975 ind_type = ind_type | DICT_CLUSTERED;
1976 }
1977
1978 index = dict_mem_index_create(NULL, index_sym->name,
1979 ind_type, n_fields);
1980 column = column_list;
1981
1982 while (column) {
1983 dict_mem_index_add_field(index, column->name, 0);
1984
1985 column->resolved = TRUE;
1986 column->token_type = SYM_COLUMN;
1987
1988 column = static_cast<sym_node_t*>(que_node_get_next(column));
1989 }
1990
1991 node = ind_create_graph_create(index, table_sym->name,
1992 pars_sym_tab_global->heap);
1993
1994 table_sym->resolved = TRUE;
1995 table_sym->token_type = SYM_TABLE;
1996
1997 index_sym->resolved = TRUE;
1998 index_sym->token_type = SYM_TABLE;
1999
2000 return(node);
2001}
2002
2003/*********************************************************************//**
2004Parses a procedure definition.
2005@return query fork node */
2006que_fork_t*
2007pars_procedure_definition(
2008/*======================*/
2009 sym_node_t* sym_node, /*!< in: procedure id node in the symbol
2010 table */
2011 sym_node_t* param_list, /*!< in: parameter declaration list */
2012 que_node_t* stat_list) /*!< in: statement list */
2013{
2014 proc_node_t* node;
2015 que_fork_t* fork;
2016 que_thr_t* thr;
2017 mem_heap_t* heap;
2018
2019 heap = pars_sym_tab_global->heap;
2020
2021 fork = que_fork_create(NULL, NULL, QUE_FORK_PROCEDURE, heap);
2022 fork->trx = NULL;
2023
2024 thr = que_thr_create(fork, heap, NULL);
2025
2026 node = static_cast<proc_node_t*>(
2027 mem_heap_alloc(heap, sizeof(proc_node_t)));
2028
2029 node->common.type = QUE_NODE_PROC;
2030 node->common.parent = thr;
2031
2032 sym_node->token_type = SYM_PROCEDURE_NAME;
2033 sym_node->resolved = TRUE;
2034
2035 node->proc_id = sym_node;
2036 node->param_list = param_list;
2037 node->stat_list = stat_list;
2038
2039 pars_set_parent_in_list(stat_list, node);
2040
2041 node->sym_tab = pars_sym_tab_global;
2042
2043 thr->child = node;
2044
2045 pars_sym_tab_global->query_graph = fork;
2046
2047 return(fork);
2048}
2049
2050/*************************************************************//**
2051Parses a stored procedure call, when this is not within another stored
2052procedure, that is, the client issues a procedure call directly.
2053In MySQL/InnoDB, stored InnoDB procedures are invoked via the
2054parsed procedure tree, not via InnoDB SQL, so this function is not used.
2055@return query graph */
2056que_fork_t*
2057pars_stored_procedure_call(
2058/*=======================*/
2059 sym_node_t* sym_node MY_ATTRIBUTE((unused)))
2060 /*!< in: stored procedure name */
2061{
2062 ut_error;
2063 return(NULL);
2064}
2065
2066/*************************************************************//**
2067Retrieves characters to the lexical analyzer. */
2068int
2069pars_get_lex_chars(
2070/*===============*/
2071 char* buf, /*!< in/out: buffer where to copy */
2072 int max_size) /*!< in: maximum number of characters which fit
2073 in the buffer */
2074{
2075 int len;
2076
2077 len = int(pars_sym_tab_global->string_len)
2078 - pars_sym_tab_global->next_char_pos;
2079 if (len == 0) {
2080 return(0);
2081 }
2082
2083 if (len > max_size) {
2084 len = max_size;
2085 }
2086
2087 memcpy(buf, pars_sym_tab_global->sql_string
2088 + pars_sym_tab_global->next_char_pos, ulint(len));
2089
2090 pars_sym_tab_global->next_char_pos += len;
2091
2092 return(len);
2093}
2094
2095/*************************************************************//**
2096Called by yyparse on error. */
2097void
2098yyerror(
2099/*====*/
2100 const char* s MY_ATTRIBUTE((unused)))
2101 /*!< in: error message string */
2102{
2103 ut_ad(s);
2104
2105 ib::fatal() << "PARSER: Syntax error in SQL string";
2106}
2107
2108/*************************************************************//**
2109Parses an SQL string returning the query graph.
2110@return own: the query graph */
2111que_t*
2112pars_sql(
2113/*=====*/
2114 pars_info_t* info, /*!< in: extra information, or NULL */
2115 const char* str) /*!< in: SQL string */
2116{
2117 sym_node_t* sym_node;
2118 mem_heap_t* heap;
2119 que_t* graph;
2120
2121 ut_ad(str);
2122
2123 heap = mem_heap_create(16000);
2124
2125 /* Currently, the parser is not reentrant: */
2126 ut_ad(mutex_own(&dict_sys->mutex));
2127
2128 pars_sym_tab_global = sym_tab_create(heap);
2129
2130 pars_sym_tab_global->string_len = strlen(str);
2131 pars_sym_tab_global->sql_string = static_cast<char*>(
2132 mem_heap_dup(heap, str, pars_sym_tab_global->string_len + 1));
2133 pars_sym_tab_global->next_char_pos = 0;
2134 pars_sym_tab_global->info = info;
2135
2136 yyparse();
2137
2138 sym_node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
2139
2140 while (sym_node) {
2141 ut_a(sym_node->resolved);
2142
2143 sym_node = UT_LIST_GET_NEXT(sym_list, sym_node);
2144 }
2145
2146 graph = pars_sym_tab_global->query_graph;
2147
2148 graph->sym_tab = pars_sym_tab_global;
2149 graph->info = info;
2150
2151 pars_sym_tab_global = NULL;
2152
2153 /* fprintf(stderr, "SQL graph size %lu\n", mem_heap_get_size(heap)); */
2154
2155 return(graph);
2156}
2157
2158/** Completes a query graph by adding query thread and fork nodes
2159above it and prepares the graph for running. The fork created is of
2160type QUE_FORK_MYSQL_INTERFACE.
2161@param[in] node root node for an incomplete query
2162 graph, or NULL for dummy graph
2163@param[in] trx transaction handle
2164@param[in] heap memory heap from which allocated
2165@param[in] prebuilt row prebuilt structure
2166@return query thread node to run */
2167que_thr_t*
2168pars_complete_graph_for_exec(
2169 que_node_t* node,
2170 trx_t* trx,
2171 mem_heap_t* heap,
2172 row_prebuilt_t* prebuilt)
2173{
2174 que_fork_t* fork;
2175 que_thr_t* thr;
2176
2177 fork = que_fork_create(NULL, NULL, QUE_FORK_MYSQL_INTERFACE, heap);
2178 fork->trx = trx;
2179
2180 thr = que_thr_create(fork, heap, prebuilt);
2181
2182 thr->child = node;
2183
2184 if (node) {
2185 que_node_set_parent(node, thr);
2186 }
2187
2188 trx->graph = NULL;
2189
2190 return(thr);
2191}
2192
2193/****************************************************************//**
2194Create parser info struct.
2195@return own: info struct */
2196pars_info_t*
2197pars_info_create(void)
2198/*==================*/
2199{
2200 pars_info_t* info;
2201 mem_heap_t* heap;
2202
2203 heap = mem_heap_create(512);
2204
2205 info = static_cast<pars_info_t*>(mem_heap_alloc(heap, sizeof(*info)));
2206
2207 info->heap = heap;
2208 info->funcs = NULL;
2209 info->bound_lits = NULL;
2210 info->bound_ids = NULL;
2211 info->graph_owns_us = TRUE;
2212
2213 return(info);
2214}
2215
2216/****************************************************************//**
2217Free info struct and everything it contains. */
2218void
2219pars_info_free(
2220/*===========*/
2221 pars_info_t* info) /*!< in, own: info struct */
2222{
2223 mem_heap_free(info->heap);
2224}
2225
2226/****************************************************************//**
2227Add bound literal. */
2228void
2229pars_info_add_literal(
2230/*==================*/
2231 pars_info_t* info, /*!< in: info struct */
2232 const char* name, /*!< in: name */
2233 const void* address, /*!< in: address */
2234 ulint length, /*!< in: length of data */
2235 ulint type, /*!< in: type, e.g. DATA_FIXBINARY */
2236 ulint prtype) /*!< in: precise type, e.g.
2237 DATA_UNSIGNED */
2238{
2239 pars_bound_lit_t* pbl;
2240
2241 ut_ad(!pars_info_get_bound_lit(info, name));
2242
2243 pbl = static_cast<pars_bound_lit_t*>(
2244 mem_heap_alloc(info->heap, sizeof(*pbl)));
2245
2246 pbl->name = name;
2247
2248 pbl->address = address;
2249 pbl->length = length;
2250 pbl->type = type;
2251 pbl->prtype = prtype;
2252
2253 if (!info->bound_lits) {
2254 ib_alloc_t* heap_alloc;
2255
2256 heap_alloc = ib_heap_allocator_create(info->heap);
2257
2258 info->bound_lits = ib_vector_create(heap_alloc, sizeof(*pbl), 8);
2259 }
2260
2261 ib_vector_push(info->bound_lits, pbl);
2262}
2263
2264/****************************************************************//**
2265Equivalent to pars_info_add_literal(info, name, str, strlen(str),
2266DATA_VARCHAR, DATA_ENGLISH). */
2267void
2268pars_info_add_str_literal(
2269/*======================*/
2270 pars_info_t* info, /*!< in: info struct */
2271 const char* name, /*!< in: name */
2272 const char* str) /*!< in: string */
2273{
2274 pars_info_add_literal(info, name, str, strlen(str),
2275 DATA_VARCHAR, DATA_ENGLISH);
2276}
2277
2278/********************************************************************
2279If the literal value already exists then it rebinds otherwise it
2280creates a new entry.*/
2281void
2282pars_info_bind_literal(
2283/*===================*/
2284 pars_info_t* info, /* in: info struct */
2285 const char* name, /* in: name */
2286 const void* address, /* in: address */
2287 ulint length, /* in: length of data */
2288 ulint type, /* in: type, e.g. DATA_FIXBINARY */
2289 ulint prtype) /* in: precise type, e.g. */
2290{
2291 pars_bound_lit_t* pbl;
2292
2293 pbl = pars_info_lookup_bound_lit(info, name);
2294
2295 if (!pbl) {
2296 pars_info_add_literal(
2297 info, name, address, length, type, prtype);
2298 } else {
2299 pbl->address = address;
2300 pbl->length = length;
2301
2302 sym_tab_rebind_lit(pbl->node, address, length);
2303 }
2304}
2305
2306/********************************************************************
2307If the literal value already exists then it rebinds otherwise it
2308creates a new entry.*/
2309void
2310pars_info_bind_varchar_literal(
2311/*===========================*/
2312 pars_info_t* info, /*!< in: info struct */
2313 const char* name, /*!< in: name */
2314 const byte* str, /*!< in: string */
2315 ulint str_len) /*!< in: string length */
2316{
2317 pars_bound_lit_t* pbl;
2318
2319 pbl = pars_info_lookup_bound_lit(info, name);
2320
2321 if (!pbl) {
2322 pars_info_add_literal(
2323 info, name, str, str_len, DATA_VARCHAR, DATA_ENGLISH);
2324 } else {
2325
2326 pbl->address = str;
2327 pbl->length = str_len;
2328
2329 sym_tab_rebind_lit(pbl->node, str, str_len);
2330 }
2331}
2332
2333/****************************************************************//**
2334Equivalent to:
2335
2336char buf[4];
2337mach_write_to_4(buf, val);
2338pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
2339
2340except that the buffer is dynamically allocated from the info struct's
2341heap. */
2342void
2343pars_info_add_int4_literal(
2344/*=======================*/
2345 pars_info_t* info, /*!< in: info struct */
2346 const char* name, /*!< in: name */
2347 ulint val) /*!< in: value */
2348{
2349 byte* buf = static_cast<byte*>(mem_heap_alloc(info->heap, 4));
2350
2351 mach_write_to_4(buf, val);
2352 pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
2353}
2354
2355/********************************************************************
2356If the literal value already exists then it rebinds otherwise it
2357creates a new entry. */
2358void
2359pars_info_bind_int4_literal(
2360/*========================*/
2361 pars_info_t* info, /* in: info struct */
2362 const char* name, /* in: name */
2363 const ib_uint32_t* val) /* in: value */
2364{
2365 pars_bound_lit_t* pbl;
2366
2367 pbl = pars_info_lookup_bound_lit(info, name);
2368
2369 if (!pbl) {
2370 pars_info_add_literal(info, name, val, 4, DATA_INT, 0);
2371 } else {
2372
2373 pbl->address = val;
2374 pbl->length = sizeof(*val);
2375
2376 sym_tab_rebind_lit(pbl->node, val, sizeof(*val));
2377 }
2378}
2379
2380/********************************************************************
2381If the literal value already exists then it rebinds otherwise it
2382creates a new entry. */
2383void
2384pars_info_bind_int8_literal(
2385/*========================*/
2386 pars_info_t* info, /* in: info struct */
2387 const char* name, /* in: name */
2388 const ib_uint64_t* val) /* in: value */
2389{
2390 pars_bound_lit_t* pbl;
2391
2392 pbl = pars_info_lookup_bound_lit(info, name);
2393
2394 if (!pbl) {
2395 pars_info_add_literal(
2396 info, name, val, sizeof(*val), DATA_INT, 0);
2397 } else {
2398
2399 pbl->address = val;
2400 pbl->length = sizeof(*val);
2401
2402 sym_tab_rebind_lit(pbl->node, val, sizeof(*val));
2403 }
2404}
2405
2406/****************************************************************//**
2407Equivalent to:
2408
2409char buf[8];
2410mach_write_to_8(buf, val);
2411pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
2412
2413except that the buffer is dynamically allocated from the info struct's
2414heap. */
2415void
2416pars_info_add_ull_literal(
2417/*======================*/
2418 pars_info_t* info, /*!< in: info struct */
2419 const char* name, /*!< in: name */
2420 ib_uint64_t val) /*!< in: value */
2421{
2422 byte* buf = static_cast<byte*>(mem_heap_alloc(info->heap, 8));
2423
2424 mach_write_to_8(buf, val);
2425
2426 pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
2427}
2428
2429/****************************************************************//**
2430If the literal value already exists then it rebinds otherwise it
2431creates a new entry. */
2432void
2433pars_info_bind_ull_literal(
2434/*=======================*/
2435 pars_info_t* info, /*!< in: info struct */
2436 const char* name, /*!< in: name */
2437 const ib_uint64_t* val) /*!< in: value */
2438{
2439 pars_bound_lit_t* pbl;
2440
2441 pbl = pars_info_lookup_bound_lit(info, name);
2442
2443 if (!pbl) {
2444 pars_info_add_literal(
2445 info, name, val, sizeof(*val), DATA_FIXBINARY, 0);
2446 } else {
2447
2448 pbl->address = val;
2449 pbl->length = sizeof(*val);
2450
2451 sym_tab_rebind_lit(pbl->node, val, sizeof(*val));
2452 }
2453}
2454
2455/****************************************************************//**
2456Add user function. */
2457void
2458pars_info_bind_function(
2459/*====================*/
2460 pars_info_t* info, /*!< in: info struct */
2461 const char* name, /*!< in: function name */
2462 pars_user_func_cb_t func, /*!< in: function address */
2463 void* arg) /*!< in: user-supplied argument */
2464{
2465 pars_user_func_t* puf;
2466
2467 puf = pars_info_lookup_user_func(info, name);
2468
2469 if (!puf) {
2470 if (!info->funcs) {
2471 ib_alloc_t* heap_alloc;
2472
2473 heap_alloc = ib_heap_allocator_create(info->heap);
2474
2475 info->funcs = ib_vector_create(
2476 heap_alloc, sizeof(*puf), 8);
2477 }
2478
2479 /* Create a "new" element */
2480 puf = static_cast<pars_user_func_t*>(
2481 ib_vector_push(info->funcs, NULL));
2482 puf->name = name;
2483 }
2484
2485 puf->arg = arg;
2486 puf->func = func;
2487}
2488
2489/********************************************************************
2490Add bound id. */
2491void
2492pars_info_bind_id(
2493/*==============*/
2494 pars_info_t* info, /*!< in: info struct */
2495 ibool copy_name, /* in: copy name if TRUE */
2496 const char* name, /*!< in: name */
2497 const char* id) /*!< in: id */
2498{
2499 pars_bound_id_t* bid;
2500
2501 bid = pars_info_lookup_bound_id(info, name);
2502
2503 if (!bid) {
2504
2505 if (!info->bound_ids) {
2506 ib_alloc_t* heap_alloc;
2507
2508 heap_alloc = ib_heap_allocator_create(info->heap);
2509
2510 info->bound_ids = ib_vector_create(
2511 heap_alloc, sizeof(*bid), 8);
2512 }
2513
2514 /* Create a "new" element */
2515 bid = static_cast<pars_bound_id_t*>(
2516 ib_vector_push(info->bound_ids, NULL));
2517
2518 bid->name = (copy_name)
2519 ? mem_heap_strdup(info->heap, name) : name;
2520 }
2521
2522 bid->id = id;
2523}
2524
2525/********************************************************************
2526Get bound identifier with the given name.*/
2527pars_bound_id_t*
2528pars_info_get_bound_id(
2529/*===================*/
2530 /* out: bound id, or NULL if not
2531 found */
2532 pars_info_t* info, /* in: info struct */
2533 const char* name) /* in: bound id name to find */
2534{
2535 return(pars_info_lookup_bound_id(info, name));
2536}
2537
2538/****************************************************************//**
2539Get bound literal with the given name.
2540@return bound literal, or NULL if not found */
2541pars_bound_lit_t*
2542pars_info_get_bound_lit(
2543/*====================*/
2544 pars_info_t* info, /*!< in: info struct */
2545 const char* name) /*!< in: bound literal name to find */
2546{
2547 return(pars_info_lookup_bound_lit(info, name));
2548}
2549