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