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