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