CUBRID Engine  latest
parser_support.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * parser_support.c - Utility functions for parse trees
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <assert.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <limits.h>
32 #include <ctype.h>
33 
34 #if defined (_AIX)
35 #include <stdarg.h>
36 #endif
37 
38 #include "authenticate.h"
39 #include "chartype.h"
40 #include "parser.h"
41 #include "parser_message.h"
42 #include "mem_block.hpp"
43 #include "memory_alloc.h"
44 #include "intl_support.h"
45 #include "error_manager.h"
46 #include "work_space.h"
47 #include "oid.h"
48 #include "class_object.h"
49 #include "optimizer.h"
50 #include "object_primitive.h"
51 #include "object_representation.h"
52 #include "parser_support.h"
53 #include "system_parameter.h"
54 #include "xasl_generation.h"
55 #include "schema_manager.h"
56 #include "object_print.h"
57 #include "show_meta.h"
58 #include "db.h"
59 #include "object_printer.hpp"
60 #include "string_buffer.hpp"
61 #include "dbtype.h"
62 #include "parser_allocator.hpp"
63 
64 #if defined (SUPPRESS_STRLEN_WARNING)
65 #define strlen(s1) ((int) strlen(s1))
66 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
67 
68 #define DEFAULT_VAR "."
69 
71 {
76 };
77 
78 #define COMPATIBLE_WITH_INSTNUM(node) \
79  (pt_is_expr_node (node) && PT_EXPR_INFO_IS_FLAGED (node, PT_EXPR_INFO_INSTNUM_C))
80 
81 #define NOT_COMPATIBLE_WITH_INSTNUM(node) \
82  (pt_is_dot_node (node) || pt_is_attr (node) || pt_is_correlated_subquery (node) \
83  || (pt_is_expr_node (node) && PT_EXPR_INFO_IS_FLAGED (node, PT_EXPR_INFO_INSTNUM_NC)))
84 
85 #define COMPATIBLE_WITH_GROUPBYNUM(node) \
86  ((pt_is_function (node) && node->info.function.function_type == PT_GROUPBY_NUM) \
87  || (pt_is_expr_node (node) && PT_EXPR_INFO_IS_FLAGED (node, PT_EXPR_INFO_GROUPBYNUM_C)))
88 
89 #define NOT_COMPATIBLE_WITH_GROUPBYNUM(node) \
90  (pt_is_dot_node (node) || pt_is_attr (node) || pt_is_query (node) \
91  || (pt_is_expr_node (node) && PT_EXPR_INFO_IS_FLAGED (node, PT_EXPR_INFO_GROUPBYNUM_NC)))
92 
93 /* reserve half a page for the total enum domain size. we used to consider BTREE_ROOT_HEADER size here, but this is
94  * client and we no longer have that information. but half of page should be enough... the alternative is to get
95  * that info from server. */
96 #define DB_ENUM_ELEMENTS_MAX_AGG_SIZE (DB_PAGESIZE / 2)
97 
99 
100 static const int PACKING_MMGR_CHUNK_SIZE = 1024;
101 static const int PACKING_MMGR_BLOCK_SIZE = 10;
102 
103 static int packing_heap_num_slot = 0;
104 static HL_HEAPID *packing_heap = NULL;
105 static int packing_level = 0;
106 
107 static void pt_free_packing_buf (int slot);
108 
109 static bool pt_datatypes_match (const PT_NODE * a, const PT_NODE * b);
110 static PT_NODE *pt_get_select_from_spec (const PT_NODE * spec);
111 static PT_NODE *pt_insert_host_var (PARSER_CONTEXT * parser, PT_NODE * h_var, PT_NODE * list);
112 static PT_NODE *pt_collect_host_info (PARSER_CONTEXT * parser, PT_NODE * node, void *h_var, int *continue_walk);
113 static PT_NODE *pt_collect_parameters (PARSER_CONTEXT * parser, PT_NODE * node, void *param_list, int *continue_walk);
114 static PT_NODE *pt_must_be_filtering (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
115 static bool pt_is_filtering_predicate (PARSER_CONTEXT * parser, PT_NODE * predicate);
116 static PT_NODE *pt_is_filtering_skip_and_or (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
117 
118 static PT_NODE *pt_create_param_for_value (PARSER_CONTEXT * parser, PT_NODE * value, int host_var_index);
119 static PT_NODE *pt_make_dotted_identifier (PARSER_CONTEXT * parser, const char *identifier_str);
120 static PT_NODE *pt_make_dotted_identifier_internal (PARSER_CONTEXT * parser, const char *identifier_str, int depth);
121 static int pt_add_name_col_to_sel_list (PARSER_CONTEXT * parser, PT_NODE * select, const char *identifier_str,
122  const char *col_alias);
123 static void pt_add_string_col_to_sel_list (PARSER_CONTEXT * parser, PT_NODE * select, const char *identifier_str,
124  const char *col_alias);
125 static PT_NODE *pt_make_pred_name_int_val (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *col_name,
126  const int int_value);
127 static PT_NODE *pt_make_pred_name_string_val (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *identifier_str,
128  const char *str_value);
129 static PT_NODE *pt_make_pred_with_identifiers (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *lhs_identifier,
130  const char *rhs_identifier);
131 static PT_NODE *pt_make_if_with_expressions (PARSER_CONTEXT * parser, PT_NODE * pred, PT_NODE * expr1, PT_NODE * expr2,
132  const char *alias);
133 static PT_NODE *pt_make_if_with_strings (PARSER_CONTEXT * parser, PT_NODE * pred, const char *string1,
134  const char *string2, const char *alias);
135 static PT_NODE *pt_make_like_col_expr (PARSER_CONTEXT * parser, PT_NODE * rhs_expr, const char *col_name);
137  const char *select_alias);
142 static PT_NODE *pt_make_sort_spec_with_identifier (PARSER_CONTEXT * parser, const char *identifier,
143  PT_MISC_TYPE sort_mode);
144 static PT_NODE *pt_make_sort_spec_with_number (PARSER_CONTEXT * parser, const int number_pos, PT_MISC_TYPE sort_mode);
145 static PT_NODE *pt_make_collection_type_subquery_node (PARSER_CONTEXT * parser, const char *table_name);
146 static PT_NODE *pt_make_dummy_query_check_table (PARSER_CONTEXT * parser, const char *table_name);
147 static PT_NODE *pt_make_query_user_groups (PARSER_CONTEXT * parser, const char *user_name);
148 static void pt_help_show_create_table (PARSER_CONTEXT * parser, PT_NODE * table_name, string_buffer & strbuf);
149 static int pt_get_query_limit_from_orderby_for (PARSER_CONTEXT * parser, PT_NODE * orderby_for, DB_VALUE * upper_limit,
150  bool * has_limit);
151 static int pt_get_query_limit_from_limit (PARSER_CONTEXT * parser, PT_NODE * limit, DB_VALUE * limit_val);
152 static PT_NODE *pt_create_delete_stmt (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * target_class);
153 static PT_NODE *pt_is_spec_referenced (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk);
155  bool add_as_attr);
158 static bool check_arg_valid (PARSER_CONTEXT * parser, const SHOWSTMT_NAMED_ARG * arg_meta, int arg_num, PT_NODE * val);
160  int arg_info_count, PT_NODE * args);
162  int arg_info_count, PT_NODE * args);
163 #define NULL_ATTRID -1
164 
165 /*
166  * pt_make_integer_value () -
167  * return: return a PT_NODE for the integer value
168  * parser(in): parser context
169  * value_int(in): integer value to make up a PT_NODE
170  */
171 PT_NODE *
173 {
174  PT_NODE *node;
175 
176  node = parser_new_node (parser, PT_VALUE);
177  if (node)
178  {
179  node->type_enum = PT_TYPE_INTEGER;
180  node->info.value.data_value.i = value_int;
181  }
182  return node;
183 }
184 
185 /*
186  * pt_make_string_value () -
187  * return: return a PT_NODE for the string value
188  * parser(in): parser context
189  * value_string(in): string value to make up a PT_NODE
190  */
191 
192 PT_NODE *
193 pt_make_string_value (PARSER_CONTEXT * parser, const char *value_string)
194 {
195  PT_NODE *node;
196 
197  node = parser_new_node (parser, PT_VALUE);
198  if (node)
199  {
200  if (value_string == NULL)
201  {
202  node->type_enum = PT_TYPE_NULL;
203  }
204  else
205  {
206  node->info.value.data_value.str = pt_append_bytes (parser, NULL, value_string, strlen (value_string));
207  node->type_enum = PT_TYPE_CHAR;
208  node->info.value.string_type = ' ';
209  PT_NODE_PRINT_VALUE_TO_TEXT (parser, node);
210  }
211  }
212  return node;
213 }
214 
215 /*
216  * pt_and () - Create a PT_AND node with arguments of the nodes passed in
217  * return:
218  * parser(in):
219  * arg1(in):
220  * arg2(in):
221  */
222 PT_NODE *
223 pt_and (PARSER_CONTEXT * parser, const PT_NODE * arg1, const PT_NODE * arg2)
224 {
225  PT_NODE *node;
226 
227  node = parser_new_node (parser, PT_EXPR);
228  if (node)
229  {
230  node->info.expr.op = PT_AND;
231  node->info.expr.arg1 = (PT_NODE *) arg1;
232  node->info.expr.arg2 = (PT_NODE *) arg2;
233  }
234 
235  return node;
236 }
237 
238 /*
239  * pt_union () - Create a PT_UNION node with arguments of the nodes passed in
240  * return:
241  * parser(in):
242  * arg1(in/out):
243  * arg2(in/out):
244  */
245 PT_NODE *
247 {
248  PT_NODE *node;
249  int arg1_corr = 0, arg2_corr = 0, corr;
250 
251  node = parser_new_node (parser, PT_UNION);
252 
253  if (node)
254  {
255  /* set query id # */
256  node->info.query.id = (UINTPTR) node;
257 
258  node->info.query.q.union_.arg1 = arg1;
259  node->info.query.q.union_.arg2 = arg2;
260 
261  if (arg1)
262  {
264  arg1_corr = arg1->info.query.correlation_level;
265  }
266  if (arg2)
267  {
269  arg2_corr = arg2->info.query.correlation_level;
270  }
271  if (arg1_corr)
272  {
273  corr = arg1_corr;
274  if (arg2_corr && arg2_corr < corr)
275  {
276  corr = arg2_corr;
277  }
278  }
279  else
280  {
281  corr = arg2_corr;
282  }
283 
284  if (corr)
285  {
286  corr--;
287  }
288 
289  node->info.query.correlation_level = corr;
290  }
291 
292  return node;
293 }
294 
295 /*
296  * pt_name () - Create a PT_NAME node using the name string passed in
297  * return:
298  * parser(in):
299  * name(in):
300  */
301 PT_NODE *
302 pt_name (PARSER_CONTEXT * parser, const char *name)
303 {
304  PT_NODE *node;
305 
306  node = parser_new_node (parser, PT_NAME);
307  if (node)
308  {
309  node->info.name.original = pt_append_string (parser, NULL, name);
310  }
311 
312  return node;
313 }
314 
315 /*
316  * pt_table_option () - Create a PT_TABLE_OPTION node
317  * return: the new node or NULL on error
318  * parser(in):
319  * option(in): the type of the table option
320  * val(in): a value associated with the table option or NULL
321  */
322 PT_NODE *
324 {
325  PT_NODE *node;
326 
327  node = parser_new_node (parser, PT_TABLE_OPTION);
328  if (node)
329  {
330  node->info.table_option.option = option;
331  node->info.table_option.val = val;
332  }
333 
334  return node;
335 }
336 
337 /*
338  * pt_expression () - Create a PT_EXPR node using the arguments passed in
339  * return:
340  * parser(in):
341  * op(in): the expression operation type
342  * arg1(in):
343  * arg2(in):
344  * arg3(in):
345  */
346 PT_NODE *
348 {
349  PT_NODE *node;
350 
351  node = parser_new_node (parser, PT_EXPR);
352  if (node)
353  {
354  node->info.expr.op = op;
355  node->info.expr.arg1 = arg1;
356  node->info.expr.arg2 = arg2;
357  node->info.expr.arg3 = arg3;
358  }
359 
360  return node;
361 }
362 
363 PT_NODE *
365 {
366  return pt_expression (parser, op, NULL, NULL, NULL);
367 }
368 
369 PT_NODE *
371 {
372  return pt_expression (parser, op, arg1, NULL, NULL);
373 }
374 
375 PT_NODE *
377 {
378  return pt_expression (parser, op, arg1, arg2, NULL);
379 }
380 
381 PT_NODE *
383 {
384  return pt_expression (parser, op, arg1, arg2, arg3);
385 }
386 
387 /*
388  * pt_node_list () - Create a PT_NODE_LIST node using the arguments passed in
389  * return:
390  * parser(in):
391  * list_type(in):
392  * list(in):
393  */
394 PT_NODE *
396 {
397  PT_NODE *node;
398 
399  node = parser_new_node (parser, PT_NODE_LIST);
400  if (node)
401  {
402  node->info.node_list.list_type = list_type;
403  node->info.node_list.list = list;
404  }
405 
406  return node;
407 }
408 
409 /*
410  * pt_entity () - Create a PT_SPEC node using the node string passed
411  * for the entity name
412  * return:
413  * parser(in):
414  * entity_name(in):
415  * range_var(in):
416  * flat_list(in):
417  */
418 PT_NODE *
419 pt_entity (PARSER_CONTEXT * parser, const PT_NODE * entity_name, const PT_NODE * range_var, const PT_NODE * flat_list)
420 {
421  PT_NODE *node;
422 
423  node = parser_new_node (parser, PT_SPEC);
424  if (node)
425  {
426  node->info.spec.entity_name = (PT_NODE *) entity_name;
427  node->info.spec.range_var = (PT_NODE *) range_var;
428  node->info.spec.flat_entity_list = (PT_NODE *) flat_list;
429  }
430 
431  return node;
432 }
433 
434 /*
435  * pt_tuple_value () - create a tuple_value node with the specified name and
436  * index in a query result
437  * return : new node or NULL
438  * parser (in) : parser context
439  * name (in) : name node
440  * cursor_p (in) : cursor for which to fetch tuple value
441  * index (in) : index in cursor column list
442  */
443 PT_NODE *
445 {
446  PT_NODE *node;
447  node = parser_new_node (parser, PT_TUPLE_VALUE);
448  if (node)
449  {
450  node->info.tuple_value.name = name;
451  node->info.tuple_value.index = index;
452  node->info.tuple_value.cursor_p = cursor_p;
453  }
454  return node;
455 }
456 
457 /*
458  * pt_insert_value () - Creates an insert value setting node argument as
459  * original node.
460  *
461  * return : PT_INSERT_VALUE node.
462  * parser (in) : Parser context.
463  * node (in) : Original node.
464  */
465 PT_NODE *
467 {
468  PT_NODE *insert_val = parser_new_node (parser, PT_INSERT_VALUE);
469  if (insert_val != NULL)
470  {
471  insert_val->info.insert_value.original_node = node;
472  }
473  return insert_val;
474 }
475 
476 /*
477  * pt_datatypes_match () -
478  * return: 1 if the two data types are not virtual objects or the same
479  * class of virtual object. 0 otherwise.
480  * a(in):
481  * b(in): data types to compare
482  */
483 
484 static bool
485 pt_datatypes_match (const PT_NODE * a, const PT_NODE * b)
486 {
487  if (!a && !b)
488  {
489  return true; /* both non objects, ok */
490  }
491  if (!a || !b)
492  {
493  return true; /* typed and untyped node, ignore difference */
494  }
496  {
497  return true; /* both non objects again, ok */
498  }
499 
501  {
502  return false;
503  }
505  {
506  return false;
507  }
508 
509  /* both the same flavor virtual objects */
510  return true;
511 }
512 
513 /*
514  * pt_name_equal () - Tests name nodes for equality
515  * return: true on equal
516  * parser(in):
517  * name1(in):
518  * name2(in):
519  *
520  * Note :
521  * Assumes semantic processing has resolved name information
522  */
523 bool
524 pt_name_equal (PARSER_CONTEXT * parser, const PT_NODE * name1, const PT_NODE * name2)
525 {
526  if (!name1 || !name2)
527  {
528  return false;
529  }
530 
531  CAST_POINTER_TO_NODE (name1);
532  CAST_POINTER_TO_NODE (name2);
533 
534  if (name1->node_type != PT_NAME)
535  {
536  return false;
537  }
538 
539  if (name2->node_type != PT_NAME)
540  {
541  return false;
542  }
543 
544  /* identity */
545  if (name1 == name2)
546  {
547  return true;
548  }
549 
550  /* are the id's equal? */
551  if (name1->info.name.spec_id != name2->info.name.spec_id)
552  {
553  return false;
554  }
555 
556  /* raw names the same? (NULL not allowed here) */
557  if (!name1->info.name.original)
558  {
559  return false;
560  }
561  if (!name2->info.name.original)
562  {
563  return false;
564  }
565 
566  if (name1->info.name.meta_class != name2->info.name.meta_class)
567  {
568  /* check for equivalence class PT_SHARED == PT_NORMAL */
569  if (name1->info.name.meta_class != PT_SHARED && name1->info.name.meta_class != PT_NORMAL)
570  {
571  return false;
572  }
573  if (name2->info.name.meta_class != PT_SHARED && name2->info.name.meta_class != PT_NORMAL)
574  {
575  return false;
576  }
577  }
578 
579  if (intl_identifier_casecmp (name1->info.name.original, name2->info.name.original) != 0)
580  {
581  return false;
582  }
583 
584 
585  if (!pt_datatypes_match (name1->data_type, name2->data_type))
586  {
587  return false;
588  }
589 
590  return true;
591 }
592 
593 /*
594  * pt_find_name () - Looks for a name on a list
595  * return:
596  * parser(in):
597  * name(in):
598  * list(in):
599  */
600 PT_NODE *
601 pt_find_name (PARSER_CONTEXT * parser, const PT_NODE * name, const PT_NODE * list)
602 {
603  while (list)
604  {
605  if (pt_name_equal (parser, name, list))
606  {
607  return (PT_NODE *) list;
608  }
609  list = list->next;
610  }
611 
612  return NULL;
613 }
614 
615 /*
616  * pt_is_aggregate_function () -
617  * return: true in arg if node is a PT_FUNCTION
618  * node with a PT_MIN, PT_MAX, PT_SUM, PT_AVG, or PT_COUNT type
619  * parser(in):
620  * node(in):
621  */
622 bool
624 {
625  FUNC_TYPE function_type;
626 
627  if (node->node_type == PT_FUNCTION)
628  {
629  function_type = node->info.function.function_type;
630  if (!node->info.function.analytic.is_analytic
631  && (function_type == PT_MIN || function_type == PT_MAX || function_type == PT_SUM || function_type == PT_AVG
632  || function_type == PT_STDDEV || function_type == PT_STDDEV_POP || function_type == PT_STDDEV_SAMP
633  || function_type == PT_VARIANCE || function_type == PT_VAR_POP || function_type == PT_VAR_SAMP
634  || function_type == PT_GROUPBY_NUM || function_type == PT_COUNT || function_type == PT_COUNT_STAR
635  || function_type == PT_AGG_BIT_AND || function_type == PT_AGG_BIT_OR || function_type == PT_AGG_BIT_XOR
636  || function_type == PT_GROUP_CONCAT || function_type == PT_MEDIAN || function_type == PT_PERCENTILE_CONT
637  || function_type == PT_PERCENTILE_DISC || function_type == PT_CUME_DIST
638  || function_type == PT_PERCENT_RANK || function_type == PT_JSON_ARRAYAGG
639  || function_type == PT_JSON_OBJECTAGG))
640  {
641  return true;
642  }
643  }
644 
645  return false;
646 }
647 
648 /*
649  * pt_is_analytic_function () -
650  * return: true in arg if node is an analytic function
651  * parser(in):
652  * node(in):
653  */
654 bool
656 {
657  if (node != NULL && node->node_type == PT_FUNCTION && node->info.function.analytic.is_analytic)
658  {
659  return true;
660  }
661  else
662  {
663  return false;
664  }
665 }
666 
667 /*
668  * pt_is_expr_wrapped_function () -
669  * return: true if node is a PT_FUNCTION node with which may be evaluated
670  * like an expression
671  * parser(in): parser context
672  * node(in): PT_FUNTION node
673  */
674 bool
676 {
677  FUNC_TYPE function_type;
678 
679  if (node->node_type == PT_FUNCTION)
680  {
681  function_type = node->info.function.function_type;
682  if (function_type == F_INSERT_SUBSTRING
683  || function_type == F_ELT
684  || function_type == F_JSON_ARRAY
685  || function_type == F_JSON_ARRAY_APPEND || function_type == F_JSON_ARRAY_INSERT
686  || function_type == F_JSON_CONTAINS || function_type == F_JSON_CONTAINS_PATH
687  || function_type == F_JSON_DEPTH
688  || function_type == F_JSON_EXTRACT
689  || function_type == F_JSON_GET_ALL_PATHS
690  || function_type == F_JSON_INSERT
691  || function_type == F_JSON_KEYS
692  || function_type == F_JSON_LENGTH
693  || function_type == F_JSON_MERGE || function_type == F_JSON_MERGE_PATCH
694  || function_type == F_JSON_OBJECT
695  || function_type == F_JSON_PRETTY
696  || function_type == F_JSON_QUOTE
697  || function_type == F_JSON_REMOVE
698  || function_type == F_JSON_REPLACE
699  || function_type == F_JSON_SEARCH
700  || function_type == F_JSON_SET
701  || function_type == F_JSON_TYPE || function_type == F_JSON_UNQUOTE || function_type == F_JSON_VALID
702  || function_type == F_REGEXP_COUNT || function_type == F_REGEXP_INSTR || function_type == F_REGEXP_LIKE
703  || function_type == F_REGEXP_REPLACE || function_type == F_REGEXP_SUBSTR)
704  {
705  return true;
706  }
707  }
708 
709  return false;
710 }
711 
712 /*
713  * pt_find_spec_in_statement () - find the node spec in given statement
714  * return: the spec with same id as the name, or NULL
715  * parser(in):
716  * stmt(in):
717  * name(in):
718  */
719 PT_NODE *
721 {
722  PT_NODE *spec = NULL;
723 
724  switch (stmt->node_type)
725  {
726  case PT_SPEC:
727  spec = pt_find_spec (parser, stmt, name);
728  break;
729 
730  case PT_DELETE:
731  spec = pt_find_spec (parser, stmt->info.delete_.spec, name);
732  if (spec == NULL)
733  {
734  spec = pt_find_spec (parser, stmt->info.delete_.class_specs, name);
735  }
736  break;
737 
738  case PT_UPDATE:
739  spec = pt_find_spec (parser, stmt->info.update.spec, name);
740  if (spec == NULL)
741  {
742  spec = pt_find_spec (parser, stmt->info.update.class_specs, name);
743  }
744  break;
745 
746  case PT_MERGE:
747  spec = pt_find_spec (parser, stmt->info.merge.into, name);
748  if (spec == NULL)
749  {
750  spec = pt_find_spec (parser, stmt->info.merge.using_clause, name);
751  }
752  break;
753 
754  default:
755  break;
756  }
757 
758  return (PT_NODE *) spec;
759 }
760 
761 /*
762  * pt_find_spec () -
763  * return: the spec in the from list with same id as the name, or NULL
764  * parser(in):
765  * from(in):
766  * name(in):
767  */
768 PT_NODE *
769 pt_find_spec (PARSER_CONTEXT * parser, const PT_NODE * from, const PT_NODE * name)
770 {
771  while (from && from->info.spec.id != name->info.name.spec_id)
772  {
773  /* check for path-entities */
774  if (from->info.spec.path_entities && pt_find_spec (parser, from->info.spec.path_entities, name))
775  {
776  break;
777  }
778  from = from->next;
779  }
780 
781  return (PT_NODE *) from;
782 }
783 
784 /*
785  * pt_find_aggregate_names - find names within select_stack
786  * returns: unmodified tree
787  * parser(in): parser context
788  * tree(in): tree to search into
789  * arg(in/out): a PT_AGG_NAME_INFO structure
790  * continue_walk(in/out): walk type
791  *
792  * NOTE: this function is called on an aggregate function or it's arguments
793  * and it returns the maximum level within the stack that owns PT_NAMEs within
794  * the called-on tree.
795  */
796 PT_NODE *
797 pt_find_aggregate_names (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
798 {
799  PT_AGG_NAME_INFO *info = (PT_AGG_NAME_INFO *) arg;
800  PT_NODE *node = NULL, *select_stack;
801  int level = 0;
802  bool max_level_has_gby = false;
803 
804  switch (tree->node_type)
805  {
806  case PT_SELECT:
807  *continue_walk = PT_LIST_WALK;
808  break;
809 
810  case PT_DOT_:
811  node = tree->info.dot.arg2;
812  break;
813 
814  case PT_NAME:
815  node = tree;
816  break;
817 
818  default:
819  break;
820  }
821 
822  if (node == NULL || node->node_type != PT_NAME)
823  {
824  /* nothing to do */
825  return tree;
826  }
827  else
828  {
829  info->name_count++;
830  }
831 
832  select_stack = info->select_stack;
833  while (select_stack != NULL)
834  {
835  PT_NODE *select = select_stack->info.pointer.node;
836 
837  if (select == NULL || select->node_type != PT_SELECT)
838  {
839  PT_INTERNAL_ERROR (parser, "stack entry is not SELECT");
840  return tree;
841  }
842 
843  if (level > info->max_level && pt_find_spec (parser, select->info.query.q.select.from, node))
844  {
845  /* found! */
846  info->max_level = level;
847  max_level_has_gby = (select->info.query.q.select.group_by != NULL);
848  }
849 
850  /* next stack level */
851  select_stack = select_stack->next;
852  level++;
853  }
854 
855  /* Note: we need to deal with corelated queries when an aggregate function in the subquery contains arguments in
856  * outer-level queries. For example: 'select (select sum(t1.i) from t2) from t1;' It should be evaluted over the
857  * rows of the nearest outer level. */
858  if (!max_level_has_gby)
859  {
860  info->max_level = level - 1;
861  }
862 
863  return tree;
864 }
865 
866 /*
867  * pt_find_aggregate_functions_pre () - finds aggregate functions in a tree
868  * returns: unmodified tree
869  * parser(in): parser context
870  * tree(in): tree to search into
871  * arg(in/out): a PT_AGG_FIND_INFO structure
872  * continue_walk(in/out): walk type
873  *
874  * NOTE: this routine searches for aggregate functions that belong to the
875  * SELECT statement at the base of the stack
876  */
877 PT_NODE *
878 pt_find_aggregate_functions_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
879 {
880  PT_AGG_FIND_INFO *info = (PT_AGG_FIND_INFO *) arg;
881  PT_NODE *select_stack = info->select_stack;
882  PT_NODE *stack_top = select_stack;
883 
884  if (tree == NULL)
885  {
886  /* nothing to do */
887  return tree;
888  }
889 
890  while (stack_top != NULL && stack_top->next != NULL)
891  {
892  stack_top = stack_top->next;
893  }
894  if (stack_top && stack_top->info.pointer.node && stack_top->info.pointer.node->node_type == PT_SELECT
895  && stack_top->info.pointer.node->info.query.q.select.where == tree)
896  {
897  /* subqueries of WHERE clause will not be walked for this parent query; they must be treated separately as they
898  * own any aggregates referring upper-level names */
899  info->stop_on_subquery = true;
900  }
901 
902  if (pt_is_aggregate_function (parser, tree))
903  {
905  {
906  /* found count(*), groupby_num() */
907  if (select_stack == NULL)
908  {
909  /* no spec stack, this was not called on a select */
910  info->out_of_context_count++;
911  }
912  else if (select_stack->next == NULL)
913  {
914  /* first level on spec stack, this function belongs to the callee statement */
915  info->base_count++;
916 
918  {
919  /* can't use count star in loose scan */
920  info->disable_loose_scan = true;
921  }
922  }
923  }
924  else
925  {
926  PT_AGG_NAME_INFO name_info;
927  name_info.select_stack = info->select_stack;
928  name_info.max_level = -1;
929  name_info.name_count = 0;
930 
931  (void) parser_walk_tree (parser, tree->info.function.arg_list, pt_find_aggregate_names, &name_info,
933 
934  if (name_info.max_level == 0)
935  {
936  /* only names from base SELECT were found */
937  info->base_count++;
938 
940  && tree->info.function.function_type != PT_MAX)
941  {
942  /* only DISTINCT allowed for functions other than MIN/MAX */
943  info->disable_loose_scan = true;
944  }
945  }
946  else if (name_info.max_level < 0 && name_info.name_count > 0)
947  {
948  /* no names within stack limit were found */
949  info->out_of_context_count++;
950  }
951  else if (name_info.name_count == 0)
952  {
953  /* no names were found at all */
954  if (select_stack == NULL)
955  {
956  info->out_of_context_count++;
957  }
958  else if (select_stack->next == NULL)
959  {
960  info->base_count++;
961  }
962  }
963  }
964  }
965  else if (tree->node_type == PT_SELECT)
966  {
967  PT_NODE *spec;
968 
969  /* we must evaluate nexts before pushing SELECT on stack */
970  if (tree->next)
971  {
972  (void) parser_walk_tree (parser, tree->next, pt_find_aggregate_functions_pre, info,
974  *continue_walk = PT_LEAF_WALK;
975  }
976 
977  /* if we encountered a subquery while walking where clause, stop this walk and make subquery owner of all
978  * aggregate functions that reference upper-level names */
979  if (info->stop_on_subquery)
980  {
981  PT_AGG_FIND_INFO sub_info;
982  sub_info.base_count = 0;
983  sub_info.out_of_context_count = 0;
984  sub_info.select_stack = NULL;
985  sub_info.stop_on_subquery = false;
986 
987  (void) parser_walk_tree (parser, tree, pt_find_aggregate_functions_pre, &sub_info,
989 
990  if (sub_info.out_of_context_count > 0)
991  {
992  /* mark as agg select; base_count > 0 case will be handled later on */
994  }
995 
996  *continue_walk = PT_STOP_WALK;
997  }
998 
999  /* don't get confused by uncorrelated, set-derived subqueries. */
1000  if (tree->info.query.correlation_level == 0 && (spec = tree->info.query.q.select.from)
1002  {
1003  /* no need to dive into the uncorrelated, set-derived subqueries */
1004  *continue_walk = PT_STOP_WALK;
1005  }
1006 
1007  /* stack push */
1008  info->select_stack = pt_pointer_stack_push (parser, info->select_stack, tree);
1009  }
1010 
1011  return tree;
1012 }
1013 
1014 /*
1015  * pt_find_aggregate_functions_post () - finds aggregate functions in a tree
1016  * returns: unmodified tree
1017  * parser(in): parser context
1018  * tree(in): tree to search into
1019  * arg(in/out): a PT_AGG_FIND_INFO structure
1020  * continue_walk(in/out): walk type
1021  */
1022 PT_NODE *
1023 pt_find_aggregate_functions_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1024 {
1025  PT_AGG_FIND_INFO *info = (PT_AGG_FIND_INFO *) arg;
1026 
1027  if (tree->node_type == PT_SELECT)
1028  {
1029  info->select_stack = pt_pointer_stack_pop (parser, info->select_stack, NULL);
1030  }
1031  else
1032  {
1033  PT_NODE *stack_top = info->select_stack;
1034 
1035  while (stack_top != NULL && stack_top->next != NULL)
1036  {
1037  stack_top = stack_top->next;
1038  }
1039  if (stack_top && stack_top->info.pointer.node && stack_top->info.pointer.node->node_type == PT_SELECT
1040  && stack_top->info.pointer.node->info.query.q.select.where == tree)
1041  {
1042  info->stop_on_subquery = false;
1043  }
1044  }
1045 
1046  /* nothing can stop us! */
1047  *continue_walk = PT_CONTINUE_WALK;
1048 
1049  return tree;
1050 }
1051 
1052 /*
1053  * pt_is_analytic_node_post () -
1054  * return:
1055  * parser(in):
1056  * tree(in):
1057  * arg(in/out):
1058  * continue_walk(in/out):
1059  */
1060 PT_NODE *
1061 pt_is_analytic_node_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1062 {
1063  bool *has_analytic = (bool *) arg;
1064 
1065  if (*has_analytic)
1066  {
1067  *continue_walk = PT_STOP_WALK;
1068  }
1069  else
1070  {
1071  *continue_walk = PT_CONTINUE_WALK;
1072  }
1073 
1074  return tree;
1075 }
1076 
1077 /*
1078  * pt_is_analytic_node () -
1079  * return:
1080  * parser(in):
1081  * tree(in):
1082  * arg(in/out): true if node is an analytic function node
1083  * continue_walk(in/out):
1084  */
1085 PT_NODE *
1086 pt_is_analytic_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1087 {
1088  bool *has_analytic = (bool *) arg;
1089 
1090  if (tree && tree->node_type == PT_FUNCTION && tree->info.function.analytic.is_analytic)
1091  {
1092  *has_analytic = true;
1093  }
1094 
1095  if (*has_analytic)
1096  {
1097  *continue_walk = PT_STOP_WALK;
1098  }
1099  else if (PT_IS_QUERY_NODE_TYPE (tree->node_type))
1100  {
1101  *continue_walk = PT_LIST_WALK;
1102  }
1103  else
1104  {
1105  *continue_walk = PT_CONTINUE_WALK;
1106  }
1107 
1108  return tree;
1109 }
1110 
1111 /*
1112  * pt_has_non_idx_sarg_coll_pre () - pre function for determining if a tree has
1113  * contains a node with a collation that
1114  * renders it unusable for key range/filter
1115  * returns: input node
1116  * parser(in): parser to use
1117  * tree(in): tree node to analyze
1118  * arg(out): integer, will be set to "1" if node is found unfit
1119  * continue_walk(out): to be set to PT_STOP_WALK where necessary
1120  */
1121 PT_NODE *
1122 pt_has_non_idx_sarg_coll_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1123 {
1124  int *mark = (int *) arg;
1125 
1126  assert (tree != NULL);
1127  assert (arg != NULL);
1128  assert (continue_walk != NULL);
1129 
1130  if (PT_HAS_COLLATION (tree->type_enum) && (tree->data_type != NULL))
1131  {
1132  int collation_id = tree->data_type->info.data_type.collation_id;
1133  LANG_COLLATION *lang_coll = lang_get_collation (collation_id);
1134 
1135  if (!lang_coll->options.allow_index_opt)
1136  {
1137  *mark = 1;
1138  *continue_walk = PT_STOP_WALK;
1139  }
1140  }
1141 
1142  return tree;
1143 }
1144 
1145 /*
1146  * pt_is_inst_or_orderby_num_node_post () -
1147  * return:
1148  * parser(in):
1149  * tree(in):
1150  * arg(in/out):
1151  * continue_walk(in/out):
1152  */
1153 PT_NODE *
1154 pt_is_inst_or_orderby_num_node_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1155 {
1156  bool *has_inst_orderby_num = (bool *) arg;
1157 
1158  if (*has_inst_orderby_num)
1159  {
1160  *continue_walk = PT_STOP_WALK;
1161  }
1162  else
1163  {
1164  *continue_walk = PT_CONTINUE_WALK;
1165  }
1166 
1167  return tree;
1168 }
1169 
1170 /*
1171  * pt_is_inst_or_orderby_num_node () -
1172  * return:
1173  * parser(in):
1174  * tree(in):
1175  * arg(in/out): true if node is an INST_NUM or ORDERBY_NUM expression node
1176  * continue_walk(in/out):
1177  */
1178 PT_NODE *
1179 pt_is_inst_or_orderby_num_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1180 {
1181  bool *has_inst_orderby_num = (bool *) arg;
1182 
1183  if (PT_IS_INSTNUM (tree) || PT_IS_ORDERBYNUM (tree))
1184  {
1185  *has_inst_orderby_num = true;
1186  }
1187 
1188  if (*has_inst_orderby_num)
1189  {
1190  *continue_walk = PT_STOP_WALK;
1191  }
1192  else if (PT_IS_QUERY_NODE_TYPE (tree->node_type))
1193  {
1194  *continue_walk = PT_LIST_WALK;
1195  }
1196 
1197  return tree;
1198 }
1199 
1200 /*
1201  * pt_is_ddl_statement () - test PT_NODE statement types,
1202  * without exposing internals
1203  * return:
1204  * node(in):
1205  */
1206 int
1208 {
1209  if (node)
1210  {
1211  switch (node->node_type)
1212  {
1213  case PT_ALTER:
1214  case PT_ALTER_INDEX:
1215  case PT_ALTER_SERIAL:
1217  case PT_ALTER_TRIGGER:
1218  case PT_ALTER_USER:
1219  case PT_CREATE_ENTITY:
1220  case PT_CREATE_INDEX:
1221  case PT_CREATE_SERIAL:
1223  case PT_CREATE_TRIGGER:
1224  case PT_CREATE_USER:
1225  case PT_DROP:
1226  case PT_DROP_INDEX:
1227  case PT_DROP_SERIAL:
1229  case PT_DROP_TRIGGER:
1230  case PT_DROP_USER:
1231  case PT_GRANT:
1232  case PT_RENAME:
1233  case PT_REVOKE:
1234  case PT_REMOVE_TRIGGER:
1235  case PT_RENAME_TRIGGER:
1236  case PT_UPDATE_STATS:
1237  return true;
1238  default:
1239  break;
1240  }
1241  }
1242  return false;
1243 }
1244 
1245 /*
1246  * pt_is_method_call () -
1247  * return:
1248  * node(in/out):
1249  */
1250 int
1252 {
1253  if (node == NULL)
1254  {
1255  return false;
1256  }
1257 
1258  node = pt_get_end_path_node (node);
1259  return (node->node_type == PT_METHOD_CALL);
1260 }
1261 
1262 /*
1263  * pt_is_attr () -
1264  * return:
1265  * node(in/out):
1266  */
1267 int
1269 {
1270  if (node == NULL)
1271  {
1272  return false;
1273  }
1274 
1275  node = pt_get_end_path_node (node);
1276 
1277  if (node->node_type == PT_NAME)
1278  {
1279  if (node->info.name.meta_class == PT_NORMAL || node->info.name.meta_class == PT_SHARED
1280  || node->info.name.meta_class == PT_OID_ATTR || node->info.name.meta_class == PT_VID_ATTR)
1281  {
1282  return true;
1283  }
1284  }
1285  return false;
1286 }
1287 
1288 /*
1289  * pt_is_function_index_expression () - check for function index expression
1290  * return: true if function index expression, false otherwise
1291  * node(in/out): PT_EXPR node
1292  */
1293 int
1295 {
1296  if (node == NULL || node->node_type != PT_EXPR)
1297  {
1298  return false;
1299  }
1300 
1302  {
1303  return false;
1304  }
1305 
1306  return true;
1307 }
1308 
1309 /*
1310  * pt_is_pseudocolumn_node() -
1311  * return:
1312  * tree(in/out):
1313  * arg(in/out):
1314  * continue_walk(in/out):
1315  */
1316 PT_NODE *
1317 pt_is_pseudocolumn_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
1318 {
1319  int *found = (int *) arg;
1320 
1321  if (tree->node_type == PT_EXPR)
1322  {
1323  if (tree->info.expr.op == PT_LEVEL || tree->info.expr.op == PT_CONNECT_BY_ISLEAF
1324  || tree->info.expr.op == PT_CONNECT_BY_ISCYCLE)
1325  {
1326  *found = 1;
1327  *continue_walk = PT_STOP_WALK;
1328  }
1329  }
1330 
1331  return tree;
1332 }
1333 
1334 /*
1335  * pt_instnum_compatibility () -
1336  * return:
1337  * expr(in/out):
1338  */
1339 int
1341 {
1342  PT_NODE *arg1 = NULL, *arg2 = NULL, *arg3 = NULL;
1343 
1344  if (expr->node_type != PT_EXPR)
1345  {
1346  return true;
1347  }
1348 
1349  /* attr and subquery is not compatible with inst_num() */
1350 
1351  if (expr->info.expr.op != PT_IF)
1352  {
1353  arg1 = expr->info.expr.arg1;
1354  if (arg1)
1355  {
1356  if (COMPATIBLE_WITH_INSTNUM (arg1))
1357  {
1359  }
1360  if (NOT_COMPATIBLE_WITH_INSTNUM (arg1))
1361  {
1363  }
1364  }
1365  }
1366 
1367  arg2 = expr->info.expr.arg2;
1368  if (arg2)
1369  {
1370  if (COMPATIBLE_WITH_INSTNUM (arg2))
1371  {
1373  }
1374  if (NOT_COMPATIBLE_WITH_INSTNUM (arg2))
1375  {
1377  }
1378  }
1379 
1380  if (expr->info.expr.op != PT_CASE && expr->info.expr.op != PT_DECODE)
1381  {
1382  arg3 = expr->info.expr.arg3;
1383  if (arg3)
1384  {
1385  if (COMPATIBLE_WITH_INSTNUM (arg3))
1386  {
1388  }
1389  if (NOT_COMPATIBLE_WITH_INSTNUM (arg3))
1390  {
1392  }
1393  }
1394  }
1395 
1396  switch (expr->info.expr.op)
1397  {
1398  case PT_AND:
1399  /* AND hides inst_num() compatibility */
1400  return true;
1401  case PT_IS_NULL:
1402  case PT_IS_NOT_NULL:
1403  case PT_EXISTS:
1404  case PT_ASSIGN:
1405  case PT_IFNULL:
1406  /* those operator cannot have inst_num() */
1408  break;
1409  default:
1410  break;
1411  }
1412 
1413  /* detect semantic error in pt_semantic_check_local */
1415  {
1416  if (expr->info.expr.op != PT_IF)
1417  {
1418  if (arg1 && pt_is_instnum (arg1))
1419  {
1421  }
1422  }
1423  if (arg2 && pt_is_instnum (arg2))
1424  {
1426  }
1427  if (expr->info.expr.op != PT_CASE && expr->info.expr.op != PT_DECODE)
1428  {
1429  if (arg3 && pt_is_instnum (arg3))
1430  {
1432  }
1433  }
1434  }
1435 
1436  /* expression is not compatible with inst_num() */
1438  {
1439  /* to prevent repeated error */
1441  return false;
1442  }
1443 
1444  return true;
1445 }
1446 
1447 /*
1448  * pt_groupbynum_compatibility () -
1449  * return:
1450  * expr(in):
1451  */
1452 int
1454 {
1455  PT_NODE *arg1, *arg2, *arg3;
1456 
1457  if (expr->node_type != PT_EXPR)
1458  {
1459  return true;
1460  }
1461 
1462  /* attr and subquery is not compatible with groupby_num() */
1463  arg1 = expr->info.expr.arg1;
1464  if (arg1)
1465  {
1466  if (COMPATIBLE_WITH_GROUPBYNUM (arg1))
1467  {
1469  }
1470  if (NOT_COMPATIBLE_WITH_GROUPBYNUM (arg1))
1471  {
1473  }
1474  }
1475 
1476  arg2 = expr->info.expr.arg2;
1477  if (arg2)
1478  {
1479  if (COMPATIBLE_WITH_GROUPBYNUM (arg2))
1480  {
1482  }
1483  if (NOT_COMPATIBLE_WITH_GROUPBYNUM (arg2))
1484  {
1486  }
1487  }
1488 
1489  arg3 = expr->info.expr.arg3;
1490  if (arg3)
1491  {
1492  if (COMPATIBLE_WITH_GROUPBYNUM (arg3))
1493  {
1495  }
1496  if (NOT_COMPATIBLE_WITH_GROUPBYNUM (arg3))
1497  {
1499  }
1500  }
1501 
1502  switch (expr->info.expr.op)
1503  {
1504  case PT_AND:
1505  /* AND hides groupby_num() compatibility */
1506  return true;
1507  case PT_IS_NULL:
1508  case PT_IS_NOT_NULL:
1509  case PT_EXISTS:
1510  case PT_ASSIGN:
1511  /* those operator cannot have groupby_num() */
1513  break;
1514  default:
1515  break;
1516  }
1517 
1518  /* expression is not compatible with groupby_num() */
1521  {
1522  /* to prevent repeated error */
1524  return false;
1525  }
1526 
1527  return true;
1528 }
1529 
1530 /*
1531  * pt_check_instnum_pre () - Identify if the expression tree has inst_num()
1532  * return:
1533  * parser(in):
1534  * node(in):
1535  * arg(in):
1536  * continue_walk(in/out):
1537  */
1538 PT_NODE *
1539 pt_check_instnum_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1540 {
1541  if (node->node_type == PT_SELECT)
1542  {
1543  *continue_walk = PT_STOP_WALK;
1544  }
1545 
1546  return node;
1547 }
1548 
1549 /*
1550  * pt_check_instnum_post () -
1551  * return:
1552  * parser(in):
1553  * node(in):
1554  * arg(in/out):
1555  * continue_walk(in/out):
1556  */
1557 PT_NODE *
1558 pt_check_instnum_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1559 {
1560  bool *inst_num = (bool *) arg;
1561 
1562  if (node->node_type == PT_EXPR && (node->info.expr.op == PT_INST_NUM || node->info.expr.op == PT_ROWNUM))
1563  {
1564  *inst_num = true;
1565  }
1566 
1567  if (node->node_type == PT_SELECT)
1568  {
1569  *continue_walk = PT_CONTINUE_WALK;
1570  }
1571 
1572  return node;
1573 }
1574 
1575 /*
1576  * pt_check_groupbynum_pre () - Identify if the expression has groupby_num()
1577  * return:
1578  * parser(in):
1579  * node(in):
1580  * arg(in):
1581  * continue_walk(in/out):
1582  */
1583 PT_NODE *
1584 pt_check_groupbynum_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1585 {
1586  if (node->node_type == PT_SELECT)
1587  {
1588  *continue_walk = PT_STOP_WALK;
1589  }
1590 
1591  return node;
1592 }
1593 
1594 /*
1595  * pt_check_groupbynum_post () -
1596  * return:
1597  * parser(in):
1598  * node(in):
1599  * arg(in/out):
1600  * continue_walk(in/out):
1601  */
1602 PT_NODE *
1603 pt_check_groupbynum_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1604 {
1605  bool *grby_num = (bool *) arg;
1606 
1608  {
1609  *grby_num = true;
1610  }
1611 
1612  if (node->node_type == PT_SELECT)
1613  {
1614  *continue_walk = PT_CONTINUE_WALK;
1615  }
1616 
1617  return node;
1618 }
1619 
1620 /*
1621  * pt_check_orderbynum_pre () - Identify if the expression has orderby_num()
1622  * return:
1623  * parser(in):
1624  * node(in):
1625  * arg(in):
1626  * continue_walk(in/out):
1627  */
1628 PT_NODE *
1629 pt_check_orderbynum_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1630 {
1631  if (node->node_type == PT_SELECT)
1632  {
1633  *continue_walk = PT_STOP_WALK;
1634  }
1635 
1636  return node;
1637 }
1638 
1639 /*
1640  * pt_check_orderbynum_post () -
1641  * return:
1642  * parser(in):
1643  * node(in):
1644  * arg(in/out):
1645  * continue_walk(in/out):
1646  */
1647 PT_NODE *
1648 pt_check_orderbynum_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1649 {
1650  bool *ordby_num = (bool *) arg;
1651 
1652  if (node->node_type == PT_EXPR && node->info.expr.op == PT_ORDERBY_NUM)
1653  {
1654  *ordby_num = true;
1655  }
1656 
1657  if (node->node_type == PT_SELECT)
1658  {
1659  *continue_walk = PT_CONTINUE_WALK;
1660  }
1661 
1662  return node;
1663 }
1664 
1665 /*
1666  * pt_check_subquery_pre () - Identify if the expression has sub query
1667  * return:
1668  * parser(in):
1669  * node(in):
1670  * arg(in):
1671  * continue_walk(in/out):
1672  */
1673 PT_NODE *
1674 pt_check_subquery_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1675 {
1676  if (node->node_type == PT_SELECT)
1677  {
1678  *continue_walk = PT_STOP_WALK;
1679  }
1680 
1681  return node;
1682 }
1683 
1684 /*
1685  * pt_check_subquery_post () -
1686  * return:
1687  * parser(in):
1688  * node(in):
1689  * arg(in/out):
1690  * continue_walk(in/out):
1691  */
1692 PT_NODE *
1693 pt_check_subquery_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1694 {
1695  bool *has_subquery = (bool *) arg;
1696 
1697  if (node->node_type == PT_SELECT)
1698  {
1699  if (node->info.query.is_subquery == PT_IS_SUBQUERY)
1700  {
1701  *has_subquery = true;
1702  }
1703  else
1704  {
1705  *continue_walk = PT_CONTINUE_WALK;
1706  }
1707  }
1708 
1709  return node;
1710 }
1711 
1712 /*
1713  * pt_expr_disallow_op_pre () - looks if the expression op is in the list
1714  * given as argument and throws an error if
1715  * found
1716  *
1717  * return: node
1718  * parser(in):
1719  * node(in):
1720  * arg(in): integer list with forbidden operators. arg[0] keeps the number of
1721  * operators
1722  * continue_wals (in/out):
1723  */
1724 PT_NODE *
1725 pt_expr_disallow_op_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1726 {
1727  int *op_list = (int *) arg;
1728  int i;
1729 
1730  if (!PT_IS_EXPR_NODE (node))
1731  {
1732  return node;
1733  }
1734 
1735  if (*continue_walk == PT_STOP_WALK)
1736  {
1737  return node;
1738  }
1739 
1740  assert (op_list != NULL);
1741 
1742  for (i = 1; i <= op_list[0]; i++)
1743  {
1744  if (op_list[i] == node->info.expr.op)
1745  {
1747  pt_show_binopcode (node->info.expr.op));
1748  }
1749  }
1750  return node;
1751 }
1752 
1753 /*
1754  * pt_check_level_expr () - check if expression can be reduced to "LEVEL <= x
1755  * AND ..." or to "LEVEL >= x AND ...".
1756  *
1757  * parser(in): PARSER_CONTEXT
1758  * expr(in): expression PT_NODE
1759  * has_greater(out): can be reduced to LEVEL >= x
1760  * has_lesser(out): can be reduced to LEVEL <= x
1761  *
1762  * NOTE: this was originally designed to check connect by clause in order to
1763  * determine if cycles can be allowed or if we risk to generate infinite
1764  * loops
1765  */
1766 void
1767 pt_check_level_expr (PARSER_CONTEXT * parser, PT_NODE * expr, bool * has_greater, bool * has_lesser)
1768 {
1769  bool has_greater_1;
1770  bool has_lesser_1;
1771  bool has_greater_2;
1772  bool has_lesser_2;
1773  int op;
1774  PT_NODE *arg1;
1775  PT_NODE *arg2;
1776 
1777  *has_greater = 0;
1778  *has_lesser = 0;
1779 
1780  if (!expr)
1781  {
1782  return;
1783  }
1784  if (!PT_IS_EXPR_NODE (expr))
1785  {
1786  return;
1787  }
1788 
1789  op = expr->info.expr.op;
1790  arg1 = expr->info.expr.arg1;
1791  arg2 = expr->info.expr.arg2;
1792  switch (expr->info.expr.op)
1793  {
1794  case PT_NOT:
1795  /* NOT greater => lesser */
1796  /* NOT lesser => greater */
1797  pt_check_level_expr (parser, arg1, &has_greater_1, &has_lesser_1);
1798  *has_greater = has_lesser_1;
1799  *has_lesser = has_greater_1;
1800  break;
1801  case PT_OR:
1802  /* the OR EXPR will have as result a lesser value or a greater value for LEVEL if both branches have lesser,
1803  * respective greater values for LEVEL */
1804  pt_check_level_expr (parser, arg1, &has_greater_1, &has_lesser_1);
1805  pt_check_level_expr (parser, arg2, &has_greater_2, &has_lesser_2);
1806  *has_greater = has_greater_1 && has_greater_2;
1807  *has_lesser = has_lesser_1 && has_lesser_2;
1808  break;
1809  case PT_AND:
1810  /* the AND EXPR will have as result a lesser value or a greater value for LEVEL if any branch has a lesser,
1811  * respective a greater value for LEVEL */
1812  pt_check_level_expr (parser, arg1, &has_greater_1, &has_lesser_1);
1813  pt_check_level_expr (parser, arg2, &has_greater_2, &has_lesser_2);
1814  *has_greater = has_greater_1 || has_greater_2;
1815  *has_lesser = has_lesser_1 || has_lesser_2;
1816  break;
1817  case PT_EQ:
1818  case PT_LT:
1819  case PT_GT:
1820  case PT_LE:
1821  case PT_GE:
1822  {
1823  bool lhs_level = PT_IS_EXPR_NODE (arg1) && arg1->info.expr.op == PT_LEVEL;
1824  bool rhs_level = PT_IS_EXPR_NODE (arg2) && arg2->info.expr.op == PT_LEVEL;
1825  if ((lhs_level && rhs_level) || (!lhs_level && !rhs_level))
1826  {
1827  /* leave both has_greater and has_lesser as false */
1828  return;
1829  }
1830  if (op == PT_EQ)
1831  {
1832  *has_lesser = true;
1833  *has_greater = true;
1834  }
1835  else if (op == PT_GE || op == PT_GT)
1836  {
1837  if (lhs_level)
1838  {
1839  *has_greater = true;
1840  }
1841  else
1842  {
1843  *has_lesser = true;
1844  }
1845  }
1846  else if (op == PT_LE || op == PT_LT)
1847  {
1848  if (lhs_level)
1849  {
1850  *has_lesser = true;
1851  }
1852  else
1853  {
1854  *has_greater = true;
1855  }
1856  }
1857  }
1858  break;
1859  case PT_BETWEEN:
1860  case PT_RANGE:
1861  case PT_EQ_SOME:
1862  case PT_IS_IN:
1863  if (arg1->info.expr.op == PT_LEVEL)
1864  {
1865  *has_lesser = true;
1866  *has_greater = true;
1867  }
1868  break;
1869  default:
1870  /* leave both has_greater and has_lesser as false */
1871  break;
1872  }
1873 }
1874 
1875 #if defined (ENABLE_UNUSED_FUNCTION)
1876 /*
1877  * pt_arg1_part () - returns arg1 for union, intersection or difference
1878  * return:
1879  * node(in):
1880  */
1881 PT_NODE *
1882 pt_arg1_part (const PT_NODE * node)
1883 {
1884  if (node && (node->node_type == PT_INTERSECTION || node->node_type == PT_DIFFERENCE || node->node_type == PT_UNION))
1885  {
1886  return node->info.query.q.union_.arg1;
1887  }
1888 
1889  return NULL;
1890 }
1891 
1892 /*
1893  * pt_arg2_part () - returns arg2 for union, intersection or difference
1894  * return:
1895  * node(in):
1896  */
1897 PT_NODE *
1898 pt_arg2_part (const PT_NODE * node)
1899 {
1900  if (node && (node->node_type == PT_INTERSECTION || node->node_type == PT_DIFFERENCE || node->node_type == PT_UNION))
1901  {
1902  return node->info.query.q.union_.arg2;
1903  }
1904 
1905  return NULL;
1906 }
1907 
1908 /*
1909  * pt_select_list_part () - returns select list from select statement
1910  * return:
1911  * node(in):
1912  */
1913 PT_NODE *
1914 pt_select_list_part (const PT_NODE * node)
1915 {
1916  if (node && node->node_type == PT_SELECT)
1917  {
1918  return node->info.query.q.select.list;
1919  }
1920 
1921  return NULL;
1922 }
1923 #endif
1924 
1925 /*
1926  * pt_from_list_part () - returns from list from select statement
1927  * return:
1928  * node(in):
1929  */
1930 PT_NODE *
1932 {
1933  if (node && node->node_type == PT_SELECT)
1934  {
1935  return node->info.query.q.select.from;
1936  }
1937 
1938  return NULL;
1939 }
1940 
1941 #if defined (ENABLE_UNUSED_FUNCTION)
1942 /*
1943  * pt_where_part () - returns where part from select statement
1944  * return:
1945  * node(in):
1946  */
1947 PT_NODE *
1948 pt_where_part (const PT_NODE * node)
1949 {
1950  if (node)
1951  {
1952  if (node->node_type == PT_SELECT)
1953  {
1954  return node->info.query.q.select.where;
1955  }
1956 
1957  if (node->node_type == PT_UPDATE)
1958  {
1959  return node->info.update.search_cond;
1960  }
1961 
1962  if (node->node_type == PT_DELETE)
1963  {
1964  return node->info.delete_.search_cond;
1965  }
1966  }
1967 
1968  return NULL;
1969 }
1970 
1971 /*
1972  * pt_order_by_part () - returns order by part from select statement
1973  * return:
1974  * node(in):
1975  */
1976 PT_NODE *
1977 pt_order_by_part (const PT_NODE * node)
1978 {
1979  if (node && node->node_type == PT_SELECT)
1980  {
1981  return node->info.query.order_by;
1982  }
1983 
1984  return NULL;
1985 }
1986 
1987 /*
1988  * pt_group_by_part () - returns group by part from select statement
1989  * return:
1990  * node(in):
1991  */
1992 PT_NODE *
1993 pt_group_by_part (const PT_NODE * node)
1994 {
1995  if (node && node->node_type == PT_SELECT)
1996  {
1997  return node->info.query.q.select.group_by;
1998  }
1999 
2000  return NULL;
2001 }
2002 
2003 /*
2004  * pt_having_part () - returns having part from select statement
2005  * return:
2006  * node(in):
2007  */
2008 PT_NODE *
2009 pt_having_part (const PT_NODE * node)
2010 {
2011  if (node && node->node_type == PT_SELECT)
2012  {
2013  return node->info.query.q.select.having;
2014  }
2015 
2016  return NULL;
2017 }
2018 #endif
2019 
2020 /*
2021  * pt_from_entity_part () - Returns first entity name of from list node
2022  * return:
2023  * node(in):
2024  */
2025 PT_NODE *
2027 {
2028  if (node && node->node_type == PT_SPEC)
2029  {
2030  return node->info.spec.entity_name;
2031  }
2032 
2033  return NULL;
2034 }
2035 
2036 /*
2037  * pt_left_part () - returns arg1 for PT_DOT_ and PT_EXPR
2038  * return:
2039  * node(in):
2040  */
2041 PT_NODE *
2042 pt_left_part (const PT_NODE * node)
2043 {
2044  if (node == NULL)
2045  {
2046  return NULL;
2047  }
2048  if (node->node_type == PT_EXPR)
2049  {
2050  return node->info.expr.arg1;
2051  }
2052  if (node->node_type == PT_DOT_)
2053  {
2054  return node->info.dot.arg1;
2055  }
2056  return NULL;
2057 }
2058 
2059 /*
2060  * pt_right_part () - returns arg2 for PT_DOT_ and PT_EXPR
2061  * return:
2062  * node(in):
2063  */
2064 PT_NODE *
2065 pt_right_part (const PT_NODE * node)
2066 {
2067  if (node == NULL)
2068  {
2069  return NULL;
2070  }
2071  if (node->node_type == PT_EXPR)
2072  {
2073  return node->info.expr.arg2;
2074  }
2075  if (node->node_type == PT_DOT_)
2076  {
2077  return node->info.dot.arg2;
2078  }
2079  return NULL;
2080 }
2081 
2082 /*
2083  * pt_get_end_path_node () -
2084  * return: the original name node at the end of a path expression
2085  * node(in):
2086  */
2087 PT_NODE *
2089 {
2090  while (node != NULL && node->node_type == PT_DOT_)
2091  {
2092  node = node->info.dot.arg2;
2093  }
2094  return node;
2095 }
2096 
2097 /*
2098  * pt_get_first_arg_ignore_prior () -
2099  * return: the first argument of an expression node; if the argument is
2100  * PRIOR (arg) then PRIOR's argument is returned instead
2101  * node(in):
2102  * Note: Also see the related PT_IS_EXPR_WITH_PRIOR_ARG macro.
2103  */
2104 PT_NODE *
2106 {
2107  PT_NODE *arg1 = NULL;
2108 
2109  assert (PT_IS_EXPR_NODE (node));
2110 
2111  if (!PT_IS_EXPR_NODE (node))
2112  {
2113  return NULL;
2114  }
2115 
2116  arg1 = node->info.expr.arg1;
2118  {
2119  arg1 = arg1->info.expr.arg1;
2120  }
2121  /* Although semantically valid, PRIOR(PRIOR(expr)) is not allowed at runtime so this combination is restricted during
2122  * parsing. See the parser rule for PRIOR for details. */
2124 
2125  return arg1;
2126 }
2127 
2128 #if defined (ENABLE_UNUSED_FUNCTION)
2129 /*
2130  * pt_operator_part () - returns operator for PT_EXPR
2131  * return:
2132  * node(in):
2133  */
2134 int
2135 pt_operator_part (const PT_NODE * node)
2136 {
2137  if (node)
2138  {
2139  if (node->node_type == PT_EXPR)
2140  {
2141  return node->info.expr.op;
2142  }
2143  }
2144 
2145  return 0;
2146 }
2147 #endif
2148 
2149 /*
2150  * pt_class_part () -
2151  * return:
2152  * node(in):
2153  */
2154 PT_NODE *
2155 pt_class_part (const PT_NODE * node)
2156 {
2157  if (node)
2158  {
2159  if (node->node_type == PT_UPDATE)
2160  {
2161  return node->info.update.spec;
2162  }
2163 
2164  if (node->node_type == PT_DELETE)
2165  {
2166  return node->info.delete_.spec;
2167  }
2168 
2169  if (node->node_type == PT_INSERT)
2170  {
2171  return node->info.insert.spec;
2172  }
2173 
2174  if (node->node_type == PT_SELECT)
2175  {
2176  return node->info.query.q.select.from;
2177  }
2178  }
2179 
2180  return NULL;
2181 }
2182 
2183 #if defined (ENABLE_UNUSED_FUNCTION)
2184 /*
2185  * pt_class_names_part () -
2186  * return:
2187  * node(in):
2188  */
2189 PT_NODE *
2190 pt_class_names_part (const PT_NODE * node)
2191 {
2192  PT_NODE *temp;
2193 
2194  temp = pt_class_part (node);
2195  if (temp)
2196  {
2197  node = temp;
2198  }
2199 
2200  if (node && node->node_type == PT_SPEC)
2201  {
2202  return node->info.spec.flat_entity_list;
2203  }
2204 
2205  return NULL;
2206 }
2207 
2208 /*
2209  * pt_assignments_part () -
2210  * return:
2211  * node(in):
2212  */
2213 PT_NODE *
2214 pt_assignments_part (const PT_NODE * node)
2215 {
2216  if (node && node->node_type == PT_UPDATE)
2217  {
2218  return node->info.update.assignment;
2219  }
2220 
2221  return NULL;
2222 }
2223 #endif
2224 
2225 /*
2226  * pt_attrs_part () -
2227  * return:
2228  * node(in):
2229  */
2230 PT_NODE *
2231 pt_attrs_part (const PT_NODE * node)
2232 {
2233  if (node && node->node_type == PT_INSERT)
2234  {
2235  return node->info.insert.attr_list;
2236  }
2237 
2238  return NULL;
2239 }
2240 
2241 /*
2242  * pt_values_part () -
2243  * return:
2244  * node(in):
2245  */
2246 PT_NODE *
2247 pt_values_part (const PT_NODE * node)
2248 {
2249  if (node && node->node_type == PT_INSERT
2251  {
2252  return node->info.insert.value_clauses;
2253  }
2254 
2255  return NULL;
2256 }
2257 
2258 /*
2259  * pt_get_subquery_of_insert_select () -
2260  * return:
2261  * node(in):
2262  */
2263 PT_NODE *
2265 {
2266  PT_NODE *ptr_values = NULL;
2267  PT_NODE *ptr_subquery = NULL;
2268 
2269  if (node == NULL || node->node_type != PT_INSERT)
2270  {
2271  return NULL;
2272  }
2273 
2274  ptr_values = node->info.insert.value_clauses;
2275  assert (ptr_values != NULL);
2276  assert (ptr_values->node_type == PT_NODE_LIST);
2277 
2278  if (ptr_values->info.node_list.list_type != PT_IS_SUBQUERY)
2279  {
2280  return NULL;
2281  }
2282 
2283  assert (ptr_values->next == NULL);
2284  ptr_subquery = ptr_values->info.node_list.list;
2285  assert (PT_IS_QUERY (ptr_subquery));
2286  assert (ptr_subquery->next == NULL);
2287 
2288  return ptr_subquery;
2289 }
2290 
2291 /*
2292  * pt_string_part () -
2293  * return:
2294  * node(in):
2295  */
2296 const char *
2297 pt_string_part (const PT_NODE * node)
2298 {
2299  if (node && node->node_type == PT_NAME)
2300  {
2301  return node->info.name.original;
2302  }
2303 
2304  return NULL;
2305 }
2306 
2307 #if defined (ENABLE_UNUSED_FUNCTION)
2308 /*
2309  * pt_qualifier_part () -
2310  * return:
2311  * node(in):
2312  */
2313 const char *
2314 pt_qualifier_part (const PT_NODE * node)
2315 {
2316  if (node && node->node_type == PT_NAME)
2317  {
2318  return node->info.name.resolved;
2319  }
2320 
2321  return NULL;
2322 }
2323 
2324 /*
2325  * pt_object_part () -
2326  * return:
2327  * node(in):
2328  */
2329 void *
2330 pt_object_part (const PT_NODE * node)
2331 {
2332  if (node && node->node_type == PT_NAME)
2333  {
2334  return node->info.name.db_object;
2335  }
2336 
2337  return NULL;
2338 }
2339 #endif
2340 
2341 /*
2342  * pt_must_be_filtering () - Finds expressions that are incompatible with
2343  * executing joins before a hierarchical query (connect by). If such
2344  * expressions are found the predicate must be executed after connect by
2345  * (it is a filtering predicate, not a join predicate).
2346  * In addition, it figures out if the predicate refers to only one spec_id
2347  * or more. This is needed to correctly classify the predicate as a join
2348  * predicate.
2349  */
2350 static PT_NODE *
2351 pt_must_be_filtering (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
2352 {
2354 
2355  if (info->must_be_filtering)
2356  {
2357  *continue_walk = PT_STOP_WALK;
2358  return node;
2359  }
2360 
2361  if (PT_IS_QUERY (node))
2362  {
2363  info->must_be_filtering = true;
2364  *continue_walk = PT_STOP_WALK;
2365  return node;
2366  }
2367 
2368  if (PT_IS_NAME_NODE (node))
2369  {
2370  if (node->info.name.spec_id != 0 && node->info.name.correlation_level == 0)
2371  {
2372  if (info->first_spec_id == 0)
2373  {
2374  info->first_spec_id = node->info.name.spec_id;
2375  }
2376  else if (info->first_spec_id != node->info.name.spec_id)
2377  {
2378  info->has_second_spec_id = true;
2379  }
2380  }
2381  *continue_walk = PT_CONTINUE_WALK;
2382  return node;
2383  }
2384 
2385  if (PT_IS_EXPR_NODE (node)
2388  {
2389  info->must_be_filtering = true;
2390  *continue_walk = PT_STOP_WALK;
2391  return node;
2392  }
2393 
2394  *continue_walk = PT_CONTINUE_WALK;
2395 
2396  return node;
2397 }
2398 
2399 /*
2400  * pt_is_filtering_predicate ()
2401  * return: Whether the given predicate is to be executed as filtering after
2402  * the hierarchical query or as a join predicate before the
2403  * hierarchical query.
2404  */
2405 static bool
2407 {
2409 
2410  info.must_be_filtering = false;
2411  info.first_spec_id = 0;
2412  info.has_second_spec_id = false;
2413 
2414  parser_walk_tree (parser, predicate, pt_must_be_filtering, &info, NULL, NULL);
2415 
2416  if (!info.has_second_spec_id)
2417  {
2418  /* It's not a join predicate as it has references to one spec only. */
2419  return true;
2420  }
2421  else
2422  {
2423  /* It references more than one spec (like a join predicate), but we consider it to be a filtering predicate if it
2424  * contains certain expressions. */
2425  return info.must_be_filtering;
2426  }
2427 }
2428 
2429 /*
2430  * pt_is_filtering_skip_and_or () Checks for the existence of at least a
2431  * filtering predicate in a tree of predicates.
2432  */
2433 static PT_NODE *
2434 pt_is_filtering_skip_and_or (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
2435 {
2436  bool *already_found_filtering = (bool *) arg;
2437 
2438  if (*already_found_filtering)
2439  {
2440  *continue_walk = PT_STOP_WALK;
2441  return node;
2442  }
2444  {
2445  *continue_walk = PT_CONTINUE_WALK;
2446  return node;
2447  }
2448 
2449  if (pt_is_filtering_predicate (parser, node))
2450  {
2451  *already_found_filtering = true;
2452  }
2453 
2454  *continue_walk = PT_STOP_WALK;
2455 
2456  return node;
2457 }
2458 
2459 /*
2460  * pt_is_filtering_expression ()
2461  * return: Whether the given expression is to be executed as filtering after
2462  * the hierarchical query or as a join expression before the
2463  * hierarchical query.
2464  * Unfortunately this expression can contain PT_AND and PT_OR because
2465  * CNF is not performed in some cases; see TRANSFORM_CNF_OR_COMPACT.
2466  * Because of this we must dig inside the tree to find the predicates.
2467  */
2468 static bool
2470 {
2471  PT_NODE *or_next_save;
2472  bool result = false;
2473 
2474  assert (expression->next == NULL);
2475  or_next_save = expression->or_next;
2476  expression->or_next = NULL;
2477 
2478  parser_walk_tree (parser, expression, pt_is_filtering_skip_and_or, &result, NULL, NULL);
2479 
2480  expression->or_next = or_next_save;
2481  return result;
2482 }
2483 
2484 /*
2485  * pt_is_filtering_expression ()
2486  * return: Splits the given predicate list into two: a part to be executed
2487  * before the hierarchical query as it defines the join conditions and
2488  * a second part to be executed as filtering after the connect by
2489  * execution.
2490  */
2491 void
2492 pt_split_join_preds (PARSER_CONTEXT * parser, PT_NODE * predicates, PT_NODE ** join_part, PT_NODE ** after_cb_filter)
2493 {
2494  PT_NODE *current_conj, *current_pred;
2495  PT_NODE *next_conj = NULL;
2496 
2497  for (current_conj = predicates; current_conj != NULL; current_conj = next_conj)
2498  {
2499  bool has_filter_pred = false;
2500 
2501  assert (PT_IS_EXPR_NODE (current_conj) || PT_IS_VALUE_NODE (current_conj));
2502  /* It is either fully CNF or not at all. */
2503  assert (!(current_conj->next != NULL
2504  && (PT_IS_EXPR_NODE_WITH_OPERATOR (current_conj, PT_AND)
2505  || PT_IS_EXPR_NODE_WITH_OPERATOR (current_conj, PT_OR))));
2506  next_conj = current_conj->next;
2507  current_conj->next = NULL;
2508 
2509  for (current_pred = current_conj; current_pred != NULL; current_pred = current_pred->or_next)
2510  {
2511  assert (PT_IS_EXPR_NODE (current_pred) || PT_IS_VALUE_NODE (current_pred));
2512  /* It is either fully CNF or not at all. */
2513  assert (!(current_pred->or_next != NULL
2514  && (PT_IS_EXPR_NODE_WITH_OPERATOR (current_pred, PT_AND)
2515  || PT_IS_EXPR_NODE_WITH_OPERATOR (current_pred, PT_OR))));
2516  if (pt_is_filtering_expression (parser, current_pred))
2517  {
2518  has_filter_pred = true;
2519  break;
2520  }
2521  }
2522 
2523  if (has_filter_pred)
2524  {
2525  *after_cb_filter = parser_append_node (current_conj, *after_cb_filter);
2526  }
2527  else
2528  {
2529  *join_part = parser_append_node (current_conj, *join_part);
2530  }
2531  }
2532 }
2533 
2534 /*
2535  * pt_node_next () - return the next node in a list
2536  * return:
2537  * node(in):
2538  */
2539 PT_NODE *
2540 pt_node_next (const PT_NODE * node)
2541 {
2542  if (node)
2543  {
2544  return node->next;
2545  }
2546  return NULL;
2547 }
2548 
2549 #if defined (ENABLE_UNUSED_FUNCTION)
2550 /*
2551  * pt_set_node_etc () - sets the etc void pointer of a node
2552  * return:
2553  * node(in):
2554  * etc(in):
2555  */
2556 void
2557 pt_set_node_etc (PT_NODE * node, const void *etc)
2558 {
2559  if (node)
2560  {
2561  node->etc = (void *) etc;
2562  }
2563 }
2564 #endif
2565 
2566 /*
2567  * pt_node_etc () - return the etc void pointer from a node
2568  * return:
2569  * node(in):
2570  */
2571 void *
2572 pt_node_etc (const PT_NODE * node)
2573 {
2574  if (node)
2575  {
2576  return node->etc;
2577  }
2578  return NULL;
2579 }
2580 
2581 /*
2582  * pt_null_etc () - sets the etc void pointer to null
2583  * return:
2584  * node(in/out):
2585  */
2586 void
2588 {
2589  if (node)
2590  {
2591  node->etc = NULL;
2592  }
2593 }
2594 
2595 /*
2596  * pt_record_warning () - creates a new PT_ZZ_ERROR_MSG node appends it
2597  * to parser->warning
2598  * return:
2599  * parser(in): pointer to parser structure
2600  * stmt_no(in): source statement where warning was detected
2601  * line_no(in): source line number where warning was detected
2602  * col_no(in): source column number where warning was detected
2603  * msg(in): a helpful explanation of the warning
2604  */
2605 void
2606 pt_record_warning (PARSER_CONTEXT * parser, int stmt_no, int line_no, int col_no, const char *msg)
2607 {
2608  PT_NODE *node = parser_new_node (parser, PT_ZZ_ERROR_MSG);
2609  node->info.error_msg.statement_number = stmt_no;
2610  node->line_number = line_no;
2611  node->column_number = col_no;
2612  node->info.error_msg.error_message = pt_append_string (parser, NULL, msg);
2613  parser->warnings = parser_append_node (node, parser->warnings);
2614 }
2615 
2616 /*
2617  * pt_get_warnings () - return the etc void pointer from a parser
2618  * return:
2619  * parser(in):
2620  */
2621 PT_NODE *
2623 {
2624  if (parser)
2625  {
2626  return parser->warnings;
2627  }
2628  return NULL;
2629 }
2630 
2631 /*
2632  * pt_reset_error () - resets the errors recorded in a parser to none
2633  * return:
2634  * parser(in/out):
2635  */
2636 void
2638 {
2639  if (parser)
2640  {
2641  if (pt_has_error (parser))
2642  {
2643  parser_free_tree (parser, parser->error_msgs);
2644  parser->error_msgs = NULL;
2645  }
2646  parser->oid_included = PT_NO_OID_INCLUDED;
2647  }
2648  return;
2649 }
2650 
2651 #if defined (ENABLE_UNUSED_FUNCTION)
2652 /*
2653  * pt_column_updatable () - takes a subquery expansion of a class, and tests
2654  * it for column aka object-master updatability
2655  * return: true on updatable
2656  * parser(in):
2657  * statement(in):
2658  */
2659 bool
2660 pt_column_updatable (PARSER_CONTEXT * parser, PT_NODE * statement)
2661 {
2662  bool updatable = (statement != NULL);
2663 
2664  while (updatable && statement)
2665  {
2666  switch (statement->node_type)
2667  {
2668  case PT_SELECT:
2669  if (statement->info.query.q.select.group_by || statement->info.query.q.select.from->info.spec.derived_table
2670  || statement->info.query.all_distinct == PT_DISTINCT)
2671  {
2672  updatable = false;
2673  }
2674 
2675  if (updatable)
2676  {
2677  updatable = !pt_has_aggregate (parser, statement);
2678  }
2679  break;
2680 
2681  case PT_UNION:
2682  if (statement->info.query.all_distinct == PT_DISTINCT)
2683  {
2684  updatable = false;
2685  }
2686 
2687  if (updatable)
2688  {
2689  updatable = pt_column_updatable (parser, statement->info.query.q.union_.arg1);
2690  }
2691 
2692  if (updatable)
2693  {
2694  updatable = pt_column_updatable (parser, statement->info.query.q.union_.arg2);
2695  }
2696  break;
2697 
2698  case PT_DIFFERENCE:
2699  case PT_INTERSECTION:
2700  default:
2701  updatable = false;
2702  break;
2703  }
2704  statement = statement->next;
2705  }
2706 
2707  return updatable;
2708 }
2709 #endif
2710 
2711 /*
2712  * pt_statement_line_number () -
2713  * return: a statement's starting source line number
2714  * stmt(in):
2715  */
2716 int
2718 {
2719  if (stmt)
2720  {
2721  return stmt->line_number;
2722  }
2723 
2724  return 1;
2725 }
2726 
2727 /*
2728  * pt_get_select_from_spec () - return a select query_spec's from PT_NAME node
2729  * return: spec's from PT_NAME node if all OK, null otherwise
2730  * spec(in): a parsed SELECT query specification
2731  */
2732 static PT_NODE *
2734 {
2735  PT_NODE *from_spec, *from_name;
2736 
2737  if (!spec || !(from_spec = pt_from_list_part (spec)) || !pt_length_of_list (from_spec)
2738  || from_spec->node_type != PT_SPEC || !(from_name = from_spec->info.spec.entity_name)
2739  || from_name->node_type != PT_NAME)
2740  {
2741  return NULL;
2742  }
2743 
2744  return from_name;
2745 }
2746 
2747 /*
2748  * pt_get_select_from_name () - return a select query_spec's from entity name
2749  * return: spec's from entity name if all OK, null otherwise
2750  * parser(in): the parser context
2751  * spec(in): a parsed SELECT query specification
2752  */
2753 const char *
2755 {
2756  PT_NODE *from_name;
2757  char *result = NULL;
2758 
2759  from_name = pt_get_select_from_spec (spec);
2760  if (from_name != NULL)
2761  {
2762  if (from_name->info.name.resolved == NULL)
2763  {
2764  result = (char *) from_name->info.name.original;
2765  }
2766  else
2767  {
2768  result = pt_append_string (parser, NULL, from_name->info.name.resolved);
2769  result = pt_append_string (parser, result, ".");
2770  result = pt_append_string (parser, result, from_name->info.name.original);
2771  }
2772  }
2773 
2774  return result;
2775 }
2776 
2777 /*
2778  * pt_get_spec_name () - get this SELECT query's from spec name so that
2779  * 'select ... from class foo' yields 'class foo'
2780  * return: selqry's from spec name
2781  * parser(in): the parser context
2782  * selqry(in): a SELECT query
2783  */
2784 const char *
2785 pt_get_spec_name (PARSER_CONTEXT * parser, const PT_NODE * selqry)
2786 {
2787  char *result = NULL;
2788  PT_NODE *from_spec;
2789 
2790  from_spec = pt_from_list_part (selqry);
2791  if (from_spec && from_spec->node_type == PT_SPEC)
2792  {
2793  if (from_spec->info.spec.meta_class == PT_META_CLASS)
2794  {
2795  result = pt_append_string (parser, result, "class ");
2796  }
2797 
2798  result = pt_append_string (parser, result, pt_get_select_from_name (parser, selqry));
2799  }
2800 
2801  return result;
2802 }
2803 
2804 /*
2805  * pt_has_aggregate () -
2806  * return: true if statement has an aggregate node in its parse tree
2807  * parser(in):
2808  * node(in/out):
2809  *
2810  * Note :
2811  * for aggregate select statement, set agg flag for next re-check
2812  */
2813 bool
2815 {
2816  PT_AGG_FIND_INFO info;
2817  PT_NODE *save_next;
2818  info.select_stack = NULL;
2819  info.base_count = 0;
2820  info.out_of_context_count = 0;
2821  info.stop_on_subquery = false;
2822  info.disable_loose_scan = false;
2823 
2824  if (!node)
2825  {
2826  return false;
2827  }
2828 
2829  if (node->node_type == PT_SELECT)
2830  {
2831  bool found = false;
2832 
2833  /* STEP 1: check agg flag */
2835  {
2836  /* we've been here before */
2837  return true;
2838  }
2839 
2840  /* STEP 2: check GROUP BY, HAVING */
2841  if (node->info.query.q.select.group_by || node->info.query.q.select.having)
2842  {
2843  found = true;
2844  /* fall trough, we need to check for loose scan */
2845  }
2846 
2847  /* STEP 3: check tree */
2850  {
2851  /* UPDATE, DELETE and MERGE queries cannot own aggregates from subqueries, so this SELECT can't either */
2852  info.stop_on_subquery = true;
2853  }
2854  save_next = node->next;
2855  node->next = NULL;
2857  &info);
2858  node->next = save_next;
2859 
2860  if (info.base_count > 0)
2861  {
2862  found = true;
2863  if (info.disable_loose_scan)
2864  {
2866  }
2867  }
2868 
2869  if (found)
2870  {
2872  return true;
2873  }
2874  }
2875  else if (node->node_type == PT_MERGE)
2876  {
2877  /* for MERGE statement, free aggregates in search condition and in update assignments are not allowed; however,
2878  * those contained in subqueries are, even if they reference high level specs */
2879  info.stop_on_subquery = true;
2886 
2887  if (info.out_of_context_count > 0)
2888  {
2889  return true;
2890  }
2891  }
2892  else
2893  {
2894  info.stop_on_subquery = true;
2895  save_next = node->next;
2896  node->next = NULL;
2898  &info);
2899  node->next = save_next;
2900 
2901  if (info.out_of_context_count > 0)
2902  {
2903  return true;
2904  }
2905  }
2906 
2907  return false;
2908 }
2909 
2910 /*
2911  * pt_has_analytic () -
2912  * return: true if statement has an analytic function in its parse tree
2913  * parser(in):
2914  * node(in/out):
2915  *
2916  */
2917 bool
2919 {
2920  bool has_analytic = false;
2921  bool has_analytic_arg1 = false;
2922  bool has_analytic_arg2 = false;
2923 
2924  if (!node)
2925  {
2926  return false;
2927  }
2928 
2929  switch (node->node_type)
2930  {
2931  case PT_SELECT:
2933  {
2934  has_analytic = true;
2935  }
2936  else
2937  {
2938  (void) parser_walk_tree (parser, node->info.query.q.select.list, pt_is_analytic_node, &has_analytic,
2939  pt_is_analytic_node_post, &has_analytic);
2940  if (has_analytic)
2941  {
2943  }
2944  }
2945  break;
2946 
2947  case PT_UNION:
2948  case PT_DIFFERENCE:
2949  case PT_INTERSECTION:
2950  has_analytic_arg1 = pt_has_analytic (parser, node->info.query.q.union_.arg1);
2951  has_analytic_arg2 = pt_has_analytic (parser, node->info.query.q.union_.arg2);
2952  if (has_analytic_arg1 || has_analytic_arg2)
2953  {
2954  has_analytic = true;
2955  }
2956  break;
2957 
2958  default:
2959  (void) parser_walk_tree (parser, node, pt_is_analytic_node, &has_analytic, pt_is_analytic_node_post,
2960  &has_analytic);
2961  break;
2962  }
2963 
2964  return has_analytic;
2965 }
2966 
2967 /*
2968  * pt_has_inst_or_orderby_num () - check if tree has an INST_NUM or ORDERBY_NUM
2969  * node somewhere
2970  * return: true if tree has INST_NUM/ORDERBY_NUM
2971  * parser(in):
2972  * node(in):
2973  */
2974 bool
2976 {
2977  bool has_inst_orderby_num = false;
2978 
2979  (void) parser_walk_tree (parser, node, pt_is_inst_or_orderby_num_node, &has_inst_orderby_num,
2980  pt_is_inst_or_orderby_num_node_post, &has_inst_orderby_num);
2981 
2982  return has_inst_orderby_num;
2983 }
2984 
2985 /*
2986  * pt_insert_host_var () - insert a host_var into a list based on
2987  * its ordinal position
2988  * return: a list of PT_HOST_VAR type nodes
2989  * parser(in): the parser context
2990  * h_var(in): a PT_HOST_VAR type node
2991  * list(in/out): a list of PT_HOST_VAR type nodes
2992  */
2993 static PT_NODE *
2995 {
2996  PT_NODE *temp, *tail, *new_node;
2997 
2998  if (!list || list->info.host_var.index > h_var->info.host_var.index)
2999  {
3000  /* the new node goes before the rest of the list */
3001  new_node = parser_copy_tree (parser, h_var);
3002  if (new_node == NULL)
3003  {
3004  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
3005  return NULL;
3006  }
3007 
3008  new_node->next = list;
3009  list = new_node;
3010  }
3011  else
3012  {
3013  tail = temp = list;
3014  while (temp && temp->info.host_var.index <= h_var->info.host_var.index)
3015  {
3016  tail = temp;
3017  temp = temp->next;
3018  }
3019 
3020  if (tail->info.host_var.index < h_var->info.host_var.index)
3021  {
3022  new_node = parser_copy_tree (parser, h_var);
3023  if (new_node == NULL)
3024  {
3025  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
3026  return NULL;
3027  }
3028 
3029  tail->next = new_node;
3030  new_node->next = temp;
3031  }
3032  }
3033 
3034  return list;
3035 }
3036 
3037 /*
3038  * pt_collect_host_info () - collect host_var or cursor info from this node
3039  * return: node
3040  * parser(in): the parser context used in deriving this node
3041  * node(in): a node of the parse tree of an esql statement
3042  * h_var(in/out): a PT_HOST_VARS for depositing host_var or cursor info
3043  * continue_walk(in/out): flag that tells when to stop traversal
3044  *
3045  * Note :
3046  * if node is a host_var then
3047  * append a copy of node into h_var.inputs or h_var.outputs
3048  * or if node is a host descriptor then
3049  * save node into h_var.in_descr or h_var.out_descr
3050  * or if node is an UPDATE or DELETE current of cursor then
3051  * save cursor name into h_var.cursor
3052  */
3053 static PT_NODE *
3054 pt_collect_host_info (PARSER_CONTEXT * parser, PT_NODE * node, void *h_var, int *continue_walk)
3055 {
3056  PT_HOST_VARS *hvars = (PT_HOST_VARS *) h_var;
3057 
3058  switch (node->node_type)
3059  {
3060  case PT_HOST_VAR:
3061  switch (node->info.host_var.var_type)
3062  {
3063  case PT_HOST_IN: /* an input host variable */
3064  hvars->inputs = pt_insert_host_var (parser, node, hvars->inputs);
3065  break;
3066 
3067  case PT_HOST_OUT: /* an output host variable */
3068  hvars->outputs = pt_insert_host_var (parser, node, hvars->outputs);
3069  break;
3070 
3071  case PT_HOST_OUT_DESCR: /* an output host descriptor */
3072  hvars->out_descr = parser_copy_tree (parser, node);
3073  break;
3074 
3075  default:
3076  break;
3077  }
3078  break;
3079 
3080  case PT_DELETE:
3081  if (node->info.delete_.cursor_name)
3082  {
3083  hvars->cursor = parser_copy_tree (parser, node->info.delete_.cursor_name);
3084  }
3085  break;
3086 
3087  case PT_UPDATE:
3088  if (node->info.update.cursor_name)
3089  {
3090  hvars->cursor = parser_copy_tree (parser, node->info.update.cursor_name);
3091  }
3092  break;
3093 
3094  default:
3095  break;
3096  }
3097 
3098  return node;
3099 }
3100 
3101 /*
3102  * pt_host_info () - collect & return host_var & cursor info
3103  * from a parsed embedded statement
3104  * return: PT_HOST_VARS
3105  * parser(in): the parser context used in deriving stmt
3106  * stmt(in): parse tree of a an esql statement
3107  *
3108  * Note :
3109  * caller assumes responsibility for freeing PT_HOST_VARS via pt_free_host_info
3110  */
3111 
3112 PT_HOST_VARS *
3114 {
3115  PT_HOST_VARS *result = (PT_HOST_VARS *) calloc (1, sizeof (PT_HOST_VARS));
3116 
3117  if (result)
3118  {
3119  memset (result, 0, sizeof (PT_HOST_VARS));
3120 
3121  (void) parser_walk_tree (parser, stmt, pt_collect_host_info, (void *) result, NULL, NULL);
3122  }
3123 
3124  return result;
3125 }
3126 
3127 /*
3128  * pt_free_host_info () - deallocate a PT_HOST_VARS structure
3129  * return:
3130  * hv(in): a PT_HOST_VARS structure created by pt_host_info
3131  */
3132 void
3134 {
3135  if (hv)
3136  {
3137  free_and_init (hv);
3138  }
3139 }
3140 
3141 /*
3142  * pt_collect_parameters () - collect parameter info from this node
3143  * return: node
3144  * parser(in): the parser context used in deriving this node
3145  * node(in): a node of the parse tree of an esql statement
3146  * param_list(in/out): a PT_HOST_VARS for depositing host_var or cursor info
3147  * continue_walk(in/out): flag that tells when to stop traversal
3148  */
3149 
3150 static PT_NODE *
3151 pt_collect_parameters (PARSER_CONTEXT * parser, PT_NODE * node, void *param_list, int *continue_walk)
3152 {
3153  PT_NODE **list = (PT_NODE **) param_list;
3154 
3155  if (node->node_type == PT_NAME && node->info.name.meta_class == PT_PARAMETER)
3156  {
3157  if (!pt_find_name (parser, node, (*list)))
3158  {
3159  (*list) = parser_append_node (parser_copy_tree (parser, node), *list);
3160  }
3161  }
3162 
3163  return node;
3164 }
3165 
3166 /*
3167  * pt_get_parameters () - collect parameters into a list
3168  * return: PT_NODE * a copy of a list of paramater names
3169  * parser(in): the parser context used in deriving stmt
3170  * stmt(in): parse tree of a csql statement
3171  *
3172  * Note :
3173  * caller assumes responsibility for freeing PT_HOST_VARS via pt_free_host_info
3174  */
3175 
3176 PT_NODE *
3178 {
3179  PT_NODE *result = NULL;
3180 
3181  (void) parser_walk_tree (parser, stmt, pt_collect_parameters, (void *) &result, NULL, NULL);
3182 
3183  return result;
3184 }
3185 
3186 /*
3187  * pt_get_cursor () - return a PT_HOST_VARS' cursor information
3188  * return: hv's cursor information
3189  * hv(in): a PT_HOST_VARS structure created by pt_host_info
3190  */
3191 
3192 PT_NODE *
3194 {
3195  if (hv)
3196  {
3197  return hv->cursor;
3198  }
3199  else
3200  {
3201  return NULL;
3202  }
3203 }
3204 
3205 /*
3206  * pt_get_name () - return a PT_NAME's original name
3207  * return: nam's original name if all OK, NULL otherwise.
3208  * nam(in): a PT_NAME node
3209  */
3210 
3211 const char *
3213 {
3214  if (nam && nam->node_type == PT_NAME)
3215  {
3216  assert (nam->info.name.original != NULL);
3217 
3218  return nam->info.name.original;
3219  }
3220  else
3221  {
3222  return NULL;
3223  }
3224 }
3225 
3226 /*
3227  * pt_host_var_index () - return a PT_HOST_VAR's index
3228  * return: hv's index if all OK, -1 otherwise.
3229  * hv(in): a PT_HOST_VAR type node
3230  */
3231 
3232 int
3234 {
3235  if (hv && hv->node_type == PT_HOST_VAR)
3236  {
3237  return hv->info.host_var.index;
3238  }
3239  else
3240  {
3241  return -1;
3242  }
3243 }
3244 
3245 /*
3246  * pt_get_input_host_vars () - return a PT_HOST_VARS' list of input host_vars
3247  * return: hv's list of input host_vars
3248  * hv(in): a PT_HOST_VARS structure created by pt_host_info
3249  */
3250 
3251 PT_NODE *
3253 {
3254  if (hv)
3255  {
3256  return hv->inputs;
3257  }
3258  else
3259  {
3260  return NULL;
3261  }
3262 }
3263 
3264 /*
3265  * pt_get_output_host_vars () - return a PT_HOST_VARS' list of output host_vars
3266  * return: hv's list of output host_vars
3267  * hv(in): a PT_HOST_VARS structure created by pt_host_info
3268  */
3269 
3270 PT_NODE *
3272 {
3273  if (hv)
3274  {
3275  return hv->outputs;
3276  }
3277  else
3278  {
3279  return NULL;
3280  }
3281 }
3282 
3283 #if defined (ENABLE_UNUSED_FUNCTION)
3284 /*
3285  * pt_get_output_host_descr () - return a PT_HOST_VARS' output host_descriptor
3286  * return: hv's output host_descriptor
3287  * hv(in): a PT_HOST_VARS structure created by pt_host_info
3288  */
3289 
3290 PT_NODE *
3291 pt_get_output_host_descr (PT_HOST_VARS * hv)
3292 {
3293  if (hv)
3294  {
3295  return hv->out_descr;
3296  }
3297  else
3298  {
3299  return NULL;
3300  }
3301 }
3302 #endif
3303 
3304 /*
3305  * pt_set_update_object () - convert update statement to
3306  * update object statement
3307  * return: none
3308  * parser(in): the parser context
3309  * node(in/out): an esql statement in parse tree form
3310  */
3311 
3312 void
3314 {
3315  PT_NODE *hostvar;
3316 
3317  parser_free_tree (parser, node->info.update.spec);
3318  node->info.update.spec = NULL;
3319  hostvar = parser_new_node (parser, PT_HOST_VAR);
3320  hostvar->info.host_var.str = pt_append_string (parser, NULL, "?");
3321  node->info.update.object_parameter = hostvar;
3322 }
3323 
3324 /*
3325  * pt_chop_trailing_dots () - return copy of string with
3326  * its trailing dots removed
3327  * return: copy of msg with any trailing dots removed if all OK,
3328  * NULL otherwise
3329  * parser(in): the parser context
3330  * msg(in) : a null-terminated character string
3331  */
3332 
3333 char *
3334 pt_chop_trailing_dots (PARSER_CONTEXT * parser, const char *msg)
3335 {
3336  char *c, *s = NULL;
3337  int l;
3338 
3339  assert (parser != NULL);
3340 
3341  if (!msg || (l = strlen (msg)) <= 0)
3342  {
3343  return (char *) "NULL message string";
3344  }
3345 
3346  c = pt_append_string (parser, s, msg);
3347  s = &c[l - 1];
3348  while (char_isspace (*s) || *s == '.')
3349  {
3350  s--;
3351  }
3352 
3353  *(s + 1) = '\0';
3354  return c;
3355 }
3356 
3357 /*
3358  * pt_get_proxy_spec_name () - return a proxy query_spec's "from" entity name
3359  * return: qspec's from entity name if all OK, NULL otherwise
3360  * qspec(in): a proxy's SELECT query specification
3361  */
3362 
3363 const char *
3364 pt_get_proxy_spec_name (const char *qspec)
3365 {
3366  PT_NODE **qtree;
3367  PARSER_CONTEXT *parser = NULL;
3368  const char *from_name = NULL, *result;
3369  size_t newlen;
3370 
3371  /* the parser and its strings go away upon return, but the caller probably wants the proxy_spec_name to remain, so */
3372  static char tblname[256], *name;
3373  static size_t namelen = 256;
3374 
3375  name = tblname;
3376 
3377  if (qspec && (parser = parser_create_parser ()) && (qtree = parser_parse_string (parser, qspec))
3378  && !pt_has_error (parser) && qtree[0])
3379  {
3380  from_name = pt_get_spec_name (parser, qtree[0]);
3381  }
3382 
3383  if (from_name == NULL)
3384  {
3385  result = NULL; /* no, it failed */
3386  }
3387  else
3388  {
3389  /* copy from_name into tblname but do not overrun it! */
3390  newlen = strlen (from_name) + 1;
3391  if (newlen + 1 > namelen)
3392  {
3393  /* get a bigger name buffer */
3394  if (name != tblname)
3395  {
3396  free_and_init (name);
3397  }
3398  name = (char *) malloc (newlen);
3399  namelen = newlen;
3400  }
3401 
3402 
3403  if (name)
3404  {
3405  strcpy (name, from_name);
3406  }
3407 
3408  result = name;
3409  }
3410 
3411  if (parser != NULL)
3412  {
3413  parser_free_parser (parser);
3414  }
3415 
3416  return result;
3417 }
3418 
3419 /*
3420  * pt_register_orphan () - Accepts PT_NODE and puts it on the parser's
3421  * orphan list for subsequent freeing
3422  * return: none
3423  * parser(in):
3424  * orphan(in):
3425  */
3426 void
3427 pt_register_orphan (PARSER_CONTEXT * parser, const PT_NODE * orphan)
3428 {
3429  PT_NODE *dummy;
3430 
3431  if (orphan)
3432  {
3433  /* this node has already been freed. */
3434  if (orphan->node_type == PT_LAST_NODE_NUMBER)
3435  {
3436  assert_release (false);
3437  return;
3438  }
3439 
3440  dummy = parser_new_node (parser, PT_EXPR);
3441  dummy->info.expr.op = PT_NOT; /* probably not necessary */
3442  dummy->info.expr.arg1 = (PT_NODE *) orphan;
3443  parser->orphans = parser_append_node (dummy, parser->orphans);
3444  }
3445 }
3446 
3447 /*
3448  * pt_register_orphan_db_value () - Accepts a db_value, wraps a PT_VALUE node
3449  * around it for convenience, and puts it on the parser's orphan
3450  * list for subsequent freeing
3451  * return: none
3452  * parser(in):
3453  * orphan(in):
3454  */
3455 void
3457 {
3458  PT_NODE *dummy;
3459 
3460  if (orphan)
3461  {
3462  dummy = parser_new_node (parser, PT_VALUE);
3463  dummy->info.value.db_value_is_in_workspace = 1;
3464  dummy->info.value.db_value = *orphan; /* structure copy */
3465  parser->orphans = parser_append_node (dummy, parser->orphans);
3466  }
3467 }
3468 
3469 /*
3470  * pt_free_orphans () - Frees all of the registered orphans
3471  * return:
3472  * parser(in):
3473  */
3474 void
3476 {
3477  PT_NODE *ptr, *next;
3478 
3479  ptr = parser->orphans;
3480  while (ptr)
3481  {
3482  next = ptr->next;
3483  ptr->next = NULL; /* cut off link */
3484  parser_free_tree (parser, ptr);
3485  ptr = next; /* next to the link */
3486  }
3487 
3488  parser->orphans = NULL;
3489 }
3490 
3491 /*
3492  * pt_sort_spec_cover () -
3493  * return: true or false
3494  * cur_list(in): current PT_SORT_SPEC list pointer
3495  * new_list(in): new PT_SORT_SPEC list pointer
3496  */
3497 
3498 bool
3499 pt_sort_spec_cover (PT_NODE * cur_list, PT_NODE * new_list)
3500 {
3501  PT_NODE *s1, *s2;
3502  QFILE_TUPLE_VALUE_POSITION *p1, *p2;
3503 
3504  if (new_list == NULL)
3505  {
3506  return false;
3507  }
3508 
3509  for (s1 = cur_list, s2 = new_list; s1 && s2; s1 = s1->next, s2 = s2->next)
3510  {
3511  p1 = &(s1->info.sort_spec.pos_descr);
3512  p2 = &(s2->info.sort_spec.pos_descr);
3513 
3514  if (p1->pos_no <= 0)
3515  {
3516  s1 = NULL; /* mark as end-of-sort */
3517  }
3518 
3519  if (p2->pos_no <= 0)
3520  {
3521  s2 = NULL; /* mark as end-of-sort */
3522  }
3523 
3524  /* end-of-sort check */
3525  if (s1 == NULL || s2 == NULL)
3526  {
3527  break;
3528  }
3529 
3530  /* equality check */
3531  if (p1->pos_no != p2->pos_no || s1->info.sort_spec.asc_or_desc != s2->info.sort_spec.asc_or_desc
3532  || (s1->info.sort_spec.nulls_first_or_last != s2->info.sort_spec.nulls_first_or_last))
3533  {
3534  return false;
3535  }
3536  }
3537 
3538  return (s2 == NULL) ? true : false;
3539 }
3540 
3541 /* pt_enter_packing_buf() - mark the beginning of another level of packing
3542  * return: none
3543  */
3544 void
3546 {
3547  ++packing_level;
3548 }
3549 
3550 /* pt_alloc_packing_buf() - allocate space for packing
3551  * return: pointer to the allocated space if all OK, NULL otherwise
3552  * size(in): the amount of space to be allocated
3553  */
3554 char *
3556 {
3557  char *res;
3558  HL_HEAPID heap_id;
3559  int i;
3560 
3561  if (size <= 0)
3562  {
3563  return NULL;
3564  }
3565 
3566  if (packing_heap == NULL)
3567  {
3569  packing_heap = (HL_HEAPID *) calloc (packing_heap_num_slot, sizeof (HL_HEAPID));
3570  if (packing_heap == NULL)
3571  {
3573  PACKING_MMGR_BLOCK_SIZE * sizeof (HL_HEAPID));
3574  return NULL;
3575  }
3576  }
3577  else if (packing_heap_num_slot == packing_level - 1)
3578  {
3580 
3581  packing_heap = (HL_HEAPID *) realloc (packing_heap, packing_heap_num_slot * sizeof (HL_HEAPID));
3582  if (packing_heap == NULL)
3583  {
3585  PACKING_MMGR_BLOCK_SIZE * sizeof (HL_HEAPID));
3586  return NULL;
3587  }
3588 
3589  for (i = 0; i < PACKING_MMGR_BLOCK_SIZE; i++)
3590  {
3591  packing_heap[packing_heap_num_slot - i - 1] = 0;
3592  }
3593  }
3594 
3595  heap_id = packing_heap[packing_level - 1];
3596  if (heap_id == 0)
3597  {
3599  packing_heap[packing_level - 1] = heap_id;
3600  }
3601 
3602  if (heap_id == 0)
3603  {
3604  /* make sure an error is set, one way or another */
3606  res = NULL;
3607  }
3608  else
3609  {
3610  res = (char *) db_ostk_alloc (heap_id, size);
3611  }
3612 
3613  if (res == NULL)
3614  {
3615  qp_Packing_er_code = -1;
3616  }
3617 
3618  return res;
3619 }
3620 
3621 /* pt_free_packing_buf() - free packing space
3622  * return: none
3623  * slot(in): index of the packing space
3624  */
3625 static void
3627 {
3628  if (packing_heap && slot >= 0 && packing_heap[slot])
3629  {
3631  packing_heap[slot] = 0;
3632  }
3633 }
3634 
3635 /* pt_exit_packing_buf() - mark the end of another level of packing
3636  * return: none
3637  */
3638 void
3640 {
3641  --packing_level;
3643 }
3644 
3645 /* pt_final_packing_buf() - free all resources for packing
3646  * return: none
3647  */
3648 void
3650 {
3651  int i;
3652 
3653  for (i = 0; i < packing_level; i++)
3654  {
3655  pt_free_packing_buf (i);
3656  }
3657 
3659  packing_level = packing_heap_num_slot = 0;
3660 }
3661 
3662 
3663 
3664 /*
3665  *
3666  * Function group:
3667  * Query process regulator
3668  *
3669  */
3670 
3671 
3672 /*
3673  * regu_set_error_with_zero_args () -
3674  * return:
3675  * err_type(in) : error code
3676  *
3677  * Note: Error reporting function for error messages with no arguments.
3678  */
3679 void
3681 {
3682  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err_type, 0);
3683  qp_Packing_er_code = err_type;
3684 }
3685 
3686 #if defined (ENABLE_UNUSED_FUNCTION)
3687 /*
3688  * regu_set_error_with_one_args () -
3689  * return:
3690  * err_type(in) : error code
3691  * infor(in) : message
3692  *
3693  * Note: Error reporting function for error messages with one string argument.
3694  */
3695 void
3696 regu_set_error_with_one_args (int err_type, const char *infor)
3697 {
3698  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, err_type, 1, infor);
3699  qp_Packing_er_code = err_type;
3700 }
3701 
3702 /*
3703  * regu_set_global_error () -
3704  * return:
3705  *
3706  * Note: Set the client side query processor global error code.
3707  */
3708 void
3709 regu_set_global_error (void)
3710 {
3712 }
3713 #endif /* ENABLE_UNUSED_FUNCTION */
3714 
3715 /*
3716  * pt_limit_to_numbering_expr () -rewrite limit expr to xxx_num() expr
3717  * return: expr node with numbering
3718  * limit(in): limit node
3719  * num_op(in):
3720  * is_gry_num(in):
3721  *
3722  */
3723 PT_NODE *
3724 pt_limit_to_numbering_expr (PARSER_CONTEXT * parser, PT_NODE * limit, PT_OP_TYPE num_op, bool is_gby_num)
3725 {
3726  PT_NODE *lhs, *sum, *part1, *part2, *node;
3727  DB_VALUE sum_val;
3728 
3729  db_make_null (&sum_val);
3730 
3731  if (limit == NULL)
3732  {
3733  return NULL;
3734  }
3735 
3736  lhs = sum = part1 = part2 = node = NULL;
3737 
3738  if (is_gby_num == true)
3739  {
3740  lhs = parser_new_node (parser, PT_FUNCTION);
3741  if (lhs != NULL)
3742  {
3743  lhs->type_enum = PT_TYPE_INTEGER;
3745  lhs->info.function.arg_list = NULL;
3747  }
3748  }
3749  else
3750  {
3751  lhs = parser_new_node (parser, PT_EXPR);
3752  if (lhs != NULL)
3753  {
3754  lhs->info.expr.op = num_op;
3755  }
3756  }
3757 
3758  if (lhs == NULL)
3759  {
3760  PT_INTERNAL_ERROR (parser, "allocate new node");
3761  return NULL;
3762  }
3763 
3764  if (limit->next == NULL)
3765  {
3766  node = parser_new_node (parser, PT_EXPR);
3767  if (node == NULL)
3768  {
3769  PT_INTERNAL_ERROR (parser, "allocate new node");
3770  goto error_exit;
3771  }
3772 
3773  if (is_gby_num)
3774  {
3776  }
3777  node->info.expr.op = PT_LE;
3778  node->info.expr.arg1 = lhs;
3779  lhs = NULL;
3780 
3781  node->info.expr.arg2 = parser_copy_tree (parser, limit);
3782  if (node->info.expr.arg2 == NULL)
3783  {
3784  goto error_exit;
3785  }
3786  }
3787  else
3788  {
3789  part1 = parser_new_node (parser, PT_EXPR);
3790  if (part1 == NULL)
3791  {
3792  PT_INTERNAL_ERROR (parser, "allocate new node");
3793  goto error_exit;
3794  }
3795 
3796  part1->info.expr.op = PT_GT;
3797  part1->type_enum = PT_TYPE_LOGICAL;
3798  part1->info.expr.arg1 = lhs;
3799  lhs = NULL;
3800 
3801  part1->info.expr.arg2 = parser_copy_tree (parser, limit);
3802  if (part1->info.expr.arg2 == NULL)
3803  {
3804  goto error_exit;
3805  }
3806 
3807  part2 = parser_new_node (parser, PT_EXPR);
3808  if (part2 == NULL)
3809  {
3810  PT_INTERNAL_ERROR (parser, "allocate new node");
3811  goto error_exit;
3812  }
3813 
3814  part2->info.expr.op = PT_LE;
3815  part2->type_enum = PT_TYPE_LOGICAL;
3816  part2->info.expr.arg1 = parser_copy_tree (parser, part1->info.expr.arg1);
3817  if (part2->info.expr.arg1 == NULL)
3818  {
3819  goto error_exit;
3820  }
3821 
3822  sum = parser_new_node (parser, PT_EXPR);
3823  if (sum == NULL)
3824  {
3825  PT_INTERNAL_ERROR (parser, "allocate new node");
3826  goto error_exit;
3827  }
3828 
3829  sum->info.expr.op = PT_PLUS;
3830  sum->type_enum = PT_TYPE_NUMERIC;
3831  sum->data_type = parser_new_node (parser, PT_DATA_TYPE);
3832  if (sum->data_type == NULL)
3833  {
3834  PT_INTERNAL_ERROR (parser, "allocate new node");
3835  goto error_exit;
3836  }
3837 
3839  sum->data_type->info.data_type.precision = 38;
3841 
3842  sum->info.expr.arg1 = parser_copy_tree (parser, limit);
3843  sum->info.expr.arg2 = parser_copy_tree (parser, limit->next);
3844  if (sum->info.expr.arg1 == NULL || sum->info.expr.arg2 == NULL)
3845  {
3846  goto error_exit;
3847  }
3848 
3849  if (limit->node_type == PT_VALUE && limit->next->node_type == PT_VALUE)
3850  {
3851  pt_evaluate_tree (parser, sum, &sum_val, 1);
3852  part2->info.expr.arg2 = pt_dbval_to_value (parser, &sum_val);
3853  if (part2->info.expr.arg2 == NULL)
3854  {
3855  goto error_exit;
3856  }
3857 
3858  parser_free_tree (parser, sum);
3859  }
3860  else
3861  {
3862  part2->info.expr.arg2 = sum;
3863  }
3864  sum = NULL;
3865 
3866  node = parser_new_node (parser, PT_EXPR);
3867  if (node == NULL)
3868  {
3869  PT_INTERNAL_ERROR (parser, "allocate new node");
3870  goto error_exit;
3871  }
3872 
3873  if (is_gby_num)
3874  {
3877  }
3878  node->info.expr.op = PT_AND;
3879  node->type_enum = PT_TYPE_LOGICAL;
3880  node->info.expr.arg1 = part1;
3881  node->info.expr.arg2 = part2;
3882  }
3883 
3884  return node;
3885 
3886 error_exit:
3887  if (lhs)
3888  {
3889  parser_free_tree (parser, lhs);
3890  }
3891  if (sum)
3892  {
3893  parser_free_tree (parser, sum);
3894  }
3895  if (part1)
3896  {
3897  parser_free_tree (parser, part1);
3898  }
3899  if (part2)
3900  {
3901  parser_free_tree (parser, part2);
3902  }
3903  if (node)
3904  {
3905  parser_free_tree (parser, node);
3906  }
3907 
3908  return NULL;
3909 }
3910 
3911 /*
3912  * pt_create_param_for_value () - Creates a PT_NODE to be used as a host
3913  * variable that replaces an existing value
3914  * return: the node or NULL on error
3915  * parser(in):
3916  * value(in): the value to be replaced
3917  * host_var_index(in): the index of the host variable that replaces the value
3918  */
3919 static PT_NODE *
3920 pt_create_param_for_value (PARSER_CONTEXT * parser, PT_NODE * value, int host_var_index)
3921 {
3923  if (host_var == NULL)
3924  {
3925  PT_INTERNAL_ERROR (parser, "allocate new node");
3926  return NULL;
3927  }
3928 
3929  host_var->type_enum = value->type_enum;
3930  host_var->expected_domain = value->expected_domain;
3931  host_var->data_type = parser_copy_tree (parser, value->data_type);
3932  host_var->info.host_var.var_type = PT_HOST_IN;
3933  host_var->info.host_var.str = pt_append_string (parser, NULL, "?");
3934  if (PT_IS_VALUE_NODE (value) && value->info.value.host_var_index != -1)
3935  {
3936  /* this value come from a host_var, we just need restore host_var. */
3937  host_var->info.host_var.index = value->info.value.host_var_index;
3938  assert (host_var->info.host_var.index < parser->host_var_count);
3939  }
3940  else
3941  {
3942  host_var->info.host_var.index = host_var_index;
3943  }
3945 
3946  return host_var;
3947 }
3948 
3949 /*
3950  * pt_rewrite_to_auto_param () - Rewrites a value to a host variable and fills
3951  * in the value of the new host variable in the
3952  * auto parameters values array
3953  * return: the new node or NULL on error
3954  * parser(in):
3955  * value(in): the value to be replaced by a host variable parameter
3956  */
3957 PT_NODE *
3959 {
3960  PT_NODE *host_var = NULL;
3961  DB_VALUE *host_var_val = NULL;
3962  DB_VALUE *val = NULL;
3963  int count_to_realloc = 0;
3964  DB_VALUE *larger_host_variables = NULL;
3965 
3966  assert (pt_is_const_not_hostvar (value));
3967 
3968  /* The index number of auto-parameterized host variables starts after the last one of the user-specified host
3969  * variables. */
3970  host_var = pt_create_param_for_value (parser, value, parser->host_var_count + parser->auto_param_count);
3971  if (host_var == NULL)
3972  {
3973  goto error_exit;
3974  }
3975 
3976  PT_NODE_MOVE_NUMBER_OUTERLINK (host_var, value);
3977 
3978  if (PT_IS_VALUE_NODE (value) && value->info.value.host_var_index != -1)
3979  {
3980  /* this value come from a host_var, realloc is not needed. */
3981  assert (host_var->info.host_var.index < parser->host_var_count);
3982  }
3983  else
3984  {
3985  /* Expand parser->host_variables by realloc */
3986  count_to_realloc = parser->host_var_count + parser->auto_param_count + 1;
3987  /* We actually allocate around twice more than needed so that we don't do useless copies too often. */
3988  count_to_realloc = (count_to_realloc / 2) * 4;
3989  if (count_to_realloc == 0)
3990  {
3991  count_to_realloc = 1;
3992  }
3993  larger_host_variables = (DB_VALUE *) realloc (parser->host_variables, count_to_realloc * sizeof (DB_VALUE));
3994  if (larger_host_variables == NULL)
3995  {
3997  goto error_exit;
3998  }
3999  parser->host_variables = larger_host_variables;
4000  ++parser->auto_param_count;
4001  larger_host_variables = NULL;
4002 
4003  /* Copy the DB_VALUE to parser->host_variables */
4004  host_var_val = parser->host_variables + host_var->info.host_var.index;
4005  val = pt_value_to_db (parser, value);
4006  /* TODO Is it ok to ignore errors here? */
4007  if (val != NULL)
4008  {
4009  (void) pr_clone_value (val, host_var_val);
4010  }
4011  else
4012  {
4013  db_make_null (host_var_val);
4014  }
4015  }
4016  parser_free_tree (parser, value);
4017 
4018  return host_var;
4019 
4020 error_exit:
4021  if (host_var != NULL)
4022  {
4023  parser_free_tree (parser, host_var);
4024  host_var = NULL;
4025  }
4026  return NULL;
4027 }
4028 
4029 /*
4030  * pt_copy_statement_flags () - Copies the special flags relevant for statement
4031  * execution from one node to another. This is
4032  * useful for executing statements that are
4033  * generated by rewriting existing statements
4034  * (see CREATE ... AS SELECT for an example).
4035  * source(in): the statement to copy the flags from
4036  * destination(in/out): the statement to copy the flags to
4037  *
4038  * Note: Not all the PT_NODE flags are copied, only the ones needed for correct
4039  * execution of a statement are copied.
4040  */
4041 void
4042 pt_copy_statement_flags (PT_NODE * source, PT_NODE * destination)
4043 {
4044  destination->flag.recompile = source->flag.recompile;
4045  destination->flag.cannot_prepare = source->flag.cannot_prepare;
4046  destination->flag.si_datetime = source->flag.si_datetime;
4047  destination->flag.si_tran_id = source->flag.si_tran_id;
4048 }
4049 
4050 /*
4051  * pt_get_dup_key_oid_var_index () - Gets the index of the auto-parameterized
4052  * host variable in the INSERT ON DUPLICATE
4053  * KEY UPDATE statement
4054  * return: the index or -1 on error
4055  * parser(in):
4056  * update_statement(in):
4057  *
4058  * Note: The host variable will be replaced at runtime with the value of the
4059  * OID of an existing duplicate key that will be updated. See
4060  * pt_dup_key_update_stmt () to have a better understanding of what will
4061  * be executed.
4062  */
4063 int
4065 {
4066  PT_NODE *search_cond = NULL;
4067  PT_NODE *oid_node = NULL;
4068  int index = -1;
4069 
4070  if (update_statement == NULL || update_statement->node_type != PT_UPDATE)
4071  {
4072  return -1;
4073  }
4074  search_cond = update_statement->info.update.search_cond;
4075  if (search_cond == NULL || search_cond->node_type != PT_EXPR)
4076  {
4077  return -1;
4078  }
4079  oid_node = search_cond->info.expr.arg2;
4080  if (oid_node == NULL || oid_node->node_type != PT_HOST_VAR)
4081  {
4082  return -1;
4083  }
4084  index = oid_node->info.host_var.index;
4085  if (oid_node->info.host_var.var_type != PT_HOST_IN)
4086  {
4087  return -1;
4088  }
4089  if (index < 0 || index >= (parser->host_var_count + parser->auto_param_count))
4090  {
4091  return -1;
4092  }
4093  return index;
4094 }
4095 
4096 /*
4097  * pt_dup_key_update_stmt () - Builds a special UPDATE statement to be used
4098  * for INSERT ON DUPLICATE KEY UPDATE statement
4099  * processing
4100  * return: the UPDATE statement or NULL on error
4101  * parser(in):
4102  * spec(in):
4103  * assignment(in):
4104  *
4105  * Note: For the following INSERT statement:
4106  * INSERT INTO tbl VALUES (1) ON DUPLICATE KEY UPDATE id = 4
4107  * the following UPDATE statement will be generated:
4108  * UPDATE tbl SET id = 4 WHERE tbl = OID_OF_DUPLICATE_KEY (tbl)
4109  * After type checking, constant folding and auto-parameterization, the
4110  * OID_OF_DUPLICATE_KEY (tbl) node will be replaced by a host variable.
4111  * At runtime, the variable will be assigned the OID of a duplicate key
4112  * and the UPDATE XASL will be executed.
4113  */
4114 PT_NODE *
4115 pt_dup_key_update_stmt (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * assignment)
4116 {
4117  PT_NODE *node = parser_new_node (parser, PT_UPDATE);
4118  PT_NODE *name_node = NULL;
4119  PT_NODE *name_arg_node = NULL;
4120  PT_NODE *func_node = NULL;
4121 
4122  if (node == NULL)
4123  {
4124  goto error_exit;
4125  }
4126 
4127  if (spec->node_type != PT_SPEC || spec->info.spec.entity_name == NULL)
4128  {
4129  goto error_exit;
4130  }
4131  name_node = parser_copy_tree (parser, spec->info.spec.entity_name);
4132  if (name_node == NULL || name_node->node_type != PT_NAME)
4133  {
4134  goto error_exit;
4135  }
4137 
4138  name_arg_node = parser_copy_tree (parser, name_node);
4139  if (name_arg_node == NULL)
4140  {
4141  goto error_exit;
4142  }
4143 
4144  node->info.update.spec = parser_copy_tree (parser, spec);
4145  if (node->info.update.spec == NULL)
4146  {
4147  goto error_exit;
4148  }
4149 
4150  /* This will be replaced by a OID PT_VALUE node in constant folding, see pt_fold_const_expr () */
4151  func_node = pt_expression_1 (parser, PT_OID_OF_DUPLICATE_KEY, name_arg_node);
4152  if (func_node == NULL)
4153  {
4154  goto error_exit;
4155  }
4156  name_arg_node = NULL;
4157 
4158  node->info.update.search_cond = pt_expression_2 (parser, PT_EQ, name_node, func_node);
4159  if (node->info.update.search_cond == NULL)
4160  {
4161  goto error_exit;
4162  }
4163 
4164  /* We need the OID PT_VALUE to become a host variable, see qo_optimize_queries () */
4166 
4167  /* We don't want constant folding on the WHERE clause because it might result in the host variable being removed from
4168  * the tree. */
4169  node->info.update.search_cond->flag.do_not_fold = 1;
4170 
4171  func_node = NULL;
4172  name_node = NULL;
4173 
4174  node->info.update.assignment = assignment;
4175 
4176  return node;
4177 
4178 error_exit:
4179 
4180  if (func_node != NULL)
4181  {
4182  parser_free_tree (parser, func_node);
4183  func_node = NULL;
4184  }
4185  if (name_arg_node != NULL)
4186  {
4187  parser_free_tree (parser, name_arg_node);
4188  name_arg_node = NULL;
4189  }
4190  if (name_node != NULL)
4191  {
4192  parser_free_tree (parser, name_node);
4193  name_node = NULL;
4194  }
4195  if (node != NULL)
4196  {
4197  parser_free_tree (parser, node);
4198  node = NULL;
4199  }
4200  return NULL;
4201 }
4202 
4203 /*
4204  * pt_fixup_column_type() - Fixes the type of a SELECT column so that it can
4205  * be used for view creation and for CREATE AS SELECT
4206  * statements
4207  * col(in/out): the SELECT statement column
4208  *
4209  * Note: modifies TP_FLOATING_PRECISION_VALUE precision for char/bit constants
4210  * This code is mostly a hack needed because string literals do not have
4211  * the proper precision set. A better fix is to modify
4212  * pt_db_value_initialize () so that the precision information is set.
4213  */
4214 void
4216 {
4217  int fixed_precision = 0;
4218 
4219  if (col->node_type == PT_VALUE)
4220  {
4221  switch (col->type_enum)
4222  {
4223  /* for NCHAR(3) type column, we reserve only 3bytes. precision and length for NCHAR(n) type is n */
4224  case PT_TYPE_NCHAR:
4225  case PT_TYPE_VARNCHAR:
4226  case PT_TYPE_CHAR:
4227  case PT_TYPE_VARCHAR:
4228  if (col->info.value.data_value.str != NULL)
4229  {
4230  fixed_precision = col->info.value.data_value.str->length;
4231  if (fixed_precision == 0)
4232  {
4233  fixed_precision = 1;
4234  }
4235  }
4236  break;
4237 
4238  case PT_TYPE_BIT:
4239  case PT_TYPE_VARBIT:
4240  switch (col->info.value.string_type)
4241  {
4242  case 'B':
4243  if (col->info.value.data_value.str != NULL)
4244  {
4245  fixed_precision = col->info.value.data_value.str->length;
4246  if (fixed_precision == 0)
4247  {
4248  fixed_precision = 1;
4249  }
4250  }
4251  break;
4252 
4253  case 'X':
4254  if (col->info.value.data_value.str != NULL)
4255  {
4256  fixed_precision = col->info.value.data_value.str->length;
4257  if (fixed_precision == 0)
4258  {
4259  fixed_precision = 1;
4260  }
4261  }
4262  break;
4263 
4264  default:
4265  break;
4266  }
4267  break;
4268 
4269  default:
4270  break;
4271  }
4272  }
4273 
4274  /* Convert char(max) to varchar(max), nchar(max) to varnchar(max), bit(max) to varbit(max) */
4275  if ((col->type_enum == PT_TYPE_CHAR || col->type_enum == PT_TYPE_NCHAR || col->type_enum == PT_TYPE_BIT)
4277  {
4278  if (col->type_enum == PT_TYPE_CHAR)
4279  {
4280  col->type_enum = PT_TYPE_VARCHAR;
4282  }
4283  else if (col->type_enum == PT_TYPE_NCHAR)
4284  {
4285  col->type_enum = PT_TYPE_VARNCHAR;
4287  }
4288  else
4289  {
4290  col->type_enum = PT_TYPE_VARBIT;
4292  }
4293 
4294  if (fixed_precision != 0)
4295  {
4296  col->data_type->info.data_type.precision = fixed_precision;
4297  }
4298  }
4299 }
4300 
4301 /*
4302  * pt_get_select_query_columns() - Retrieves the columns of a SELECT query
4303  * result
4304  * return: NO_ERROR on success, non-zero for ERROR
4305  * parser(in): Parser context
4306  * create_select(in): the select statement parse tree
4307  * query_columns(out): the columns of the select statement
4308  *
4309  * Note: The code is very similar to the one in db_compile_statement_local ()
4310  */
4311 int
4312 pt_get_select_query_columns (PARSER_CONTEXT * parser, PT_NODE * create_select, DB_QUERY_TYPE ** query_columns)
4313 {
4314  PT_NODE *temp_copy = NULL;
4315  DB_QUERY_TYPE *qtype = NULL;
4316  int error = NO_ERROR;
4317 
4318  assert (query_columns != NULL);
4319 
4320  if (pt_node_to_cmd_type (create_select) != CUBRID_STMT_SELECT)
4321  {
4322  ERROR1 (error, ER_UNEXPECTED, "Expecting a select statement.");
4323  goto error_exit;
4324  }
4325 
4326  temp_copy = parser_copy_tree (parser, create_select);
4327  if (temp_copy == NULL)
4328  {
4329  error = ER_FAILED;
4330  goto error_exit;
4331  }
4332 
4333  qtype = pt_get_titles (parser, create_select);
4334  if (qtype == NULL)
4335  {
4336  /* We ignore this for now and we try again later. */
4337  }
4338 
4339  /* Semantic check for the statement */
4340  temp_copy = pt_compile (parser, temp_copy);
4341  if (temp_copy == NULL || pt_has_error (parser))
4342  {
4343 #if 0
4344  assert (er_errid () != NO_ERROR);
4345 #endif
4346  error = er_errid ();
4347  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, temp_copy);
4348  if (error == NO_ERROR)
4349  {
4350  assert (er_errid () != NO_ERROR);
4351  error = er_errid ();
4352  }
4353  goto error_exit;
4354  }
4355 
4356  if (qtype == NULL)
4357  {
4358  qtype = pt_get_titles (parser, temp_copy);
4359  }
4360 
4361  if (qtype == NULL)
4362  {
4363  assert (er_errid () != NO_ERROR);
4364  error = er_errid ();
4365  goto error_exit;
4366  }
4367 
4368  qtype = pt_fillin_type_size (parser, temp_copy, qtype, DB_NO_OIDS, true, true);
4369  if (qtype == NULL)
4370  {
4371  assert (er_errid () != NO_ERROR);
4372  error = er_errid ();
4373  goto error_exit;
4374  }
4375 
4376  /* qtype will be freed later */
4377  *query_columns = qtype;
4378 
4379  parser_free_tree (parser, temp_copy);
4380  temp_copy = NULL;
4381 
4382  return error;
4383 
4384 error_exit:
4385  if (qtype != NULL)
4386  {
4387  db_free_query_format (qtype);
4388  qtype = NULL;
4389  }
4390  if (temp_copy != NULL)
4391  {
4392  parser_free_tree (parser, temp_copy);
4393  temp_copy = NULL;
4394  }
4395  return error;
4396 }
4397 
4398 /*
4399  * pt_node_list_to_array() - returns an array of nodes(PT_NODE) from a
4400  * PT_NODE list. Used mainly to convert a list of
4401  * argument nodes to an array of argument nodes
4402  * return: NO_ERROR on success, ER_GENERIC_ERROR on failure
4403  * parser(in): Parser context
4404  * arg_list(in): List of nodes (arguments) chained on next
4405  * arg_array(out): array of nodes (arguments)
4406  * array_size(in): the (allocated) size of array
4407  * num_args(out): the number of nodes found in list
4408  *
4409  * Note: the arg_array must be allocated and sized to 'array_size'
4410  */
4411 int
4412 pt_node_list_to_array (PARSER_CONTEXT * parser, PT_NODE * arg_list, PT_NODE * arg_array[], const int array_size,
4413  int *num_args)
4414 {
4415  PT_NODE *arg = NULL;
4416  int error = NO_ERROR, len = 0;
4417 
4418  assert (array_size > 0);
4419  assert (arg_array != NULL);
4420  assert (arg_list != NULL);
4421  assert (num_args != NULL);
4422 
4423  *num_args = 0;
4424 
4425  for (arg = arg_list; arg != NULL; arg = arg->next)
4426  {
4427  if (len >= array_size)
4428  {
4429  return ER_GENERIC_ERROR;
4430  }
4431  arg_array[len] = arg;
4432  *num_args = ++len;
4433  }
4434  return error;
4435 }
4436 
4437 /*
4438  * pt_make_dotted_identifier() - returns an identifier node (type PT_NAME) or
4439  * a PT_DOT node tree
4440  *
4441  * return: node with constructed identifier, NULL if construction fails
4442  * parser(in): Parser context
4443  * identifier_str(in): string containing full identifier name. Dots ('.')
4444  * are used to delimit class names and column
4445  * names; for this reason, column and class names should
4446  * not contain dots.
4447  */
4448 static PT_NODE *
4449 pt_make_dotted_identifier (PARSER_CONTEXT * parser, const char *identifier_str)
4450 {
4451  return pt_make_dotted_identifier_internal (parser, identifier_str, 0);
4452 }
4453 
4454 /*
4455  * pt_make_dotted_identifier_internal() - builds an identifier node
4456  * (type PT_NAME) or tree (type PT_DOT)
4457  *
4458  * return: node with constructed identifier, NULL if construction fails
4459  * parser(in): Parser context
4460  * identifier_str(in): string containing full identifier name (with dots);
4461  * length must be smaller than maximum allowed
4462  * identifier length
4463  * depth(in): depth of current constructed node relative to PT_DOT subtree
4464  *
4465  * Note : the depth argument is used to flag the PT_NAME node corresponding
4466  * to the first scoping name as 'meta_class = PT_NORMAL'.
4467  * This applies only to dotted identifier names.
4468  */
4469 static PT_NODE *
4470 pt_make_dotted_identifier_internal (PARSER_CONTEXT * parser, const char *identifier_str, int depth)
4471 {
4472  PT_NODE *identifier = NULL;
4473  char *p_dot = NULL;
4474 
4475  assert (depth >= 0);
4476  if (strlen (identifier_str) >= SM_MAX_IDENTIFIER_LENGTH)
4477  {
4478  assert (false);
4479  return NULL;
4480  }
4481 
4482  p_dot = (char *) strrchr (identifier_str, '.');
4483 
4484  if (p_dot != NULL)
4485  {
4486  char string_name1[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
4487  char string_name2[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
4488  PT_NODE *name1 = NULL;
4489  PT_NODE *name2 = NULL;
4490  int position = CAST_BUFLEN (p_dot - identifier_str);
4491  int remaining = strlen (identifier_str) - position - 1;
4492 
4493  assert ((remaining > 0) && (remaining < strlen (identifier_str) - 1));
4494  assert ((position > 0) && (position < strlen (identifier_str) - 1));
4495 
4496  strncpy (string_name1, identifier_str, position);
4497  string_name1[position] = '\0';
4498  strncpy (string_name2, p_dot + 1, remaining);
4499  string_name2[remaining] = '\0';
4500 
4501  /* create PT_DOT_ - must be left - balanced */
4502  name1 = pt_make_dotted_identifier_internal (parser, string_name1, depth + 1);
4503  name2 = pt_name (parser, string_name2);
4504  if (name1 == NULL || name2 == NULL)
4505  {
4506  return NULL;
4507  }
4508 
4509  identifier = parser_new_node (parser, PT_DOT_);
4510  if (identifier == NULL)
4511  {
4512  return NULL;
4513  }
4514 
4515  identifier->info.dot.arg1 = name1;
4516  identifier->info.dot.arg2 = name2;
4517  }
4518  else
4519  {
4520  identifier = pt_name (parser, identifier_str);
4521  if (identifier == NULL)
4522  {
4523  return NULL;
4524  }
4525 
4526  /* it is a dotted identifier, make the first name PT_NORMAL */
4527  if (depth != 0)
4528  {
4529  identifier->info.name.meta_class = PT_NORMAL;
4530  }
4531  }
4532 
4533  assert (identifier != NULL);
4534 
4535  return identifier;
4536 }
4537 
4538 /*
4539  * pt_add_name_col_to_sel_list() - builds a corresponding node for a table
4540  * column and adds it to the end of the select
4541  * list of a SELECT node
4542  *
4543  * return: error code
4544  * parser(in): Parser context
4545  * select(in): SELECT node
4546  * identifier_str(in): string identifying the column (may contain dots)
4547  * col_alias(in): alias of the new select item
4548  */
4549 static int
4550 pt_add_name_col_to_sel_list (PARSER_CONTEXT * parser, PT_NODE * select, const char *identifier_str,
4551  const char *col_alias)
4552 {
4553  PT_NODE *sel_item = NULL;
4554 
4555  assert (select != NULL);
4556  assert (identifier_str != NULL);
4557 
4558  sel_item = pt_make_dotted_identifier (parser, identifier_str);
4559  if (sel_item == NULL)
4560  {
4561  return ER_FAILED;
4562  }
4563  sel_item->alias_print = pt_append_string (parser, NULL, col_alias);
4564 
4565  select->info.query.q.select.list = parser_append_node (sel_item, select->info.query.q.select.list);
4566  return NO_ERROR;
4567 }
4568 
4569 /*
4570  * pt_add_string_col_to_sel_list() - builds a corresponding node for a table
4571  * column and adds it to the end of the select
4572  * list of a SELECT node
4573  *
4574  * return: void
4575  * parser(in): Parser context
4576  * select(in): SELECT node
4577  * value_string(in): string value
4578  * col_alias(in): alias of the new select item
4579  */
4580 static void
4581 pt_add_string_col_to_sel_list (PARSER_CONTEXT * parser, PT_NODE * select, const char *value_string,
4582  const char *col_alias)
4583 {
4584  PT_NODE *sel_item = NULL;
4585 
4586  assert (select != NULL);
4587  assert (value_string != NULL);
4588 
4589  sel_item = pt_make_string_value (parser, value_string);
4590  if (sel_item == NULL)
4591  {
4592  return;
4593  }
4594  sel_item->alias_print = pt_append_string (parser, NULL, col_alias);
4595 
4596  select->info.query.q.select.list = parser_append_node (sel_item, select->info.query.q.select.list);
4597 }
4598 
4599 /*
4600  * pt_add_table_name_to_from_list() - builds a corresponding node for a table
4601  * 'spec' and adds it to the end of the FROM list
4602  * of a SELECT node
4603  *
4604  * return: newly build PT_NODE, NULL if construction fails
4605  * parser(in): Parser context
4606  * select(in): SELECT node
4607  * table_name(in): table name (should not contain dots), may be NULL if spec
4608  * is a subquery (instead of a table)
4609  * table_alias(in): alias of the table
4610  * auth_bypass(in): bit mask of privileges flags that will bypass
4611  * authorizations
4612  */
4613 PT_NODE *
4614 pt_add_table_name_to_from_list (PARSER_CONTEXT * parser, PT_NODE * select, const char *table_name,
4615  const char *table_alias, const DB_AUTH auth_bypass)
4616 {
4617  PT_NODE *spec = NULL;
4618  PT_NODE *from_item = NULL;
4619  PT_NODE *range_var = NULL;
4620 
4621  if (table_name != NULL)
4622  {
4623  from_item = pt_name (parser, table_name);
4624  if (from_item == NULL)
4625  {
4626  return NULL;
4627  }
4628  }
4629  if (table_alias != NULL)
4630  {
4631  range_var = pt_name (parser, table_alias);
4632  if (range_var == NULL)
4633  {
4634  return NULL;
4635  }
4636  }
4637 
4638  spec = pt_entity (parser, from_item, range_var, NULL);
4639  if (spec == NULL)
4640  {
4641  return NULL;
4642  }
4643 
4644  spec->info.spec.only_all = PT_ONLY;
4645  spec->info.spec.meta_class = PT_CLASS;
4646  select->info.query.q.select.from = parser_append_node (spec, select->info.query.q.select.from);
4647  spec->info.spec.auth_bypass_mask = auth_bypass;
4648 
4649  return spec;
4650 }
4651 
4652 /*
4653  * pt_make_pred_name_int_val() - builds a predicate node (PT_EXPR) using a
4654  * column identifier on LHS and a integer value on
4655  * RHS
4656  *
4657  * return: newly build node (PT_NODE)
4658  * parser(in): Parser context
4659  * op_type(in): operator type; should be a binary operator that makes sense
4660  * for the passed arguments (such as PT_EQ, PT_GT, ...)
4661  * col_name(in): column name (may contain dots)
4662  * int_value(in): integer to assign to PT_VALUE RHS node
4663  */
4664 static PT_NODE *
4665 pt_make_pred_name_int_val (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *col_name, const int int_value)
4666 {
4667  PT_NODE *pred_rhs = NULL;
4668  PT_NODE *pred_lhs = NULL;
4669  PT_NODE *pred = NULL;
4670 
4671  /* create PT_VALUE for rhs */
4672  pred_rhs = pt_make_integer_value (parser, int_value);
4673  /* create PT_NAME for lhs */
4674  pred_lhs = pt_make_dotted_identifier (parser, col_name);
4675 
4676  pred = parser_make_expression (parser, op_type, pred_lhs, pred_rhs, NULL);
4677  return pred;
4678 }
4679 
4680 /*
4681  * pt_make_pred_name_string_val() - builds a predicate node (PT_EXPR) using an
4682  * identifier on LHS and a string value on
4683  * RHS
4684  *
4685  * return: newly build node (PT_NODE)
4686  * parser(in): Parser context
4687  * op_type(in): operator type; should be a binary operator that makes sense
4688  * for the passed arguments (such as PT_EQ, PT_GT, ...)
4689  * identifier_str(in): column name (may contain dots)
4690  * str_value(in): string to assign to PT_VALUE RHS node
4691  */
4692 static PT_NODE *
4693 pt_make_pred_name_string_val (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *identifier_str,
4694  const char *str_value)
4695 {
4696  PT_NODE *pred_rhs = NULL;
4697  PT_NODE *pred_lhs = NULL;
4698  PT_NODE *pred = NULL;
4699 
4700  /* create PT_VALUE for rhs */
4701  pred_rhs = pt_make_string_value (parser, str_value);
4702  /* create PT_NAME for lhs */
4703  pred_lhs = pt_make_dotted_identifier (parser, identifier_str);
4704 
4705  pred = parser_make_expression (parser, op_type, pred_lhs, pred_rhs, NULL);
4706 
4707  return pred;
4708 }
4709 
4710 /*
4711  * pt_make_pred_with_identifiers() - builds a predicate node (PT_EXPR) using
4712  * an identifier on LHS and another identifier on
4713  * RHS
4714  *
4715  * return: newly build node (PT_NODE)
4716  * parser(in): Parser context
4717  * op_type(in): operator type; should be a binary operator that makes sense
4718  * for the passed arguments (such as PT_EQ, PT_GT, ...)
4719  * lhs_identifier(in): LHS column name (may contain dots)
4720  * rhs_identifier(in): RHS column name (may contain dots)
4721  */
4722 static PT_NODE *
4723 pt_make_pred_with_identifiers (PARSER_CONTEXT * parser, PT_OP_TYPE op_type, const char *lhs_identifier,
4724  const char *rhs_identifier)
4725 {
4726  PT_NODE *pred_rhs = NULL;
4727  PT_NODE *pred_lhs = NULL;
4728  PT_NODE *pred = NULL;
4729 
4730  /* create PT_DOT_ for lhs */
4731  pred_lhs = pt_make_dotted_identifier (parser, lhs_identifier);
4732  /* create PT_DOT_ for rhs */
4733  pred_rhs = pt_make_dotted_identifier (parser, rhs_identifier);
4734 
4735  pred = parser_make_expression (parser, op_type, pred_lhs, pred_rhs, NULL);
4736 
4737  return pred;
4738 }
4739 
4740 /*
4741  * pt_make_if_with_expressions() - builds an IF (pred, expr_true, expr_false)
4742  * operator node (PT_EXPR) given two expression
4743  * nodes for true/false values
4744  *
4745  * return: newly build node (PT_NODE)
4746  * parser(in): Parser context
4747  * pred(in): a node for expression used as predicate
4748  * expr1(in): expression node for true value of predicate
4749  * expr2(in): expression node for false value of predicate
4750  * alias(in): alias for this new node
4751  */
4752 static PT_NODE *
4754  const char *alias)
4755 {
4756  PT_NODE *if_node = NULL;
4757 
4758  if_node = parser_make_expression (parser, PT_IF, pred, expr1, expr2);
4759 
4760  if (alias != NULL)
4761  {
4762  if_node->alias_print = pt_append_string (parser, NULL, alias);
4763  }
4764  return if_node;
4765 }
4766 
4767 /*
4768  * pt_make_if_with_strings() - builds an IF (pred, expr_true, expr_false)
4769  * operator node (PT_EXPR) using two strings as
4770  * true/false values
4771  *
4772  * return: newly build node (PT_NODE)
4773  * parser(in): Parser context
4774  * pred(in): a node for expression used as predicate
4775  * string1(in): string used to build a value node for true value of predicate
4776  * string2(in): string used to build a value node for false value of predicate
4777  * alias(in): alias for this new node
4778  */
4779 static PT_NODE *
4780 pt_make_if_with_strings (PARSER_CONTEXT * parser, PT_NODE * pred, const char *string1, const char *string2,
4781  const char *alias)
4782 {
4783  PT_NODE *val1_node = NULL;
4784  PT_NODE *val2_node = NULL;
4785  PT_NODE *if_node = NULL;
4786 
4787  val1_node = pt_make_string_value (parser, string1);
4788  val2_node = pt_make_string_value (parser, string2);
4789 
4790  if_node = pt_make_if_with_expressions (parser, pred, val1_node, val2_node, alias);
4791  return if_node;
4792 }
4793 
4794 /*
4795  * pt_make_like_col_expr() - builds a LIKE operator node (PT_EXPR) using
4796  * an identifier on LHS an expression node on RHS
4797  * '<col_name> LIKE <rhs_expr>'
4798  *
4799  * return: newly build node (PT_NODE)
4800  * parser(in): Parser context
4801  * rhs_expr(in): expression node
4802  * col_name(in): LHS column name (may contain dots)
4803  */
4804 static PT_NODE *
4805 pt_make_like_col_expr (PARSER_CONTEXT * parser, PT_NODE * rhs_expr, const char *col_name)
4806 {
4807  PT_NODE *like_lhs = NULL;
4808  PT_NODE *like_node = NULL;
4809 
4810  like_lhs = pt_make_dotted_identifier (parser, col_name);
4811  like_node = parser_make_expression (parser, PT_LIKE, like_lhs, rhs_expr, NULL);
4812 
4813  return like_node;
4814 }
4815 
4816 /*
4817  * pt_make_outer_select_for_show_stmt() - builds a SELECT node and wrap the
4818  * inner supplied SELECT node
4819  * 'SELECT * FROM (<inner_select>) <select_alias>'
4820  *
4821  * return: newly build node (PT_NODE), NULL if construction fails
4822  * parser(in): Parser context
4823  * inner_select(in): PT_SELECT node
4824  * select_alias(in): alias for the 'FROM specs'
4825  */
4826 static PT_NODE *
4827 pt_make_outer_select_for_show_stmt (PARSER_CONTEXT * parser, PT_NODE * inner_select, const char *select_alias)
4828 {
4829  /* SELECT * from ( SELECT .... ) <select_alias>; */
4830  PT_NODE *val_node = NULL;
4831  PT_NODE *outer_node = NULL;
4832  PT_NODE *alias_subquery = NULL;
4833  PT_NODE *from_item = NULL;
4834 
4835  assert (inner_select != NULL);
4836  assert (inner_select->node_type == PT_SELECT);
4837 
4838  val_node = parser_new_node (parser, PT_VALUE);
4839  if (val_node)
4840  {
4841  val_node->type_enum = PT_TYPE_STAR;
4842  }
4843  else
4844  {
4845  return NULL;
4846  }
4847 
4848  outer_node = parser_new_node (parser, PT_SELECT);
4849  if (outer_node == NULL)
4850  {
4851  return NULL;
4852  }
4853 
4855 
4856  outer_node->info.query.q.select.list = parser_append_node (val_node, outer_node->info.query.q.select.list);
4857  inner_select->info.query.is_subquery = PT_IS_SUBQUERY;
4858 
4859  alias_subquery = pt_name (parser, select_alias);
4860  /* add to FROM an empty entity, the entity will be populated later */
4861  from_item = pt_add_table_name_to_from_list (parser, outer_node, NULL, NULL, DB_AUTH_NONE);
4862 
4863  if (from_item == NULL)
4864  {
4865  return NULL;
4866 
4867  }
4868 
4869  from_item->info.spec.derived_table = inner_select;
4870  from_item->info.spec.meta_class = PT_MISC_NONE;
4871  from_item->info.spec.range_var = alias_subquery;
4873  from_item->info.spec.join_type = PT_JOIN_NONE;
4874 
4875  return outer_node;
4876 }
4877 
4878 /*
4879  * pt_make_outer_select_for_show_columns() - builds a SELECT node and wrap the
4880  * inner supplied SELECT node
4881  * 'SELECT * FROM (<inner_select>) <select_alias>'
4882  *
4883  * return: newly build node (PT_NODE), NULL if construction fails
4884  * parser(in): Parser context
4885  * inner_select(in): PT_SELECT node
4886  * select_alias(in): alias for the 'FROM specs'
4887  * query_names(in): query column names
4888  * query_aliases(in): query column aliasses
4889  * names_length(in): the length of query_names array
4890  * is_show_full(in): non zero if show full columns
4891  * outer_node(out): the result query
4892  */
4893 static int
4894 pt_make_outer_select_for_show_columns (PARSER_CONTEXT * parser, PT_NODE * inner_select, const char *select_alias,
4895  const char **query_names, const char **query_aliases, int names_length,
4896  int is_show_full, PT_NODE ** outer_node)
4897 {
4898  /* SELECT * from ( SELECT .... ) <select_alias>; */
4899  PT_NODE *alias_subquery = NULL;
4900  PT_NODE *from_item = NULL;
4901  PT_NODE *query = NULL;
4902  int i, error = NO_ERROR;
4903 
4904  assert (inner_select != NULL);
4905  assert (inner_select->node_type == PT_SELECT);
4906  assert (outer_node != NULL);
4907 
4908  *outer_node = NULL;
4909 
4910  query = parser_new_node (parser, PT_SELECT);
4911  if (query == NULL)
4912  {
4913  return ER_OUT_OF_VIRTUAL_MEMORY;
4914  }
4915 
4916  if (is_show_full)
4917  {
4919  }
4920  else
4921  {
4923  }
4924 
4925  for (i = 0; i < names_length; i++)
4926  {
4927  error = pt_add_name_col_to_sel_list (parser, query, query_names[i], query_aliases ? query_aliases[i] : NULL);
4928  if (error != NO_ERROR)
4929  {
4930  goto error_exit;
4931  }
4932  }
4933 
4934  /* add to FROM an empty entity, the entity will be populated later */
4935  from_item = pt_add_table_name_to_from_list (parser, query, NULL, NULL, DB_AUTH_NONE);
4936 
4937  if (from_item == NULL)
4938  {
4939  error = ER_FAILED;
4940  goto error_exit;
4941  }
4942 
4943  inner_select->info.query.is_subquery = PT_IS_SUBQUERY;
4944  alias_subquery = pt_name (parser, select_alias);
4945  from_item->info.spec.derived_table = inner_select;
4946  from_item->info.spec.meta_class = PT_MISC_NONE;
4947  from_item->info.spec.range_var = alias_subquery;
4949  from_item->info.spec.join_type = PT_JOIN_NONE;
4950 
4951  *outer_node = query;
4952  return NO_ERROR;
4953 
4954 error_exit:
4955 
4956  if (query)
4957  {
4958  parser_free_tree (parser, query);
4959  }
4960  return error;
4961 }
4962 
4963 /*
4964  * pt_make_select_count_star() - builds a 'SELECT COUNT(*)' node
4965  *
4966  * return: newly build node (PT_NODE), NULL if construnction fails
4967  * parser(in): Parser context
4968  *
4969  * Note : The created node is not complete : FROM and WHERE should be filled
4970  * after using this function
4971  */
4972 static PT_NODE *
4974 {
4975  PT_NODE *query = NULL;
4976  PT_NODE *sel_item = NULL;
4977 
4978  query = parser_new_node (parser, PT_SELECT);
4979 
4980  sel_item = parser_new_node (parser, PT_FUNCTION);
4981 
4982  if (sel_item == NULL || query == NULL)
4983  {
4984  return NULL;
4985  }
4986  sel_item->info.function.arg_list = NULL;
4988  query->info.query.q.select.list = parser_append_node (sel_item, query->info.query.q.select.list);
4989 
4990  return query;
4991 }
4992 
4993 
4994 /*
4995  * pt_make_field_type_expr_node() - builds the node required to print the type
4996  * of column in SHOW COLUMNS
4997  *
4998  * CONCAT(type_name, IF (prec > 0
4999  * AND (type_id=27 OR
5000  * type_id=26 OR
5001  * type_id=25 OR
5002  * type_id=24 OR
5003  * type_id=23 OR
5004  * type_id=4 OR
5005  * type_id=22),
5006  * CONCAT( '(',
5007  * prec ,
5008  * IF (type_id=22,
5009  * CONCAT( ',',
5010  * scale,
5011  * ')' )
5012  * ,')')
5013  * ) ,
5014  * IF ( type_id = 6 OR
5015  * type_id = 7 OR
5016  * type_id=8 ,
5017  * CONCAT( ' OF ',
5018  * Types_t.Composed_types),
5019  * IF (type_id = 35,
5020  * CONCAT('(',
5021  * SELECT GROUP_CONCAT(CONCAT('''', EV.a, '''') SEPARATOR ', ')
5022  * FROM TABLE(D.enumeration) as EV(a), ')'), ''))
5023  * )
5024  * ) AS Type
5025  *
5026  * - type_id values are defined in dbtype.h in DB_TYPE
5027  *
5028  *
5029  * return: newly build node (PT_NODE)
5030  * parser(in): Parser context
5031  */
5032 static PT_NODE *
5034 {
5035  PT_NODE *concat_node = NULL;
5036  PT_NODE *if_node = NULL;
5037  PT_NODE *if_node_types = NULL;
5038  PT_NODE *if_node_enum = NULL;
5039 
5040  /* CONCAT(',',scale,')') */
5041  {
5042  PT_NODE *concat_arg_list = NULL;
5043  PT_NODE *concat_arg = NULL;
5044 
5045  concat_arg = pt_make_string_value (parser, ",");
5046  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5047 
5048  concat_arg = pt_name (parser, "scale");
5049  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5050 
5051  concat_arg = pt_make_string_value (parser, ")");
5052  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5053 
5054  concat_node = parser_keyword_func ("concat", concat_arg_list);
5055  if (concat_node == NULL)
5056  {
5057  return NULL;
5058  }
5059  }
5060 
5061  /* IF( type_id=22 , CONCAT(',',scale,')') , ')' ) */
5062  {
5063  PT_NODE *pred_for_if = NULL;
5064  PT_NODE *val1_node = NULL;
5065  PT_NODE *val2_node = NULL;
5066 
5067  pred_for_if = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 22);
5068  assert (concat_node != NULL);
5069  val1_node = concat_node;
5070  val2_node = pt_make_string_value (parser, ")");
5071 
5072  if_node = parser_make_expression (parser, PT_IF, pred_for_if, val1_node, val2_node);
5073  if (if_node == NULL)
5074  {
5075  return NULL;
5076  }
5077  concat_node = NULL;
5078  }
5079 
5080  /* CONCAT( '(' , prec , IF(..) ) */
5081  {
5082  PT_NODE *concat_arg_list = NULL;
5083  PT_NODE *concat_arg = NULL;
5084 
5085  concat_arg = pt_make_string_value (parser, "(");
5086  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5087 
5088  concat_arg = pt_name (parser, "prec");
5089  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5090 
5091  assert (if_node != NULL);
5092  concat_arg = if_node;
5093  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5094 
5095  concat_node = parser_keyword_func ("concat", concat_arg_list);
5096  if (concat_node == NULL)
5097  {
5098  return NULL;
5099  }
5100 
5101  if_node = NULL;
5102  }
5103 
5104  /* IF (prec > 0 AND (type_id=27 OR type_id=26 OR type_id=25 OR type_id=24 OR type_id=23 OR type_id=4 or type_id=22),
5105  * CONCAT(...) , '' ) */
5106  {
5107  PT_NODE *cond_item1 = NULL;
5108  PT_NODE *cond_item2 = NULL;
5109  PT_NODE *val1_node = NULL;
5110  PT_NODE *val2_node = NULL;
5111  PT_NODE *pred_for_if = NULL;
5112 
5113  /* VARNCHAR and CHAR */
5114  cond_item1 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 27);
5115  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 26);
5116  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5117  /* CHAR */
5118  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 25);
5119  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5120  /* VARBIT */
5121  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 24);
5122  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5123  /* BIT */
5124  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 23);
5125  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5126  /* VARCHAR */
5127  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 4);
5128  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5129  /* NUMERIC */
5130  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 22);
5131  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5132  cond_item1->info.expr.paren_type = 1;
5133 
5134  /* prec */
5135  cond_item2 = pt_make_pred_name_int_val (parser, PT_GT, "prec", 0);
5136  cond_item1 = parser_make_expression (parser, PT_AND, cond_item2, cond_item1, NULL);
5137 
5138  pred_for_if = cond_item1;
5139  assert (concat_node != NULL);
5140  val1_node = concat_node;
5141  val2_node = pt_make_string_value (parser, "");
5142 
5143  if_node = parser_make_expression (parser, PT_IF, pred_for_if, val1_node, val2_node);
5144  if (if_node == NULL)
5145  {
5146  return NULL;
5147  }
5148 
5149  concat_node = NULL;
5150  }
5151 
5152  /* CONCAT(' OF ',Types_t.Composed_types) */
5153  {
5154  PT_NODE *concat_arg_list = NULL;
5155  PT_NODE *concat_arg = NULL;
5156 
5157  concat_arg = pt_make_string_value (parser, " OF ");
5158  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5159 
5160  concat_arg = pt_make_dotted_identifier (parser, "Types_t.Composed_types");
5161  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5162 
5163  concat_node = parser_keyword_func ("concat", concat_arg_list);
5164  if (concat_node == NULL)
5165  {
5166  return NULL;
5167  }
5168  }
5169 
5170  /* IF (type_id = 35, CONCAT('(', SELECT GROUP_CONCAT(CONCAT('''', EV.a, '''') SEPARATOR ', ') FROM TABLE
5171  * (D.enumeration) as EV(a), ')' ), '') */
5172  {
5173  PT_NODE *node1 = parser_new_node (parser, PT_FUNCTION);
5174  PT_NODE *node2 = NULL;
5175  PT_NODE *node3 = NULL;
5176 
5177  if (node1 == NULL)
5178  {
5179  return NULL;
5180  }
5181 
5182  /* CONCAT('''', EV.a, '''') */
5183  node2 = pt_make_string_value (parser, "'");
5184  node3 = pt_make_dotted_identifier (parser, "EV.a");
5185  node2 = parser_append_node (node3, node2);
5186  node3 = pt_make_string_value (parser, "'");
5187  node2 = parser_append_node (node3, node2);
5188  node2 = parser_keyword_func ("concat", node2);
5189 
5190  /* GROUP_CONCAT(EV.a SEPARATOR ', ') */
5193 
5194  node3 = pt_make_string_value (parser, ", ");
5195  node1->info.function.arg_list = parser_append_node (node3, node2);
5196  node1->info.function.order_by = NULL;
5197 
5198  /* TABLE(D.enumeration) as EV(a) */
5199  node2 = parser_new_node (parser, PT_SPEC);
5200  if (node2 == NULL)
5201  {
5202  return NULL;
5203  }
5204  node2->info.spec.derived_table = pt_make_dotted_identifier (parser, "D.enumeration");
5206  node2->info.spec.range_var = pt_name (parser, "EV");
5207  node2->info.spec.as_attr_list = pt_name (parser, "a");
5208 
5209  /* SELECT GROUP_CONCAT(EV.a SEPARATOR ', ') FROM TABLE(D.enumeration) as EV(a) */
5210  node3 = parser_new_node (parser, PT_SELECT);
5211  if (node3 == NULL)
5212  {
5213  return NULL;
5214  }
5215  node3->info.query.q.select.list = node1;
5216  node3->info.query.q.select.from = node2;
5217 
5218  /* CONCAT('(', SELECT ..., ')') */
5219  node1 = pt_make_string_value (parser, "(");
5220  node1 = parser_append_node (node3, node1);
5221  node1 = parser_append_node (pt_make_string_value (parser, ")"), node1);
5222  node2 = parser_keyword_func ("concat", node1);
5223 
5224  /* IF (type_id = 35, CONCAT('(', SELECT ..., ')'), '') */
5225  node1 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 35);
5226  node3 = pt_make_string_value (parser, "");
5227  if_node_enum = parser_make_expression (parser, PT_IF, node1, node2, node3);
5228  if (if_node_enum == NULL)
5229  {
5230  return NULL;
5231  }
5232  }
5233 
5234  /* IF ( type_id = 6 OR type_id = 7 OR type_id=8 , CONCAT( .. ),'') */
5235  {
5236  PT_NODE *cond_item1 = NULL;
5237  PT_NODE *cond_item2 = NULL;
5238  PT_NODE *val1_node = NULL;
5239  PT_NODE *val2_node = NULL;
5240  PT_NODE *pred_for_if = NULL;
5241 
5242  /* SET and MULTISET */
5243  cond_item1 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 6);
5244  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 7);
5245  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5246  /* SEQUENCE */
5247  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 8);
5248  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5249 
5250  pred_for_if = cond_item1;
5251  assert (concat_node != NULL);
5252  val1_node = concat_node;
5253  val2_node = if_node_enum;
5254 
5255  assert (pred_for_if != NULL && val1_node != NULL && val2_node != NULL);
5256 
5257  if_node_types = parser_make_expression (parser, PT_IF, pred_for_if, val1_node, val2_node);
5258  if (if_node_types == NULL)
5259  {
5260  return NULL;
5261  }
5262  }
5263 
5264  /* CONCAT( type_name, IF(...) , IF (...) ) */
5265  {
5266  PT_NODE *concat_arg_list = NULL;
5267  PT_NODE *concat_arg = NULL;
5268 
5269  concat_arg = pt_name (parser, "type_name");
5270  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5271 
5272  assert (if_node != NULL);
5273  concat_arg = if_node;
5274  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5275 
5276  assert (if_node_types != NULL);
5277  concat_arg = if_node_types;
5278  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
5279 
5280  concat_node = parser_keyword_func ("concat", concat_arg_list);
5281  if (concat_node == NULL)
5282  {
5283  return NULL;
5284  }
5285  }
5286 
5287  concat_node->alias_print = pt_append_string (parser, NULL, "Type");
5288 
5289  return concat_node;
5290 }
5291 
5292 
5293 /*
5294  * pt_make_collation_expr_node() - builds the node required to print the
5295  * collation of column in SHOW COLUMNS
5296  *
5297  * (IF (type_id=27 OR type_id=26 OR type_id=25 OR type_id=4,
5298  * CL.coll_name, NULL)) AS Collation
5299  *
5300  * return: newly build node (PT_NODE)
5301  * parser(in): Parser context
5302  */
5303 static PT_NODE *
5305 {
5306  PT_NODE *collation_name = NULL;
5307  PT_NODE *null_expr = NULL;
5308  PT_NODE *if_node = NULL;
5309 
5310  collation_name = pt_make_dotted_identifier (parser, "CL.coll_name");
5311 
5312  null_expr = parser_new_node (parser, PT_VALUE);
5313  if (null_expr)
5314  {
5315  null_expr->type_enum = PT_TYPE_NULL;
5316  }
5317 
5318  /* IF (type_id=27 OR type_id=26 OR type_id=25 OR type_id=4, CL.name , NULL ) */
5319  {
5320  PT_NODE *cond_item1 = NULL;
5321  PT_NODE *cond_item2 = NULL;
5322  PT_NODE *pred_for_if = NULL;
5323 
5324  /* VARNCHAR and CHAR */
5325  cond_item1 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 27);
5326  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 26);
5327  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5328  /* CHAR */
5329  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 25);
5330  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5331  /* STRING */
5332  cond_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "type_id", 4);
5333  cond_item1 = parser_make_expression (parser, PT_OR, cond_item1, cond_item2, NULL);
5334 
5335  pred_for_if = cond_item1;
5336 
5337  if_node = parser_make_expression (parser, PT_IF, pred_for_if, collation_name, null_expr);
5338 
5339  if (if_node != NULL)
5340  {
5341  if_node->alias_print = pt_append_string (parser, NULL, "Collation");
5342  }
5343  }
5344 
5345  return if_node;
5346 }
5347 
5348 /*
5349  * pt_make_field_extra_expr_node() - builds the 'Extra' field for the
5350  * SHOW COLUMNS statment
5351  *
5352  * return: newly build node (PT_NODE), NULL if construction fails
5353  * parser(in): Parser context
5354  *
5355  * IF( (SELECT count(*)
5356  * FROM db_serial S
5357  * WHERE S.att_name = A.attr_name AND
5358  * S.class_name = C.class_name
5359  * ) >= 1 ,
5360  * 'auto_increment',
5361  * '' )
5362  * AS Extra
5363  *
5364  * Note : Currently, only 'auto_increment' is diplayed in the Extra field
5365  */
5366 static PT_NODE *
5368 {
5369  PT_NODE *where_item1 = NULL;
5370  PT_NODE *where_item2 = NULL;
5371  PT_NODE *from_item = NULL;
5372  PT_NODE *query = NULL;
5373  PT_NODE *extra_node = NULL;
5374  PT_NODE *pred = NULL;
5375  PT_NODE *pred_rhs = NULL;
5376 
5377  /* SELECT .. FROM .. WHERE */
5378  query = pt_make_select_count_star (parser);
5379  if (query == NULL)
5380  {
5381  return NULL;
5382  }
5383 
5384  from_item = pt_add_table_name_to_from_list (parser, query, "db_serial", "S", DB_AUTH_NONE);
5385 
5386  /* S.att_name = A.attr_name */
5387  where_item1 = pt_make_pred_with_identifiers (parser, PT_EQ, "S.att_name", "A.attr_name");
5388  /* S.class_name = C.class_name */
5389  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "S.class_name", "C.class_name");
5390 
5391  /* item1 = item2 AND item2 */
5392  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5393  query->info.query.q.select.where = parser_append_node (where_item1, query->info.query.q.select.where);
5394 
5395  /* IF ( SELECT (..) >=1 , 'auto_increment' , '' ) */
5396  pred_rhs = pt_make_integer_value (parser, 1);
5397 
5398  pred = parser_make_expression (parser, PT_GE, query, pred_rhs, NULL);
5399 
5400  extra_node = pt_make_if_with_strings (parser, pred, "auto_increment", "", "Extra");
5401 
5402  return extra_node;
5403 }
5404 
5405 /*
5406  * pt_make_field_key_type_expr_node() - builds the 'Key' field for the
5407  * SHOW COLUMNS statment
5408  *
5409  * return: newly build node (PT_NODE), NULL if construction fails
5410  * parser(in): Parser context
5411  *
5412  * IF ( pri_key_count > 0,
5413  * 'PRI' ,
5414  * IF (uni_key_count > 0 ,
5415  * 'UNI',
5416  * IF (mul_count > 0 ,
5417  * 'MUL',
5418  * '')
5419  * )
5420  * )
5421  *
5422  *
5423  * Note : PRI : when the column is part of an index with primary key
5424  * UNI : when the column is part of an index with unique key
5425  * MUL : when the column is the first column in a non-unique index
5426  * if more than one applies to a column, only the one is displayed,
5427  * in the order PRI,UNI,MUL
5428  * '' : no index on the column
5429  */
5430 static PT_NODE *
5432 {
5433  PT_NODE *pri_key_query = NULL;
5434  PT_NODE *uni_key_query = NULL;
5435  PT_NODE *mul_query = NULL;
5436  PT_NODE *key_node = NULL;
5437 
5438  {
5439  /* pri_key_count : (SELECT count (*) FROM (SELECT IK.key_attr_name ATTR, I.is_primary_key PRI_KEY FROM
5440  * _db_index_key IK , _db_index I WHERE IK IN I.key_attrs AND IK.key_attr_name = A.attr_name AND I.class_of =
5441  * A.class_of AND A.class_of.class_name=C.class_name) constraints_pri_key WHERE PRI_KEY=1) */
5442  PT_NODE *sub_query = NULL;
5443  PT_NODE *from_item = NULL;
5444  PT_NODE *where_item1 = NULL;
5445  PT_NODE *where_item2 = NULL;
5446  PT_NODE *alias_subquery = NULL;
5447 
5448  /* SELECT IK.key_attr_name ATTR, I.is_primary_key PRI_KEY FROM _db_index_key IK , _db_index I WHERE IK IN
5449  * I.key_attrs AND IK.key_attr_name = A.attr_name AND I.class_of = A.class_of AND A.class_of.class_name =
5450  * C.class_name */
5451  sub_query = parser_new_node (parser, PT_SELECT);
5452  if (sub_query == NULL)
5453  {
5454  return NULL;
5455  }
5456 
5457  /* SELECT list : */
5458  pt_add_name_col_to_sel_list (parser, sub_query, "IK.key_attr_name", "ATTR");
5459  pt_add_name_col_to_sel_list (parser, sub_query, "I.is_primary_key", "PRI_KEY");
5460  /* .. FROM : */
5461  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index_key", "IK", DB_AUTH_SELECT);
5462  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index", "I", DB_AUTH_SELECT);
5463 
5464  /* .. WHERE : */
5465  where_item1 = pt_make_pred_with_identifiers (parser, PT_IS_IN, "IK", "I.key_attrs");
5466  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "IK.key_attr_name", "A.attr_name");
5467  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5468 
5469  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "I.class_of", "A.class_of");
5470  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5471 
5472  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "A.class_of.class_name", "C.class_name");
5473  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5474 
5475  /* WHERE clause should be empty */
5476  assert (sub_query->info.query.q.select.where == NULL);
5477  sub_query->info.query.q.select.where = parser_append_node (where_item1, sub_query->info.query.q.select.where);
5478 
5479  /* outer query : SELECT count (*) FROM (..) WHERE PRI_KEY=1 */
5480  pri_key_query = pt_make_select_count_star (parser);
5481  if (pri_key_query == NULL)
5482  {
5483  return NULL;
5484  }
5485 
5486  /* add to FROM and empy entity, the entity will be populated later */
5487  from_item = pt_add_table_name_to_from_list (parser, pri_key_query, NULL, NULL, DB_AUTH_NONE);
5488  if (from_item == NULL)
5489  {
5490  return NULL;
5491  }
5492  alias_subquery = pt_name (parser, "constraints_pri_key");
5493 
5494  from_item->info.spec.derived_table = sub_query;
5495  from_item->info.spec.meta_class = PT_MISC_NONE;
5496  from_item->info.spec.range_var = alias_subquery;
5498  from_item->info.spec.join_type = PT_JOIN_NONE;
5499  where_item1 = pt_make_pred_name_int_val (parser, PT_EQ, "PRI_KEY", 1);
5500  pri_key_query->info.query.q.select.where =
5501  parser_append_node (where_item1, pri_key_query->info.query.q.select.where);
5502  /* pri_key_count query is done */
5503  }
5504 
5505  {
5506  /* uni_key_count : (SELECT count (*) FROM (SELECT IK.key_attr_name ATTR, I.is_unique UNI_KEY FROM _db_index_key IK
5507  * , _db_index I WHERE IK IN I.key_attrs AND IK.key_attr_name = A.attr_name AND I.class_of = A.class_of AND
5508  * A.class_of.class_name = C.class_name) constraints_pri_key WHERE UNI_KEY=1) */
5509  PT_NODE *sub_query = NULL;
5510  PT_NODE *from_item = NULL;
5511  PT_NODE *where_item1 = NULL;
5512  PT_NODE *where_item2 = NULL;
5513  PT_NODE *alias_subquery = NULL;
5514 
5515  /* SELECT IK.key_attr_name ATTR, I.is_unique UNI_KEY FROM _db_index_key IK , _db_index I WHERE IK IN I.key_attrs
5516  * AND IK.key_attr_name = A.attr_name AND I.class_of = A.class_of AND A.class_of.class_name = C.class_name */
5517  sub_query = parser_new_node (parser, PT_SELECT);
5518  if (sub_query == NULL)
5519  {
5520  return NULL;
5521  }
5522 
5523  /* SELECT list : */
5524  pt_add_name_col_to_sel_list (parser, sub_query, "IK.key_attr_name", "ATTR");
5525  pt_add_name_col_to_sel_list (parser, sub_query, "I.is_unique", "UNI_KEY");
5526  /* .. FROM : */
5527  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index_key", "IK", DB_AUTH_SELECT);
5528  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index", "I", DB_AUTH_SELECT);
5529 
5530  /* .. WHERE : */
5531  where_item1 = pt_make_pred_with_identifiers (parser, PT_IS_IN, "IK", "I.key_attrs");
5532  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "IK.key_attr_name", "A.attr_name");
5533  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5534 
5535  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "I.class_of", "A.class_of");
5536  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5537 
5538  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "A.class_of.class_name", "C.class_name");
5539  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5540 
5541  /* where should be empty */
5542  assert (sub_query->info.query.q.select.where == NULL);
5543  sub_query->info.query.q.select.where = parser_append_node (where_item1, sub_query->info.query.q.select.where);
5544 
5545  /* outer query : SELECT count (*) FROM (..) WHERE PRI_KEY=1 */
5546  uni_key_query = pt_make_select_count_star (parser);
5547  if (uni_key_query == NULL)
5548  {
5549  return NULL;
5550  }
5551 
5552  /* add to FROM and empy entity, the entity will be populated later */
5553  from_item = pt_add_table_name_to_from_list (parser, uni_key_query, NULL, NULL, DB_AUTH_NONE);
5554  if (from_item == NULL)
5555  {
5556  return NULL;
5557  }
5558  alias_subquery = pt_name (parser, "constraints_uni_key");
5559 
5560  from_item->info.spec.derived_table = sub_query;
5561  from_item->info.spec.meta_class = PT_MISC_NONE;
5562  from_item->info.spec.range_var = alias_subquery;
5564  from_item->info.spec.join_type = PT_JOIN_NONE;
5565 
5566  where_item1 = pt_make_pred_name_int_val (parser, PT_EQ, "UNI_KEY", 1);
5567  uni_key_query->info.query.q.select.where =
5568  parser_append_node (where_item1, uni_key_query->info.query.q.select.where);
5569  /* uni_key_count query is done */
5570  }
5571 
5572  {
5573  /* mul_count : (SELECT count (*) FROM (SELECT IK.key_attr_name ATTR FROM _db_index_key IK , _db_index I WHERE IK IN
5574  * I.key_attrs AND IK.key_attr_name = A.attr_name AND I.class_of = A.class_of AND A.class_of.class_name =
5575  * C.class_name AND IK.key_order = 0) constraints_no_index ) */
5576  PT_NODE *sub_query = NULL;
5577  PT_NODE *from_item = NULL;
5578  PT_NODE *where_item1 = NULL;
5579  PT_NODE *where_item2 = NULL;
5580  PT_NODE *alias_subquery = NULL;
5581 
5582  /* SELECT IK.key_attr_name ATTR FROM _db_index_key IK , _db_index I WHERE IK IN I.key_attrs AND IK.key_attr_name =
5583  * A.attr_name AND I.class_of = A.class_of AND A.class_of.class_name = C.class_name AND IK.key_order = 0 */
5584  sub_query = parser_new_node (parser, PT_SELECT);
5585  if (sub_query == NULL)
5586  {
5587  return NULL;
5588  }
5589 
5590  /* SELECT list : */
5591  pt_add_name_col_to_sel_list (parser, sub_query, "IK.key_attr_name", "ATTR");
5592  /* .. FROM : */
5593  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index_key", "IK", DB_AUTH_SELECT);
5594  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_index", "I", DB_AUTH_SELECT);
5595 
5596  /* .. WHERE : */
5597  where_item1 = pt_make_pred_with_identifiers (parser, PT_IS_IN, "IK", "I.key_attrs");
5598  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "IK.key_attr_name", "A.attr_name");
5599  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5600 
5601  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "I.class_of", "A.class_of");
5602  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5603 
5604  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "A.class_of.class_name", "C.class_name");
5605  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5606 
5607  where_item2 = pt_make_pred_name_int_val (parser, PT_EQ, "IK.key_order", 0);
5608  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5609 
5610  /* where should be empty */
5611  assert (sub_query->info.query.q.select.where == NULL);
5612  sub_query->info.query.q.select.where = parser_append_node (where_item1, sub_query->info.query.q.select.where);
5613 
5614  /* outer query : SELECT count (*) FROM (..) WHERE PRI_KEY=1 */
5615  mul_query = pt_make_select_count_star (parser);
5616 
5617  /* add to FROM and empy entity, the entity will be populated later */
5618  from_item = pt_add_table_name_to_from_list (parser, mul_query, NULL, NULL, DB_AUTH_NONE);
5619  if (from_item == NULL)
5620  {
5621  return NULL;
5622  }
5623  alias_subquery = pt_name (parser, "constraints_no_index");
5624  assert (alias_subquery != NULL);
5625 
5626  from_item->info.spec.derived_table = sub_query;
5627  from_item->info.spec.meta_class = PT_MISC_NONE;
5628  from_item->info.spec.range_var = alias_subquery;
5630  from_item->info.spec.join_type = PT_JOIN_NONE;
5631  /* mul_count query is done */
5632  }
5633 
5634  /* IF ( pri_key_count > 0, 'PRI' , IF (uni_key_count > 0 , 'UNI', IF (mul_count > 0 , 'MUL', '') ) ) */
5635  {
5636  PT_NODE *if_node1 = NULL;
5637  PT_NODE *if_node2 = NULL;
5638  PT_NODE *if_node3 = NULL;
5639 
5640  {
5641  /* IF (mul_count > 0 , 'MUL', '' */
5642  PT_NODE *pred_rhs = NULL;
5643  PT_NODE *pred = NULL;
5644 
5645  pred_rhs = pt_make_integer_value (parser, 0);
5646 
5647  pred = parser_make_expression (parser, PT_GT, mul_query, pred_rhs, NULL);
5648 
5649  if_node3 = pt_make_if_with_strings (parser, pred, "MUL", "", NULL);
5650  }
5651 
5652  {
5653  /* IF (uni_key_count > 0 , 'UNI', (..IF..) */
5654  PT_NODE *pred_rhs = NULL;
5655  PT_NODE *pred = NULL;
5656  PT_NODE *string1_node = NULL;
5657 
5658  pred_rhs = pt_make_integer_value (parser, 0);
5659 
5660  pred = parser_make_expression (parser, PT_GT, uni_key_query, pred_rhs, NULL);
5661 
5662  string1_node = pt_make_string_value (parser, "UNI");
5663 
5664  if_node2 = pt_make_if_with_expressions (parser, pred, string1_node, if_node3, NULL);
5665  }
5666 
5667  {
5668  /* pri_key_count > 0, 'PRI', (..IF..) */
5669  PT_NODE *pred_rhs = NULL;
5670  PT_NODE *pred = NULL;
5671  PT_NODE *string1_node = NULL;
5672 
5673  pred_rhs = pt_make_integer_value (parser, 0);
5674 
5675  pred = parser_make_expression (parser, PT_GT, pri_key_query, pred_rhs, NULL);
5676 
5677  string1_node = pt_make_string_value (parser, "PRI");
5678 
5679  if_node1 = pt_make_if_with_expressions (parser, pred, string1_node, if_node2, "Key");
5680  }
5681  key_node = if_node1;
5682  }
5683  return key_node;
5684 }
5685 
5686 /*
5687  * pt_make_sort_spec_with_identifier() - builds a SORT_SPEC for GROUP BY or
5688  * ORDER BY using a column indentifier
5689  *
5690  * return: newly build node (PT_NODE), NULL if construction fails
5691  * parser(in): Parser context
5692  * identifier(in): full name of identifier
5693  * sort_mode(in): sorting ascendint or descending; if this parameter is not
5694  * PT_ASC or PT_DESC, the function will return NULL
5695  */
5696 static PT_NODE *
5697 pt_make_sort_spec_with_identifier (PARSER_CONTEXT * parser, const char *identifier, PT_MISC_TYPE sort_mode)
5698 {
5699  PT_NODE *group_by_node = NULL;
5700  PT_NODE *group_by_col = NULL;
5701 
5702  if (sort_mode != PT_ASC && sort_mode != PT_DESC)
5703  {
5704  assert (false);
5705  return NULL;
5706  }
5707  group_by_node = parser_new_node (parser, PT_SORT_SPEC);
5708  if (group_by_node == NULL)
5709  {
5710  return NULL;
5711  }
5712 
5713  group_by_col = pt_make_dotted_identifier (parser, identifier);
5714  group_by_node->info.sort_spec.asc_or_desc = sort_mode;
5715  group_by_node->info.sort_spec.expr = group_by_col;
5716 
5717  return group_by_node;
5718 }
5719 
5720 /*
5721  * pt_make_sort_spec_with_number() - builds a SORT_SPEC for ORDER BY using
5722  * a numeric indentifier
5723  * used in : < ORDER BY <x> <ASC|DESC> >
5724  *
5725  * return: newly build node (PT_NODE), NULL if construction fails
5726  * parser(in): Parser context
5727  * number_pos(in): position number for ORDER BY
5728  * sort_mode(in): sorting ascendint or descending; if this parameter is not
5729  * PT_ASC or PT_DESC, the function will return NULL
5730  */
5731 static PT_NODE *
5732 pt_make_sort_spec_with_number (PARSER_CONTEXT * parser, const int number_pos, PT_MISC_TYPE sort_mode)
5733 {
5734  PT_NODE *sort_spec_node = NULL;
5735  PT_NODE *sort_spec_num = NULL;
5736 
5737  if (sort_mode != PT_ASC && sort_mode != PT_DESC)
5738  {
5739  assert (false);
5740  return NULL;
5741  }
5742  sort_spec_node = parser_new_node (parser, PT_SORT_SPEC);
5743  if (sort_spec_node == NULL)
5744  {
5745  return NULL;
5746  }
5747 
5748  sort_spec_num = pt_make_integer_value (parser, number_pos);
5749  sort_spec_node->info.sort_spec.asc_or_desc = sort_mode;
5750  sort_spec_node->info.sort_spec.expr = sort_spec_num;
5751 
5752  return sort_spec_node;
5753 }
5754 
5755 /*
5756  * pt_make_collection_type_subquery_node() - builds a SELECT subquery used
5757  * construct the string to display
5758  * the list of sub-types for a collection
5759  * type (SET , SEQUENCE, MULTISET);
5760  * used to build SHOW COLUMNS statement
5761  *
5762  *
5763  * SELECT AA.attr_name ATTR,
5764  * GROUP_CONCAT( TT.type_name ORDER BY 1 SEPARATOR ',')
5765  * Composed_types
5766  * FROM _db_attribute AA, _db_domain DD , _db_data_type TT
5767  * WHERE AA.class_of.class_name = '<table_name>' AND
5768  * DD.data_type = TT.type_id AND
5769  * DD.object_of IN AA.domains
5770  * GROUP BY AA.attr_name)
5771  *
5772  * return: newly build node (PT_NODE), NULL if construction fails
5773  * parser(in): Parser context
5774  * table_name(in): name of table to filter by ; only the columns from this
5775  * table are checked for their type
5776  *
5777  */
5778 static PT_NODE *
5779 pt_make_collection_type_subquery_node (PARSER_CONTEXT * parser, const char *table_name)
5780 {
5781  PT_NODE *where_item1 = NULL;
5782  PT_NODE *where_item2 = NULL;
5783  PT_NODE *from_item = NULL;
5784  PT_NODE *query = NULL;
5785 
5786  assert (table_name != NULL);
5787 
5788  /* SELECT .. FROM .. WHERE */
5789  query = parser_new_node (parser, PT_SELECT);
5790  if (query == NULL)
5791  {
5792  return NULL;
5793  }
5794 
5796 
5797  /* SELECT list : */
5798  pt_add_name_col_to_sel_list (parser, query, "AA.attr_name", "ATTR");
5799 
5800  {
5801  /* add GROUP_CONCAT (...) */
5802  PT_NODE *sel_item = NULL;
5803  PT_NODE *group_concat_field = NULL;
5804  PT_NODE *group_concat_sep = NULL;
5805  PT_NODE *order_by_item = NULL;
5806 
5807  sel_item = parser_new_node (parser, PT_FUNCTION);
5808  if (sel_item == NULL)
5809  {
5810  return NULL;
5811  }
5812 
5814  sel_item->info.function.all_or_distinct = PT_ALL;
5815 
5816  group_concat_field = pt_make_dotted_identifier (parser, "TT.type_name");
5817  group_concat_sep = pt_make_string_value (parser, ",");
5818  sel_item->info.function.arg_list = parser_append_node (group_concat_sep, group_concat_field);
5819 
5820  /* add ORDER BY */
5821  assert (sel_item->info.function.order_by == NULL);
5822 
5823  /* By 1 */
5824  order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC);
5825  sel_item->info.function.order_by = order_by_item;
5826 
5827  sel_item->alias_print = pt_append_string (parser, NULL, "Composed_types");
5828  query->info.query.q.select.list = parser_append_node (sel_item, query->info.query.q.select.list);
5829  }
5830 
5831  /* FROM : */
5832  from_item = pt_add_table_name_to_from_list (parser, query, "_db_attribute", "AA", DB_AUTH_SELECT);
5833  from_item = pt_add_table_name_to_from_list (parser, query, "_db_domain", "DD", DB_AUTH_SELECT);
5834  from_item = pt_add_table_name_to_from_list (parser, query, "_db_data_type", "TT", DB_AUTH_SELECT);
5835 
5836  /* WHERE : */
5837  /* AA.class_of.class_name = '<table_name>' */
5838  where_item1 = pt_make_pred_name_string_val (parser, PT_EQ, "AA.class_of.class_name", table_name);
5839  /* DD.data_type = TT.type_id */
5840  where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "DD.data_type", "TT.type_id");
5841  /* item1 = item2 AND item2 */
5842  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5843 
5844  /* DD.object_of IN AA.domains */
5845  where_item2 = pt_make_pred_with_identifiers (parser, PT_IS_IN, "DD.object_of", "AA.domains");
5846  where_item1 = parser_make_expression (parser, PT_AND, where_item1, where_item2, NULL);
5847 
5848  query->info.query.q.select.where = parser_append_node (where_item1, query->info.query.q.select.where);
5849 
5850  /* GROUP BY : */
5851  {
5852  PT_NODE *group_by_node = NULL;
5853 
5854  group_by_node = pt_make_sort_spec_with_identifier (parser, "AA.attr_name", PT_ASC);
5855  if (group_by_node == NULL)
5856  {
5857  return NULL;
5858  }
5859  query->info.query.q.select.group_by = group_by_node;
5860  }
5861 
5862  return query;
5863 }
5864 
5865 /*
5866  * pt_make_dummy_query_check_table() - builds a SELECT subquery used check
5867  * if the table exists; when attached to
5868  * the SHOW statement, it should cause an
5869  * execution error, instead of displaying
5870  * 'no results';
5871  * used to build SHOW COLUMNS statement
5872  *
5873  * SELECT COUNT(*) FROM <table_name> LIMIT 1;
5874  *
5875  * return: newly build node (PT_NODE), NULL if construction fails
5876  * parser(in): Parser context
5877  * table_name(in): name of table
5878  *
5879  */
5880 static PT_NODE *
5881 pt_make_dummy_query_check_table (PARSER_CONTEXT * parser, const char *table_name)
5882 {
5883  PT_NODE *limit_item = NULL;
5884  PT_NODE *from_item = NULL;
5885  PT_NODE *query = NULL;
5886 
5887  assert (table_name != NULL);
5888 
5889  /* This query should cause an execution errors when performing SHOW COLUMNS on a non-existing table or when the user
5890  * doesn't have SELECT privilege on that table; A simpler query like: SELECT 1 FROM <table_name> WHERE FALSE; is
5891  * removed during parse tree optimizations, and no error is printed when user has insuficient privileges. We need a
5892  * query which will not be removed on translation (in order to be kept up to the authentication stage, but also with
5893  * low impact on performance. */
5894  /* We use : SELECT COUNT(*) FROM <table_name> LIMIT 1; TODO: this will impact performance so we might find a better
5895  * solution */
5896  query = pt_make_select_count_star (parser);
5897  if (query == NULL)
5898  {
5899  return NULL;
5900  }
5901  from_item = pt_add_table_name_to_from_list (parser, query, table_name, "DUMMY", DB_AUTH_NONE);
5902 
5903  limit_item = pt_make_integer_value (parser, 1);
5904  query->info.query.limit = limit_item;
5905 
5906  return query;
5907 }
5908 
5909 /*
5910  * pt_make_query_show_table() - builds the query used for SHOW TABLES
5911  *
5912  * SELECT * FROM (SELECT C.class_name AS tables_in_<dbname>,
5913  * IF(class_type='CLASS','VIEW','BASE TABLE')
5914  * AS table_type
5915  * FROM db_class C
5916  * WHERE is_system_class='NO') show_tables
5917  * ORDER BY 1;
5918  *
5919  * return: newly build node (PT_NODE), NULL if construnction fails
5920  * parser(in): Parser context
5921  * is_full_syntax(in): true, if the SHOW statement contains the 'FULL' token
5922  * like_where_syntax(in): indicator of presence for LIKE or WHERE clauses in
5923  * SHOW statement. Values : 0 = none of LIKE or WHERE,
5924  * 1 = contains LIKE, 2 = contains WHERE
5925  * like_or_where_expr(in): node expression supplied as condition (in WHERE)
5926  * or RHS for LIKE
5927  *
5928  */
5929 PT_NODE *
5930 pt_make_query_show_table (PARSER_CONTEXT * parser, bool is_full_syntax, int like_where_syntax,
5931  PT_NODE * like_or_where_expr)
5932 {
5933  PT_NODE *node = NULL;
5934  PT_NODE *sub_query = NULL;
5935  PT_NODE *from_item = NULL;
5936  PT_NODE *where_item = NULL;
5937  char tables_col_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
5938 
5939  {
5940  char *db_name = db_get_database_name ();
5941  const char *const col_header = "Tables_in_";
5942 
5943  if (db_name == NULL)
5944  {
5945  return NULL;
5946  }
5947 
5948  strcpy (tables_col_name, col_header);
5949  strncat (tables_col_name, db_name, SM_MAX_IDENTIFIER_LENGTH - strlen (col_header) - 1);
5950  tables_col_name[SM_MAX_IDENTIFIER_LENGTH - 1] = '\0';
5951  db_string_free (db_name);
5952  db_name = NULL;
5953  }
5954 
5955  sub_query = parser_new_node (parser, PT_SELECT);
5956  if (sub_query == NULL)
5957  {
5958  return NULL;
5959  }
5960 
5961  /* ------ SELECT list ------- */
5962  pt_add_name_col_to_sel_list (parser, sub_query, "C.class_name", tables_col_name);
5963 
5964  /* ------ SELECT ... FROM ------- */
5965  /* db_class is a view on the _db_class table; we are selecting from the view, to avoid checking the authorization as
5966  * this check is already performed by the view */
5967  from_item = pt_add_table_name_to_from_list (parser, sub_query, "db_class", "C", DB_AUTH_SELECT);
5968 
5969  /* ------ SELECT ... WHERE ------- */
5970  /* create item for "WHERE is_system_class = 'NO'" */
5971  where_item = pt_make_pred_name_string_val (parser, PT_EQ, "is_system_class", "NO");
5972  sub_query->info.query.q.select.where = parser_append_node (where_item, sub_query->info.query.q.select.where);
5973 
5974  if (is_full_syntax)
5975  {
5976  /* SHOW FULL : add second column : 'BASE TABLE' or 'VIEW' */
5977  PT_NODE *eq_node = NULL;
5978  PT_NODE *if_node = NULL;
5979 
5980  /* create IF ( class_type = 'CLASS', 'BASE TABLE', 'VIEW') */
5981  eq_node = pt_make_pred_name_string_val (parser, PT_EQ, "class_type", "CLASS");
5982  if_node = pt_make_if_with_strings (parser, eq_node, "BASE TABLE", "VIEW", "Table_type");
5983 
5984  /* add IF to SELECT list, list should not be empty at this point */
5985  assert (sub_query->info.query.q.select.list != NULL);
5986 
5987  sub_query->info.query.q.select.list = parser_append_node (if_node, sub_query->info.query.q.select.list);
5988  }
5989 
5990  /* done with subquery, create the enclosing query : SELECT * from ( SELECT .... ) show_tables; */
5991 
5992  node = pt_make_outer_select_for_show_stmt (parser, sub_query, "show_tables");
5993  if (node == NULL)
5994  {
5995  return NULL;
5996  }
5997 
5998  {
5999  /* add ORDER BY */
6000  PT_NODE *order_by_item = NULL;
6001 
6002  assert (node->info.query.order_by == NULL);
6003  /* By Tables_in_<db_name> */
6004  order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC);
6005  node->info.query.order_by = parser_append_node (order_by_item, node->info.query.order_by);
6006  }
6007 
6008  if (like_or_where_expr != NULL)
6009  {
6010  if (like_where_syntax == 1)
6011  {
6012  /* make LIKE */
6013  where_item = pt_make_like_col_expr (parser, like_or_where_expr, tables_col_name);
6014  }
6015  else
6016  {
6017  /* WHERE */
6018  assert (like_where_syntax == 2);
6019  where_item = like_or_where_expr;
6020  }
6021 
6022  node->info.query.q.select.where = parser_append_node (where_item, node->info.query.q.select.where);
6023  }
6024  else
6025  {
6026  assert (like_where_syntax == 0);
6027  }
6028 
6029  return node;
6030 }
6031 
6032 /*
6033  * check_arg_valid() - check argument type and set error code if not valid
6034  *
6035  * return: true - valid, false - not valid, semantic check error will set when return false.
6036  * parser(in):
6037  * arg_meta(in): argument validation rule
6038  * arg_num(in): argument sequence
6039  * val(in): argument value node
6040  */
6041 static bool
6042 check_arg_valid (PARSER_CONTEXT * parser, const SHOWSTMT_NAMED_ARG * arg_meta, int arg_num, PT_NODE * val)
6043 {
6044  bool valid = false;
6045 
6046  switch (arg_meta->type)
6047  {
6048  case AVT_INTEGER:
6049  if (PT_IS_VALUE_NODE (val) && val->type_enum == PT_TYPE_INTEGER)
6050  {
6051  valid = true;
6052  }
6053  else if (arg_meta->optional && PT_IS_NULL_NODE (val))
6054  {
6055  valid = true;
6056  }
6057 
6058  if (!valid)
6059  {
6060  /* expect unsigned integer value in here */
6062  "positive integer value", arg_num);
6063  }
6064  break;
6065 
6066  case AVT_STRING:
6067  if (PT_IS_VALUE_NODE (val) && val->type_enum == PT_TYPE_CHAR)
6068  {
6069  valid = true;
6070  }
6071  else if (arg_meta->optional && PT_IS_NULL_NODE (val))
6072  {
6073  valid = true;
6074  }
6075 
6076  if (!valid)
6077  {
6078  /* expect string value in here */
6080  arg_num);
6081  }
6082  break;
6083 
6084  case AVT_IDENTIFIER:
6085  if (PT_IS_NAME_NODE (val))
6086  {
6087  valid = true;
6088  }
6089  else if (arg_meta->optional && PT_IS_NULL_NODE (val))
6090  {
6091  valid = true;
6092  }
6093 
6094  if (!valid)
6095  {
6096  /* expect identifier in here */
6098  arg_num);
6099  }
6100  break;
6101 
6102  default:
6103  assert (0);
6104  }
6105 
6106  return valid;
6107 }
6108 
6109 /*
6110  * pt_resolve_showstmt_args_unnamed() -
6111  * do semantic check for unnamed arguments by specified meta data
6112  * from SHOWSTMT_NAMED_ARG.
6113  *
6114  * return: newly build node (PT_NODE) for arguments
6115  * parser(in): Parser context
6116  * arg_infos(in): array for meta data of argument
6117  * arg_info_count(in): array count of arg_infos
6118  * arg_infos(in): argument node to be processed
6119  */
6120 static PT_NODE *
6121 pt_resolve_showstmt_args_unnamed (PARSER_CONTEXT * parser, const SHOWSTMT_NAMED_ARG * arg_infos, int arg_info_count,
6122  PT_NODE * args)
6123 {
6124  int i;
6125  PT_NODE *arg, *id_string;
6126  PT_NODE *prev = NULL, *head = NULL;
6127 
6128  if (arg_info_count == 0)
6129  {
6130  return args;
6131  }
6132 
6133  /* process each argument by meta information */
6134  i = 0;
6135  arg = args;
6136 
6137  for (; i < arg_info_count && arg != NULL; i++, arg = arg->next)
6138  {
6139  if (!check_arg_valid (parser, &arg_infos[i], i + 1, arg))
6140  {
6141  goto error;
6142  }
6143 
6144  if (arg_infos[i].type == AVT_IDENTIFIER)
6145  {
6146  /* replace identifier node with string value node */
6147  id_string = pt_make_string_value (parser, arg->info.name.original);
6148  if (id_string == NULL)
6149  {
6150  goto error;
6151  }
6152 
6153  id_string->next = arg->next;
6154  arg = id_string;
6155  }
6156 
6157  if (prev == NULL)
6158  {
6159  head = arg;
6160  }
6161  else
6162  {
6163  prev->next = arg;
6164  }
6165 
6166  prev = arg;
6167  }
6168 
6169  if (arg != NULL)
6170  {
6171  /* too many arguments, n-th argument is not needed */
6173  goto error;
6174  }
6175 
6176  if (i < arg_info_count)
6177  {
6178  /* too few arguments */
6180  goto error;
6181  }
6182 
6183  return head;
6184 
6185 error:
6186  return NULL;
6187 }
6188 
6189 /*
6190  * pt_resolve_showstmt_args_named() -
6191  * do semantic check for named arguments by specified meta data
6192  * from SHOWSTMT_NAMED_ARG.
6193  *
6194  * return: newly build node (PT_NODE) for arguments
6195  * parser(in): Parser context
6196  * arg_infos(in): array for meta data of argument
6197  * arg_info_count(in): array count of arg_infos
6198  * arg_infos(in): argument node to be processed
6199  */
6200 static PT_NODE *
6201 pt_resolve_showstmt_args_named (PARSER_CONTEXT * parser, const SHOWSTMT_NAMED_ARG * arg_infos, int arg_info_count,
6202  PT_NODE * args)
6203 {
6204  int i;
6205  bool found = false;
6206  PT_NODE *name_node, *value_node;
6207  PT_NODE *prev = NULL, *res = NULL;
6208  PT_NODE *arg = NULL;
6209 
6210  if (arg_info_count == 0)
6211  {
6212  return args;
6213  }
6214 
6215  for (i = 0; i < arg_info_count; i++)
6216  {
6217  found = false;
6218  prev = NULL;
6219 
6220  for (arg = args; arg != NULL; arg = arg->next)
6221  {
6222  assert (arg->node_type == PT_NAMED_ARG);
6223 
6224  name_node = arg->info.named_arg.name;
6225  value_node = arg->info.named_arg.value;
6226 
6227  if (strcasecmp (name_node->info.name.original, arg_infos[i].name) == 0)
6228  {
6229  if (!check_arg_valid (parser, &arg_infos[i], i + 1, value_node))
6230  {
6231  goto error;
6232  }
6233 
6234  if (arg_infos[i].type == AVT_IDENTIFIER)
6235  {
6236  /* replace identifier node with string value node */
6237  value_node = pt_make_string_value (parser, value_node->info.name.original);
6238  }
6239 
6240  res = parser_append_node (value_node, res);
6241  arg->info.named_arg.value = NULL;
6242 
6243  /* remove processed arg */
6244  if (prev)
6245  {
6246  prev->next = arg->next;
6247  }
6248  else
6249  {
6250  args = arg->next;
6251  }
6252  found = true;
6253  break;
6254  }
6255 
6256  prev = arg;
6257  }
6258 
6259  if (!found)
6260  {
6261  /* missing argument */
6262  PT_ERRORmf (parser, args, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_MISSING_ARGUMENT, arg_infos[i].name);
6263  goto error;
6264  }
6265  }
6266 
6267  /* all argument should be processed and nothing left */
6268  if (args != NULL)
6269  {
6270  /* unknown argument */
6273  goto error;
6274  }
6275 
6276  return res;
6277 
6278 error:
6279  return NULL;
6280 }
6281 
6282 /*
6283  * pt_make_query_showstmt () - builds the query for SHOW statement
6284  *
6285  * return: newly built node (PT_NODE), NULL if construction fails
6286  * parser(in): Parser context
6287  * type (int): show statement type
6288  * arg (in): show statement arguments
6289  *
6290  * Notes: make query as:
6291  *
6292  * SELECT *
6293  * FROM (pt_showstmt_info(type, args))
6294  * [WHERE expr]
6295  * [ORDER BY sort_col asc_or_desc]
6296  *
6297  */
6298 PT_NODE *
6299 pt_make_query_showstmt (PARSER_CONTEXT * parser, unsigned int type, PT_NODE * args, int like_where_syntax,
6300  PT_NODE * like_or_where_expr)
6301 {
6302  const SHOWSTMT_METADATA *meta = NULL;
6303  const SHOWSTMT_COLUMN_ORDERBY *orderby = NULL;
6304  int num_orderby;
6305  PT_NODE *query = NULL;
6306  PT_NODE *value, *from_item, *showstmt_info;
6307  PT_NODE *order_by_item;
6308  int i;
6309 
6310  /* get show column info */
6311  meta = showstmt_get_metadata ((SHOWSTMT_TYPE) type);
6312 
6313  if (meta->only_for_dba)
6314  {
6316  {
6318  return NULL;
6319  }
6320  }
6321 
6322  orderby = meta->orderby;
6323  num_orderby = meta->num_orderby;
6324 
6325  query = parser_new_node (parser, PT_SELECT);
6326  if (query == NULL)
6327  {
6328  return NULL;
6329  }
6330 
6332 
6333  value = parser_new_node (parser, PT_VALUE);
6334  if (value == NULL)
6335  {
6336  goto error;
6337  }
6338  value->type_enum = PT_TYPE_STAR;
6339  query->info.query.q.select.list = parser_append_node (value, query->info.query.q.select.list);
6340 
6341  showstmt_info = parser_new_node (parser, PT_SHOWSTMT);
6342  if (showstmt_info == NULL)
6343  {
6344  goto error;
6345  }
6346  showstmt_info->info.showstmt.show_type = (SHOWSTMT_TYPE) type;
6347 
6348  if (meta->args != NULL)
6349  {
6350  if (meta->args[0].name == NULL)
6351  {
6352  showstmt_info->info.showstmt.show_args =
6353  pt_resolve_showstmt_args_unnamed (parser, meta->args, meta->arg_size, args);
6354  }
6355  else
6356  {
6357  showstmt_info->info.showstmt.show_args =
6358  pt_resolve_showstmt_args_named (parser, meta->args, meta->arg_size, args);
6359  }
6360  if (showstmt_info->info.showstmt.show_args == NULL)
6361  {
6362  goto error;
6363  }
6364  }
6365 
6366  /* add to FROM an empty entity, the entity will be populated later */
6367  from_item = pt_add_table_name_to_from_list (parser, query, NULL, NULL, DB_AUTH_NONE);
6368  if (from_item == NULL)
6369  {
6370  goto error;
6371  }
6372  from_item->info.spec.derived_table = showstmt_info;
6374  from_item->info.spec.meta_class = PT_MISC_NONE;
6375  from_item->info.spec.join_type = PT_JOIN_NONE;
6376 
6377  if (like_or_where_expr != NULL)
6378  {
6379  PT_NODE *where_item = NULL;
6380 
6381  if (like_where_syntax == 1)
6382  {
6383  /* there would be least one column */
6384  assert (meta->num_cols > 0);
6385  where_item = pt_make_like_col_expr (parser, like_or_where_expr, meta->cols[0].name);
6386  }
6387  else
6388  {
6389  assert (like_where_syntax == 2);
6390  where_item = like_or_where_expr;
6391  }
6392 
6393  query->info.query.q.select.where = parser_append_node (where_item, query->info.query.q.select.where);
6394  }
6395  else
6396  {
6397  assert (like_where_syntax == 0);
6398  }
6399 
6400  for (i = 0; i < num_orderby; i++)
6401  {
6402  order_by_item = pt_make_sort_spec_with_number (parser, orderby[i].pos, orderby[i].asc ? PT_ASC : PT_DESC);
6403  if (order_by_item == NULL)
6404  {
6405  goto error;
6406  }
6407  query->info.query.order_by = parser_append_node (order_by_item, query->info.query.order_by);
6408  }
6409  return query;
6410 
6411 error:
6412  if (query != NULL)
6413  {
6414  parser_free_tree (parser, query);
6415  }
6416 
6417  return NULL;
6418 }
6419 
6420 /*
6421  * pt_make_query_show_columns() - builds the query for SHOW COLUMNS
6422  *
6423  * return: newly built node (PT_NODE), NULL if construnction fails
6424  * parser(in): Parser context
6425  * original_cls_id(in): node (PT_NAME) containing name of class
6426  *
6427  * SELECT Field AS Field,
6428  * Type AS Type
6429  * [Collation AS Collation]
6430  * Null AS Null
6431  * Key AS Key
6432  * Default AS Default
6433  * Extra AS Extra
6434  * [Comment AS Comment]
6435  * FROM
6436  * (SELECT 0 AS Attr_Type,
6437  * 0 AS Def_Order
6438  * "" AS Field,
6439  * 0 AS Type,
6440  * ["" AS Collation]
6441  * "" AS Null,
6442  * 0 AS Key,
6443  * "" AS Default,
6444  * "" AS Extra,
6445  * ["" AS Comment]
6446  * FROM <table> ORDER BY 3, 5)
6447  * [LIKE 'pattern' | WHERE expr];
6448  *
6449  * like_where_syntax(in): indicator of presence for LIKE or WHERE clauses in
6450  * SHOW statement. Values : 0 = none of LIKE or WHERE,
6451  * 1 = contains LIKE, 2 = contains WHERE
6452  * like_or_where_expr(in): node expression supplied as condition (in WHERE)
6453  * or RHS for LIKE
6454  *
6455  * Note : Order is defined by: attr_type (shared attributes first, then
6456  * class attributes, then normal attributes), order of definition in
6457  * table
6458  * [ ] -> optional fields controlled by 'is_show_full' argument
6459  * Note : At execution, all empty fields from inner query will be replaced by
6460  * values that will be read from class schema
6461  */
6462 PT_NODE *
6463 pt_make_query_show_columns (PARSER_CONTEXT * parser, PT_NODE * original_cls_id, int like_where_syntax,
6464  PT_NODE * like_or_where_expr, int is_show_full)
6465 {
6466  PT_NODE *from_item = NULL;
6467  PT_NODE *order_by_item = NULL;
6468  PT_NODE *sub_query = NULL;
6469  PT_NODE *outer_query = NULL;
6470  char lower_table_name[DB_MAX_IDENTIFIER_LENGTH];
6471  PT_NODE *value = NULL, *value_list = NULL;
6472  DB_VALUE db_valuep[10];
6473  const char **psubquery_aliases = NULL, **pquery_names = NULL, **pquery_aliases = NULL;
6474  int subquery_list_size = is_show_full ? 10 : 8;
6475  int query_list_size = subquery_list_size - 2;
6476 
6477  const char *subquery_aliases[] = { "Attr_Type", "Def_Order", "Field", "Type", "Null", "Key", "Default",
6478  "Extra"
6479  };
6480  const char *subquery_full_aliases[] = { "Attr_Type", "Def_Order", "Field", "Type", "Collation", "Null",
6481  "Key", "Default", "Extra", "Comment"
6482  };
6483 
6484  const char *query_names[] = { "Field", "Type", "Null", "Key", "Default", "Extra" };
6485 
6486  const char *query_aliases[] = { "Field", "Type", "Null", "Key", "Default", "Extra" };
6487 
6488  const char *query_full_names[] = { "Field", "Type", "Collation", "Null", "Key", "Default", "Extra",
6489  "Comment"
6490  };
6491 
6492  const char *query_full_aliases[] = { "Field", "Type", "Collation", "Null", "Key", "Default", "Extra",
6493  "Comment"
6494  };
6495 
6496  int i = 0;
6497 
6498  assert (original_cls_id != NULL);
6499  assert (original_cls_id->node_type == PT_NAME);
6500 
6501  sub_query = parser_new_node (parser, PT_SELECT);
6502  if (sub_query == NULL)
6503  {
6504  return NULL;
6505  }
6506 
6507  if (is_show_full)
6508  {
6510  }
6511  else
6512  {
6514  }
6515 
6516  intl_identifier_lower (original_cls_id->info.name.original, lower_table_name);
6517 
6518  db_make_int (db_valuep + 0, 0);
6519  db_make_int (db_valuep + 1, 0);
6520  for (i = 2; i < subquery_list_size; i++)
6521  {
6524  }
6525 
6526  psubquery_aliases = is_show_full ? subquery_full_aliases : subquery_aliases;
6527  pquery_names = is_show_full ? query_full_names : query_names;
6528  pquery_aliases = is_show_full ? query_full_aliases : query_aliases;
6529 
6530  for (i = 0; i < subquery_list_size; i++)
6531  {
6532  value = pt_dbval_to_value (parser, db_valuep + i);
6533  if (value == NULL)
6534  {
6535  goto error;
6536  }
6537  value->alias_print = pt_append_string (parser, NULL, psubquery_aliases[i]);
6538  value_list = parser_append_node (value, value_list);
6539  }
6540 
6541  sub_query->info.query.q.select.list = value_list;
6542  value_list = NULL;
6543 
6544  from_item = pt_add_table_name_to_from_list (parser, sub_query, lower_table_name, NULL, DB_AUTH_NONE);
6545  if (from_item == NULL)
6546  {
6547  goto error;
6548  }
6549 
6550  if (pt_make_outer_select_for_show_columns (parser, sub_query, NULL, pquery_names, pquery_aliases, query_list_size,
6551  is_show_full, &outer_query) != NO_ERROR)
6552  {
6553  goto error;
6554  }
6555 
6556  order_by_item = pt_make_sort_spec_with_identifier (parser, "Attr_Type", PT_DESC);
6557  if (order_by_item == NULL)
6558  {
6559  goto error;
6560  }
6561  outer_query->info.query.order_by = parser_append_node (order_by_item, outer_query->info.query.order_by);
6562 
6563  order_by_item = pt_make_sort_spec_with_identifier (parser, "Def_Order", PT_ASC);
6564  if (order_by_item == NULL)
6565  {
6566  goto error;
6567  }
6568  outer_query->info.query.order_by = parser_append_node (order_by_item, outer_query->info.query.order_by);
6569 
6570  /* no ORDER BY to outer SELECT */
6571  /* add LIKE or WHERE from SHOW , if present */
6572  if (like_or_where_expr != NULL)
6573  {
6574  PT_NODE *where_item = NULL;
6575 
6576  if (like_where_syntax == 1)
6577  {
6578  /* LIKE token */
6579  where_item = pt_make_like_col_expr (parser, like_or_where_expr, "Field");
6580  }
6581  else
6582  {
6583  /* WHERE token */
6584  assert (like_where_syntax == 2);
6585  where_item = like_or_where_expr;
6586  }
6587 
6588  outer_query->info.query.q.select.where = parser_append_node (where_item, outer_query->info.query.q.select.where);
6589  }
6590  else
6591  {
6592  assert (like_where_syntax == 0);
6593  }
6594 
6595  return outer_query;
6596 
6597 error:
6598  if (outer_query)
6599  {
6600  parser_free_tree (parser, outer_query);
6601  }
6602  else if (sub_query)
6603  {
6604  parser_free_tree (parser, sub_query);
6605  }
6606 
6607  if (value_list)
6608  {
6609  parser_free_tree (parser, value_list);
6610  }
6611 
6612  return NULL;
6613 }
6614 
6615 /*
6616  * pt_help_show_create_table() help to generate create table string.
6617  * parser(in) : Parser context
6618  * table_name(in): table name node
6619  * strbuf(out) : string of create table.
6620  */
6621 static void
6623 {
6624  DB_OBJECT *class_op;
6625  int is_class = 0;
6626 
6627  /* look up class in all schema's */
6628  class_op = sm_find_class (table_name->info.name.original);
6629  if (class_op == NULL)
6630  {
6631  if (er_errid () != NO_ERROR)
6632  {
6633  PT_ERRORc (parser, table_name, er_msg ());
6634  }
6635  return;
6636  }
6637 
6638  is_class = db_is_class (class_op);
6639  if (is_class < 0)
6640  {
6641  if (er_errid () != NO_ERROR)
6642  {
6643  PT_ERRORc (parser, table_name, er_msg ());
6644  }
6645  return;
6646  }
6647  else if (!is_class)
6648  {
6650  table_name->info.name.original, pt_show_misc_type (PT_CLASS));
6651  }
6652 
6653  object_printer obj_print (strbuf);
6654  obj_print.describe_class (class_op);
6655 
6656  if (strbuf.len () == 0)
6657  {
6658  int error = er_errid ();
6659 
6660  assert (error != NO_ERROR);
6661 
6662  if (error == ER_AU_SELECT_FAILURE)
6663  {
6665  db_get_class_name (class_op));
6666  }
6667  else
6668  {
6669  PT_ERRORc (parser, table_name, er_msg ());
6670  }
6671  }
6672 }
6673 
6674 /*
6675  * pt_make_query_show_create_table() builds the query used for SHOW CREATE
6676  * TABLE
6677  *
6678  * SELECT 'table_name' as TABLE, 'create table ...' as CREATE TABLE
6679  * FROM db_root
6680  *
6681  * return string of create table.
6682  * parser(in) : Parser context
6683  * table_name(in): table name node
6684  */
6685 PT_NODE *
6687 {
6688  PT_NODE *select;
6689 
6690  assert (table_name != NULL);
6691  assert (table_name->node_type == PT_NAME);
6692 
6693  parser_block_allocator alloc (parser);
6694  string_buffer strbuf (alloc);
6695 
6696  pt_help_show_create_table (parser, table_name, strbuf);
6697  if (strbuf.len () == 0)
6698  {
6699  return NULL;
6700  }
6701 
6702  select = parser_new_node (parser, PT_SELECT);
6703  if (select == NULL)
6704  {
6705  return NULL;
6706  }
6707 
6709 
6710  /*
6711  * SELECT 'table_name' as TABLE, 'create table ...' as CREATE TABLE
6712  * FROM db_root
6713  */
6714  pt_add_string_col_to_sel_list (parser, select, table_name->info.name.original, "TABLE");
6715  pt_add_string_col_to_sel_list (parser, select, strbuf.get_buffer (), "CREATE TABLE");
6716  pt_add_table_name_to_from_list (parser, select, "dual", NULL, DB_AUTH_SELECT);
6717  return select;
6718 }
6719 
6720 /*
6721  * pt_make_query_show_create_view() - builds the query used for SHOW CREATE
6722  * VIEW
6723  *
6724  * SELECT * FROM
6725  * (SELECT IF( VC.vclass_name = '',
6726  * (SELECT COUNT(*) FROM <view_name> LIMIT 1),
6727  * VC.vclass_name )
6728  * AS View_,
6729  * IF( VC.comment IS NULL or VC.comment = '',
6730  * VC.vclass_def,
6731  * VC.vclass_def + ' COMMENT=''' + VC.comment + '''' )
6732  * AS Create_View
6733  * FROM db_vclass VC
6734  * WHERE VC.vclass_name=<view_name>)
6735  * show_create_view;
6736  *
6737  * Note : The first column in query (name of view = VC.vclass_name) is wrapped
6738  * with IF, in order to accomodate a dummy query, which has the role to
6739  * trigger the apropiate error if the view doesn't exist or the user
6740  * doesn't have the privilege to SELECT it; the condition in IF
6741  * expression (VC.vclass_name = '') is supposed to always evaluate to
6742  * false (class name cannot be empty), in order for the query to always
6743  * print what it is supposed to (view name); second purpose of the
6744  * condition is to avoid optimisation (otherwise the IF will evalute to
6745  * <VC.vclass_name>)
6746  *
6747  * return: newly build node (PT_NODE), NULL if construnction fails
6748  * parser(in): Parser context
6749  * view_identifier(in): node identifier for view
6750  */
6751 PT_NODE *
6753 {
6754  PT_NODE *node = NULL;
6755  PT_NODE *from_item = NULL;
6756  char lower_view_name[DB_MAX_IDENTIFIER_LENGTH];
6757 
6758  assert (view_identifier != NULL);
6759  assert (view_identifier->node_type == PT_NAME);
6760 
6761  node = parser_new_node (parser, PT_SELECT);
6762  if (node == NULL)
6763  {
6764  return NULL;
6765  }
6766 
6767  intl_identifier_lower (view_identifier->info.name.original, lower_view_name);
6768 
6769  /* ------ SELECT list ------- */
6770  {
6771  /* View name : IF( VC.vclass_name = '', (SELECT COUNT(*) FROM <view_name> LIMIT 1), VC.vclass_name ) AS View */
6772  PT_NODE *if_true_node = NULL;
6773  PT_NODE *if_false_node = NULL;
6774  PT_NODE *pred = NULL;
6775  PT_NODE *view_field = NULL;
6776 
6777  if_true_node = pt_make_dummy_query_check_table (parser, lower_view_name);
6778  if_false_node = pt_make_dotted_identifier (parser, "VC.vclass_name");
6779  pred = pt_make_pred_name_string_val (parser, PT_EQ, "VC.vclass_name", "");
6780 
6781  view_field = pt_make_if_with_expressions (parser, pred, if_true_node, if_false_node, "View");
6782  node->info.query.q.select.list = parser_append_node (view_field, node->info.query.q.select.list);
6783  }
6784 
6785  {
6786  /* Create View: IF( VC.comment IS NULL or VC.comment = '', VC.vclass_def, VC.vclass_def + ' COMMENT=''' +
6787  * VC.comment + '''' ) AS Create_View */
6788  PT_NODE *if_true_node = NULL;
6789  PT_NODE *if_false_node = NULL;
6790  PT_NODE *pred = NULL;
6791  PT_NODE *comment_node = NULL;
6792  PT_NODE *create_view_field = NULL;
6793  PT_NODE *lhs = NULL, *rhs = NULL;
6794 
6795  if_true_node = pt_make_dotted_identifier (parser, "VC.vclass_def");
6796 
6797  lhs = pt_make_pred_name_string_val (parser, PT_CONCAT, "VC.vclass_def", " comment='");
6798  rhs = pt_make_pred_name_string_val (parser, PT_CONCAT, "VC.comment", "'");
6799  if_false_node = parser_make_expression (parser, PT_CONCAT, lhs, rhs, NULL);
6800 
6801  comment_node = pt_make_dotted_identifier (parser, "VC.comment");
6802  lhs = parser_make_expression (parser, PT_IS_NULL, comment_node, NULL, NULL);
6803  rhs = pt_make_pred_name_string_val (parser, PT_EQ, "VC.comment", "");
6804  pred = parser_make_expression (parser, PT_OR, lhs, rhs, NULL);
6805 
6806  create_view_field = pt_make_if_with_expressions (parser, pred, if_true_node, if_false_node, "Create View");
6807 
6808  node->info.query.q.select.list = parser_append_node (create_view_field, node->info.query.q.select.list);
6809  }
6810 
6811  /* ------ SELECT ... FROM ------- */
6812  from_item = pt_add_table_name_to_from_list (parser, node, "db_vclass", "VC", DB_AUTH_SELECT);
6813 
6814  /* ------ SELECT ... WHERE ------- */
6815  {
6816  PT_NODE *where_item = NULL;
6817  where_item = pt_make_pred_name_string_val (parser, PT_EQ, "VC.vclass_name", lower_view_name);
6818 
6819  /* WHERE list should be empty */
6820  assert (node->info.query.q.select.where == NULL);
6821  node->info.query.q.select.where = parser_append_node (where_item, node->info.query.q.select.where);
6822  }
6823 
6824  return node;
6825 }
6826 
6827 PT_NODE *
6829 {
6830  PT_NODE **node = NULL;
6831  PT_NODE *show_node;
6832  const char *query =
6833  "(SELECT 'data_page_fetches' as [variable] , exec_stats('Num_data_page_fetches') as [value])"
6834  "UNION ALL (SELECT 'data_page_dirties' as [variable] , exec_stats('Num_data_page_dirties') as [value])"
6835  "UNION ALL (SELECT 'data_page_ioreads' as [variable] , exec_stats('Num_data_page_ioreads') as [value])"
6836  "UNION ALL (SELECT 'data_page_iowrites' as [variable] , exec_stats('Num_data_page_iowrites') as [value]);";
6837 
6838  /* parser ';' will empty and reset the stack of parser, this make the status machine be right for the next statement,
6839  * and avoid nested parser statement. */
6840  parser_parse_string (parser, ";");
6841 
6842  node = parser_parse_string_use_sys_charset (parser, query);
6843  if (node == NULL)
6844  {
6845  return NULL;
6846  }
6847 
6848  parser->flag.dont_collect_exec_stats = 1;
6849 
6850  show_node = pt_pop (parser);
6851  assert (show_node == node[0]);
6852 
6853  return node[0];
6854 }
6855 
6856 PT_NODE *
6858 {
6859  PT_NODE **node = NULL;
6860  PT_NODE *show_node;
6861  const char *query =
6862  "(SELECT 'file_creates' as [variable] , exec_stats('Num_file_creates') as [value])"
6863  "UNION ALL (SELECT 'file_removes' as [variable] , exec_stats('Num_file_removes') as [value])"
6864  "UNION ALL (SELECT 'file_ioreads' as [variable] , exec_stats('Num_file_ioreads') as [value])"
6865  "UNION ALL (SELECT 'file_iowrites' as [variable] , exec_stats('Num_file_iowrites') as [value])"
6866  "UNION ALL (SELECT 'file_iosynches' as [variable] , exec_stats('Num_file_iosynches') as [value])"
6867  "UNION ALL (SELECT 'data_page_fetches' as [variable] , exec_stats('Num_data_page_fetches') as [value])"
6868  "UNION ALL (SELECT 'data_page_dirties' as [variable] , exec_stats('Num_data_page_dirties') as [value])"
6869  "UNION ALL (SELECT 'data_page_ioreads' as [variable] , exec_stats('Num_data_page_ioreads') as [value])"
6870  "UNION ALL (SELECT 'data_page_iowrites' as [variable] , exec_stats('Num_data_page_iowrites') as [value])"
6871  "UNION ALL (SELECT 'log_page_ioreads' as [variable] , exec_stats('Num_log_page_ioreads') as [value])"
6872  "UNION ALL (SELECT 'log_page_iowrites' as [variable] , exec_stats('Num_log_page_iowrites') as [value])"
6873  "UNION ALL (SELECT 'log_append_records' as [variable] , exec_stats('Num_log_append_records') as [value])"
6874  "UNION ALL (SELECT 'log_archives' as [variable] , exec_stats('Num_log_archives') as [value])"
6875  "UNION ALL (SELECT 'log_start_checkpoints' as [variable] , exec_stats('Num_log_start_checkpoints') as [value])"
6876  "UNION ALL (SELECT 'log_end_checkpoints' as [variable] , exec_stats('Num_log_end_checkpoints') as [value])"
6877  "UNION ALL (SELECT 'log_wals' as [variable] , exec_stats('Num_log_wals') as [value])"
6878  "UNION ALL (SELECT 'page_locks_acquired' as [variable] , exec_stats('Num_page_locks_acquired') as [value])"
6879  "UNION ALL (SELECT 'object_locks_acquired' as [variable] , exec_stats('Num_object_locks_acquired') as [value])"
6880  "UNION ALL (SELECT 'page_locks_converted' as [variable] , exec_stats('Num_page_locks_converted') as [value])"
6881  "UNION ALL (SELECT 'object_locks_converted' as [variable] , exec_stats('Num_object_locks_converted') as [value])"
6882  "UNION ALL (SELECT 'page_locks_re-requested' as [variable] , exec_stats('Num_page_locks_re-requested') as [value])"
6883  "UNION ALL (SELECT 'object_locks_re-requested' as [variable] , exec_stats('Num_object_locks_re-requested') as [value])"
6884  "UNION ALL (SELECT 'page_locks_waits' as [variable] , exec_stats('Num_page_locks_waits') as [value])"
6885  "UNION ALL (SELECT 'object_locks_waits' as [variable] , exec_stats('Num_object_locks_waits') as [value])"
6886  "UNION ALL (SELECT 'tran_commits' as [variable] , exec_stats('Num_tran_commits') as [value])"
6887  "UNION ALL (SELECT 'tran_rollbacks' as [variable] , exec_stats('Num_tran_rollbacks') as [value])"
6888  "UNION ALL (SELECT 'tran_savepoints' as [variable] , exec_stats('Num_tran_savepoints') as [value])"
6889  "UNION ALL (SELECT 'tran_start_topops' as [variable] , exec_stats('Num_tran_start_topops') as [value])"
6890  "UNION ALL (SELECT 'tran_end_topops' as [variable] , exec_stats('Num_tran_end_topops') as [value])"
6891  "UNION ALL (SELECT 'tran_interrupts' as [variable] , exec_stats('Num_tran_interrupts') as [value])"
6892  "UNION ALL (SELECT 'btree_inserts' as [variable] , exec_stats('Num_btree_inserts') as [value])"
6893  "UNION ALL (SELECT 'btree_deletes' as [variable] , exec_stats('Num_btree_deletes') as [value])"
6894  "UNION ALL (SELECT 'btree_updates' as [variable] , exec_stats('Num_btree_updates') as [value])"
6895  "UNION ALL (SELECT 'btree_covered' as [variable] , exec_stats('Num_btree_covered') as [value])"
6896  "UNION ALL (SELECT 'btree_noncovered' as [variable] , exec_stats('Num_btree_noncovered') as [value])"
6897  "UNION ALL (SELECT 'btree_resumes' as [variable] , exec_stats('Num_btree_resumes') as [value])"
6898  "UNION ALL (SELECT 'btree_multirange_optimization' as [variable] , exec_stats('Num_btree_multirange_optimization') as [value])"
6899  "UNION ALL (SELECT 'btree_splits' as [variable] , exec_stats('Num_btree_splits') as [value])"
6900  "UNION ALL (SELECT 'btree_merges' as [variable] , exec_stats('Num_btree_merges') as [value])"
6901  "UNION ALL (SELECT 'query_selects' as [variable] , exec_stats('Num_query_selects') as [value])"
6902  "UNION ALL (SELECT 'query_inserts' as [variable] , exec_stats('Num_query_inserts') as [value])"
6903  "UNION ALL (SELECT 'query_deletes' as [variable] , exec_stats('Num_query_deletes') as [value])"
6904  "UNION ALL (SELECT 'query_updates' as [variable] , exec_stats('Num_query_updates') as [value])"
6905  "UNION ALL (SELECT 'query_sscans' as [variable] , exec_stats('Num_query_sscans') as [value])"
6906  "UNION ALL (SELECT 'query_iscans' as [variable] , exec_stats('Num_query_iscans') as [value])"
6907  "UNION ALL (SELECT 'query_lscans' as [variable] , exec_stats('Num_query_lscans') as [value])"
6908  "UNION ALL (SELECT 'query_setscans' as [variable] , exec_stats('Num_query_setscans') as [value])"
6909  "UNION ALL (SELECT 'query_methscans' as [variable] , exec_stats('Num_query_methscans') as [value])"
6910  "UNION ALL (SELECT 'query_nljoins' as [variable] , exec_stats('Num_query_nljoins') as [value])"
6911  "UNION ALL (SELECT 'query_mjoins' as [variable] , exec_stats('Num_query_mjoins') as [value])"
6912  "UNION ALL (SELECT 'query_objfetches' as [variable] , exec_stats('Num_query_objfetches') as [value])"
6913  "UNION ALL (SELECT 'query_holdable_cursors' as [variable] , exec_stats('Num_query_holdable_cursors') as [value])"
6914  "UNION ALL (SELECT 'sort_io_pages' as [variable] , exec_stats('Num_sort_io_pages') as [value])"
6915  "UNION ALL (SELECT 'sort_data_pages' as [variable] , exec_stats('Num_sort_data_pages') as [value])"
6916  "UNION ALL (SELECT 'network_requests' as [variable] , exec_stats('Num_network_requests') as [value])"
6917  "UNION ALL (SELECT 'adaptive_flush_pages' as [variable] , exec_stats('Num_adaptive_flush_pages') as [value])"
6918  "UNION ALL (SELECT 'adaptive_flush_log_pages' as [variable] , exec_stats('Num_adaptive_flush_log_pages') as [value])"
6919  "UNION ALL (SELECT 'adaptive_flush_max_pages' as [variable] , exec_stats('Num_adaptive_flush_max_pages') as [value])"
6920  "UNION ALL (SELECT 'prior_lsa_list_size' as [variable] , exec_stats('Num_prior_lsa_list_size') as [value])"
6921  "UNION ALL (SELECT 'prior_lsa_list_maxed' as [variable] , exec_stats('Num_prior_lsa_list_maxed') as [value])"
6922  "UNION ALL (SELECT 'prior_lsa_list_removed' as [variable] , exec_stats('Num_prior_lsa_list_removed') as [value])"
6923  "UNION ALL (SELECT 'heap_stats_bestspace_entries' as [variable] , exec_stats('Num_heap_stats_bestspace_entries') as [value])"
6924  "UNION ALL (SELECT 'heap_stats_bestspace_maxed' as [variable] , exec_stats('Num_heap_stats_bestspace_maxed') as [value])";
6925 
6926  /* parser ';' will empty and reset the stack of parser, this make the status machine be right for the next statement,
6927  * and avoid nested parser statement. */
6928  parser_parse_string (parser, ";");
6929 
6930  node = parser_parse_string_use_sys_charset (parser, query);
6931  if (node == NULL)
6932  {
6933  return NULL;
6934  }
6935 
6936  show_node = pt_pop (parser);
6937  assert (show_node == node[0]);
6938  parser->flag.dont_collect_exec_stats = 1;
6939 
6940  return node[0];
6941 }
6942 
6943 /*
6944  * pt_make_query_user_groups() - builds the query to return the SET of DB
6945  * groups to which a DB user belongs to.
6946  *
6947  * SELECT SUM(SET{t.g.name})
6948  * FROM db_user U, TABLE(groups) AS t(g)
6949  * WHERE U.name=<user_name>
6950  *
6951  *
6952  * return: newly build node (PT_NODE), NULL if construnction fails
6953  * parser(in): Parser context
6954  * user_name(in): DB user name
6955  */
6956 static PT_NODE *
6957 pt_make_query_user_groups (PARSER_CONTEXT * parser, const char *user_name)
6958 {
6959  PT_NODE *query = NULL;
6960  PT_NODE *sel_item = NULL;
6961  PT_NODE *from_item = NULL;
6962 
6963  assert (user_name != NULL);
6964 
6965  query = parser_new_node (parser, PT_SELECT);
6966  if (query == NULL)
6967  {
6968  return NULL;
6969  }
6970 
6971  /* SELECT list : */
6972  /* SUM(SET{t.g.name}) */
6973  {
6974  PT_NODE *group_name_identifier = NULL;
6975  PT_NODE *set_of_group_name = NULL;
6976 
6977  group_name_identifier = pt_make_dotted_identifier (parser, "t.g.name");
6978  set_of_group_name = parser_new_node (parser, PT_VALUE);
6979  if (set_of_group_name == NULL)
6980  {
6981  return NULL;
6982  }
6983  set_of_group_name->info.value.data_value.set = group_name_identifier;
6984  set_of_group_name->type_enum = PT_TYPE_SET;
6985 
6986  sel_item = parser_new_node (parser, PT_FUNCTION);
6987  if (sel_item == NULL)
6988  {
6989  return NULL;
6990  }
6991 
6992  sel_item->info.function.function_type = PT_SUM;
6993  sel_item->info.function.all_or_distinct = PT_ALL;
6994  sel_item->info.function.arg_list = parser_append_node (set_of_group_name, sel_item->info.function.arg_list);
6995  }
6996  query->info.query.q.select.list = parser_append_node (sel_item, query->info.query.q.select.list);
6997 
6998  /* FROM : */
6999  /* db_user U */
7000  from_item = pt_add_table_name_to_from_list (parser, query, "db_user", "U", DB_AUTH_SELECT);
7001 
7002 
7003  {
7004  /* TABLE(groups) AS t(g) */
7005  PT_NODE *table_col = NULL;
7006  PT_NODE *alias_table = NULL;
7007  PT_NODE *alias_col = NULL;
7008 
7009  from_item = pt_add_table_name_to_from_list (parser, query, NULL, NULL, DB_AUTH_SELECT);
7010 
7011  if (from_item == NULL)
7012  {
7013  return NULL;
7014  }
7015  table_col = pt_name (parser, "groups");
7016  alias_table = pt_name (parser, "t");
7017  alias_col = pt_name (parser, "g");
7018  if (table_col == NULL || alias_table == NULL || alias_col == NULL)
7019  {
7020  return NULL;
7021  }
7022  table_col->info.name.meta_class = PT_NORMAL;
7023 
7024  from_item->info.spec.derived_table = table_col;
7025  from_item->info.spec.meta_class = PT_MISC_NONE;
7026  from_item->info.spec.range_var = alias_table;
7027  from_item->info.spec.as_attr_list = alias_col;
7029  from_item->info.spec.join_type = PT_JOIN_NONE;
7030  }
7031  /* WHERE : */
7032  {
7033  /* U.name = <user_name> */
7034  PT_NODE *where_item = NULL;
7035 
7036  where_item = pt_make_pred_name_string_val (parser, PT_EQ, "U.name", user_name);
7037  /* WHERE list should be empty */
7038  assert (query->info.query.q.select.where == NULL);
7039  query->info.query.q.select.where = parser_append_node (where_item, query->info.query.q.select.where);
7040  }
7041 
7042  return query;
7043 }
7044 
7045 /*
7046  * pt_make_query_show_grants_curr_usr() - builds the query used for
7047  * SHOW GRANTS for current user
7048  *
7049  * return: newly build node (PT_NODE), NULL if construnction fails
7050  * parser(in): Parser context
7051  */
7052 PT_NODE *
7054 {
7055  const char *user_name = NULL;
7056  PT_NODE *node = NULL;
7057 
7058  user_name = au_user_name ();
7059  if (user_name == NULL)
7060  {
7061  return NULL;
7062  }
7063 
7064  node = pt_make_query_show_grants (parser, user_name);
7065 
7066  if (user_name != NULL)
7067  {
7068  db_string_free ((char *) user_name);
7069  }
7070  return node;
7071 }
7072 
7073 /*
7074  * pt_make_query_show_grants() - builds the query used for SHOW GRANTS for a
7075  * given user
7076  *
7077  * SELECT CONCAT ( 'GRANT ',
7078  * GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', '),
7079  * ' ON ' ,
7080  * AU.class_of.class_name,
7081  * ' TO ',
7082  * AU.grantee.name ,
7083  * IF (AU.is_grantable=1,
7084  * ' WITH GRANT OPTION',
7085  * '')
7086  * ) AS GRANTS
7087  * FROM db_class C, _db_auth AU
7088  * WHERE AU.class_of.class_name = C.class_name AND
7089  * C.is_system_class='NO' AND
7090  * ( AU.grantee.name=<user_name> OR
7091  * SET{ AU.grantee.name} SUBSETEQ (
7092  * SELECT SUM(SET{t.g.name})
7093  * FROM db_user U, TABLE(groups) AS t(g)
7094  * WHERE U.name=<user_name>)
7095  * )
7096  * GROUP BY AU.grantee, AU.class_of, AU.is_grantable
7097  * ORDER BY 1;
7098  *
7099  * Note : The purpose of GROUP BY is to group all the privilege by user,
7100  * table and the presence of 'WITH GRANT OPTION' flag. We output the
7101  * privileges for the user but also for all groups to which the user
7102  * belongs to : these privileges are shown in separate lines. Multiple
7103  * privileges for the same table are displayed on the same line,
7104  * except when 'WITH GRANT OPTION' is present, case when these
7105  * privileges are displayed on another line.
7106  *
7107  * return: newly build node (PT_NODE), NULL if construnction fails
7108  * parser(in): Parser context
7109  * user_name(in): DB user name
7110  */
7111 PT_NODE *
7112 pt_make_query_show_grants (PARSER_CONTEXT * parser, const char *original_user_name)
7113 {
7114  PT_NODE *node = NULL;
7115  PT_NODE *from_item = NULL;
7116  PT_NODE *where_expr = NULL;
7117  PT_NODE *concat_node = NULL;
7118  PT_NODE *group_by_item = NULL;
7119  char user_name[SM_MAX_IDENTIFIER_LENGTH];
7120 
7121  assert (original_user_name != NULL);
7122  assert (strlen (original_user_name) < SM_MAX_IDENTIFIER_LENGTH);
7123 
7124  /* conversion to uppercase can cause <original_user_name> to double size, if internationalization is used : size
7125  * <user_name> accordingly */
7126  intl_identifier_upper (original_user_name, user_name);
7127 
7128  node = parser_new_node (parser, PT_SELECT);
7129  if (node == NULL)
7130  {
7131  return NULL;
7132  }
7133 
7135 
7136  /* ------ SELECT list ------- */
7137  /*
7138  * CONCAT ( 'GRANT ',
7139  * GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', '),
7140  * ' ON ' ,
7141  * AU.class_of.class_name,
7142  * ' TO ',
7143  * AU.grantee.name ,
7144  * IF (AU.is_grantable=1,
7145  * ' WITH GRANT OPTION',
7146  * '')
7147  * ) AS GRANTS
7148  */
7149  {
7150  PT_NODE *concat_arg_list = NULL;
7151  PT_NODE *concat_arg = NULL;
7152 
7153  concat_arg = pt_make_string_value (parser, "GRANT ");
7154  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7155 
7156  {
7157  /* GROUP_CONCAT(AU.auth_type ORDER BY 1 SEPARATOR ', ') */
7158  PT_NODE *group_concat_field = NULL;
7159  PT_NODE *group_concat_sep = NULL;
7160  PT_NODE *order_by_item = NULL;
7161 
7162  concat_arg = parser_new_node (parser, PT_FUNCTION);
7163  if (concat_arg == NULL)
7164  {
7165  return NULL;
7166  }
7167 
7169  concat_arg->info.function.all_or_distinct = PT_ALL;
7170 
7171  group_concat_field = pt_make_dotted_identifier (parser, "AU.auth_type");
7172  group_concat_sep = pt_make_string_value (parser, ", ");
7173  concat_arg->info.function.arg_list = parser_append_node (group_concat_sep, group_concat_field);
7174 
7175  /* add ORDER BY */
7176  assert (concat_arg->info.function.order_by == NULL);
7177 
7178  /* By 1 */
7179  order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC);
7180  concat_arg->info.function.order_by = order_by_item;
7181  }
7182  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7183 
7184  concat_arg = pt_make_string_value (parser, " ON ");
7185  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7186 
7187  concat_arg = pt_make_dotted_identifier (parser, "AU.class_of.class_name");
7188  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7189 
7190  concat_arg = pt_make_string_value (parser, " TO ");
7191  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7192 
7193  concat_arg = pt_make_dotted_identifier (parser, "AU.grantee.name");
7194  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7195 
7196  /* IF (AU.is_grantable=1, ' WITH GRANT OPTION','') */
7197  {
7198  PT_NODE *pred_for_if = NULL;
7199 
7200  pred_for_if = pt_make_pred_name_int_val (parser, PT_EQ, "AU.is_grantable", 1);
7201  concat_arg = pt_make_if_with_strings (parser, pred_for_if, " WITH GRANT OPTION", "", NULL);
7202  }
7203  concat_arg_list = parser_append_node (concat_arg, concat_arg_list);
7204 
7205  concat_node = parser_keyword_func ("concat", concat_arg_list);
7206  if (concat_node == NULL)
7207  {
7208  return NULL;
7209  }
7210 
7211  {
7212  char col_alias[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
7213  const char *const col_header = "Grants for ";
7214 
7215  strcpy (col_alias, col_header);
7216  strncat (col_alias, user_name, SM_MAX_IDENTIFIER_LENGTH - strlen (col_header) - 1);
7217  col_alias[SM_MAX_IDENTIFIER_LENGTH - 1] = '\0';
7218  concat_node->alias_print = pt_append_string (parser, NULL, col_alias);
7219  }
7220  }
7221  node->info.query.q.select.list = parser_append_node (concat_node, node->info.query.q.select.list);
7222 
7223  /* ------ SELECT ... FROM ------- */
7224  from_item = pt_add_table_name_to_from_list (parser, node, "db_class", "C", DB_AUTH_SELECT);
7225 
7226  from_item = pt_add_table_name_to_from_list (parser, node, "_db_auth", "AU", DB_AUTH_SELECT);
7227 
7228  /* ------ SELECT ... WHERE ------- */
7229  /*
7230  * WHERE AU.class_of.class_name = C.class_name AND
7231  * C.is_system_class='NO' AND
7232  * ( AU.grantee.name=<user_name> OR
7233  * SET{ AU.grantee.name} SUBSETEQ ( <query_user_groups> )
7234  * )
7235  */
7236  {
7237  /* AU.class_of.class_name = C.class_name */
7238  PT_NODE *where_item = NULL;
7239 
7240  where_item = pt_make_pred_with_identifiers (parser, PT_EQ, "AU.class_of.class_name", "C.class_name");
7241  where_expr = where_item;
7242  }
7243  {
7244  /* C.is_system_class = 'NO' */
7245  PT_NODE *where_item = NULL;
7246 
7247  where_item = pt_make_pred_name_string_val (parser, PT_EQ, "C.is_system_class", "NO");
7248  /* <where_expr> = <where_expr> AND <where_item> */
7249  where_expr = parser_make_expression (parser, PT_AND, where_expr, where_item, NULL);
7250  }
7251  {
7252  PT_NODE *user_cond = NULL;
7253  PT_NODE *group_cond = NULL;
7254  /* AU.grantee.name = <user_name> */
7255  user_cond = pt_make_pred_name_string_val (parser, PT_EQ, "AU.grantee.name", user_name);
7256 
7257  /* SET{ AU.grantee.name} SUBSETEQ ( <query_user_groups> */
7258  {
7259  /* query to get a SET of user's groups */
7260  PT_NODE *query_user_groups = NULL;
7261  PT_NODE *set_of_grantee_name = NULL;
7262 
7263  {
7264  /* SET{ AU.grantee.name} */
7265  PT_NODE *grantee_name_identifier = NULL;
7266 
7267  grantee_name_identifier = pt_make_dotted_identifier (parser, "AU.grantee.name");
7268  set_of_grantee_name = parser_new_node (parser, PT_VALUE);
7269  if (set_of_grantee_name == NULL)
7270  {
7271  return NULL;
7272  }
7273  set_of_grantee_name->info.value.data_value.set = grantee_name_identifier;
7274  set_of_grantee_name->type_enum = PT_TYPE_SET;
7275  }
7276 
7277  query_user_groups = pt_make_query_user_groups (parser, user_name);
7278 
7279  group_cond = parser_make_expression (parser, PT_SUBSETEQ, set_of_grantee_name, query_user_groups, NULL);
7280  }
7281  user_cond = parser_make_expression (parser, PT_OR, user_cond, group_cond, NULL);
7282 
7283  where_expr = parser_make_expression (parser, PT_AND, where_expr, user_cond, NULL);
7284  }
7285 
7286 
7287 
7288  /* WHERE list should be empty */
7289  assert (node->info.query.q.select.where == NULL);
7290  node->info.query.q.select.where = parser_append_node (where_expr, node->info.query.q.select.where);
7291 
7292  /* GROUP BY : AU.grantee, AU.class_of, AU.is_grantable */
7293  assert (node->info.query.q.select.group_by == NULL);
7294  group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.grantee", PT_ASC);
7295  node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by);
7296 
7297  group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.class_of", PT_ASC);
7298  node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by);
7299 
7300  group_by_item = pt_make_sort_spec_with_identifier (parser, "AU.is_grantable", PT_ASC);
7301  node->info.query.q.select.group_by = parser_append_node (group_by_item, node->info.query.q.select.group_by);
7302  group_by_item = NULL;
7303 
7304  {
7305  PT_NODE *order_by_item = NULL;
7306 
7307  assert (node->info.query.order_by == NULL);
7308 
7309  /* By GROUPS */
7310  order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC);
7311  node->info.query.order_by = parser_append_node (order_by_item, node->info.query.order_by);
7312  }
7313  return node;
7314 }
7315 
7316 /*
7317  * pt_is_spec_referenced() - check if the current node references the spec id
7318  * passed as parameter
7319  * return: the current node
7320  * parser(in): Parser context
7321  * node(in):
7322  * void_arg(in): must contain an address to the id of the spec. If the spec id
7323  * is referenced then reference of this parameter is modified to
7324  * 0.
7325  * continue_walk(in):
7326  *
7327  */
7328 static PT_NODE *
7329 pt_is_spec_referenced (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk)
7330 {
7331  UINTPTR spec_id = *(UINTPTR *) void_arg;
7332 
7333  *continue_walk = PT_CONTINUE_WALK;
7334 
7335  if (node->node_type == PT_NAME && node->info.name.spec_id == spec_id && node->info.name.meta_class != PT_METHOD
7336  && node->info.name.meta_class != PT_INDEX_NAME)
7337  {
7338  *(UINTPTR *) void_arg = 0;
7339  *continue_walk = PT_STOP_WALK;
7340  return node;
7341  }
7342 
7343  if (node->node_type == PT_SPEC)
7344  {
7345  /* The only part of a spec node that could contain references to the given spec_id are derived tables,
7346  * path_entities, path_conjuncts, and on_cond. All the rest of the name nodes for the spec are not references,
7347  * but range variables, class names, etc. We don't want to mess with these. We'll handle the ones that we want by
7348  * hand. */
7352  NULL);
7354  /* don't visit any other leaf nodes */
7355  *continue_walk = PT_LIST_WALK;
7356  return node;
7357  }
7358 
7359  /* Data type nodes can not contain any valid references. They do contain class names and other things we don't want.
7360  */
7361  if (node->node_type == PT_DATA_TYPE)
7362  {
7363  *continue_walk = PT_LIST_WALK;
7364  }
7365 
7366  return node;
7367 }
7368 
7369 /*
7370  * pt_create_delete_stmt() - create a new simple delete statement
7371  * return: the PT_DELETE node on success or NULL otherwise
7372  * parser(in/out): Parser context
7373  * spec(in): the spec for which the DELETE statement is created
7374  * target_class(in): the PT_NAME node that will appear in the target_classes
7375  * list.
7376  *
7377  * Note: The 'spec' and 'target_class' parameters are assigned to the new
7378  * statement.
7379  */
7380 static PT_NODE *
7381 pt_create_delete_stmt (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * target_class)
7382 {
7383  PT_NODE *delete_stmt = NULL;
7384 
7385  assert (spec != NULL && spec->node_type == PT_SPEC);
7386 
7387  delete_stmt = parser_new_node (parser, PT_DELETE);
7388  if (delete_stmt == NULL)
7389  {
7391  return NULL;
7392  }
7393 
7394  delete_stmt->info.delete_.spec = spec;
7395  delete_stmt->info.delete_.target_classes = target_class;
7396 
7397  return delete_stmt;
7398 }
7399 
7400 /*
7401  * pt_split_delete_stmt() - split DELETE statement into independent DELETE
7402  * statements
7403  * return: NO_ERROR or error code;
7404  * parser(in/out): Parser context
7405  * delete_stmt(in): the source DELETE statement
7406  *
7407  * Note: The function checks each spec if it is referenced. If the spec was
7408  * specified in the target_classes list (for deletion) and is not
7409  * referenced then it removes it from the current statement and a new
7410  * DELETE statement is generated only for this spec. The newly generated
7411  * statements are stored in del_stmt_list member of the current
7412  * PT_DELETE_INFO node.
7413  */
7414 int
7416 {
7417  PT_NODE *spec = NULL, *prev_spec = NULL, *rem_spec = NULL, *to_delete = NULL;
7418  PT_NODE *prev_name = NULL, *new_del_stmts = NULL, *last_new_del_stmt = NULL;
7419  PT_NODE *rem_name = NULL;
7420  UINTPTR spec_id = 0;
7421 
7422  if (delete_stmt == NULL || delete_stmt->node_type != PT_DELETE)
7423  {
7424  PT_INTERNAL_ERROR (parser, "Invalid argument");
7425  return ER_FAILED;
7426  }
7427 
7428  /* if we have hints that refers globally to the join statement then we skip the split */
7429  if ((delete_stmt->info.delete_.hint & PT_HINT_ORDERED && delete_stmt->info.delete_.ordered_hint == NULL)
7430  || ((delete_stmt->info.delete_.hint & PT_HINT_USE_NL) && delete_stmt->info.delete_.use_nl_hint == NULL)
7431  || ((delete_stmt->info.delete_.hint & PT_HINT_USE_IDX) && delete_stmt->info.delete_.use_idx_hint == NULL)
7432  || ((delete_stmt->info.delete_.hint & PT_HINT_USE_MERGE) && delete_stmt->info.delete_.use_merge_hint == NULL))
7433  {
7434  return NO_ERROR;
7435  }
7436 
7437  spec = delete_stmt->info.delete_.spec;
7438  /* if the delete statement has only one spec then we do not split anything */
7439  if (spec->next == NULL)
7440  {
7441  return NO_ERROR;
7442  }
7443 
7444  /* iterate through specs and put in separate delete statements the specs that aren't referenced */
7445  while (spec != NULL && delete_stmt->info.delete_.target_classes->next != NULL)
7446  {
7447  /* skip the derived tables and tables that will not be deleted */
7448  if (spec->info.spec.derived_table != NULL || !(spec->info.spec.flag & PT_SPEC_FLAG_DELETE))
7449  {
7450  prev_spec = spec;
7451  spec = spec->next;
7452  continue;
7453  }
7454 
7455  spec_id = spec->info.spec.id;
7456  to_delete = delete_stmt->info.delete_.target_classes;
7457  /* remove temporarily all target_classes from statement because these references must not be counted, then check
7458  * if the current spec is referenced */
7459  delete_stmt->info.delete_.target_classes = NULL;
7460  parser_walk_tree (parser, delete_stmt, pt_is_spec_referenced, &spec_id, pt_continue_walk, NULL);
7461  delete_stmt->info.delete_.target_classes = to_delete;
7462 
7463  /* if the spec is not referenced and if it is not the only remaining spec from the original command that will be
7464  * deleted then remove it */
7465  if (spec_id)
7466  {
7467  /* move the iterator (spec) to the next spec and remove the current spec from the original list of specs */
7468  rem_spec = spec;
7469  spec = spec->next;
7470  rem_spec->next = NULL;
7471  if (prev_spec != NULL)
7472  {
7473  prev_spec->next = spec;
7474  }
7475  else
7476  {
7477  delete_stmt->info.delete_.spec = spec;
7478  }
7479 
7480  /* remove PT_NAMEs from target_classes list */
7481  rem_name = prev_name = NULL;
7482  while (to_delete != NULL)
7483  {
7484  /* if the target class name references the removed spec then remove it from target_classes list */
7485  if (to_delete->info.name.spec_id == spec_id)
7486  {
7487  /* free the previous removed PT_NAME */
7488  if (rem_name != NULL)
7489  {
7490  parser_free_tree (parser, rem_name);
7491  }
7492  /* remove the current PT_NAME from target_classes and keep it for a new DELETE statement */
7493  rem_name = to_delete;
7494  to_delete = to_delete->next;
7495  rem_name->next = NULL;
7496  if (prev_name != NULL)
7497  {
7498  prev_name->next = to_delete;
7499  }
7500  else
7501  {
7502  delete_stmt->info.delete_.target_classes = to_delete;
7503  }
7504  }
7505  else
7506  {
7507  prev_name = to_delete;
7508  to_delete = to_delete->next;
7509  }
7510  }
7511 
7512  /* because the spec is referenced in the target_classes list, we need to generate a new DELETE statement */
7513  if (new_del_stmts == NULL)
7514  {
7515  last_new_del_stmt = new_del_stmts = pt_create_delete_stmt (parser, rem_spec, rem_name);
7516  }
7517  else
7518  {
7519  last_new_del_stmt->next = pt_create_delete_stmt (parser, rem_spec, rem_name);
7520  last_new_del_stmt = last_new_del_stmt->next;
7521  }
7522 
7523  if (last_new_del_stmt == NULL)
7524  {
7525  goto exit_on_error;
7526  }
7527 
7528  /* handle hints */
7529  if (last_new_del_stmt != NULL)
7530  {
7531  last_new_del_stmt->info.delete_.hint = delete_stmt->info.delete_.hint;
7532  last_new_del_stmt->flag.recompile = delete_stmt->flag.recompile;
7533  if ((last_new_del_stmt->info.delete_.hint & PT_HINT_LK_TIMEOUT)
7534  && delete_stmt->info.delete_.waitsecs_hint != NULL)
7535  {
7536  last_new_del_stmt->info.delete_.waitsecs_hint =
7537  parser_copy_tree (parser, delete_stmt->info.delete_.waitsecs_hint);
7538  if (last_new_del_stmt->info.delete_.waitsecs_hint == NULL)
7539  {
7540  goto exit_on_error;
7541  }
7542  }
7543  }
7544  }
7545  else
7546  {
7547  prev_spec = spec;
7548  spec = spec->next;
7549  }
7550  }
7551 
7552  delete_stmt->info.delete_.del_stmt_list = new_del_stmts;
7553 
7554  return NO_ERROR;
7555 
7556 exit_on_error:
7557  if (new_del_stmts != NULL)
7558  {
7559  parser_free_tree (parser, new_del_stmts);
7560  }
7561 
7562  if (!pt_has_error (parser))
7563  {
7565  }
7566 
7567  return ER_GENERIC_ERROR;
7568 }
7569 
7570 /*
7571  * pt_make_query_describe_w_identifier() - builds the query used for DESCRIBE
7572  * with a column name
7573  *
7574  * DESCRIBE <table_name> <column_name>
7575  *
7576  * return: newly build node (PT_NODE), NULL if construnction fails
7577  * parser(in): Parser context
7578  * original_cls_id(in): node identifier for table (PT_NAME)
7579  * att_id(in): node identifier for attribute (PT_NAME)
7580  */
7581 PT_NODE *
7583 {
7584  PT_NODE *node = NULL;
7585  PT_NODE *where_node = NULL;
7586 
7587  assert (original_cls_id != NULL);
7588  assert (original_cls_id->node_type == PT_NAME);
7589  assert (att_id != NULL);
7590 
7591  if (att_id != NULL)
7592  {
7593  assert (att_id->node_type == PT_NAME);
7594  if (att_id->node_type == PT_NAME)
7595  {
7596  char lower_att_name[DB_MAX_IDENTIFIER_LENGTH];
7597  /* build WHERE */
7598  intl_identifier_lower (att_id->info.name.original, lower_att_name);
7599  where_node = pt_make_pred_name_string_val (parser, PT_EQ, "Field", lower_att_name);
7600  }
7601  }
7602 
7603  node = pt_make_query_show_columns (parser, original_cls_id, (where_node == NULL) ? 0 : 2, where_node, 0);
7604 
7605  return node;
7606 }
7607 
7608 /*
7609  * pt_make_query_show_index() - builds the query used for
7610  * SHOW INDEX IN <table>
7611  *
7612  * return: newly built node (PT_NODE), NULL if construnction fails
7613  * parser(in): Parser context
7614  * original_cls_id(in): node (PT_NAME) containing name of class
7615  *
7616  * SELECT "" AS Table,
7617  * 0 AS Non_unique,
7618  * "" AS Key_name,
7619  * 0 AS Seq_in_index,
7620  * "" AS Column_name,
7621  * "" AS Collation,
7622  * 0 AS Cardinality,
7623  * 0 AS Sub_part,
7624  * NULL AS Packed,
7625  * "" AS [Null],
7626  * 'BTREE' AS Index_type
7627  * "" AS Func,
7628  * "" AS Comment,
7629  * "" AS Visible
7630  * FROM <table> ORDER BY 3, 5;
7631  *
7632  * Note: At execution, all empty fields will be replaced by values
7633  * that will be read from class schema
7634  */
7635 PT_NODE *
7636 pt_make_query_show_index (PARSER_CONTEXT * parser, PT_NODE * original_cls_id)
7637 {
7638  PT_NODE *from_item = NULL;
7639  PT_NODE *order_by_item = NULL;
7640  PT_NODE *query = NULL;
7641  char lower_table_name[DB_MAX_IDENTIFIER_LENGTH];
7642  PT_NODE *value = NULL, *value_list = NULL;
7643  DB_VALUE db_valuep[14];
7644  const char *aliases[] = {
7645  "Table", "Non_unique", "Key_name", "Seq_in_index", "Column_name",
7646  "Collation", "Cardinality", "Sub_part", "Packed", "Null", "Index_type",
7647  "Func", "Comment", "Visible"
7648  };
7649  unsigned int i = 0;
7650 
7651  assert (original_cls_id != NULL);
7652  assert (original_cls_id->node_type == PT_NAME);
7653 
7654  query = parser_new_node (parser, PT_SELECT);
7655  if (query == NULL)
7656  {
7657  return NULL;
7658  }
7659 
7662 
7663  intl_identifier_lower (original_cls_id->info.name.original, lower_table_name);
7664 
7667  db_make_int (db_valuep + 1, 0);
7670  db_make_int (db_valuep + 3, 0);
7675  db_make_int (db_valuep + 6, 0);
7676  db_make_int (db_valuep + 7, 0);
7677  db_make_null (db_valuep + 8);
7687 
7688  for (i = 0; i < sizeof (db_valuep) / sizeof (db_valuep[0]); i++)
7689  {
7690  value = pt_dbval_to_value (parser, db_valuep + i);
7691  if (value == NULL)
7692  {
7693  goto error;
7694  }
7695  value->alias_print = pt_append_string (parser, NULL, aliases[i]);
7696  value_list = parser_append_node (value, value_list);
7697  }
7698 
7699  query->info.query.q.select.list = value_list;
7700  value_list = NULL;
7701 
7702  from_item = pt_add_table_name_to_from_list (parser, query, lower_table_name, NULL, DB_AUTH_NONE);
7703  if (from_item == NULL)
7704  {
7705  goto error;
7706  }
7707 
7708  /* By Key_name */
7709  order_by_item = pt_make_sort_spec_with_number (parser, 3, PT_ASC);
7710  if (order_by_item == NULL)
7711  {
7712  goto error;
7713  }
7714  query->info.query.order_by = parser_append_node (order_by_item, query->info.query.order_by);
7715 
7716  /* By Seq_in_index */
7717  order_by_item = pt_make_sort_spec_with_number (parser, 4, PT_ASC);
7718  if (order_by_item == NULL)
7719  {
7720  goto error;
7721  }
7722  query->info.query.order_by = parser_append_node (order_by_item, query->info.query.order_by);
7723 
7724  return query;
7725 
7726 error:
7727  if (query)
7728  {
7729  parser_free_tree (parser, query);
7730  }
7731 
7732  if (value_list)
7733  {
7734  parser_free_tree (parser, value_list);
7735  }
7736 
7737  return NULL;
7738 }
7739 
7740 /*
7741  * pt_convert_to_logical_expr () - if necessary, creates a logically correct
7742  * expression from the given node
7743  *
7744  * return: - the same node if conversion was not necessary, OR
7745  * - a new PT_EXPR: (node <> 0), OR
7746  * - NULL on failures
7747  * parser (in): Parser context
7748  * node (in): the node to be checked and wrapped
7749  * use_parens (in): set to true if parantheses are needed around the original node
7750  *
7751  * Note: we see if the given node is of type PT_TYPE_LOGICAL, and if not,
7752  * we create an expression of the form "(node <> 0)" - with parens
7753  */
7754 PT_NODE *
7755 pt_convert_to_logical_expr (PARSER_CONTEXT * parser, PT_NODE * node, bool use_parens_inside, bool use_parens_outside)
7756 {
7757  PT_NODE *expr = NULL;
7758  PT_NODE *zero = NULL;
7759 
7760  (void) use_parens_inside;
7761  (void) use_parens_outside;
7762 
7763  /* If there's nothing to be done, go away */
7764  if (node == NULL || node->type_enum == PT_TYPE_LOGICAL)
7765  {
7766  return node;
7767  }
7768 
7769  /* allocate a new node for the zero value */
7770  zero = parser_new_node (parser, PT_VALUE);
7771  if (NULL == zero)
7772  {
7773  return NULL;
7774  }
7775 
7776  zero->info.value.data_value.i = 0;
7777  zero->type_enum = PT_TYPE_INTEGER;
7778 
7779  /* make a new expression comparing the node to zero */
7780  expr = parser_make_expression (parser, PT_NE, node, zero, NULL);
7781  if (expr != NULL)
7782  {
7783  expr->type_enum = PT_TYPE_LOGICAL;
7784  }
7785 
7786  return expr;
7787 }
7788 
7789 /*
7790  * pt_is_operator_logical() - returns TRUE if the operator has a logical
7791  * return type (i.e. <, >, AND etc.) and FALSE
7792  * otherwise.
7793  *
7794  * return: boolean
7795  * op(in): the operator
7796  */
7797 bool
7799 {
7800  switch (op)
7801  {
7802  case PT_OR:
7803  case PT_XOR:
7804  case PT_AND:
7805  case PT_IS_NOT:
7806  case PT_IS:
7807  case PT_NOT:
7808  case PT_EXISTS:
7809  case PT_LIKE_ESCAPE:
7810  case PT_LIKE:
7811  case PT_NOT_LIKE:
7812  case PT_RLIKE:
7813  case PT_NOT_RLIKE:
7814  case PT_RLIKE_BINARY:
7815  case PT_NOT_RLIKE_BINARY:
7816  case PT_EQ:
7817  case PT_EQ_ALL:
7818  case PT_EQ_SOME:
7819  case PT_NE:
7820  case PT_NE_ALL:
7821  case PT_NE_SOME:
7822  case PT_GT:
7823  case PT_GT_ALL:
7824  case PT_GT_SOME:
7825  case PT_GE:
7826  case PT_GE_ALL:
7827  case PT_GE_SOME:
7828  case PT_LT:
7829  case PT_LT_ALL:
7830  case PT_LT_SOME:
7831  case PT_LE:
7832  case PT_LE_ALL:
7833  case PT_LE_SOME:
7834  case PT_NULLSAFE_EQ:
7835  case PT_IS_NOT_NULL:
7836  case PT_IS_NULL:
7837  case PT_NOT_BETWEEN:
7838  case PT_BETWEEN:
7839  case PT_IS_IN:
7840  case PT_IS_NOT_IN:
7841  case PT_BETWEEN_GE_LE:
7842  case PT_BETWEEN_GT_LE:
7843  case PT_BETWEEN_GE_LT:
7844  case PT_BETWEEN_GT_LT:
7845  case PT_BETWEEN_EQ_NA:
7846  case PT_BETWEEN_GE_INF:
7847  case PT_BETWEEN_GT_INF:
7848  case PT_BETWEEN_INF_LE:
7849  case PT_BETWEEN_INF_LT:
7850  case PT_SETEQ:
7851  case PT_SETNEQ:
7852  case PT_SUBSET:
7853  case PT_SUBSETEQ:
7854  case PT_SUPERSETEQ:
7855  case PT_SUPERSET:
7856  case PT_RANGE:
7857  return true;
7858  default:
7859  return false;
7860  }
7861 }
7862 
7863 /*
7864  * pt_list_has_logical_nodes () - returns TRUE if the node list contains
7865  * top level PT_TYPE_LOGICAL nodes.
7866  *
7867  * return: boolean
7868  * list(in): the node list
7869  *
7870  * Note: this function is important because there are cases (such as arg lists)
7871  * when we want to forbid logical expressions, because of ambiguity over
7872  * the ->next node: is it in a list context, or a CNF context?
7873  */
7874 bool
7876 {
7877  for (; list; list = list->next)
7878  {
7879  if (list->type_enum == PT_TYPE_LOGICAL)
7880  {
7881  return true;
7882  }
7883  }
7884  return false;
7885 }
7886 
7887 /*
7888  * pt_sort_spec_cover_groupby () -
7889  * return: true if group list is covered by sort list
7890  * sort_list(in):
7891  * group_list(in):
7892  */
7893 bool
7895 {
7896  PT_NODE *s1, *s2, *save_node, *col;
7897  QFILE_TUPLE_VALUE_POSITION pos_descr;
7898  int i;
7899 
7900  if (group_list == NULL)
7901  {
7902  return false;
7903  }
7904 
7905  s1 = sort_list;
7906  s2 = group_list;
7907 
7908  while (s1 && s2)
7909  {
7910  pt_to_pos_descr (parser, &pos_descr, s2->info.sort_spec.expr, tree, NULL);
7911  if (pos_descr.pos_no > 0)
7912  {
7913  col = tree->info.query.q.select.list;
7914  for (i = 1; i < pos_descr.pos_no && col; i++)
7915  {
7916  col = col->next;
7917  }
7918  if (col != NULL)
7919  {
7920  col = pt_get_end_path_node (col);
7921 
7923  {
7924  s2 = s2->next;
7925  continue; /* skip out constant order */
7926  }
7927  }
7928  }
7929 
7930  save_node = s1->info.sort_spec.expr;
7932 
7933  if (!pt_name_equal (parser, s1->info.sort_spec.expr, s2->info.sort_spec.expr)
7936  {
7937  s1->info.sort_spec.expr = save_node;
7938  return false;
7939  }
7940 
7941  s1->info.sort_spec.expr = save_node;
7942 
7943  s1 = s1->next;
7944  s2 = s2->next;
7945  }
7946 
7947  return (s2 == NULL) ? true : false;
7948 }
7949 
7950 /*
7951  * pt_rewrite_derived_for_upd_del () - adds ROWOID to select list of
7952  * query so it can be later pulled
7953  * when building the SELECT
7954  * statement for UPDATEs and DELETEs
7955  * returns: rewritten subquery or NULL on error
7956  * parser(in): parser context
7957  * spec(in): spec whose derived table will be rewritten
7958  *
7959  * NOTE: query must be a SELECT statement
7960  */
7961 static PT_NODE *
7962 pt_rewrite_derived_for_upd_del (PARSER_CONTEXT * parser, PT_NODE * spec, PT_SPEC_FLAG what_for, bool add_as_attr)
7963 {
7964  PT_NODE *derived_table = NULL, *as_attr = NULL, *col = NULL, *upd_del_spec = NULL, *spec_list = NULL;
7965  PT_NODE *save_spec = NULL, *save_next = NULL, *flat_copy = NULL;
7966  const char *spec_name = NULL;
7967  int upd_del_count = 0;
7968 
7969  derived_table = spec->info.spec.derived_table;
7970  spec_list = derived_table->info.query.q.select.from;
7971  if ((what_for == PT_SPEC_FLAG_DELETE) && (spec_list == NULL || spec_list->next != NULL))
7972  {
7973  PT_INTERNAL_ERROR (parser, "only one spec expected for delete");
7974  return NULL;
7975  }
7976 
7977  while (spec_list != NULL)
7978  {
7979  if (spec_list->info.spec.flag & what_for)
7980  {
7981  if (upd_del_count == 0)
7982  {
7983  upd_del_spec = spec_list;
7984  }
7985  upd_del_count++;
7986  }
7987 
7988  spec_list = spec_list->next;
7989  }
7990 
7991  if (upd_del_spec == NULL)
7992  {
7993  /* no specs; error */
7994  PT_INTERNAL_ERROR (parser, "no target spec for update/delete");
7995  return NULL;
7996  }
7997 
7998  if (upd_del_count > 1)
7999  {
8001  return NULL;
8002  }
8003 
8004  /* dual update/delete checks have been made - check if oids were already added */
8006  {
8007  return spec;
8008  }
8009 
8010  /* retrieve spec's name, which will be appended to OID attribute names */
8011  if (spec->info.spec.range_var && spec->info.spec.range_var->node_type == PT_NAME)
8012  {
8013  spec_name = spec->info.spec.range_var->info.name.original;
8014  }
8015 
8016  /* add rowoid to select list of derived table and as_attr_list of spec; it will be pulled later on when building the
8017  * select statement for OID retrieval */
8018  save_spec = derived_table->info.query.q.select.from;
8019  derived_table->info.query.q.select.from = upd_del_spec;
8020  save_next = upd_del_spec->next;
8021  assert (upd_del_spec != NULL);
8022  upd_del_spec->next = NULL;
8023 
8024  derived_table = pt_add_row_oid_name (parser, derived_table);
8025 
8026  derived_table->info.query.q.select.from = save_spec;
8027  upd_del_spec->next = save_next;
8028 
8029  col = derived_table->info.query.q.select.list;
8030  if (col->data_type && col->data_type->info.data_type.virt_object)
8031  {
8032  /* no longer comes from a vobj */
8034  col->data_type->info.data_type.virt_type_enum = PT_TYPE_NONE;
8035  }
8036 
8037  if (add_as_attr)
8038  {
8039  /* add reference for column in select list */
8040  as_attr = pt_name (parser, "rowoid_");
8041  as_attr->info.name.original =
8042  (const char *) pt_append_string (parser, (char *) as_attr->info.name.original, spec_name);
8043  as_attr->info.name.spec_id = spec->info.spec.id;
8044  as_attr->info.name.meta_class = PT_OID_ATTR;
8045  as_attr->type_enum = col->type_enum;
8046  as_attr->data_type = parser_copy_tree (parser, col->data_type);
8047 
8048  as_attr->next = spec->info.spec.as_attr_list;
8049  spec->info.spec.as_attr_list = as_attr;
8050  }
8051 
8052  /* copy flat_entity_list of derived table's spec to parent spec so it will be correctly handled further on */
8053  flat_copy = parser_copy_tree_list (parser, upd_del_spec->info.spec.flat_entity_list);
8055 
8056  while (flat_copy)
8057  {
8058  if (flat_copy->node_type == PT_NAME)
8059  {
8060  flat_copy->info.name.spec_id = spec->info.spec.id;
8061  }
8062  flat_copy = flat_copy->next;
8063  }
8064 
8065  /* all ok */
8066  return spec;
8067 }
8068 
8069 /*
8070  * pt_process_spec_for_delete () - recurses trough specs, sets DELETE flag
8071  * and adds OIDs where necessary
8072  * returns: same spec or NULL on error
8073  * parser(in): parser context
8074  * spec(in): spec
8075  */
8076 static PT_NODE *
8078 {
8079  PT_NODE *derived_table, *from, *ret;
8080 
8081  if (parser == NULL || spec == NULL || spec->node_type != PT_SPEC)
8082  {
8083  /* should not get here */
8084  assert (false);
8085  return NULL;
8086  }
8087 
8088  /* mark spec */
8090 
8091  /* fetch derived table of spec */
8092  derived_table = spec->info.spec.derived_table;
8093  if (derived_table == NULL)
8094  {
8095  /* no derived table means nothing to do further */
8096  return spec;
8097  }
8098 
8099  /* derived table - walk it's spec */
8100  if (derived_table->node_type != PT_SELECT)
8101  {
8102  PT_INTERNAL_ERROR (parser, "invalid derived spec");
8103  return NULL;
8104  }
8105 
8106  from = derived_table->info.query.q.select.from;
8107  if (pt_process_spec_for_delete (parser, from) == NULL)
8108  {
8109  /* error must have been set */
8110  return NULL;
8111  }
8112 
8113  /* add oids */
8114  ret = pt_rewrite_derived_for_upd_del (parser, spec, PT_SPEC_FLAG_DELETE, true);
8116 
8117  return ret;
8118 }
8119 
8120 /*
8121  * pt_process_spec_for_update () - recurses trough specs, sets UPDATE flag,
8122  * adds OIDs where necessary and resolves name
8123  * returns: resolved name or NULL on error
8124  * parser(in): parser context
8125  * spec(in): spec
8126  * name(in): lhs assignment node
8127  */
8128 static PT_NODE *
8130 {
8131  PT_NODE *as_attr_list = NULL, *attr_list = NULL;
8132  PT_NODE *dt_arg1, *dt_arg2, *derived_table;
8133  PT_NODE *spec_list, *subspec;
8134  PT_NODE *temp_name, *save_dt;
8135  int attr_idx, i;
8136 
8137  if (parser == NULL || spec == NULL || name == NULL || spec->node_type != PT_SPEC || name->node_type != PT_NAME)
8138  {
8139  /* should not get here */
8140  assert (false);
8141  return NULL;
8142  }
8143 
8144  /* mark spec */
8146 
8147  /* fetch derived table of spec */
8148  dt_arg1 = save_dt = spec->info.spec.derived_table;
8149  if (dt_arg1 == NULL)
8150  {
8151  /* no derived table means nothing to do further */
8152  return name;
8153  }
8154 
8155  /* check derived table */
8156  if (!(spec->info.spec.flag & PT_SPEC_FLAG_FROM_VCLASS))
8157  {
8158  PT_INTERNAL_ERROR (parser, "derived table not allowed");
8159  return NULL;
8160  }
8161 
8162  if (dt_arg1->node_type == PT_UNION)
8163  {
8164  /* union derived table (e.g. UPDATE (view1, view2) SET ...) */
8165  dt_arg2 = dt_arg1->info.query.q.union_.arg2;
8166  dt_arg1 = dt_arg1->info.query.q.union_.arg1;
8167  }
8168  else
8169  {
8170  /* simple derived table */
8171  dt_arg2 = NULL;
8172  }
8173 
8174  if (dt_arg1->node_type != PT_SELECT || (dt_arg2 != NULL && dt_arg2->node_type != PT_SELECT))
8175  {
8176  PT_INTERNAL_ERROR (parser, "invalid derived spec");
8177  return NULL;
8178  }
8179 
8180  /* find name in as_attr_list */
8181  attr_idx = 0;
8182  as_attr_list = spec->info.spec.as_attr_list;
8183  while (as_attr_list != NULL)
8184  {
8185  if (pt_name_equal (parser, name, as_attr_list))
8186  {
8187  break;
8188  }
8189  as_attr_list = as_attr_list->next;
8190  attr_idx++;
8191  }
8192 
8193  if (as_attr_list == NULL)
8194  {
8195  PT_INTERNAL_ERROR (parser, "name not found in as_attr_list");
8196  return NULL;
8197  }
8198 
8199  derived_table = dt_arg1;
8200  while (derived_table != NULL)
8201  {
8202  /* resolve name to real name in select list */
8203  attr_list = derived_table->info.query.q.select.list;
8204  for (i = 0; i < attr_idx && attr_list != NULL; i++)
8205  {
8206  attr_list = attr_list->next;
8207  }
8208  if (attr_list == NULL)
8209  {
8210  PT_INTERNAL_ERROR (parser, "name not found in list");
8211  return NULL;
8212  }
8213 
8214  /* we have a derived table we know came from a view; resolve name further down */
8215  spec_list = derived_table->info.query.q.select.from;
8216  subspec = pt_find_spec (parser, spec_list, attr_list);
8217  if (subspec == NULL)
8218  {
8219  PT_INTERNAL_ERROR (parser, "spec not found for name");
8220  return NULL;
8221  }
8222 
8223  /* don't allow other subspecs to be updated; this error will be hit when two passes of the function, called for
8224  * different assignments, will try to flag two different specs */
8225  while (spec_list != NULL)
8226  {
8227  if ((spec_list != subspec) && (spec_list->info.spec.flag & PT_SPEC_FLAG_UPDATE))
8228  {
8230  return NULL;
8231  }
8232 
8233  spec_list = spec_list->next;
8234  }
8235 
8236  /* recurse */
8237  temp_name = pt_process_spec_for_update (parser, subspec, attr_list);
8238  if (temp_name == NULL)
8239  {
8240  /* error should have been set lower down */
8241  return NULL;
8242  }
8243  if (derived_table == dt_arg1)
8244  {
8245  /* skip second resolved name */
8246  name = temp_name;
8247  }
8248 
8249  /* we now have the derived table subtree populated with oids; we can add oids to this derived table's select list
8250  * as well */
8251  spec->info.spec.derived_table = derived_table;
8252  spec = pt_rewrite_derived_for_upd_del (parser, spec, PT_SPEC_FLAG_UPDATE, (derived_table == dt_arg1));
8253  spec->info.spec.derived_table = save_dt;
8254 
8255  if (spec == NULL)
8256  {
8257  /* error should have been set lower down */
8258  return NULL;
8259  }
8260 
8261  /* next derived table of union */
8262  derived_table = (derived_table == dt_arg1 ? dt_arg2 : NULL);
8263  }
8264 
8265  /* spec has OIDs added */
8267 
8268  /* all ok */
8269  return name;
8270 }
8271 
8272 /*
8273  * pt_mark_spec_list_for_delete () - mark delete targets
8274  * return: none
8275  * parser(in): the parser context
8276  * delete_statement(in): a delete statement
8277  */
8278 void
8280 {
8281  PT_NODE *node = NULL, *from;
8282 
8283  if (statement->node_type == PT_DELETE)
8284  {
8285  node = statement->info.delete_.target_classes;
8286  }
8287  else if (statement->node_type == PT_MERGE)
8288  {
8289  node = statement->info.merge.into;
8290  }
8291 
8292  while (node != NULL)
8293  {
8294  if (statement->node_type == PT_DELETE)
8295  {
8296  from = pt_find_spec_in_statement (parser, statement, node);
8297  if (from == NULL)
8298  {
8299  PT_INTERNAL_ERROR (parser, "invalid spec id");
8300  return;
8301  }
8302  }
8303  else
8304  {
8305  from = node;
8306  }
8307 
8308  from = pt_process_spec_for_delete (parser, from);
8309  if (from == NULL)
8310  {
8311  /* error must have been set */
8312  return;
8313  }
8314 
8315  node = node->next;
8316  }
8317 }
8318 
8319 /*
8320  * pt_mark_spec_list_for_update () - mark update targets
8321  * return: none
8322  * parser(in): the parser context
8323  * statement(in): an update/merge statement
8324  */
8325 void
8327 {
8328  PT_NODE *lhs, *node_tmp, *node, *resolved;
8329  PT_NODE *assignments = NULL, *spec_list = NULL;
8330 
8331  if (statement->node_type == PT_UPDATE)
8332  {
8333  assignments = statement->info.update.assignment;
8334  spec_list = statement->info.update.spec;
8335  }
8336  else if (statement->node_type == PT_MERGE)
8337  {
8338  assignments = statement->info.merge.update.assignment;
8339  spec_list = statement->info.merge.into;
8340  }
8341 
8342  /* set flags for updatable specs */
8343  node = assignments;
8344  while (node != NULL)
8345  {
8346  lhs = node->info.expr.arg1;
8347 
8348  while (lhs != NULL && lhs->node_type != PT_NAME)
8349  {
8350  if (lhs->node_type == PT_EXPR)
8351  {
8352  /* path expression */
8353  lhs = lhs->info.expr.arg1;
8354  }
8355  else if (lhs->node_type == PT_DOT_)
8356  {
8357  /* dot expression */
8358  lhs = lhs->info.dot.arg2;
8359  }
8360  else
8361  {
8362  lhs = NULL;
8363  }
8364  }
8365 
8366  if (lhs == NULL)
8367  {
8368  /* should not get here */
8369  PT_INTERNAL_ERROR (parser, "malformed assignment");
8370  return;
8371  }
8372 
8373  while (lhs != NULL)
8374  {
8375  /* resolve to spec */
8376  node_tmp = pt_find_spec_in_statement (parser, statement, lhs);
8377  if (node_tmp == NULL)
8378  {
8379  PT_INTERNAL_ERROR (parser, "invalid spec id");
8380  return;
8381  }
8382 
8383  /* resolve name and add rowoid attributes where needed */
8384  resolved = pt_process_spec_for_update (parser, node_tmp, lhs);
8385  if (resolved == NULL || resolved->node_type != PT_NAME)
8386  {
8387  /* error should have been set */
8388  break;
8389  }
8390 
8391  /* flat_entity_list will be propagated trough derived tables of updatable views, so the assignment name
8392  * should be able to be resolved to them */
8393  lhs->info.name.original = resolved->info.name.original;
8394 
8395  /* advance to next name in set (if exists) */
8396  lhs = lhs->next;
8397  }
8398 
8399  /* next assignment */
8400  node = node->next;
8401  }
8402 }
8403 
8404 /*
8405  * pt_check_grammar_charset_collation () - validates a pair of charset and
8406  * collation nodes and return the associated identifiers
8407  * return: error status
8408  * parser(in): the parser context
8409  * charset_node(in): node containing charset string (PT_VALUE)
8410  * coll_node(in): node containing collation string (PT_VALUE)
8411  * charset(in): validated value for charset (INTL_CHARSET)
8412  * coll_id(in): validated value for collation
8413  */
8414 int
8415 pt_check_grammar_charset_collation (PARSER_CONTEXT * parser, PT_NODE * charset_node, PT_NODE * coll_node, int *charset,
8416  int *coll_id)
8417 {
8418  bool has_user_charset = false;
8419 
8420  assert (charset != NULL);
8421  assert (coll_id != NULL);
8422 
8423  *charset = LANG_SYS_CODESET;
8424  *coll_id = LANG_SYS_COLLATION;
8425 
8426  if (charset_node != NULL)
8427  {
8428  const char *cs_name;
8429  assert (charset_node->node_type == PT_VALUE);
8430 
8431  assert (charset_node->info.value.data_value.str != NULL);
8432 
8433  cs_name = (char *) charset_node->info.value.data_value.str->bytes;
8434 
8435  *charset = lang_charset_cubrid_name_to_id (cs_name);
8436  if (*charset == INTL_CODESET_NONE)
8437  {
8439 
8440  return ER_GENERIC_ERROR;
8441  }
8442 
8443  has_user_charset = true;
8444  }
8445 
8446  if (coll_node != NULL)
8447  {
8448  LANG_COLLATION *lang_coll;
8449 
8450  assert (coll_node->node_type == PT_VALUE);
8451 
8452  assert (coll_node->info.value.data_value.str != NULL);
8453  lang_coll = lang_get_collation_by_name ((const char *) coll_node->info.value.data_value.str->bytes);
8454 
8455  if (lang_coll != NULL)
8456  {
8457  int coll_charset;
8458 
8459  *coll_id = lang_coll->coll.coll_id;
8460  coll_charset = (int) lang_coll->codeset;
8461 
8462  if (has_user_charset && coll_charset != *charset)
8463  {
8464  /* error incompatible charset and collation */
8466  return ER_GENERIC_ERROR;
8467  }
8468 
8469  /* default charset for this collation */
8470  *charset = coll_charset;
8471  }
8472  else
8473  {
8475  coll_node->info.value.data_value.str->bytes);
8476  return ER_GENERIC_ERROR;
8477  }
8478  }
8479  else
8480  {
8481  assert (coll_node == NULL);
8482  /* set a default collation for a charset */
8483 
8484  switch (*charset)
8485  {
8486  case INTL_CODESET_ISO88591:
8487  *coll_id = LANG_COLL_ISO_BINARY;
8488  break;
8490  *coll_id = LANG_COLL_EUCKR_BINARY;
8491  break;
8492  case INTL_CODESET_UTF8:
8493  *coll_id = LANG_COLL_UTF8_BINARY;
8494  break;
8495  default:
8496  assert (*charset == INTL_CODESET_BINARY);
8497  *coll_id = LANG_COLL_BINARY;
8498  return NO_ERROR;
8499  }
8500  }
8501 
8502  return NO_ERROR;
8503 }
8504 
8505 /*
8506  * pt_make_tuple_value_reference () - create a PT_TUPLE_VALUE node for a
8507  * SELECT list of a SELECT statement
8508  * return : new node or NULL
8509  * parser (in) : parser context
8510  * name (in) : name node
8511  * select_list (in) : select list of a query
8512  * cursor_p (in) : cursor for the query
8513  */
8514 PT_NODE *
8515 pt_make_tuple_value_reference (PARSER_CONTEXT * parser, PT_NODE * name, PT_NODE * select_list, CURSOR_ID * cursor_p)
8516 {
8517  int index = 0;
8518  PT_NODE *node = NULL, *new_col = NULL, *last_node = NULL, *next = NULL;
8519 
8520  assert_release (select_list != NULL);
8521 
8522  for (node = select_list, index = 0; node != NULL; node = node->next, index++)
8523  {
8524  if (pt_check_path_eq (parser, node, name) == 0)
8525  {
8526  /* found it, just make a tuple_value reference to it */
8527  next = name->next;
8528  name->next = NULL;
8529  name = pt_tuple_value (parser, name, cursor_p, index);
8530  name->next = next;
8531  return name;
8532  }
8533  last_node = node;
8534  }
8535 
8536  next = name->next;
8537  name->next = NULL;
8538 
8539  /* add it to the end of the select_list */
8540  new_col = parser_copy_tree (parser, name);
8541  if (new_col == NULL)
8542  {
8543  PT_INTERNAL_ERROR (parser, "allocate new node");
8544  return NULL;
8545  }
8546  last_node->next = new_col;
8547 
8548  /* change name to tuple value */
8549  name = pt_tuple_value (parser, name, cursor_p, index);
8550  if (name == NULL)
8551  {
8552  PT_INTERNAL_ERROR (parser, "allocate new node");
8553  return NULL;
8554  }
8555  name->next = next;
8556 
8557  return name;
8558 }
8559 
8560 /*
8561  * pt_make_query_show_collation() - builds the query for SHOW COLLATION
8562  *
8563  * SELECT * FROM
8564  * (SELECT coll_name AS [Collation],
8565  * IF (charset_id = 3, 'iso88591',
8566  * IF (charset_id = 5, 'utf8',
8567  * IF (charset_id = 2, 'binary',
8568  * IF (charset_id = 4, 'euckr', 'other')))) AS Charset,
8569  * coll_id AS Id,
8570  * IF (built_in = 0, 'No', 'Yes') AS Built_in,
8571  * IF (expansions = 0, 'No', 'Yes') AS Expansions,
8572  * IF (uca_strength = 1,'Primary',
8573  * IF (uca_strength = 2,'Secondary',
8574  * IF (uca_strength = 3, 'Tertiary',
8575  * IF (uca_strength = 4,'Quaternary',
8576  * IF (uca_strength = 5, 'Identity',
8577  * 'Not applicable'))))) AS Strength
8578  * FROM _db_collation) show_colllation
8579  * ORDER BY 1;
8580  *
8581  * return: newly built node (PT_NODE), NULL if construnction fails
8582  * parser(in): Parser context
8583  * like_where_syntax(in): indicator of presence for LIKE or WHERE clauses in
8584  * SHOW statement. Values : 0 = none of LIKE or WHERE,
8585  * 1 = contains LIKE, 2 = contains WHERE
8586  * like_or_where_expr(in): node expression supplied as condition (in WHERE)
8587  * or RHS for LIKE
8588  *
8589  * Note : Order is defined by: coll_name
8590  */
8591 PT_NODE *
8592 pt_make_query_show_collation (PARSER_CONTEXT * parser, int like_where_syntax, PT_NODE * like_or_where_expr)
8593 {
8594  PT_NODE *sub_query = NULL;
8595  PT_NODE *node = NULL;
8596  PT_NODE *from_item = NULL;
8597 
8598  sub_query = parser_new_node (parser, PT_SELECT);
8599  if (sub_query == NULL)
8600  {
8601  return NULL;
8602  }
8603 
8604  /* ------ SELECT list ------- */
8605  pt_add_name_col_to_sel_list (parser, sub_query, "coll_name", "Collation");
8606 
8607  /* Charset */
8608  {
8609  PT_NODE *if_node1 = NULL;
8610  PT_NODE *if_node2 = NULL;
8611  PT_NODE *if_node3 = NULL;
8612  PT_NODE *if_node4 = NULL;
8613 
8614  {
8615  /* IF (charset_id = 4, 'euckr', 'other') */
8616  PT_NODE *pred = NULL;
8617 
8618  pred = pt_make_pred_name_int_val (parser, PT_EQ, "charset_id", 4);
8619  if_node4 = pt_make_if_with_strings (parser, pred, "euckr", "other", NULL);
8620  }
8621 
8622  {
8623  /* IF (charset_id = 2, 'binary', IF_NODE_ 4) */
8624  PT_NODE *pred = NULL;
8625  PT_NODE *string_node = NULL;
8626 
8627  pred = pt_make_pred_name_int_val (parser, PT_EQ, "charset_id", 2);
8628  string_node = pt_make_string_value (parser, "binary");
8629 
8630  if_node3 = pt_make_if_with_expressions (parser, pred, string_node, if_node4, NULL);
8631  }
8632 
8633  {
8634  /* IF (charset_id = 5, 'utf8', IF_NODE_ 3) */
8635  PT_NODE *pred = NULL;
8636  PT_NODE *string_node = NULL;
8637 
8638  pred = pt_make_pred_name_int_val (parser, PT_EQ, "charset_id", 5);
8639  string_node = pt_make_string_value (parser, "utf8");
8640 
8641  if_node2 = pt_make_if_with_expressions (parser, pred, string_node, if_node3, NULL);
8642  }
8643 
8644  {
8645  /* IF (charset_id = 3, 'iso88591', IF_NODE_ 2) */
8646  PT_NODE *pred = NULL;
8647  PT_NODE *string_node = NULL;
8648 
8649  pred = pt_make_pred_name_int_val (parser, PT_EQ, "charset_id", 3);
8650  string_node = pt_make_string_value (parser, "iso88591");
8651 
8652  if_node1 = pt_make_if_with_expressions (parser, pred, string_node, if_node2, "Charset");
8653  }
8654 
8655  sub_query->info.query.q.select.list = parser_append_node (if_node1, sub_query->info.query.q.select.list);
8656  }
8657 
8658  pt_add_name_col_to_sel_list (parser, sub_query, "coll_id", "Id");
8659 
8660  /* Built_in */
8661  {
8662  PT_NODE *if_node = NULL;
8663  PT_NODE *pred = NULL;
8664 
8665  pred = pt_make_pred_name_int_val (parser, PT_EQ, "built_in", 0);
8666  if_node = pt_make_if_with_strings (parser, pred, "No", "Yes", "Built_in");
8667  sub_query->info.query.q.select.list = parser_append_node (if_node, sub_query->info.query.q.select.list);
8668  }
8669 
8670  /* Expansions */
8671  {
8672  PT_NODE *if_node = NULL;
8673  PT_NODE *pred = NULL;
8674 
8675  pred = pt_make_pred_name_int_val (parser, PT_EQ, "expansions", 0);
8676  if_node = pt_make_if_with_strings (parser, pred, "No", "Yes", "Expansions");
8677  sub_query->info.query.q.select.list = parser_append_node (if_node, sub_query->info.query.q.select.list);
8678  }
8679 
8680  /* Strength */
8681  {
8682  PT_NODE *if_node1 = NULL;
8683  PT_NODE *if_node2 = NULL;
8684  PT_NODE *if_node3 = NULL;
8685  PT_NODE *if_node4 = NULL;
8686  PT_NODE *if_node5 = NULL;
8687 
8688  {
8689  /* IF (uca_strength = 5, 'Identity', 'Not applicable') */
8690  PT_NODE *pred = NULL;
8691 
8692  pred = pt_make_pred_name_int_val (parser, PT_EQ, "uca_strength", 5);
8693  if_node5 = pt_make_if_with_strings (parser, pred, "Identity", "Not applicable", NULL);
8694  }
8695 
8696  {
8697  /* IF (uca_strength = 4,'Quaternary', IF_node_5) */
8698  PT_NODE *pred = NULL;
8699  PT_NODE *string_node = NULL;
8700 
8701  pred = pt_make_pred_name_int_val (parser, PT_EQ, "uca_strength", 4);
8702  string_node = pt_make_string_value (parser, "Quaternary");
8703 
8704  if_node4 = pt_make_if_with_expressions (parser, pred, string_node, if_node5, NULL);
8705  }
8706 
8707  {
8708  /* IF (uca_strength = 3, 'Tertiary', IF_Node_4) */
8709  PT_NODE *pred = NULL;
8710  PT_NODE *string_node = NULL;
8711 
8712  pred = pt_make_pred_name_int_val (parser, PT_EQ, "uca_strength", 3);
8713  string_node = pt_make_string_value (parser, "Tertiary");
8714 
8715  if_node3 = pt_make_if_with_expressions (parser, pred, string_node, if_node4, NULL);
8716  }
8717 
8718  {
8719  /* IF (uca_strength = 2,'Secondary', IF_Node_3) */
8720  PT_NODE *pred = NULL;
8721  PT_NODE *string_node = NULL;
8722 
8723  pred = pt_make_pred_name_int_val (parser, PT_EQ, "uca_strength", 2);
8724  string_node = pt_make_string_value (parser, "Secondary");
8725 
8726  if_node2 = pt_make_if_with_expressions (parser, pred, string_node, if_node3, NULL);
8727  }
8728 
8729  {
8730  /* IF (uca_strength = 1,'Primary', IF_Node_2) */
8731  PT_NODE *pred = NULL;
8732  PT_NODE *string_node = NULL;
8733 
8734  pred = pt_make_pred_name_int_val (parser, PT_EQ, "uca_strength", 1);
8735  string_node = pt_make_string_value (parser, "Primary");
8736 
8737  if_node1 = pt_make_if_with_expressions (parser, pred, string_node, if_node2, "Strength");
8738  }
8739 
8740  sub_query->info.query.q.select.list = parser_append_node (if_node1, sub_query->info.query.q.select.list);
8741  }
8742 
8743  /* ------ SELECT ... FROM ------- */
8744  from_item = pt_add_table_name_to_from_list (parser, sub_query, "_db_collation", NULL, DB_AUTH_SELECT);
8745 
8746  if (from_item == NULL)
8747  {
8748  return NULL;
8749  }
8750 
8751  node = pt_make_outer_select_for_show_stmt (parser, sub_query, "show_columns");
8752  if (node == NULL)
8753  {
8754  return NULL;
8755  }
8756 
8757  {
8758  /* add ORDER BY (to outer select) */
8759  PT_NODE *order_by_item = NULL;
8760 
8761  assert (node->info.query.order_by == NULL);
8762  /* By Collation */
8763  order_by_item = pt_make_sort_spec_with_number (parser, 1, PT_ASC);
8764  node->info.query.order_by = parser_append_node (order_by_item, node->info.query.order_by);
8765  }
8766 
8767  if (like_or_where_expr != NULL)
8768  {
8769  PT_NODE *where_item = NULL;
8770 
8771  if (like_where_syntax == 1)
8772  {
8773  /* make LIKE */
8774  where_item = pt_make_like_col_expr (parser, like_or_where_expr, "Collation");
8775  }
8776  else
8777  {
8778  /* WHERE */
8779  assert (like_where_syntax == 2);
8780  where_item = like_or_where_expr;
8781  }
8782 
8783  node->info.query.q.select.where = parser_append_node (where_item, node->info.query.q.select.where);
8784  }
8785  else
8786  {
8787  assert (like_where_syntax == 0);
8788  }
8789 
8790  return node;
8791 }
8792 
8793 /*
8794  * pt_get_query_limit_from_limit () - get the value of the LIMIT clause of a query
8795  * return : error code or NO_ERROR
8796  * parser (in) : parser context
8797  * limit (in) : limit node
8798  * limit_val (in/out) : limit value
8799  *
8800  * Note: this function get the LIMIT clause value of a query as a
8801  * DB_TYPE_BIGINT value. If the LIMIT clause contains a lower limit, the
8802  * returned value is computed as lower bound + range. (i.e.: if it was
8803  * specified as LIMIT :offset, :row_count this function returns :offset + :row_count)
8804  */
8805 static int
8807 {
8808  int save_set_host_var;
8809  TP_DOMAIN *domainp = NULL;
8810  int error = NO_ERROR;
8811 
8812  db_make_null (limit_val);
8813 
8814  if (limit == NULL)
8815  {
8816  return NO_ERROR;
8817  }
8818 
8820 
8821  save_set_host_var = parser->flag.set_host_var;
8822  parser->flag.set_host_var = 1;
8823 
8824  assert (limit->node_type == PT_VALUE || limit->node_type == PT_HOST_VAR || limit->node_type == PT_EXPR);
8825 
8826  pt_evaluate_tree_having_serial (parser, limit, limit_val, 1);
8827  if (pt_has_error (parser))
8828  {
8829  error = ER_FAILED;
8830  goto cleanup;
8831  }
8832 
8833  if (DB_IS_NULL (limit_val))
8834  {
8835  /* probably value is not bound yet */
8836  goto cleanup;
8837  }
8838 
8839  if (tp_value_coerce (limit_val, limit_val, domainp) != DOMAIN_COMPATIBLE)
8840  {
8841  error = ER_FAILED;
8842  goto cleanup;
8843  }
8844 
8845  if (limit->next)
8846  {
8847  DB_VALUE range;
8848 
8849  db_make_null (&range);
8850 
8851  /* LIMIT :offset, :row_count => return :offset + :row_count */
8852  assert (limit->next->node_type == PT_VALUE || limit->next->node_type == PT_HOST_VAR
8853  || limit->next->node_type == PT_EXPR);
8854 
8855  pt_evaluate_tree_having_serial (parser, limit->next, &range, 1);
8856  if (pt_has_error (parser))
8857  {
8858  error = ER_FAILED;
8859  goto cleanup;
8860  }
8861 
8862  if (DB_IS_NULL (&range))
8863  {
8864  /* probably value is not bound yet */
8865  goto cleanup;
8866  }
8867 
8868  if (tp_value_coerce (&range, &range, domainp) != DOMAIN_COMPATIBLE)
8869  {
8870  error = ER_FAILED;
8871  goto cleanup;
8872  }
8873 
8874  /* add range to current limit */
8875  db_make_bigint (limit_val, db_get_bigint (limit_val) + db_get_bigint (&range));
8876  }
8877 
8878 cleanup:
8879  if (error != NO_ERROR)
8880  {
8881  pr_clear_value (limit_val);
8882  db_make_null (limit_val);
8883  }
8884 
8885  parser->flag.set_host_var = save_set_host_var;
8886  return error;
8887 }
8888 
8889 /*
8890  * pt_get_query_limit_value () - get the limit value from a query
8891  * return : error code or NO_ERROR
8892  * parser (in) : parser context
8893  * query (in) : query
8894  * limit_val (in/out) : limit value
8895  */
8896 int
8898 {
8899  assert_release (limit_val != NULL);
8900 
8901  db_make_null (limit_val);
8902 
8903  if (query == NULL || !PT_IS_QUERY (query))
8904  {
8905  return NO_ERROR;
8906  }
8907 
8908  if (query->info.query.limit)
8909  {
8910  return pt_get_query_limit_from_limit (parser, query->info.query.limit, limit_val);
8911  }
8912 
8913  if (query->info.query.orderby_for != NULL)
8914  {
8915  int error = NO_ERROR;
8916  bool has_limit = false;
8917 
8918  error = pt_get_query_limit_from_orderby_for (parser, query->info.query.orderby_for, limit_val, &has_limit);
8919  if (error != NO_ERROR || !has_limit)
8920  {
8921  return ER_FAILED;
8922  }
8923  }
8924 
8925  return NO_ERROR;
8926 }
8927 
8928 /*
8929  * pt_check_ordby_num_for_multi_range_opt () - checks if limit/order by for is valid for multi range opt
8930  *
8931  * return : true/false
8932  * parser (in) : parser context
8933  * query (in) : query
8934  * mro_candidate (out) : if the only failed condition is upper limit for
8935  * orderby_num (), this plan may still use multi range
8936  * optimization if that limit changes
8937  * cannot_eval (out) : upper limit is null or could not be evaluated
8938  */
8939 bool
8940 pt_check_ordby_num_for_multi_range_opt (PARSER_CONTEXT * parser, PT_NODE * query, bool * mro_candidate,
8941  bool * cannot_eval)
8942 {
8943  DB_VALUE limit_val;
8944  int save_set_host_var;
8945  bool valid = false;
8946 
8947  assert_release (query != NULL);
8948 
8949  if (cannot_eval != NULL)
8950  {
8951  *cannot_eval = true;
8952  }
8953  if (mro_candidate != NULL)
8954  {
8955  *mro_candidate = false;
8956  }
8957 
8958  if (!PT_IS_QUERY (query))
8959  {
8960  return false;
8961  }
8962 
8963  db_make_null (&limit_val);
8964 
8965  save_set_host_var = parser->flag.set_host_var;
8966  parser->flag.set_host_var = 1;
8967 
8968  if (pt_get_query_limit_value (parser, query, &limit_val) != NO_ERROR)
8969  {
8970  goto end;
8971  }
8972 
8973  if (DB_IS_NULL (&limit_val))
8974  {
8975  goto end_mro_candidate;
8976  }
8977 
8978  if (cannot_eval)
8979  {
8980  /* upper limit was successfully evaluated */
8981  *cannot_eval = false;
8982  }
8984  {
8985  goto end_mro_candidate;
8986  }
8987  else
8988  {
8989  valid = true;
8990  goto end;
8991  }
8992 
8993 end_mro_candidate:
8994  /* should be here if multi range optimization could not be validated because upper limit is too large or it could not
8995  * be evaluated. However, the query may still use optimization for different host variable values. */
8996  if (mro_candidate != NULL)
8997  {
8998  *mro_candidate = true;
8999  }
9000 
9001 end:
9002  parser->flag.set_host_var = save_set_host_var;
9003  return valid;
9004 }
9005 
9006 /*
9007  * pt_get_query_limit_from_orderby_for () - get upper limit value for orderby_for expression
9008  *
9009  * return : true if a valid order by for expression, else false
9010  * parser (in) : parser context
9011  * orderby_for (in) : order by for node
9012  * upper_limit (out) : DB_VALUE pointer that will save the upper limit
9013  *
9014  * Note: Only operations that can reduce to ORDERBY_NUM () </<= VALUE are allowed:
9015  * 1. ORDERBY_NUM () LE/LT EXPR (which evaluates to a value).
9016  * 2. EXPR (which evaluates to a values) GE/GT ORDERBY_NUM ().
9017  * 3. Any number of #1 and #2 expressions linked by PT_AND logical operator.
9018  * Lower limits are allowed.
9019  */
9020 static int
9021 pt_get_query_limit_from_orderby_for (PARSER_CONTEXT * parser, PT_NODE * orderby_for, DB_VALUE * upper_limit,
9022  bool * has_limit)
9023 {
9024  int op;
9025  PT_NODE *arg_ordby_num = NULL;
9026  PT_NODE *rhs = NULL;
9027  PT_NODE *arg1 = NULL, *arg2 = NULL;
9028  PT_NODE *save_next = NULL;
9029  DB_VALUE limit;
9030  int error = NO_ERROR;
9031  bool lt = false;
9032 
9033  if (orderby_for == NULL || upper_limit == NULL)
9034  {
9035  return NO_ERROR;
9036  }
9037 
9038  assert_release (has_limit != NULL);
9039 
9040  if (!PT_IS_EXPR_NODE (orderby_for))
9041  {
9042  goto unusable_expr;
9043  }
9044 
9045  if (orderby_for->or_next != NULL)
9046  {
9047  /* OR operator is now useful */
9048  goto unusable_expr;
9049  }
9050 
9051  if (orderby_for->next)
9052  {
9053  /* AND operator */
9054  save_next = orderby_for->next;
9055  orderby_for->next = NULL;
9056  error = pt_get_query_limit_from_orderby_for (parser, orderby_for, upper_limit, has_limit);
9057  orderby_for->next = save_next;
9058  if (error != NO_ERROR)
9059  {
9060  goto unusable_expr;
9061  }
9062 
9063  return pt_get_query_limit_from_orderby_for (parser, orderby_for->next, upper_limit, has_limit);
9064  }
9065 
9066  op = orderby_for->info.expr.op;
9067 
9068  if (op != PT_LT && op != PT_LE && op != PT_GT && op != PT_GE && op != PT_BETWEEN)
9069  {
9070  goto unusable_expr;
9071  }
9072 
9073  arg1 = orderby_for->info.expr.arg1;
9074  arg2 = orderby_for->info.expr.arg2;
9075  if (arg1 == NULL || arg2 == NULL)
9076  {
9077  /* safe guard */
9078  goto unusable_expr;
9079  }
9080 
9081  /* look for orderby_for argument */
9082  if (PT_IS_EXPR_NODE (arg1) && arg1->info.expr.op == PT_ORDERBY_NUM)
9083  {
9084  arg_ordby_num = arg1;
9085  rhs = arg2;
9086  }
9087  else if (PT_IS_EXPR_NODE (arg2) && arg2->info.expr.op == PT_ORDERBY_NUM)
9088  {
9089  arg_ordby_num = arg2;
9090  rhs = arg1;
9091  /* reverse operators */
9092  switch (op)
9093  {
9094  case PT_LE:
9095  op = PT_GT;
9096  break;
9097  case PT_LT:
9098  op = PT_GE;
9099  break;
9100  case PT_GT:
9101  op = PT_LE;
9102  break;
9103  case PT_GE:
9104  op = PT_LT;
9105  break;
9106  default:
9107  break;
9108  }
9109  }
9110  else
9111  {
9112  /* orderby_for argument was not found, this is not a valid expression */
9113  goto unusable_expr;
9114  }
9115 
9116  if (op == PT_GE || op == PT_GT)
9117  {
9118  /* lower limits are acceptable but not useful */
9119  return NO_ERROR;
9120  }
9121 
9122  if (op == PT_LT)
9123  {
9124  lt = true;
9125  }
9126  else if (op == PT_BETWEEN)
9127  {
9128  PT_NODE *between_and = orderby_for->info.expr.arg2;
9129  PT_NODE *between_upper = NULL;
9130  int between_op;
9131 
9132  assert (between_and != NULL && between_and->node_type == PT_EXPR);
9133  between_upper = between_and->info.expr.arg2;
9134  between_op = between_and->info.expr.op;
9135  switch (between_op)
9136  {
9137  case PT_BETWEEN_GT_LT:
9138  case PT_BETWEEN_GE_LT:
9139  lt = true;
9140  /* fall through */
9141  case PT_BETWEEN_AND:
9142  case PT_BETWEEN_GE_LE:
9143  case PT_BETWEEN_GT_LE:
9144  assert (between_and->info.expr.arg2 != NULL);
9145  rhs = between_and->info.expr.arg2;
9146  break;
9147  case PT_BETWEEN_EQ_NA:
9148  case PT_BETWEEN_GE_INF:
9149  case PT_BETWEEN_GT_INF:
9150  /* lower limits are acceptable but not useful */
9151  return NO_ERROR;
9152  default:
9153  /* be conservative */
9154  goto unusable_expr;
9155  }
9156  }
9157 
9158  /* evaluate the rhs expression */
9159  db_make_null (&limit);
9160  if (PT_IS_CONST (rhs) || PT_IS_CAST_CONST_INPUT_HOSTVAR (rhs))
9161  {
9162  pt_evaluate_tree_having_serial (parser, rhs, &limit, 1);
9163  }
9164 
9165  if (DB_IS_NULL (&limit)
9167  {
9168  /* has unusable upper_limit */
9169  pr_clear_value (upper_limit);
9170  *has_limit = true;
9171  return NO_ERROR;
9172  }
9173 
9174  if (lt)
9175  {
9176  /* ORDERBY_NUM () < n => ORDERBY_NUM <= n - 1 */
9177  db_make_bigint (&limit, (db_get_bigint (&limit) - 1));
9178  }
9179  if (DB_IS_NULL (upper_limit) || (db_get_bigint (upper_limit) > db_get_bigint (&limit)))
9180  {
9181  /* update upper limit */
9182  if (pr_clone_value (&limit, upper_limit) != NO_ERROR)
9183  {
9184  goto unusable_expr;
9185  }
9186  }
9187 
9188  *has_limit = true;
9189  return NO_ERROR;
9190 
9191 unusable_expr:
9192  *has_limit = false;
9193  pr_clear_value (upper_limit);
9194  return ER_FAILED;
9195 }
9196 
9197 /*
9198  * pt_find_node_type_pre () - Use parser_walk_tree to find a node with a
9199  * specific node type.
9200  *
9201  * return : node.
9202  * parser (in) : parser context.
9203  * node (in) : node in parse tree.
9204  * arg (in) : int array containing node type and found.
9205  * continue_walk (in) : continue walk.
9206  *
9207  * NOTE: Make sure to set found to 0 before calling parser_walk_tree.
9208  */
9209 PT_NODE *
9210 pt_find_node_type_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9211 {
9212  int node_type = *((int *) arg);
9213  int *found_p = ((int *) arg) + 1;
9214 
9215  if (*found_p || *continue_walk == PT_STOP_WALK || node == NULL)
9216  {
9217  return node;
9218  }
9219  if (node->node_type == node_type)
9220  {
9221  *found_p = 1;
9222  *continue_walk = PT_STOP_WALK;
9223  }
9224  return node;
9225 }
9226 
9227 /*
9228  * pt_find_op_type_pre () - Use parser_walk_tree to find an operator of a
9229  * specific type.
9230  *
9231  * return : node.
9232  * parser (in) : parser context.
9233  * node (in) : node in parse tree.
9234  * arg (in) : int array containing expr type and found.
9235  * continue_walk (in) : continue walk.
9236  *
9237  * NOTE: Make sure to set found to 0 before calling parser_walk_tree.
9238  */
9239 PT_NODE *
9240 pt_find_op_type_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9241 {
9242  int op_type = *((int *) arg);
9243  int *found_p = ((int *) arg) + 1;
9244 
9245  if (*found_p || *continue_walk == PT_STOP_WALK || node == NULL)
9246  {
9247  return node;
9248  }
9249  if (node->node_type == PT_EXPR && node->info.expr.op == op_type)
9250  {
9251  *found_p = 1;
9252  *continue_walk = PT_STOP_WALK;
9253  }
9254  return node;
9255 }
9256 
9257 /*
9258  * pt_partition_name - get actual class name of a partition from root class name
9259  * and partition suffix
9260  * return: partition class name
9261  * parser (in) : parser context
9262  * class_name (in): partitioned class name
9263  * partition (in) : partition suffix
9264  */
9265 const char *
9266 pt_partition_name (PARSER_CONTEXT * parser, const char *class_name, const char *partition)
9267 {
9268  char *name = NULL, *buf = NULL;
9269  int size = 0;
9270  size = strlen (class_name) + strlen (partition) + strlen (PARTITIONED_SUB_CLASS_TAG);
9271 
9272  buf = (char *) calloc (size + 1, sizeof (char));
9273  if (buf == NULL)
9274  {
9276  return NULL;
9277  }
9278 
9279  sprintf (buf, "%s" PARTITIONED_SUB_CLASS_TAG "%s", class_name, partition);
9280  name = pt_append_string (parser, name, buf);
9281 
9282  free (buf);
9283  return name;
9284 }
9285 
9286 /*
9287  * pt_free_statement_xasl_id () - free XASL_ID object of a prepared statement
9288  * return : void
9289  * statement (in) : statement
9290  */
9291 void
9293 {
9294  if (statement == NULL)
9295  {
9296  return;
9297  }
9298 
9299  if (statement->xasl_id != NULL)
9300  {
9301  free_and_init (statement->xasl_id);
9302  }
9303 
9304  if (statement->node_type == PT_DELETE)
9305  {
9306  /* free xasl_id for computed individual select statements */
9307  PT_NODE *del_stmt;
9308  for (del_stmt = statement->info.delete_.del_stmt_list; del_stmt != NULL; del_stmt = del_stmt->next)
9309  {
9310  if (del_stmt->xasl_id != NULL)
9311  {
9312  free_and_init (del_stmt->xasl_id);
9313  }
9314  }
9315  }
9316 }
9317 
9318 /*
9319  * pt_check_enum_data_type - validate the ENUM data type
9320  * return: NO_ERROR or error code
9321  * parser (in) : parser context
9322  * dt (in/out) : ENUM data type
9323  *
9324  * NOTE: The function removes trailing pads for each ENUM element, checks that
9325  * the number of elements is lower or equal than DB_ENUM_ELEMENTS_MAX, checks
9326  * that the aggregate size of the ENUM elements is not greater than
9327  * DB_ENUM_ELEMENTS_MAX_AGG_SIZE and checks for duplicates
9328  */
9329 int
9331 {
9332  int count = 0, err = NO_ERROR;
9333  PT_NODE *node = NULL, *temp = NULL;
9334  TP_DOMAIN *domain = NULL;
9335  int pad_size = 0, trimmed_length = 0, trimmed_size = 0;
9336  int char_count = 0;
9337  unsigned char pad[2];
9338 
9339  bool ti = true;
9340  static bool ignore_trailing_space = prm_get_bool_value (PRM_ID_IGNORE_TRAILING_SPACE);
9341 
9342  if (dt == NULL || dt->node_type != PT_DATA_TYPE || dt->type_enum != PT_TYPE_ENUMERATION)
9343  {
9344  return NO_ERROR;
9345  }
9346 
9347  /* remove trailing pads for each element */
9348  intl_pad_char ((INTL_CODESET) dt->info.data_type.units, pad, &pad_size);
9349  node = dt->info.data_type.enumeration;
9350  while (node != NULL)
9351  {
9353  (INTL_CODESET) dt->info.data_type.units, &char_count);
9354  qstr_trim_trailing (pad, pad_size, node->info.value.data_value.str->bytes, pt_node_to_db_type (node), char_count,
9356  &trimmed_length, &trimmed_size, true);
9357  if (trimmed_size < node->info.value.data_value.str->length)
9358  {
9359  node->info.value.data_value.str =
9360  pt_append_bytes (parser, NULL, (const char *) node->info.value.data_value.str->bytes, trimmed_size);
9361  node->info.value.data_value.str->length = trimmed_size;
9362  if (node->info.value.db_value.need_clear)
9363  {
9364  pr_clear_value (&node->info.value.db_value);
9365  }
9367  {
9368  node->info.value.db_value_is_initialized = false;
9369  pt_value_to_db (parser, node);
9370  }
9371  }
9372 
9373  node = node->next;
9374  count++;
9375  }
9376 
9377  /* check that number of elements is lower or equal than DB_ENUM_ELEMENTS_MAX */
9378  if (count > DB_ENUM_ELEMENTS_MAX)
9379  {
9382  err = ER_FAILED;
9383  goto end;
9384  }
9385 
9386  /* check that the aggregate size of the ENUM elements is not greater than DB_ENUM_ELEMENTS_MAX_AGG_SIZE */
9387  domain = pt_data_type_to_db_domain (parser, dt, NULL);
9388  if (domain == NULL)
9389  {
9390  PT_INTERNAL_ERROR (parser, "Cannot create domain");
9391  return ER_FAILED;
9392  }
9393  count = or_packed_domain_size (domain, 0);
9394  if (count > (int) DB_ENUM_ELEMENTS_MAX_AGG_SIZE)
9395  {
9397  err = ER_FAILED;
9398  goto end;
9399  }
9400 
9401  /* check duplicates */
9402  node = dt->info.data_type.enumeration;
9403  while (node != NULL && err == NO_ERROR)
9404  {
9405  temp = node->next;
9406  while (temp != NULL)
9407  {
9408  if (!ignore_trailing_space)
9409  {
9410  ti = (domain->type->id == DB_TYPE_CHAR || domain->type->id == DB_TYPE_NCHAR);
9411  }
9412 
9413  if (QSTR_COMPARE (domain->collation_id, node->info.value.data_value.str->bytes,
9414  node->info.value.data_value.str->length, temp->info.value.data_value.str->bytes,
9415  temp->info.value.data_value.str->length, ti) == 0)
9416  {
9418 
9419  err = ER_FAILED;
9420  break;
9421  }
9422  temp = temp->next;
9423  }
9424  node = node->next;
9425  }
9426 
9427 end:
9428  if (domain != NULL)
9429  {
9430  tp_domain_free (domain);
9431  }
9432 
9433  return err;
9434 }
9435 
9436 /*
9437  * pt_recompile_for_limit_optimizations () - verify is query plan should be
9438  * regenerated for a query due to
9439  * limit change
9440  * return : true/false
9441  * parser (in) : parser context
9442  * statement (in) : statement
9443  * xasl_flag (in) : flag which contains plan information
9444  *
9445  * Note: before executing a query plan, we have to verify if the generated
9446  * plan is still valid with the new limit values. There are four cases:
9447  * I. MRO is used but the new limit value is either too large or invalid
9448  * for this plan. In this case we have to recompile.
9449  * II. MRO is not used but the new limit value is valid for generating such
9450  * a plan. In this case we have to recompile.
9451  * III. MRO is not used and the new limit value is invalid for generating this
9452  * plan. In this case we don't have to recompile
9453  * VI. MRO is used and the new limit value is valid for this plan. In this
9454  * case we don't have to recompile
9455  * The same rules apply to SORT-LIMIT plans
9456  */
9457 bool
9458 pt_recompile_for_limit_optimizations (PARSER_CONTEXT * parser, PT_NODE * statement, int xasl_flag)
9459 {
9460  DB_VALUE limit_val;
9461  DB_BIGINT val = 0;
9462  int limit_opt_flag = (MRO_CANDIDATE | MRO_IS_USED | SORT_LIMIT_CANDIDATE | SORT_LIMIT_USED);
9463 
9464  if (!(xasl_flag & limit_opt_flag))
9465  {
9466  return false;
9467  }
9468 
9469  if (pt_get_query_limit_value (parser, statement, &limit_val) != NO_ERROR)
9470  {
9471  val = 0;
9472  }
9473  else if (DB_IS_NULL (&limit_val))
9474  {
9475  val = 0;
9476  }
9477  else
9478  {
9479  val = db_get_bigint (&limit_val);
9480  }
9481 
9482  /* verify MRO */
9483  if (xasl_flag & (MRO_CANDIDATE | MRO_IS_USED))
9484  {
9486  {
9487  if (xasl_flag & MRO_IS_USED)
9488  {
9489  /* Need to recompile because limit is not suitable for MRO anymore */
9490  return true;
9491  }
9492  }
9493  else if ((xasl_flag & MRO_CANDIDATE) && !(xasl_flag & MRO_IS_USED))
9494  {
9495  /* Suitable limit for MRO but MRO is not used. Recompile to use MRO */
9496  return true;
9497  }
9498  return false;
9499  }
9500 
9501  /* verify SORT-LIMIT */
9502  if (xasl_flag & (SORT_LIMIT_CANDIDATE | SORT_LIMIT_USED))
9503  {
9505  {
9506  if (xasl_flag & SORT_LIMIT_USED)
9507  {
9508  /* Need to recompile because limit is not suitable for SORT-LIMIT anymore */
9509  return true;
9510  }
9511  }
9512  else if ((xasl_flag & SORT_LIMIT_CANDIDATE) && !(xasl_flag & SORT_LIMIT_USED))
9513  {
9514  /* Suitable limit for SORT-LIMIT but SORT-LIMIT is not used. Recompile to use SORT-LIMIT */
9515  return true;
9516  }
9517  return false;
9518  }
9519 
9520  return false;
9521 }
9522 
9523 /*
9524  * pt_make_query_show_trace () -
9525  * return: node
9526  */
9527 PT_NODE *
9529 {
9530  PT_NODE *select, *trace_func;
9531 
9532  select = parser_new_node (parser, PT_SELECT);
9533  if (select == NULL)
9534  {
9535  return NULL;
9536  }
9537 
9539 
9540  trace_func = parser_make_expression (parser, PT_TRACE_STATS, NULL, NULL, NULL);
9541  if (trace_func == NULL)
9542  {
9543  return NULL;
9544  }
9545 
9546  trace_func->alias_print = pt_append_string (parser, NULL, "trace");
9547  select->info.query.q.select.list = parser_append_node (trace_func, select->info.query.q.select.list);
9548 
9549  parser->flag.dont_collect_exec_stats = 1;
9550  parser->query_trace = false;
9551 
9552  return select;
9553 }
9554 
9555 /*
9556  * pt_has_non_groupby_column_node () - Use parser_walk_tree to check having
9557  * clause.
9558  * return : node.
9559  * parser (in) : parser context.
9560  * node (in) : name node in having clause.
9561  * arg (in) : pt_non_groupby_col_info
9562  * continue_walk (in) : continue walk.
9563  *
9564  * NOTE: Make sure to set has_non_groupby_col to false before calling
9565  * parser_walk_tree.
9566  */
9567 PT_NODE *
9568 pt_has_non_groupby_column_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9569 {
9570  PT_NON_GROUPBY_COL_INFO *info = NULL;
9571  PT_NODE *groupby_p = NULL;
9572 
9573  if (arg == NULL)
9574  {
9575  assert (false);
9576  return node;
9577  }
9578 
9579  info = (PT_NON_GROUPBY_COL_INFO *) arg;
9580  groupby_p = info->groupby;
9581 
9582  if (node == NULL || groupby_p == NULL)
9583  {
9584  assert (false);
9585  return node;
9586  }
9587 
9588  if (!PT_IS_NAME_NODE (node))
9589  {
9590  return node;
9591  }
9592 
9593  for (; groupby_p; groupby_p = groupby_p->next)
9594  {
9595  if (!(PT_IS_SORT_SPEC_NODE (groupby_p) && PT_IS_NAME_NODE (groupby_p->info.sort_spec.expr)))
9596  {
9597  continue;
9598  }
9599 
9600  if (pt_name_equal (parser, groupby_p->info.sort_spec.expr, node))
9601  {
9602  return node;
9603  }
9604  }
9605 
9606  /* the name node is not associated with groupby columns. */
9607  info->has_non_groupby_col = true;
9608  *continue_walk = PT_STOP_WALK;
9609 
9610  return node;
9611 }
9612 
9613 /*
9614  * pt_get_default_value_from_attrnode () - get default value from data default node
9615  * return : error code or NO_ERROR
9616  *
9617  * parser (in) : parser context
9618  * data_default_node (in) : attribute node
9619  * default_expr (out) : default expression
9620  */
9621 void
9623  DB_DEFAULT_EXPR * default_expr)
9624 {
9625  PT_NODE *pt_default_expr = NULL;
9626  DB_VALUE *db_value_default_expr_format = NULL;
9627  assert (parser != NULL && default_expr != NULL);
9628 
9629  classobj_initialize_default_expr (default_expr);
9630  if (data_default_node != NULL)
9631  {
9632  assert (data_default_node->node_type == PT_DATA_DEFAULT);
9633  default_expr->default_expr_type = data_default_node->info.data_default.default_expr_type;
9634 
9635  pt_default_expr = data_default_node->info.data_default.default_value;
9636  if (pt_default_expr && pt_default_expr->node_type == PT_EXPR)
9637  {
9638  if (pt_default_expr->info.expr.op == PT_TO_CHAR)
9639  {
9640  default_expr->default_expr_op = T_TO_CHAR;
9641  assert (pt_default_expr->info.expr.arg2 != NULL
9642  && pt_default_expr->info.expr.arg2->node_type == PT_VALUE);
9643 
9644  if (PT_IS_CHAR_STRING_TYPE (pt_default_expr->info.expr.arg2->type_enum))
9645  {
9646  db_value_default_expr_format = pt_value_to_db (parser, pt_default_expr->info.expr.arg2);
9647  default_expr->default_expr_format = db_get_string (db_value_default_expr_format);
9648  }
9649  }
9650  }
9651  }
9652 }
9653 
9654 /*
9655  * pt_has_name_oid () - Check whether the node is oid name
9656  * return:
9657  * parser(in):
9658  * node(in):
9659  * arg(in):
9660  * continue_walk(in):
9661  */
9662 PT_NODE *
9663 pt_has_name_oid (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9664 {
9665  bool *has_name_oid = (bool *) arg;
9666 
9667  switch (node->node_type)
9668  {
9669  case PT_NAME:
9670  if (PT_IS_OID_NAME (node))
9671  {
9672  *has_name_oid = true;
9673  *continue_walk = PT_STOP_WALK;
9674  }
9675  break;
9676 
9677  case PT_DATA_TYPE:
9678  if (node->type_enum == PT_TYPE_OBJECT)
9679  {
9680  *has_name_oid = true;
9681  *continue_walk = PT_STOP_WALK;
9682  }
9683  break;
9684 
9685  default:
9686  break;
9687  }
9688 
9689  return node;
9690 }
#define PT_NAME_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2575
const SHOWSTMT_METADATA * showstmt_get_metadata(SHOWSTMT_TYPE show_type)
Definition: show_meta.c:734
int char_isspace(int c)
Definition: chartype.c:109
PT_NODE * order_by
Definition: parse_tree.h:2769
#define ER_REGU_SYSTEM
Definition: error_code.h:193
PT_NODE * pt_check_groupbynum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void pt_copy_statement_flags(PT_NODE *source, PT_NODE *destination)
PT_NODE * pt_compile(PARSER_CONTEXT *parser, PT_NODE *volatile statement)
Definition: compile.c:380
PT_NODE * next
Definition: parse_tree.h:3447
PT_NAME_INFO name
Definition: parse_tree.h:3318
PT_NODE * pt_make_query_show_collation(PARSER_CONTEXT *parser, int like_where_syntax, PT_NODE *like_or_where_expr)
TP_DOMAIN_STATUS tp_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
static PT_NODE * pt_make_sort_spec_with_number(PARSER_CONTEXT *parser, const int number_pos, PT_MISC_TYPE sort_mode)
QFILE_TUPLE_VALUE_POSITION pos_descr
Definition: parse_tree.h:2829
void pt_free_statement_xasl_id(PT_NODE *statement)
PT_NODE * pt_check_orderbynum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_ENUM_AGG_STRINGS_SIZE_TOO_LARGE
#define PT_IS_QUERY(n)
Definition: parse_tree.h:296
void describe_class(struct db_object *class_op)
PT_NODE * target_classes
Definition: parse_tree.h:2060
PT_NODE * arg_list
Definition: parse_tree.h:2258
static PT_NODE * pt_is_spec_referenced(PARSER_CONTEXT *parser, PT_NODE *node, void *void_arg, int *continue_walk)
#define NO_ERROR
Definition: error_code.h:46
PT_UNION_INFO union_
Definition: parse_tree.h:2782
unsigned dont_collect_exec_stats
Definition: parse_tree.h:3621
#define PT_IS_NUMBERING_AFTER_EXECUTION(op)
Definition: parse_tree.h:455
PT_NODE * pt_from_entity_part(const PT_NODE *node)
PT_NODE * out_descr
void qstr_trim_trailing(const unsigned char *trim_charset_ptr, int trim_charset_size, const unsigned char *src_ptr, DB_TYPE src_type, int src_length, int src_size, INTL_CODESET codeset, int *trail_trimmed_length, int *trail_trimmed_size, bool trim_ascii_spaces)
#define LANG_SYS_COLLATION
#define PT_SELECT_INFO_IS_FLAGED(s, f)
Definition: parse_tree.h:2735
PT_UPDATE_INFO update
Definition: parse_tree.h:3353
PT_MERGE_INFO merge
Definition: parse_tree.h:3315
UINTPTR id
Definition: parse_tree.h:2144
PT_NODE * pt_find_aggregate_names(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
static PT_NODE * pt_rewrite_derived_for_upd_del(PARSER_CONTEXT *parser, PT_NODE *spec, PT_SPEC_FLAG what_for, bool add_as_attr)
#define MSGCAT_SEMANTIC_UNEXPECTED_NTH_ARGUMENT
PT_NODE * pt_is_inst_or_orderby_num_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
static const int PACKING_MMGR_BLOCK_SIZE
int pt_check_grammar_charset_collation(PARSER_CONTEXT *parser, PT_NODE *charset_node, PT_NODE *coll_node, int *charset, int *coll_id)
#define PT_IS_SORT_SPEC_NODE(n)
Definition: parse_tree.h:473
PT_NODE ** parser_parse_string_use_sys_charset(PARSER_CONTEXT *parser, const char *buffer)
void regu_set_global_error(void)
#define PT_IS_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:164
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
TP_DOMAIN * expected_domain
Definition: parse_tree.h:3452
PT_NODE * pt_limit_to_numbering_expr(PARSER_CONTEXT *parser, PT_NODE *limit, PT_OP_TYPE num_op, bool is_gby_num)
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
PT_NODE * show_args
Definition: parse_tree.h:2816
const char * str
Definition: parse_tree.h:2316
bool pt_check_ordby_num_for_multi_range_opt(PARSER_CONTEXT *parser, PT_NODE *query, bool *mro_candidate, bool *cannot_eval)
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
PT_NODE * default_value
Definition: parse_tree.h:2004
PT_MISC_TYPE var_type
Definition: parse_tree.h:2317
PT_NODE * assignment
Definition: parse_tree.h:2861
PARSER_VARCHAR * expr_before_const_folding
Definition: parse_tree.h:3456
#define COMPATIBLE_WITH_INSTNUM(node)
PT_NODE * parser_keyword_func(const char *name, PT_NODE *args)
const char * pt_partition_name(PARSER_CONTEXT *parser, const char *class_name, const char *partition)
PT_NODE * pt_check_orderbynum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_HOST_VARS * pt_host_info(PARSER_CONTEXT *parser, PT_NODE *stmt)
PT_NODE * pt_node_list(PARSER_CONTEXT *parser, PT_MISC_TYPE list_type, PT_NODE *list)
#define PT_EXPR_INFO_GROUPBYNUM_C
Definition: parse_tree.h:2211
PT_MISC_TYPE
Definition: parse_tree.h:983
#define PARTITIONED_SUB_CLASS_TAG
Definition: parse_tree.h:2033
PT_NODE * pt_is_pseudocolumn_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
void pt_report_to_ersys_with_statement(PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type, PT_NODE *statement)
Definition: query_result.c:338
static void pt_free_packing_buf(int slot)
int db_make_bigint(DB_VALUE *value, const DB_BIGINT num)
int pt_host_var_index(const PT_NODE *hv)
#define PT_SELECT_INFO_IS_UPD_DEL_QUERY
Definition: parse_tree.h:2729
PT_NODE * assignment
Definition: parse_tree.h:2928
void pt_register_orphan(PARSER_CONTEXT *parser, const PT_NODE *orphan)
#define ER_FAILED
Definition: error_code.h:47
int db_make_varchar(DB_VALUE *value, const int max_char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
#define MSGCAT_SEMANTIC_OUT_OF_MEMORY
#define PT_REQUIRES_HIERARCHICAL_QUERY(op)
Definition: parse_tree.h:439
PT_MISC_TYPE all_or_distinct
Definition: parse_tree.h:2260
#define PT_EXPR_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2239
PT_NODE * pt_make_integer_value(PARSER_CONTEXT *parser, const int value_int)
PT_NODE * pt_get_subquery_of_insert_select(const PT_NODE *node)
PT_NODE * search_cond
Definition: parse_tree.h:2925
PT_NODE * pt_check_instnum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * arg3
Definition: parse_tree.h:2202
int pt_is_method_call(PT_NODE *node)
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
PT_HINT_ENUM hint
Definition: parse_tree.h:2074
DB_AUTH auth_bypass_mask
Definition: parse_tree.h:2154
int pt_get_dup_key_oid_var_index(PARSER_CONTEXT *parser, PT_NODE *update_statement)
PT_NODE * arg2
Definition: parse_tree.h:2664
#define MSGCAT_SEMANTIC_ONLY_ONE_UPDATE_SPEC_ALLOWED
#define PT_SELECT_INFO_DISABLE_LOOSE_SCAN
Definition: parse_tree.h:2731
int correlation_level
Definition: parse_tree.h:2745
PT_TABLE_OPTION_INFO table_option
Definition: parse_tree.h:3347
PT_NODE * pt_get_cursor(const PT_HOST_VARS *hv)
bool pt_is_expr_wrapped_function(PARSER_CONTEXT *parser, const PT_NODE *node)
const char * pt_get_select_from_name(PARSER_CONTEXT *parser, const PT_NODE *spec)
void pt_check_level_expr(PARSER_CONTEXT *parser, PT_NODE *expr, bool *has_greater, bool *has_lesser)
#define assert_release(e)
Definition: error_manager.h:96
#define SM_MAX_IDENTIFIER_LENGTH
PT_NODE * pt_has_name_oid(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * spec
Definition: parse_tree.h:2859
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
FUNC_TYPE
PARSER_CONTEXT * parser_create_parser(void)
Definition: parse_tree.c:1169
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
static PT_NODE * pt_make_query_user_groups(PARSER_CONTEXT *parser, const char *user_name)
static PT_NODE * pt_must_be_filtering(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * pt_make_query_show_grants_curr_usr(PARSER_CONTEXT *parser)
#define PT_SELECT_INFO_HAS_ANALYTIC
Definition: parse_tree.h:2718
bool au_is_dba_group_member(MOP user)
static PT_NODE * pt_make_if_with_expressions(PARSER_CONTEXT *parser, PT_NODE *pred, PT_NODE *expr1, PT_NODE *expr2, const char *alias)
void pt_get_default_expression_from_data_default_node(PARSER_CONTEXT *parser, PT_NODE *data_default_node, DB_DEFAULT_EXPR *default_expr)
#define PT_EXPR_INFO_INSTNUM_NC
Definition: parse_tree.h:2210
static PT_NODE * pt_make_pred_with_identifiers(PARSER_CONTEXT *parser, PT_OP_TYPE op_type, const char *lhs_identifier, const char *rhs_identifier)
PARSER_VARCHAR * pt_append_bytes(const PARSER_CONTEXT *parser, PARSER_VARCHAR *old_string, const char *new_tail, const int new_tail_length)
Definition: parse_tree.c:1014
PT_SPEC_FLAG
Definition: parse_tree.h:1517
union pt_query_info::@124 q
char * pt_alloc_packing_buf(int size)
void pt_exit_packing_buf(void)
int pt_check_enum_data_type(PARSER_CONTEXT *parser, PT_NODE *dt)
PT_NODE * class_specs
Definition: parse_tree.h:2062
PT_NODE * path_entities
Definition: parse_tree.h:2138
PT_NODE * node
Definition: parse_tree.h:3133
PT_NODE * pt_make_query_show_exec_stats_all(PARSER_CONTEXT *parser)
struct pt_merge_info::@125 update
PT_NODE * pt_has_non_idx_sarg_coll_pre(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
#define PT_IS_NULL_NODE(e)
Definition: parse_tree.h:122
PT_NODE * select_stack
Definition: parse_tree.h:3395
PT_NODE * group_by
Definition: parse_tree.h:2688
unsigned set_host_var
Definition: parse_tree.h:3605
int er_errid(void)
SHOWSTMT_TYPE show_type
Definition: parse_tree.h:2815
#define PT_NAME_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2574
void db_string_free(char *string)
Definition: db_admin.c:2596
PT_NODE_LIST_INFO node_list
Definition: parse_tree.h:3320
PT_NODE * pt_expression_3(PARSER_CONTEXT *parser, PT_OP_TYPE op, PT_NODE *arg1, PT_NODE *arg2, PT_NODE *arg3)
int pt_instnum_compatibility(PT_NODE *expr)
SHOWSTMT_TYPE
#define MSGCAT_SEMANTIC_NOT_ALLOWED_HERE
bool pt_sort_spec_cover(PT_NODE *cur_list, PT_NODE *new_list)
PT_NODE * pt_check_subquery_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int or_packed_domain_size(struct tp_domain *domain, int include_classoids)
PT_NODE * pt_expression_2(PARSER_CONTEXT *parser, PT_OP_TYPE op, PT_NODE *arg1, PT_NODE *arg2)
const char * pt_show_misc_type(PT_MISC_TYPE p)
PT_NODE * attr_list
Definition: parse_tree.h:2333
DB_VALUE * host_variables
Definition: parse_tree.h:3560
int pt_node_list_to_array(PARSER_CONTEXT *parser, PT_NODE *arg_list, PT_NODE *arg_array[], const int array_size, int *num_args)
PT_NODE * pt_get_first_arg_ignore_prior(PT_NODE *node)
PT_NODE * pt_add_row_oid_name(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: compile.c:347
void pt_final_packing_buf(void)
PT_NODE * class_specs
Definition: parse_tree.h:2860
PT_NODE * pt_check_subquery_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * data_type
Definition: parse_tree.h:3453
#define MSGCAT_SEMANTIC_IS_NOT_A
PT_NODE * del_stmt_list
Definition: parse_tree.h:2073
#define PT_IS_OID_NAME(n)
Definition: parse_tree.h:323
#define pt_is_instnum(n)
Definition: parse_tree.h:277
struct parser_context::@134 flag
PT_NODE * pt_is_inst_or_orderby_num_node_post(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: parse_tree.h:2006
static PT_NODE * pt_make_like_col_expr(PARSER_CONTEXT *parser, PT_NODE *rhs_expr, const char *col_name)
PT_NODE * pt_class_part(const PT_NODE *node)
PT_DOT_INFO dot
Definition: parse_tree.h:3287
PT_NODE * arg2
Definition: parse_tree.h:2086
DB_QUERY_TYPE * pt_fillin_type_size(PARSER_CONTEXT *parser, PT_NODE *query, DB_QUERY_TYPE *list, const int include_oid, bool want_spec_entity_name, bool fixup_columns_type)
Definition: query_result.c:893
PT_NODE * pt_find_node_type_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * pt_is_analytic_node_post(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
unsigned force_auto_parameterize
Definition: parse_tree.h:3473
static int pt_add_name_col_to_sel_list(PARSER_CONTEXT *parser, PT_NODE *select, const char *identifier_str, const char *col_alias)
void parser_free_parser(PARSER_CONTEXT *parser)
Definition: parse_tree.c:1240
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
int intl_identifier_lower(const char *src, char *dst)
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
#define NOT_COMPATIBLE_WITH_GROUPBYNUM(node)
PT_NODE * pt_expr_disallow_op_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
FUNC_TYPE function_type
Definition: parse_tree.h:2259
PT_TYPE_ENUM type_enum
Definition: parse_tree.h:3457
PT_NODE * use_merge_hint
Definition: parse_tree.h:2071
PT_NODE * or_next
Definition: parse_tree.h:3448
unsigned char bytes[1]
Definition: parse_tree.h:3431
#define ER_UNEXPECTED
Definition: error_code.h:1254
PT_NODE * pt_find_spec_in_statement(PARSER_CONTEXT *parser, const PT_NODE *stmt, const PT_NODE *name)
PT_NODE * pt_expression_0(PARSER_CONTEXT *parser, PT_OP_TYPE op)
PT_NODE * limit
Definition: parse_tree.h:2773
PT_NODE * warnings
Definition: parse_tree.h:3551
PT_MISC_TYPE derived_table_type
Definition: parse_tree.h:2147
static PT_NODE * pt_make_dotted_identifier(PARSER_CONTEXT *parser, const char *identifier_str)
PT_NODE * pt_right_part(const PT_NODE *node)
PT_NODE * arg1
Definition: parse_tree.h:2663
#define PT_NODE_PRINT_VALUE_TO_TEXT(p, n)
Definition: parse_tree.h:597
bool pt_has_analytic(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_make_query_describe_w_identifier(PARSER_CONTEXT *parser, PT_NODE *original_cls_id, PT_NODE *att_id)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void classobj_initialize_default_expr(DB_DEFAULT_EXPR *default_expr)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
const SHOWSTMT_NAMED_ARG * args
Definition: show_meta.h:75
#define MSGCAT_SEMANTIC_TOO_FEW_ARGUMENT
INTL_CODESET codeset
PT_NODE * arg2
Definition: parse_tree.h:2198
bool pt_recompile_for_limit_optimizations(PARSER_CONTEXT *parser, PT_NODE *statement, int xasl_flag)
LANG_COLLATION * lang_get_collation(const int coll_id)
void * db_ostk_alloc(HL_HEAPID heap_id, size_t size)
Definition: memory_alloc.c:262
PT_FUNCTION_INFO function
Definition: parse_tree.h:3301
PT_NODE * orphans
Definition: parse_tree.h:3545
#define CAST_POINTER_TO_NODE(p)
Definition: parse_tree.h:607
DB_OBJECT * db_object
Definition: parse_tree.h:2546
int pt_is_ddl_statement(const PT_NODE *node)
PT_NODE * parser_make_expression(PARSER_CONTEXT *parser, PT_OP_TYPE OP, PT_NODE *arg1, PT_NODE *arg2, PT_NODE *arg3)
#define PT_ERRORmf2(parser, node, setNo, msgNo, arg1, arg2)
Definition: parse_tree.h:65
#define assert(x)
PT_NODE * inputs
const SHOWSTMT_COLUMN_ORDERBY * orderby
Definition: show_meta.h:73
PT_NODE * pt_make_query_show_grants(PARSER_CONTEXT *parser, const char *original_user_name)
PT_NODE * outputs
PT_NODE * pt_node_next(const PT_NODE *node)
#define PT_IS_QUERY_NODE_TYPE(x)
Definition: parse_tree.h:115
static PT_NODE * pt_create_delete_stmt(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *target_class)
bool pt_sort_spec_cover_groupby(PARSER_CONTEXT *parser, PT_NODE *sort_list, PT_NODE *group_list, PT_NODE *tree)
PT_SPEC_FLAG flag
Definition: parse_tree.h:2155
PT_NODE * pt_get_parameters(PARSER_CONTEXT *parser, PT_NODE *stmt)
PT_POINTER_INFO pointer
Definition: parse_tree.h:3359
int prm_get_integer_value(PARAM_ID prm_id)
void pt_evaluate_tree(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_values, int values_count)
PT_MISC_TYPE asc_or_desc
Definition: parse_tree.h:2830
#define ER_GENERIC_ERROR
Definition: error_code.h:49
void intl_pad_char(const INTL_CODESET codeset, unsigned char *pad_char, int *pad_size)
#define ERROR1(error, code, arg1)
Definition: error_manager.h:56
char * db_get_database_name(void)
Definition: db_admin.c:432
DB_VALUE db_value
Definition: parse_tree.h:3059
#define MSGCAT_SEMANTIC_INCOMPATIBLE_CS_COLL
PT_NODE * pt_expression(PARSER_CONTEXT *parser, PT_OP_TYPE op, PT_NODE *arg1, PT_NODE *arg2, PT_NODE *arg3)
void pt_fixup_column_type(PT_NODE *col)
PT_NODE * on_cond
Definition: parse_tree.h:2149
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void regu_set_error_with_zero_args(int err_type)
static PT_NODE * pt_make_collation_expr_node(PARSER_CONTEXT *parser)
#define MSGCAT_SET_PARSER_RUNTIME
PT_INCLUDE_OID_TYPE oid_included
Definition: parse_tree.h:3586
int pt_is_attr(PT_NODE *node)
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
static PT_NODE * pt_resolve_showstmt_args_unnamed(PARSER_CONTEXT *parser, const SHOWSTMT_NAMED_ARG *arg_infos, int arg_info_count, PT_NODE *args)
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
PT_NODE ** parser_parse_string(PARSER_CONTEXT *parser, const char *buffer)
LANG_COLLATION * lang_get_collation_by_name(const char *coll_name)
PT_NODE * pt_make_string_value(PARSER_CONTEXT *parser, const char *value_string)
PT_MISC_TYPE all_distinct
Definition: parse_tree.h:2746
const char * original
Definition: parse_tree.h:2544
static PT_NODE * pt_process_spec_for_delete(PARSER_CONTEXT *parser, PT_NODE *spec)
PT_MISC_TYPE nulls_first_or_last
Definition: parse_tree.h:2831
int intl_identifier_casecmp(const char *str1, const char *str2)
void pt_evaluate_tree_having_serial(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_value, int vals_cnt)
INTL_CODESET lang_charset_cubrid_name_to_id(const char *name)
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
PT_NODE * pt_dup_key_update_stmt(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *assignment)
#define PT_EXPR_INFO_GROUPBYNUM_LIMIT
Definition: parse_tree.h:2233
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
int pt_split_delete_stmt(PARSER_CONTEXT *parser, PT_NODE *delete_stmt)
int pt_is_function_index_expression(PT_NODE *node)
HL_HEAPID db_create_ostk_heap(int chunk_size)
Definition: memory_alloc.c:239
void pt_register_orphan_db_value(PARSER_CONTEXT *parser, const DB_VALUE *orphan)
PT_NODE * parser_copy_tree(PARSER_CONTEXT *parser, const PT_NODE *tree)
PT_NODE * pt_rewrite_to_auto_param(PARSER_CONTEXT *parser, PT_NODE *value)
static void pt_help_show_create_table(PARSER_CONTEXT *parser, PT_NODE *table_name, string_buffer &strbuf)
PT_SHOWSTMT_INFO showstmt
Definition: parse_tree.h:3342
PT_NODE * having
Definition: parse_tree.h:2692
DB_DOMAIN * pt_data_type_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *dt, const char *class_name)
Definition: parse_dbi.c:1805
PT_NODE * from
Definition: parse_tree.h:2686
#define PT_SELECT_INFO_HAS_AGG
Definition: parse_tree.h:2717
const char * pt_show_binopcode(PT_OP_TYPE n)
#define PT_NAME_INFO_CONSTANT
Definition: parse_tree.h:2562
const char * pt_get_spec_name(PARSER_CONTEXT *parser, const PT_NODE *selqry)
#define PT_SELECT_INFO_COLS_SCHEMA
Definition: parse_tree.h:2721
#define PT_IS_CONST(n)
Definition: parse_tree.h:364
#define MSGCAT_SEMANTIC_MISSING_ARGUMENT
int pt_statement_line_number(const PT_NODE *stmt)
PT_NODE * enumeration
Definition: parse_tree.h:2039
UINTPTR spec_id
Definition: parse_tree.h:2543
#define PT_IS_VALUE_NODE(n)
Definition: parse_tree.h:330
#define PT_SELECT_INFO_IS_MERGE_QUERY
Definition: parse_tree.h:2723
PT_NODE * value_clauses
Definition: parse_tree.h:2938
#define PT_IS_INSTNUM(n)
Definition: parse_tree.h:387
#define MSGCAT_SEMANTIC_TOO_MANY_ARGUMENT
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
void pt_enter_packing_buf(void)
static void cleanup(int signo)
Definition: broker.c:717
PARSER_VARCHAR * str
Definition: parse_tree.h:3036
SP_PARSER_CTX * parser
PT_NODE * arg1
Definition: parse_tree.h:2197
#define NULL
Definition: freelistheap.h:34
PT_NODE * pt_pointer_stack_pop(PARSER_CONTEXT *parser, PT_NODE *stack, PT_NODE **node)
PT_NODE * as_attr_list
Definition: parse_tree.h:2136
const char * name
Definition: show_meta.h:37
bool pt_has_aggregate(PARSER_CONTEXT *parser, PT_NODE *node)
#define pt_is_const_not_hostvar(n)
Definition: parse_tree.h:274
PT_NODE * use_nl_hint
Definition: parse_tree.h:2069
const char * er_msg(void)
const char * name
Definition: show_meta.h:58
int db_is_class(MOP obj)
Definition: db_info.c:310
struct pr_type * type
Definition: object_domain.h:76
PT_NODE * value_clauses
Definition: parse_tree.h:2334
unsigned recompile
Definition: parse_tree.h:3461
CUBRID_STMT_TYPE pt_node_to_cmd_type(PT_NODE *node)
Definition: parse_dbi.c:2736
PT_MISC_TYPE is_subquery
Definition: parse_tree.h:2747
if(extra_options)
Definition: dynamic_load.c:958
void pt_free_host_info(PT_HOST_VARS *hv)
PT_NODE * pt_find_spec(PARSER_CONTEXT *parser, const PT_NODE *from, const PT_NODE *name)
PT_TABLE_OPTION_TYPE option
Definition: parse_tree.h:2916
static bool pt_datatypes_match(const PT_NODE *a, const PT_NODE *b)
void pt_split_join_preds(PARSER_CONTEXT *parser, PT_NODE *predicates, PT_NODE **join_part, PT_NODE **after_cb_filter)
char * pt_append_string(const PARSER_CONTEXT *parser, const char *old_string, const char *new_tail)
Definition: parse_tree.c:980
const char * pt_get_name(PT_NODE *nam)
#define err(fd,...)
Definition: porting.h:431
#define PT_ERRORc(parser, node, msg)
Definition: parse_tree.h:55
PT_NODE * pt_make_query_show_index(PARSER_CONTEXT *parser, PT_NODE *original_cls_id)
#define COMPATIBLE_WITH_GROUPBYNUM(node)
PT_ZZ_ERROR_MSG_INFO error_msg
Definition: parse_tree.h:3267
void pt_record_warning(PARSER_CONTEXT *parser, int stmt_no, int line_no, int col_no, const char *msg)
PT_NODE * pt_from_list_part(const PT_NODE *node)
bool pt_is_analytic_function(PARSER_CONTEXT *parser, const PT_NODE *node)
int pt_check_path_eq(PARSER_CONTEXT *parser, const PT_NODE *p, const PT_NODE *q)
static PT_NODE * pt_is_filtering_skip_and_or(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
const char * get_buffer() const
short db_value_is_in_workspace
Definition: parse_tree.h:3061
const char * pt_get_proxy_spec_name(const char *qspec)
PT_NODE * pt_continue_walk(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * pt_tuple_value(PARSER_CONTEXT *parser, PT_NODE *name, CURSOR_ID *cursor_p, int index)
PT_NODE * arg1
Definition: parse_tree.h:2085
PT_NODE * where
Definition: parse_tree.h:2687
PT_QUERY_INFO query
Definition: parse_tree.h:3325
need_clear_type need_clear
Definition: dbtype_def.h:1084
char * db_name
PT_NODE * pt_get_warnings(const PARSER_CONTEXT *parser)
PT_NODE * cursor_name
Definition: parse_tree.h:2065
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
static PT_NODE * pt_create_param_for_value(PARSER_CONTEXT *parser, PT_NODE *value, int host_var_index)
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
void db_free_query_format(DB_QUERY_TYPE *q)
Definition: db_query.c:154
const char * alias_print
Definition: show_meta.h:70
DB_BIGINT db_get_bigint(const DB_VALUE *value)
#define MSGCAT_SEMANTIC_UNKNOWN_COLL
DB_TYPE pt_node_to_db_type(PT_NODE *node)
Definition: parse_dbi.c:2453
PT_NODE * pt_entity(PARSER_CONTEXT *parser, const PT_NODE *entity_name, const PT_NODE *range_var, const PT_NODE *flat_list)
int db_value_domain_default(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale, const int codeset, const int collation_id, DB_ENUMERATION *enumeration)
Definition: db_macro.c:756
PT_NODE * pt_make_query_showstmt(PARSER_CONTEXT *parser, unsigned int type, PT_NODE *args, int like_where_syntax, PT_NODE *like_or_where_expr)
PT_NODE * set
Definition: parse_tree.h:3047
PT_TUPLE_VALUE_INFO tuple_value
Definition: parse_tree.h:3352
size_t len() const
bool pt_is_operator_logical(PT_OP_TYPE op)
int64_t DB_BIGINT
Definition: dbtype_def.h:751
PT_NODE * pt_make_query_show_exec_stats(PARSER_CONTEXT *parser)
unsigned si_datetime
Definition: parse_tree.h:3464
PT_NODE * parser_append_node(PT_NODE *node, PT_NODE *list)
#define CAST_BUFLEN
Definition: porting.h:471
MOP Au_user
Definition: authenticate.c:343
static PT_NODE * pt_insert_host_var(PARSER_CONTEXT *parser, PT_NODE *h_var, PT_NODE *list)
PT_NODE * parser_new_node(PARSER_CONTEXT *parser, PT_NODE_TYPE node_type)
static void error(const char *msg)
Definition: gencat.c:331
PT_NODE * pt_make_query_show_columns(PARSER_CONTEXT *parser, PT_NODE *original_cls_id, int like_where_syntax, PT_NODE *like_or_where_expr, int is_show_full)
#define PT_NODE_MOVE_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:572
PT_NODE * pt_pop(PARSER_CONTEXT *parser)
void pt_reset_error(PARSER_CONTEXT *parser)
static PT_NODE * pt_make_outer_select_for_show_stmt(PARSER_CONTEXT *parser, PT_NODE *inner_select, const char *select_alias)
PT_NODE * pt_check_instnum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
#define NOT_COMPATIBLE_WITH_INSTNUM(node)
static PT_NODE * pt_process_spec_for_update(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *name)
short db_value_is_initialized
Definition: parse_tree.h:3060
PT_SORT_SPEC_INFO sort_spec
Definition: parse_tree.h:3343
DB_AUTH
Definition: dbtype_def.h:239
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define ER_AU_DBA_ONLY
Definition: error_code.h:204
CURSOR_ID * cursor_p
Definition: parse_tree.h:3207
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
static int pt_get_query_limit_from_limit(PARSER_CONTEXT *parser, PT_NODE *limit, DB_VALUE *limit_val)
Definition: dbi.h:57
const char * default_expr_format
Definition: dbtype_def.h:1206
#define PT_NAME_INFO_GENERATED_OID
Definition: parse_tree.h:2566
#define ER_AU_SELECT_FAILURE
Definition: error_code.h:221
static int packing_level
PT_NODE * pt_convert_to_logical_expr(PARSER_CONTEXT *parser, PT_NODE *node, bool use_parens_inside, bool use_parens_outside)
static PT_NODE * pt_collect_parameters(PARSER_CONTEXT *parser, PT_NODE *node, void *param_list, int *continue_walk)
PT_NODE * ordered_hint
Definition: parse_tree.h:2068
PT_NODE * use_idx_hint
Definition: parse_tree.h:2070
PT_NODE * into
Definition: parse_tree.h:2923
#define PT_IS_CAST_CONST_INPUT_HOSTVAR(n)
Definition: parse_tree.h:381
#define MSGCAT_SET_PARSER_SEMANTIC
#define PT_IS_ORDERBYNUM(n)
Definition: parse_tree.h:392
PT_NODE * pt_make_query_show_trace(PARSER_CONTEXT *parser)
PT_NODE * pt_left_part(const PT_NODE *node)
static PT_NODE * pt_make_field_type_expr_node(PARSER_CONTEXT *parser)
PT_NODE * pt_union(PARSER_CONTEXT *parser, PT_NODE *arg1, PT_NODE *arg2)
bool allow_index_opt
void pt_free_orphans(PARSER_CONTEXT *parser)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
struct pt_merge_info::@126 insert
#define PT_IS_EXPR_NODE(n)
Definition: parse_tree.h:305
#define strlen(s1)
Definition: intl_support.c:43
PT_NODE * pt_values_part(const PT_NODE *node)
unsigned si_tran_id
Definition: parse_tree.h:3465
PT_NODE * pt_make_tuple_value_reference(PARSER_CONTEXT *parser, PT_NODE *name, PT_NODE *select_list, CURSOR_ID *cursor_p)
PT_TABLE_OPTION_TYPE
Definition: parse_tree.h:1308
PT_OP_TYPE
Definition: parse_tree.h:1320
#define PT_SELECT_INFO_READ_ONLY
Definition: parse_tree.h:2733
#define PT_SELECT_INFO_SET_FLAG(s, f)
Definition: parse_tree.h:2737
PT_NODE * pt_is_analytic_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
ARG_VALUE_TYPE type
Definition: show_meta.h:59
#define PT_SELECT_FULL_INFO_COLS_SCHEMA
Definition: parse_tree.h:2722
const char * pt_string_part(const PT_NODE *node)
DB_OBJECT * virt_object
Definition: parse_tree.h:2040
static bool pt_is_filtering_expression(PARSER_CONTEXT *parser, PT_NODE *expression)
PT_NODE * pt_attrs_part(const PT_NODE *node)
enum intl_codeset INTL_CODESET
Definition: intl_support.h:190
int intl_char_count(const unsigned char *src, int length_in_bytes, INTL_CODESET src_codeset, int *char_count)
Definition: intl_support.c:983
struct pt_function_info::@122 analytic
PT_NODE * pt_find_op_type_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
bool pt_has_inst_or_orderby_num(PARSER_CONTEXT *parser, PT_NODE *node)
int pt_get_query_limit_value(PARSER_CONTEXT *parser, PT_NODE *query, DB_VALUE *limit_val)
static PT_NODE * pt_make_if_with_strings(PARSER_CONTEXT *parser, PT_NODE *pred, const char *string1, const char *string2, const char *alias)
PT_NODE * search_cond
Definition: parse_tree.h:2063
PT_NODE * pt_pointer_stack_push(PARSER_CONTEXT *parser, PT_NODE *stack, PT_NODE *node)
bool prm_get_bool_value(PARAM_ID prm_id)
static const int PACKING_MMGR_CHUNK_SIZE
static PT_NODE * pt_collect_host_info(PARSER_CONTEXT *parser, PT_NODE *node, void *h_var, int *continue_walk)
PT_NODE * pt_make_query_show_create_table(PARSER_CONTEXT *parser, PT_NODE *table_name)
PT_MISC_TYPE only_all
Definition: parse_tree.h:2145
static PT_NODE * pt_make_field_extra_expr_node(PARSER_CONTEXT *parser)
PT_MISC_TYPE list_type
Definition: parse_tree.h:2324
#define PT_EXPR_INFO_FUNCTION_INDEX
Definition: parse_tree.h:2229
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2146
PT_NODE * pt_find_aggregate_functions_post(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
unsigned cannot_prepare
Definition: parse_tree.h:3462
PT_DELETE_INFO delete_
Definition: parse_tree.h:3285
static PT_NODE * pt_make_pred_name_int_val(PARSER_CONTEXT *parser, PT_OP_TYPE op_type, const char *col_name, const int int_value)
#define TP_FLOATING_PRECISION_VALUE
int pt_groupbynum_compatibility(PT_NODE *expr)
PT_NODE * pt_find_name(PARSER_CONTEXT *parser, const PT_NODE *name, const PT_NODE *list)
void * etc
Definition: parse_tree.h:3450
unsigned do_not_fold
Definition: parse_tree.h:3475
static PT_NODE * pt_make_sort_spec_with_identifier(PARSER_CONTEXT *parser, const char *identifier, PT_MISC_TYPE sort_mode)
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2067
PT_NODE * error_msgs
Definition: parse_tree.h:3550
PT_NODE * spec
Definition: parse_tree.h:2061
void pt_set_update_object(PARSER_CONTEXT *parser, PT_NODE *node)
int i
Definition: dynamic_load.c:954
PT_VALUE_INFO value
Definition: parse_tree.h:3358
int db_make_null(DB_VALUE *value)
PT_NODE * pt_get_output_host_vars(const PT_HOST_VARS *hv)
PT_NODE * select_stack
Definition: parse_tree.h:3386
DB_TYPE id
PT_NODE * list
Definition: parse_tree.h:2685
#define PT_EXPR_INFO_GROUPBYNUM_NC
Definition: parse_tree.h:2212
static PT_NODE * pt_get_select_from_spec(const PT_NODE *spec)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
XASL_ID * xasl_id
Definition: parse_tree.h:3454
void * pt_node_etc(const PT_NODE *node)
PT_OP_TYPE op
Definition: parse_tree.h:2200
PT_NODE * pt_get_input_host_vars(const PT_HOST_VARS *hv)
unsigned short correlation_level
Definition: parse_tree.h:2555
static int pt_make_outer_select_for_show_columns(PARSER_CONTEXT *parser, PT_NODE *inner_select, const char *select_alias, const char **query_names, const char **query_aliases, int names_length, int is_show_full, PT_NODE **outer_node)
PT_NODE * path_conjuncts
Definition: parse_tree.h:2139
static PT_NODE * pt_make_pred_name_string_val(PARSER_CONTEXT *parser, PT_OP_TYPE op_type, const char *identifier_str, const char *str_value)
void pt_null_etc(PT_NODE *node)
int pt_get_select_query_columns(PARSER_CONTEXT *parser, PT_NODE *create_select, DB_QUERY_TYPE **query_columns)
static PT_NODE * pt_make_dotted_identifier_internal(PARSER_CONTEXT *parser, const char *identifier_str, int depth)
PT_NODE * orderby_for
Definition: parse_tree.h:2770
#define MSGCAT_SEMANTIC_INVALID_CHARSET
#define MSGCAT_RUNTIME_IS_NOT_AUTHORIZED_ON
bool pt_is_aggregate_function(PARSER_CONTEXT *parser, const PT_NODE *node)
#define MSGCAT_SEMANTIC_ENUM_TYPE_TOO_MANY_VALUES
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
int db_make_int(DB_VALUE *value, const int num)
void pt_to_pos_descr(PARSER_CONTEXT *parser, QFILE_TUPLE_VALUE_POSITION *pos_p, PT_NODE *node, PT_NODE *root, PT_NODE **referred_node)
static PT_NODE * pt_make_dummy_query_check_table(PARSER_CONTEXT *parser, const char *table_name)
#define pt_has_error(parser)
Definition: parser.h:507
MOP sm_find_class(const char *name)
const char * alias_print
Definition: parse_tree.h:3455
PT_NODE * pt_has_non_groupby_column_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define PT_IS_EXPR_NODE_WITH_OPERATOR(n, op_type)
Definition: parse_tree.h:464
const char * resolved
Definition: parse_tree.h:2545
PT_NAMED_ARG_INFO named_arg
Definition: parse_tree.h:3319
#define MSGCAT_SEMANTIC_UNKNOWN_ARGUMENT
PT_NODE * pt_make_query_show_create_view(PARSER_CONTEXT *parser, PT_NODE *view_identifier)
#define PT_SELECT_INFO_IDX_SCHEMA
Definition: parse_tree.h:2720
static PT_NODE * pt_make_field_key_type_expr_node(PARSER_CONTEXT *parser)
static PT_NODE * pt_make_collection_type_subquery_node(PARSER_CONTEXT *parser, const char *table_name)
#define LANG_SYS_CODESET
PT_NODE * using_clause
Definition: parse_tree.h:2924
DB_QUERY_TYPE * pt_get_titles(PARSER_CONTEXT *parser, PT_NODE *query)
Definition: query_result.c:642
PT_NODE * pt_expression_1(PARSER_CONTEXT *parser, PT_OP_TYPE op, PT_NODE *arg1)
void pt_mark_spec_list_for_delete(PARSER_CONTEXT *parser, PT_NODE *statement)
#define PT_HAS_COLLATION(t)
Definition: parse_tree.h:243
PT_NODE * pt_check_groupbynum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int collation_id
Definition: object_domain.h:92
#define DB_ENUM_ELEMENTS_MAX_AGG_SIZE
static bool pt_is_filtering_predicate(PARSER_CONTEXT *parser, PT_NODE *predicate)
#define PT_EXPR_INFO_CLEAR_FLAG(e, f)
Definition: parse_tree.h:2240
PT_NODE * pt_make_query_show_table(PARSER_CONTEXT *parser, bool is_full_syntax, int like_where_syntax, PT_NODE *like_or_where_expr)
const char * au_user_name(void)
PT_NODE * pt_dbval_to_value(PARSER_CONTEXT *parser, const DB_VALUE *val)
Definition: parse_dbi.c:574
void pt_mark_spec_list_for_update(PARSER_CONTEXT *parser, PT_NODE *statement)
static PT_NODE * pt_make_select_count_star(PARSER_CONTEXT *parser)
int column_number
Definition: parse_tree.h:3442
int pt_length_of_list(const PT_NODE *list)
struct parser_node::@132 flag
PT_NODE * entity_name
Definition: parse_tree.h:2130
#define PT_IS_SERIAL(op)
Definition: parse_tree.h:461
#define MSGCAT_SEMANTIC_ENUM_TYPE_DUPLICATE_VALUES
PT_NODE * object_parameter
Definition: parse_tree.h:2865
PT_NODE * order_by
Definition: parse_tree.h:2263
PT_SELECT_INFO select
Definition: parse_tree.h:2781
DB_VALUE * pt_value_to_db(PARSER_CONTEXT *parser, PT_NODE *value)
Definition: parse_dbi.c:1088
PT_DATA_DEFAULT_INFO data_default
Definition: parse_tree.h:3283
PT_NODE * pt_and(PARSER_CONTEXT *parser, const PT_NODE *arg1, const PT_NODE *arg2)
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
PT_HOST_VAR_INFO host_var
Definition: parse_tree.h:3307
char * pt_chop_trailing_dots(PARSER_CONTEXT *parser, const char *msg)
#define PT_EXPR_INFO_INSTNUM_C
Definition: parse_tree.h:2209
static PT_NODE * pt_resolve_showstmt_args_named(PARSER_CONTEXT *parser, const SHOWSTMT_NAMED_ARG *arg_infos, int arg_info_count, PT_NODE *args)
static int packing_heap_num_slot
PT_NODE * parser_walk_tree(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE_WALK_FUNCTION pre_function, void *pre_argument, PT_NODE_WALK_FUNCTION post_function, void *post_argument)
#define PT_EXPR_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2238
PT_NODE * pt_table_option(PARSER_CONTEXT *parser, const PT_TABLE_OPTION_TYPE option, PT_NODE *val)
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
static HL_HEAPID * packing_heap
PT_NODE * parser_copy_tree_list(PARSER_CONTEXT *parser, PT_NODE *tree)
const SHOWSTMT_COLUMN * cols
Definition: show_meta.h:71
PT_NODE * pt_find_aggregate_functions_pre(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
static int pt_get_query_limit_from_orderby_for(PARSER_CONTEXT *parser, PT_NODE *orderby_for, DB_VALUE *upper_limit, bool *has_limit)
void tp_domain_free(TP_DOMAIN *dom)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
int intl_identifier_upper(const char *src, char *dst)
#define DB_ENUM_ELEMENTS_MAX
Definition: dbtype_def.h:643
#define QSTR_COMPARE(id, string1, size1, string2, size2, ti)
Definition: string_opfunc.h:66
PT_NODE * cursor_name
Definition: parse_tree.h:2866
void db_destroy_ostk_heap(HL_HEAPID heap_id)
Definition: memory_alloc.c:250
PT_JOIN_TYPE join_type
Definition: parse_tree.h:2151
bool pt_name_equal(PARSER_CONTEXT *parser, const PT_NODE *name1, const PT_NODE *name2)
PT_NODE * pt_name(PARSER_CONTEXT *parser, const char *name)
PT_INSERT_VALUE_INFO insert_value
Definition: parse_tree.h:3310
PT_NODE * pt_get_end_path_node(PT_NODE *node)
PT_NODE * derived_table
Definition: parse_tree.h:2134
PT_NODE * original_node
Definition: parse_tree.h:3227
PT_NODE * search_cond
Definition: parse_tree.h:2862
PT_NODE * pt_add_table_name_to_from_list(PARSER_CONTEXT *parser, PT_NODE *select, const char *table_name, const char *table_alias, const DB_AUTH auth_bypass)
PT_NODE * pt_insert_value(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * range_var
Definition: parse_tree.h:2135
bool pt_list_has_logical_nodes(PT_NODE *list)
static void pt_add_string_col_to_sel_list(PARSER_CONTEXT *parser, PT_NODE *select, const char *identifier_str, const char *col_alias)
int qp_Packing_er_code
PT_NODE * cursor
static bool check_arg_valid(PARSER_CONTEXT *parser, const SHOWSTMT_NAMED_ARG *arg_meta, int arg_num, PT_NODE *val)