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