CUBRID Engine  latest
name_resolution.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  * name_resolution.c - resolving related functions
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <assert.h>
28 #include <unordered_map>
29 
30 #include "authenticate.h"
31 #include "porting.h"
32 #include "error_manager.h"
33 #include "parser.h"
34 #include "parser_message.h"
35 #include "semantic_check.h"
36 #include "dbtype.h"
37 #include "object_domain.h"
38 #include "object_primitive.h"
39 #include "memory_alloc.h"
40 #include "intl_support.h"
41 #include "memory_hash.h"
42 #include "system_parameter.h"
43 #include "object_print.h"
44 #include "jsp_cl.h"
45 #include "execute_schema.h"
46 #include "schema_manager.h"
47 #include "transform.h"
48 #include "execute_statement.h"
49 #include "show_meta.h"
50 #include "network_interface_cl.h"
51 #include "locator_cl.h"
52 #include "db_json.hpp"
53 
54 #include "dbtype.h"
55 
56 extern "C"
57 {
58  extern int parser_function_code;
59  extern size_t json_table_column_count;
60 }
61 
62 #define PT_NAMES_HASH_SIZE 50
63 
66 {
69 };
70 
71 typedef struct scopes SCOPES;
72 struct scopes
73 {
74  SCOPES *next; /* next outermost scope */
75  PT_NODE *specs; /* list of PT_SPEC nodes */
76  unsigned short correlation_level;
77  /* how far up the stack was a name found? */
78  short location; /* for outer join */
79 };
80 
83 {
87 };
88 
91 {
92  char *name;
96 };
97 
98 enum
99 {
102 };
103 
104 static const char *CPTR_PT_NAME_IN_GROUP_HAVING = "name_in_group_having";
105 
108 {
111 };
112 
113 static PT_NODE *pt_bind_parameter (PARSER_CONTEXT * parser, PT_NODE * parameter);
116  PT_NODE * in_node);
118 static void pt_bind_spec_attrs (PARSER_CONTEXT * parser, PT_NODE * spec);
119 static void pt_bind_scope (PARSER_CONTEXT * parser, PT_BIND_NAMES_ARG * bind_arg);
120 static FUNC_TYPE pt_find_function_type (const char *name);
121 static PT_NODE *pt_mark_location (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
122 static PT_NODE *pt_bind_names_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
123 static PT_NODE *pt_check_Oracle_outerjoin (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
125  int *continue_walk);
126 static PT_NODE *pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
127 static PT_NODE *pt_bind_value_to_hostvar_local (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
128 static int pt_find_attr_in_class_list (PARSER_CONTEXT * parser, PT_NODE * flat, PT_NODE * attr);
129 static int pt_find_class_attribute (PARSER_CONTEXT * parser, PT_NODE * cls, PT_NODE * attr);
130 static int pt_find_name_in_spec (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * name);
131 static int pt_check_unique_exposed (PARSER_CONTEXT * parser, const PT_NODE * p);
135  const char *json_table_alias);
137  int *continue_walk);
139 static void pt_get_attr_data_type (PARSER_CONTEXT * parser, DB_ATTRIBUTE * att, PT_NODE * attr);
142  PT_NODE * exposed_spec, int col_name, PT_NODE ** p_entity);
143 static PT_NODE *pt_resolve_partition_spec (PARSER_CONTEXT * parser, PT_NODE * partition_spec, PT_NODE * spec_parent,
144  bool fo_update);
145 static int pt_spec_in_domain (PT_NODE * cls, PT_NODE * lst);
147  PT_NODE * in_node, PT_NODE ** p_entity, int col_name);
148 static PT_NODE *pt_expand_external_path (PARSER_CONTEXT * parser, PT_NODE * in_node, PT_NODE ** p_entity);
151 static PT_NODE *pt_is_on_list (PARSER_CONTEXT * parser, const PT_NODE * p, const PT_NODE * list);
152 static PT_NODE *pt_name_list_union (PARSER_CONTEXT * parser, PT_NODE * list, PT_NODE * additions);
153 static PT_NODE *pt_name_list_diff (PARSER_CONTEXT * parser, PT_NODE * list, PT_NODE * deletions);
154 static PT_NODE *pt_make_subclass_list (PARSER_CONTEXT * parser, DB_OBJECT * db, int line_num, int col_num, UINTPTR id,
155  PT_MISC_TYPE meta_class, MHT_TABLE * names_mht);
156 static PT_NODE *pt_make_flat_name_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * spec_parent,
157  bool for_update);
160 static int pt_resolve_hint_args (PARSER_CONTEXT * parser, PT_NODE ** arg_list, PT_NODE * spec_list,
161  bool discard_no_match);
162 static int pt_resolve_hint (PARSER_CONTEXT * parser, PT_NODE * node);
164 static PT_NODE *pt_insert_conjunct (PARSER_CONTEXT * parser, PT_NODE * path_dot, PT_NODE * prev_entity);
165 static PT_NODE *pt_lookup_entity (PARSER_CONTEXT * parser, PT_NODE * path_entities, PT_NODE * expr);
166 static bool pt_resolve_method_type (PARSER_CONTEXT * parser, PT_NODE * node);
168 static PT_NODE *pt_find_entity_in_scopes (PARSER_CONTEXT * parser, SCOPES * scopes, UINTPTR spec_id);
170  short *scope_location);
172 static PT_NODE *pt_undef_names_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
173 static PT_NODE *pt_undef_names_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
175 
178  int *is_spec_attr);
181  SCOPES * scopestack, PT_EXTRA_SPECS_FRAME * specs_frame);
183  SCOPES * scopestack, PT_EXTRA_SPECS_FRAME * specs_frame);
184 static const char *pt_get_unique_exposed_name (PARSER_CONTEXT * parser, PT_NODE * first_spec);
185 static PT_NODE *pt_bind_name_to_spec (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
186 
187 static PT_NODE *pt_resolve_natural_join (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk);
188 
189 static void pt_resolve_natural_join_internal (PARSER_CONTEXT * parser, PT_NODE * join_lhs, PT_NODE * join_rhs);
190 
192 
194 
196 
198 
200 
201 static void free_natural_join_attrs (NATURAL_JOIN_ATTR_INFO * attrs);
202 
203 static int generate_natural_join_attrs_from_subquery (PT_NODE * subquery_attrs_list, NATURAL_JOIN_ATTR_INFO ** attrs_p);
204 
206 
207 static bool is_pt_name_in_group_having (PT_NODE * node);
208 
209 static PT_NODE *pt_mark_pt_name (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk);
210 
211 static PT_NODE *pt_mark_group_having_pt_name (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent,
212  int *continue_walk);
213 
215 
216 static void pt_resolve_group_having_alias_pt_name (PARSER_CONTEXT * parser, PT_NODE ** node_p, PT_NODE * select_list);
217 
218 static void pt_resolve_group_having_alias_pt_expr (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * select_list);
219 
220 static void pt_resolve_group_having_alias_internal (PARSER_CONTEXT * parser, PT_NODE ** node_p, PT_NODE * select_list);
221 
222 static PT_NODE *pt_resolve_group_having_alias (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent,
223  int *continue_walk);
224 
225 static PT_NODE *pt_resolve_spec_to_cte (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
226 static PT_NODE *pt_count_ctes_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
227 
229 static PT_NODE *pt_bind_reserved_name (PARSER_CONTEXT * parser, PT_NODE * in_node, PT_NODE * spec);
230 static PT_NODE *pt_set_reserved_name_key_type (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
232 static void pt_bind_names_in_cte (PARSER_CONTEXT * parser, PT_NODE * node, PT_BIND_NAMES_ARG * bind_arg);
234  int *continue_walk);
236  PT_NODE * derived_table, PT_NODE * derived_name);
237 static void pt_set_attr_list_types (PARSER_CONTEXT * parser, PT_NODE * as_attr_list, PT_MISC_TYPE derived_table_type,
238  PT_NODE * derived_table, PT_NODE * parent_spec);
239 static PT_NODE *pt_count_with_clauses (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
240 
241 /*
242  * pt_undef_names_pre () - Set error if name matching spec is found. Used in
243  * insert to make sure no "correlated" names are used
244  * in subqueries.
245  *
246  * return : Unchanged node argument.
247  * parser (in) : Parser context.
248  * node (in) : Parse tree node.
249  * arg (in) : Insert spec.
250  * continue_walk (in) : Continue walk.
251  *
252  * NOTE: Insert spec will store in etc the correlation level in regard with
253  * INSERT VALUE clause. Only if level is greater than 0, names should
254  * be undefined. INSERT INTO SET attr_i = EXPR (attr_j1, attr_j2, ...)
255  * is allowed.
256  * If etc is NULL, correlation level is ignored and all names are
257  * undefined.
258  */
259 static PT_NODE *
260 pt_undef_names_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
261 {
262  PT_NODE *spec = (PT_NODE *) arg;
263  short *level_p = NULL;
264 
265  if (spec == NULL)
266  {
267  *continue_walk = PT_STOP_WALK;
268  return node;
269  }
270 
271  level_p = (short *) spec->etc;
272 
273  switch (node->node_type)
274  {
275  case PT_NAME:
276  if (level_p == NULL || *level_p > 0)
277  {
278  /* Using "correlated" names in INSERT VALUES clause is incorrect except when they are arguments of the
279  * DEFAULT() function. */
280  if (node->info.name.spec_id == spec->info.spec.id
282  {
283  int save_custom_print = parser->custom_print;
286  pt_short_print (parser, node));
287  parser->custom_print = save_custom_print;
288  }
289  }
290  break;
291  case PT_SELECT:
292  case PT_UNION:
293  case PT_INTERSECTION:
294  case PT_DIFFERENCE:
295  case PT_INSERT:
296  if (level_p != NULL)
297  {
298  (*level_p)++;
299  }
300  break;
301  default:
302  break;
303  }
304 
305  return node;
306 }
307 
308 /*
309  * pt_undef_names_post () - Function to be used with pt_undef_names_pre. Helps
310  * with counting the correlation level.
311  *
312  * return : Unchanged node argument.
313  * parser (in) : Parser context.
314  * node (in) : Parse tree node.
315  * arg (in) : Insert spec.
316  * continue_walk (in) : Continue walk.
317  */
318 static PT_NODE *
319 pt_undef_names_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
320 {
321  PT_NODE *spec = (PT_NODE *) arg;
322  short *level_p = NULL;
323 
324  if (spec == NULL)
325  {
326  return node;
327  }
328 
329  level_p = (short *) spec->etc;
330  if (level_p == NULL)
331  {
332  return node;
333  }
334 
335  switch (node->node_type)
336  {
337  case PT_SELECT:
338  case PT_UNION:
339  case PT_INTERSECTION:
340  case PT_DIFFERENCE:
341  case PT_INSERT:
342  (*level_p)--;
343  break;
344  default:
345  break;
346  }
347 
348  return node;
349 }
350 
351 /*
352  * pt_resolved() - check if this path expr was previously resolved
353  * return: true if expr was previously resolved
354  * expr(in): a path expression
355  */
356 
357 int
358 pt_resolved (const PT_NODE * expr)
359 {
360  if (expr)
361  {
362  switch (expr->node_type)
363  {
364  case PT_NAME:
365  return (expr->info.name.spec_id != 0);
366  case PT_DOT_:
367  return (pt_resolved (expr->info.dot.arg1) && pt_resolved (expr->info.dot.arg2));
368  default:
369  break;
370  }
371  }
372  return 0;
373 }
374 
375 
376 /*
377  * pt_eval_value_path() -
378  * return: pt_value node if successful, NULL otherwise
379  * parser(in): the parser context
380  * path(in): a path expression anchored by a PT_VALUE node
381  */
382 
383 PT_NODE *
385 {
386  DB_VALUE val;
387  PT_NODE *tmp;
388 
389  db_make_null (&val);
390 
391  if (pt_eval_path_expr (parser, path, &val))
392  {
393  /* make val into a PT_VALUE node */
394  tmp = pt_dbval_to_value (parser, &val);
395  if (tmp)
396  {
397  tmp->line_number = path->line_number;
398  tmp->column_number = path->column_number;
399  /* NOTE node IS NO LONGER TYPE PT_NAME! */
400  pr_clear_value (&val);
401  }
402  return tmp;
403  }
404  else
405  {
406  return NULL; /* error set by pt_eval_path_expr */
407  }
408 } /* pt_eval_value_path */
409 
410 /*
411  * pt_bind_param_node() - try to bind parameter for a node
412  * return:
413  * parser(in):
414  * node(in):
415  * arg(in):
416  * continue_walk(in):
417  */
418 PT_NODE *
419 pt_bind_param_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
420 {
421  if (node->node_type == PT_NAME && node->info.name.meta_class == PT_PARAMETER)
422  {
423  return pt_bind_parameter (parser, node);
424  }
425  return NULL;
426 }
427 
428 /*
429  * pt_bind_parameter() - try to resolve name as an interpreter
430  * parameter reference
431  * return: lbl's value if successful, NULL otherwise
432  * parser(in): the parser context
433  * parameter(in/out): a PT_NAME node
434  */
435 static PT_NODE *
437 {
438  PT_NODE *node = NULL;
439  const char *name;
440  DB_VALUE *db_val;
441 
442  if (!parameter || parameter->node_type != PT_NAME)
443  {
444  return NULL; /* nothing doing */
445  }
446 
447  if (parameter->type_enum != PT_TYPE_NONE)
448  {
449  return parameter; /* is already resolved */
450  }
451 
452  /* look up as an interpreter parameter */
453  name = parameter->info.name.original;
454  db_val = pt_find_value_of_label (name);
455  if (db_val) /* parameter found, resolve to its matching DB_VALUE */
456  {
457  /* create a PT_VALUE image of the matching DB_VALUE */
458 
459  /* If type is object type, the referenced object may not exist. We need to first check its existence, then we
460  * can resolve the object.
461  */
462  if (DB_VALUE_TYPE (db_val) == DB_TYPE_OBJECT)
463  {
464  MOP mop = db_get_object (db_val);
465  int does_exist = locator_does_exist_object (mop, DB_FETCH_READ);
466  if (does_exist == LC_ERROR || does_exist == LC_DOESNOT_EXIST)
467  {
468  assert (does_exist == LC_DOESNOT_EXIST || er_errid () != NO_ERROR);
469  return NULL;
470  }
471  assert (does_exist == LC_EXIST);
472  /* Fall through. */
473  }
474  node = pt_dbval_to_value (parser, db_val);
475  if (node == NULL)
476  {
477  return NULL;
478  }
479 
480  /* NOTE node IS NO LONGER TYPE PT_NAME! */
481  parameter->type_enum = node->type_enum;
482  if (parameter->data_type)
483  {
484  parser_free_tree (parser, parameter->data_type);
485  }
486  parameter->data_type = node->data_type;
487  node->data_type = NULL;
488  parser_free_tree (parser, node);
489  parameter->info.name.meta_class = PT_PARAMETER;
490  }
491 
492  if (parameter->info.name.meta_class == PT_PARAMETER)
493  {
494  return parameter;
495  }
496  else
497  {
498  return NULL;
499  }
500 }
501 
502 /*
503  * pt_bind_parameter_path() - try to resolve name or path as an interpreter
504  * parameter reference or a path expression anchored by a path expression.
505  * return: path's value (evaluated) if successful, NULL otherwise
506  * parser(in): the parser context
507  * path(in/out): a PT_NAME or PT_DOT_ node
508  */
509 static PT_NODE *
511 {
512  PT_NODE *arg1 = NULL;
513  PT_NODE *temp;
514 
515  if (!path)
516  {
517  return NULL; /* nothing doing */
518  }
519 
520  if (path->node_type == PT_NAME)
521  {
522  path = pt_bind_parameter (parser, path);
523  /* parameter paths must start with a parameter. */
524  if (!path || path->info.name.meta_class != PT_PARAMETER)
525  {
526  return NULL;
527  }
528  return path;
529  }
530 
531  if (path->node_type == PT_DOT_)
532  {
533  arg1 = pt_bind_parameter_path (parser, path->info.dot.arg1);
534  if (!arg1)
535  {
536  return NULL;
537  }
538  /* If we succesfully resolved the parameter, mark the right hand side as parameter too. This will be evaluated at
539  * run time. */
540  path->info.dot.arg1 = arg1;
542 
543  /* We need to be able to evaluate it now, in order to get the type of the expression. */
544  temp = pt_eval_value_path (parser, path);
545  if (temp)
546  {
547  path->type_enum = temp->type_enum;
548  if (path->data_type)
549  {
550  parser_free_tree (parser, path->data_type);
551  }
552  path->data_type = temp->data_type;
553  temp->data_type = NULL;
554  parser_free_tree (parser, temp);
555 
556  return path;
557  }
558  }
559 
560  return NULL;
561 } /* pt_bind_parameter_path */
562 
563 /*
564  * pt_bind_reserved_name () - Try to resolve name to one of the reserved names
565  *
566  * return : Resolved reserved name or NULL.
567  * parser (in) : Parser context.
568  * in_node (in) : Original name node.
569  * spec (in) : The spec to which the reserved name will belong.
570  *
571  * NOTE: Reserved names are allowed only if used in the context of a SELECT
572  * statement on a single table and having certain hints that unlock
573  * reserved names.
574  */
575 static PT_NODE *
577 {
578  int i = 0;
579  const char *name = NULL;
580  PT_NODE *reserved_name = NULL;
581 
582  assert (in_node != NULL && spec != NULL);
583 
584  /* get attribute name */
585  if (in_node->node_type == PT_NAME)
586  {
587  name = in_node->info.name.original;
588  }
589  else if (in_node->node_type == PT_DOT_)
590  {
591  /* we can only allow X.reserved_name where X is the name of spec */
592  if (in_node->info.dot.arg1->node_type != PT_NAME
595  {
596  return NULL;
597  }
598  if (in_node->info.dot.arg2->node_type != PT_NAME)
599  {
600  return NULL;
601  }
602  name = in_node->info.dot.arg2->info.name.original;
603  }
604  else
605  {
606  /* not the scope of this function */
607  return NULL;
608  }
609 
610  /* look for the name in reserved name table */
611  for (i = 0; i < RESERVED_ATTR_COUNT; i++)
612  {
614  {
615  /* the found reserved name should match the type of scan to which the spec is flagged... otherwise it is a
616  * wrong name */
617  if (!PT_CHECK_RESERVED_NAME_BIND (spec, i))
618  {
619  /* Unknown reserved name in current context */
620  return NULL;
621  }
622 
623  /* bind the reserved name */
624  if (in_node->node_type == PT_NAME)
625  {
626  reserved_name = in_node;
627  }
628  else /* PT_DOT_ */
629  {
630  reserved_name = in_node->info.dot.arg2;
631  in_node->info.dot.arg2 = NULL;
632  PT_NODE_MOVE_NUMBER_OUTERLINK (reserved_name, in_node);
633  parser_free_tree (parser, in_node);
634  }
635  reserved_name->info.name.spec_id = spec->info.spec.id;
636  reserved_name->info.name.resolved = spec->info.spec.range_var->info.name.original;
637  reserved_name->info.name.meta_class = PT_RESERVED;
638  reserved_name->info.name.reserved_id = (PT_RESERVED_NAME_ID) i;
639  reserved_name->type_enum = pt_db_to_type_enum (pt_Reserved_name_table[i].type);
640  if (reserved_name->type_enum == PT_TYPE_OBJECT)
641  {
642  reserved_name->data_type =
643  pt_domain_to_data_type (parser,
645  spec->info.spec.entity_name->info.name.db_object, 0, 0, NULL,
646  0));
647  }
648  return reserved_name;
649  }
650  }
651  /* this is not a reserved name */
652  return NULL;
653 }
654 
655 /*
656  * pt_bind_name_or_path_in_scope() - tries to resolve in_node using all the
657  * entity_spec_lists in scopes and returns in_node if successfully resolved
658  * return: in_node's resolution if successful, NULL if in_node is unresolved
659  * parser(in): the parser context
660  * bind_arg(in): a list of scopes for resolving names & path expressions
661  * in_node(in): an attribute reference or path expression to be resolved
662  *
663  * Note :
664  * Unfortunately, we can't push the check for naked parameters
665  * into pt_get_resolution() because parameters that have the
666  * name as an attribute of some (possibly enclosing) scope must be
667  * to the attribute and not the parameter (by our convention).
668  * when naked parameters are eliminated, this mickey mouse stuff
669  * will go away...
670  */
671 static PT_NODE *
673 {
674  PT_NODE *prev_entity = NULL;
675  PT_NODE *node = NULL;
676  SCOPES *scopes = bind_arg->scopes;
677  SCOPES *scope;
678  int level = 0;
679  PT_NODE *temp, *entity;
680  short scope_location;
681  bool error_saved = false;
682 
683  /* skip hint argument name, index name */
684  if (in_node->node_type == PT_NAME
685  && (in_node->info.name.meta_class == PT_HINT_NAME || in_node->info.name.meta_class == PT_INDEX_NAME))
686  {
687  return in_node;
688  }
689 
690  /* skip resolved nodes */
691  if (pt_resolved (in_node))
692  {
693  return in_node;
694  }
695 
696  if (er_errid () != NO_ERROR)
697  {
698  er_stack_push ();
699  error_saved = true;
700  }
701 
702  /* resolve all name nodes and path expressions */
703  if (scopes)
704  {
705  for (scope = scopes; scope != NULL; scope = scope->next)
706  {
707  node = pt_get_resolution (parser, bind_arg, scope->specs, in_node, &prev_entity, 1);
708  if (node)
709  {
710  node = pt_expand_external_path (parser, node, &prev_entity);
711  break;
712  }
713  if (is_pt_name_in_group_having (in_node))
714  {
715  /* give up; this kind of name should be in level 0 scopes */
716  break;
717  }
718  level++;
719  }
720  }
721  else
722  {
723  /* resolve class attributes and anything else that can be resolved without an enclosing scope. */
724  node = pt_get_resolution (parser, bind_arg, NULL, in_node, &prev_entity, 1);
725 
726  if (node)
727  {
728  node = pt_expand_external_path (parser, node, &prev_entity);
729  }
730  }
731 
732  if (node)
733  {
734  /* set the correlation of either the name or arg2 of the path */
735  /* expression. */
736  if (node->node_type == PT_DOT_)
737  {
738  node->info.dot.arg2->info.name.correlation_level = level;
739  }
740  else
741  {
742  node->info.name.correlation_level = level;
743  }
744 
745  /* all is well, name is resolved */
746  /* check correlation level of scope */
747  scope = scopes;
748  while (level > 0 && scope)
749  {
750  /* it was correlated. Choose the closest correlation scope. That is the same as choosing the smallest
751  * non-zero number. */
752  if (!scope->correlation_level || scope->correlation_level > (unsigned short) level)
753  {
754  scope->correlation_level = level;
755  }
756  level = level - 1;
757  scope = scope->next;
758  }
759  }
760  else
761  {
762  /* If pt_name in group by/ having, maybe it's alias. We will try to resolve it later. */
763  if (!is_pt_name_in_group_having (in_node))
764  {
765  /* it may be a naked parameter or a path expression anchored by a naked parameter. Try and resolve it as
766  * such. */
767  node = pt_bind_parameter_path (parser, in_node);
768 
769  if (node == NULL && !pt_has_error (parser))
770  {
771  if (er_errid () != NO_ERROR)
772  {
773  PT_ERRORc (parser, in_node, er_msg ());
774  }
775  else
776  {
778  pt_short_print (parser, in_node));
779  }
780  }
781  }
782  }
783 
784  if (node != NULL)
785  {
786  /* outer join restriction check */
787  for (temp = node; temp->node_type == PT_DOT_; temp = temp->info.dot.arg2)
788  {
789  ;
790  }
791  if (temp->node_type == PT_NAME && temp->info.name.location > 0)
792  {
793  /* PT_NAME node within outer join condition */
794  if (temp != node)
795  {
796  /* node->node_type is PT_DOT_; that menas path expression */
798  pt_short_print (parser, node));
799  node = NULL;
800  }
801  else
802  {
803  /* check scope */
804  scope_location = temp->info.name.location;
805  entity = pt_find_outer_entity_in_scopes (parser, scopes, temp->info.name.spec_id, &scope_location);
806  if (!entity)
807  {
808  /* cannot resolve within the outer join scope */
810  pt_short_print (parser, node));
811  node = NULL;
812  }
813  else if (entity->info.spec.location < 0 || (entity->info.spec.location > temp->info.name.location)
814  || scope_location > entity->info.spec.location)
815  {
816  /* cannot resolve within the outer join scope */
818  pt_short_print (parser, node));
819  node = NULL;
820  }
821  }
822  }
823  }
824 
825  if (error_saved)
826  {
827  er_stack_pop ();
828  }
829 
830  return node;
831 }
832 
833 
834 /*
835  * pt_bind_type_of_host_var() - set the type of a host variable to
836  * the type of its DB_VALUE
837  * return: none
838  * parser(in/out): the parser context
839  * hv(in/out): an input host variable
840  */
841 static void
843 {
844  DB_VALUE *val = NULL;
845 
846  val = pt_host_var_db_value (parser, hv);
847  if (val)
848  {
849  hv = pt_bind_type_from_dbval (parser, hv, val);
850  }
851  /* else : There isn't a host var yet. This happens if someone does a db_compile_statement before doing
852  * db_push_values, as might happen in a dynamic esql PREPARE statement where the host vars might not be supplied
853  * until some later EXECUTE or OPEN CURSOR statement. In this case, we'll have to rely on pt_coerce_value and
854  * pt_value_to_dbval to fix things up later. */
855 }
856 
857 /*
858  * pt_bind_spec_attrs() - bind name types for a derived table.
859  * return: void
860  * parser(in/out): the parser context
861  * spec(in/out): an entity spec describing a derived table
862  *
863  * Note :
864  * if spec.derived_table_type is set expr then assert: spec.derived_table.type
865  * is a set type in any case, check that:
866  * the number of derived columns in spec.as_attr_list matches
867  * the number of attributes in spec.derived_table.select_list
868  * foreach column c in spec.as_attr_list and foreach attribute a
869  * in spec.derived_table.select_list do make c assume a's datatype and
870  * tag it with spec's id
871  */
872 static void
874 {
875  PT_NODE *derived_table = NULL, *col, *attr, *cte = NULL;
876  PT_SPEC_INFO *spec_info;
877 
878  if (!parser || !spec || spec->node_type != PT_SPEC || PT_SPEC_IS_ENTITY (spec))
879  {
880  return;
881  }
882 
883  spec_info = &spec->info.spec;
884 
885  /* get aliases if they are not present */
886  if (PT_SPEC_IS_DERIVED (spec))
887  {
888  derived_table = spec_info->derived_table;
889  if (spec_info->as_attr_list == NULL)
890  {
891  spec_info->as_attr_list =
892  pt_get_attr_list_of_derived_table (parser, spec_info->derived_table_type, derived_table,
893  spec_info->range_var);
894  }
895 
896  /* get types from derived table; */
897  pt_set_attr_list_types (parser, spec_info->as_attr_list, spec_info->derived_table_type, derived_table, spec);
898  }
899  else
900  {
901  assert (PT_SPEC_IS_CTE (spec));
902  cte = spec_info->cte_pointer->info.pointer.node;
903 
904  /* copy cte as_attr_list to spec, to be used for binding */
905  if (spec_info->as_attr_list == NULL)
906  {
907  if (cte->info.cte.as_attr_list == NULL)
908  {
909  /* as_attr_list of cte should be previously computed in pt_bind_names_in_cte */
910  PT_INTERNAL_ERROR (parser, "cte definition error");
911  return;
912  }
913  spec_info->as_attr_list = parser_copy_tree_list (parser, cte->info.cte.as_attr_list);
914  }
915  else
916  {
917  /* copy cte types from its as_attr_list */
918  if (pt_length_of_list (spec_info->as_attr_list) != pt_length_of_list (cte->info.cte.as_attr_list))
919  {
921  pt_short_print (parser, spec), pt_length_of_list (cte->info.cte.as_attr_list),
922  pt_length_of_list (spec_info->as_attr_list));
923  }
924 
925  col = spec_info->as_attr_list;
926  attr = cte->info.cte.as_attr_list;
927  for (; col != NULL && attr != NULL; col = col->next, attr = attr->next)
928  {
929  col->type_enum = attr->type_enum;
930  if (attr->data_type)
931  {
932  col->data_type = parser_copy_tree_list (parser, attr->data_type);
933  }
934  else
935  {
936  parser_free_tree (parser, col->data_type);
937  col->data_type = NULL;
938  }
939  }
940  assert (col == NULL && attr == NULL);
941  }
942  }
943 
944  for (col = spec->info.spec.as_attr_list; col != NULL; col = col->next)
945  {
946  /* tag it as resolved */
947  col->info.name.spec_id = spec->info.spec.id;
948  col->info.name.meta_class = PT_NORMAL;
949  }
950 }
951 
952 /*
953  * pt_bind_scope() - bind names and types of derived tables in current scope.
954  * return: void
955  * parser(in): the parser context
956  * bind_arg(in/out): a list of scopes with the current scope on "top"
957  *
958  * Note :
959  * this definition of a derived table's scope allows us to resolve the 3rd f in
960  * select f.ssn from faculty1 f, (select ssn from faculty g where f=g) h(ssn)
961  * and still catch the 1st illegal forward reference to f in
962  * select n from (select ssn from faculty g where f=g) h(n), faculty f
963  */
964 static void
966 {
967  SCOPES *scopes = bind_arg->scopes;
968  PT_NODE *spec, *prev_spec = NULL;
969  bool save_donot_fold;
970 
971  spec = scopes->specs;
972  scopes->specs = NULL;
973  while (spec)
974  {
975 
976  if (PT_SPEC_IS_DERIVED (spec))
977  {
978  /* evaluate the names of the current table. The name scope of the first spec, is only the outer level scopes. The
979  * outer scopes are pointed to by scopes->next. The null "scopes" spec is kept to maintain correlation level
980  * calculation.
981  */
982  PT_NODE *table;
983 
984  assert (!PT_SPEC_IS_CTE (spec));
985  table = spec->info.spec.derived_table;
986  if (table->node_type == PT_JSON_TABLE)
987  {
989  table->info.json_table_info.expr =
991  bind_arg);
992  table->info.json_table_info.tree =
994  }
995  else
996  {
997  table = parser_walk_tree (parser, table, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
998  }
999  spec->info.spec.derived_table = table;
1000 
1001  /* must bind any expr types in table. pt_bind_types requires it. */
1002  save_donot_fold = bind_arg->sc_info->donot_fold; /* save */
1003  bind_arg->sc_info->donot_fold = true; /* skip folding */
1004  table = pt_semantic_type (parser, table, bind_arg->sc_info);
1005  bind_arg->sc_info->donot_fold = save_donot_fold; /* restore */
1006  if (table != NULL)
1007  {
1008  spec->info.spec.derived_table = table;
1009  /* table spec passed bind_names and semantic_type */
1010  pt_bind_spec_attrs (parser, spec);
1011  }
1012  else
1013  {
1014  assert (pt_has_error (parser));
1015  }
1016  }
1017  else if (PT_SPEC_IS_CTE (spec))
1018  {
1019  /* types and names of CTE should be already evaluated by pt_bind_names_in_cte; bind them to spec */
1020  pt_bind_spec_attrs (parser, spec);
1021  }
1022 
1023  if (prev_spec)
1024  {
1025  prev_spec->next = spec;
1026  }
1027  else
1028  {
1029  scopes->specs = spec;
1030  }
1031  prev_spec = spec;
1032  spec = prev_spec->next;
1033  prev_spec->next = NULL;
1034  }
1035 }
1036 
1037 
1038 /*
1039  * pt_find_function_type () - function name to look up
1040  * return: function_type, or generic if not found
1041  * name(in):
1042  */
1043 static FUNC_TYPE
1044 pt_find_function_type (const char *name)
1045 {
1046  if (name)
1047  {
1048  if (intl_mbs_casecmp (name, "set") == 0)
1049  {
1050  return F_TABLE_SET;
1051  }
1052  else if (intl_mbs_casecmp (name, "multiset") == 0)
1053  {
1054  return F_TABLE_MULTISET;
1055  }
1056  else if (intl_mbs_casecmp (name, "sequence") == 0)
1057  {
1058  return F_TABLE_SEQUENCE;
1059  }
1060  }
1061  return PT_GENERIC;
1062 }
1063 
1064 
1065 /*
1066  * pt_mark_location () -
1067  * return:
1068  * parser(in):
1069  * node(in):
1070  * arg(in):
1071  * continue_walk(in):
1072  */
1073 static PT_NODE *
1074 pt_mark_location (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1075 {
1076  short *location = (short *) arg;
1077 
1078  switch (node->node_type)
1079  {
1080  case PT_EXPR:
1081  node->info.expr.location = *location;
1082  break;
1083  case PT_NAME:
1084  node->info.name.location = *location;
1085  break;
1086  case PT_VALUE:
1087  node->info.value.location = *location;
1088  break;
1089  default:
1090  break;
1091  }
1092 
1093  return node;
1094 } /* pt_mark_location() */
1095 
1096 /*
1097  * pt_set_is_view_spec () -
1098  * return:
1099  * parser(in):
1100  * node(in):
1101  * arg(in):
1102  * continue_walk(in):
1103  */
1104 PT_NODE *
1105 pt_set_is_view_spec (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1106 {
1107  if (!node)
1108  {
1109  return node;
1110  }
1111 
1112  if (pt_is_query (node))
1113  {
1114  /* Reset query id # */
1115  node->info.query.id = (UINTPTR) node;
1116  node->info.query.is_view_spec = 1;
1117  }
1118 
1119  return node;
1120 } /* pt_set_is_view_spec */
1121 
1122 /*
1123  * pt_bind_names_post() - bind names & path expressions of this statement node
1124  * return: node
1125  * parser(in): the parser context
1126  * node(in): a parse tree node
1127  * arg(in): a list of scopes for resolving names & path expressions
1128  * continue_walk(in): flag that tells when to stop tree traversal
1129  */
1130 static PT_NODE *
1131 pt_bind_names_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1132 {
1133  PT_BIND_NAMES_ARG *bind_arg = (PT_BIND_NAMES_ARG *) arg;
1134 
1135  *continue_walk = PT_CONTINUE_WALK;
1136 
1137  if (!node)
1138  {
1139  return node;
1140  }
1141 
1142  switch (node->node_type)
1143  {
1144  case PT_UPDATE:
1145  case PT_MERGE:
1146  {
1147  PT_NODE *temp, *lhs, *assignments = NULL, *spec = NULL;
1148  int error = NO_ERROR;
1149 
1150  if (node->node_type == PT_UPDATE)
1151  {
1152  assignments = node->info.update.assignment;
1153  spec = node->info.update.spec;
1154  }
1155  else if (node->node_type == PT_MERGE)
1156  {
1157  assignments = node->info.merge.update.assignment;
1158  assert (node->info.merge.into->next == NULL);
1159  node->info.merge.into->next = node->info.merge.using_clause;
1160  spec = node->info.merge.into;
1161  }
1162 
1163  /* this is only to eliminate oid names from lhs of assignments per ANSI. This is because name resolution for
1164  * OID's conflicts with ANSI. */
1165  for (temp = assignments; temp && error == NO_ERROR; temp = temp->next)
1166  {
1167  lhs = temp->info.expr.arg1;
1168  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
1169  {
1170  lhs = lhs->info.expr.arg1;
1171  }
1172 
1173  for (; lhs && error == NO_ERROR; lhs = lhs->next)
1174  {
1175  if (lhs->node_type == PT_NAME)
1176  {
1177  /* make it print like ANSI */
1178  if (lhs->info.name.meta_class == PT_OID_ATTR)
1179  {
1180  /* must re-resolve the name */
1181  lhs->info.name.original = lhs->info.name.resolved;
1182  lhs->info.name.spec_id = 0;
1183  if (!pt_find_name_in_spec (parser, spec, lhs))
1184  {
1186  PT_ERRORmf (parser, lhs, MSGCAT_SET_PARSER_SEMANTIC, error, pt_short_print (parser, lhs));
1187  }
1188  }
1189  }
1190  }
1191  }
1192  if (node->node_type == PT_MERGE)
1193  {
1194  node->info.merge.into->next = NULL;
1195  }
1196  }
1197 
1198  break;
1199 
1200  case PT_VALUE:
1201  {
1202  PT_NODE *elem;
1203  int is_function = 0;
1204 
1205  if (node->type_enum == PT_TYPE_STAR)
1206  {
1207  break;
1208  }
1209 
1210  if (node && pt_is_set_type (node))
1211  {
1212  node = pt_semantic_type (parser, node, bind_arg->sc_info);
1213  if (node == NULL)
1214  {
1215  return node;
1216  }
1217 
1218  elem = node->info.value.data_value.set;
1219  while (elem)
1220  {
1221  if (elem->node_type != PT_VALUE)
1222  {
1223  is_function = 1;
1224  break;
1225  }
1226  elem = elem->next;
1227  }
1228  }
1229 
1230  if (!is_function)
1231  {
1232  if (pt_value_to_db (parser, node) == NULL)
1233  {
1234  parser_free_tree (parser, node);
1235  node = NULL;
1236  }
1237  else
1238  {
1239  /*
1240  * pt_value_to_db has already filled the contents
1241  * of node->info.value.db_value; we don't need to
1242  * repeat that work here.
1243  * The type info from "node" drove that process, and
1244  * is assumed to be good. If there was any touch-up
1245  * work required (e.g., adding a data_type node),
1246  * pt_value_to_db took care of it.
1247  */
1248  }
1249  }
1250  else
1251  {
1252  PT_NODE *arg_list = node->info.value.data_value.set;
1253  /* roll back error messages for set values. this is a set function reference, which we just realized, since
1254  * the syntax for constant sets and set functions is the same. Convert the node to a set function. */
1255  node->node_type = PT_FUNCTION;
1256  /* make info set up properly */
1257  memset (&(node->info), 0, sizeof (node->info));
1258  node->info.function.arg_list = arg_list;
1259  if (node->type_enum == PT_TYPE_SET)
1260  {
1261  node->info.function.function_type = F_SET;
1262  }
1263  else if (node->type_enum == PT_TYPE_MULTISET)
1264  {
1266  }
1267  else if (node->type_enum == PT_TYPE_SEQUENCE)
1268  {
1270  }
1271  else
1272  {
1273  node->info.function.function_type = (FUNC_TYPE) 0;
1274  }
1275 
1276  /* now we need to type the innards of the set ... */
1277  /* first we tag this not typed so the type will be recomputed from scratch. */
1278  node->type_enum = PT_TYPE_NONE;
1279  node = pt_semantic_type (parser, node, bind_arg->sc_info);
1280  }
1281 
1282  }
1283  break;
1284 
1285  case PT_EXPR:
1286  (void) pt_instnum_compatibility (node);
1287  pt_mark_function_index_expression (parser, node, bind_arg);
1288  break;
1289 
1290  case PT_SELECT:
1292  {
1293  /* This is a hack to determine type for index key attributes which may be different index. Obtain index info
1294  * and update type_enum and data type for all references to index keys. */
1295  PT_NODE *spec = node->info.query.q.select.from;
1298  SM_CLASS *class_ = NULL;
1299  SM_CLASS_CONSTRAINT *cons = NULL;
1300  TP_DOMAIN *key_domain;
1301  PT_BIND_NAMES_DATA_TYPE key_type;
1302 
1303  /* Get class object */
1304  if (au_fetch_class_force (obj, &class_, AU_FETCH_READ) != NO_ERROR)
1305  {
1306  PT_INTERNAL_ERROR (parser, "Error obtaining SM_CLASS");
1307  parser_free_tree (parser, node);
1308  return NULL;
1309  }
1310  /* Get index */
1311  cons = classobj_find_class_index (class_, index->info.name.original);
1312  if (cons == NULL)
1313  {
1314  PT_INTERNAL_ERROR (parser, "Hint argument should be the name of a" "valid index");
1315  parser_free_tree (parser, node);
1316  return NULL;
1317  }
1318  /* Get key type for index */
1319  if (btree_get_index_key_type (cons->index_btid, &key_domain) != NO_ERROR)
1320  {
1321  PT_INTERNAL_ERROR (parser, "Error obtaining index key type");
1322  parser_free_tree (parser, node);
1323  return NULL;
1324  }
1325 
1326  if (key_domain == NULL)
1327  {
1328  /* do nothing */
1329  return node;
1330  }
1331 
1332  /* Generate one data_type sample */
1333  key_type.type_enum = pt_db_to_type_enum (TP_DOMAIN_TYPE (key_domain));
1334  key_type.data_type = pt_domain_to_data_type (parser, key_domain);
1335  if (key_type.data_type == NULL)
1336  {
1338  parser_free_tree (parser, node);
1339  return NULL;
1340  }
1341 
1342  /* Walk parse tree and change type enum for all RESERVED_KEY_KEY name nodes. */
1343  node = parser_walk_tree (parser, node, pt_set_reserved_name_key_type, &key_type, NULL, NULL);
1344 
1345  parser_free_tree (parser, key_type.data_type);
1346  }
1347  break;
1348 
1349  default:
1350  break;
1351  }
1352 
1353  return node;
1354 }
1355 
1356 /*
1357  * pt_check_Oracle_outerjoin () -
1358  * return:
1359  * parser(in):
1360  * node(in):
1361  * arg(in):
1362  * continue_walk(in/out):
1363  */
1364 static PT_NODE *
1365 pt_check_Oracle_outerjoin (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1366 {
1367  PT_BIND_NAMES_ARG *bind_arg = (PT_BIND_NAMES_ARG *) arg;
1368  SEMANTIC_CHK_INFO *sc_info;
1369 
1370  if (!node)
1371  {
1372  return node;
1373  }
1374 
1375  switch (node->node_type)
1376  {
1377  case PT_NAME:
1378  sc_info = bind_arg->sc_info;
1379 
1380  /* found node which is bound to the specified spec */
1381  if (node->node_type == PT_NAME && (node->info.name.spec_id == sc_info->Oracle_outerjoin_spec->info.spec.id))
1382  {
1383  sc_info->Oracle_outerjoin_attr_num++;
1384  }
1385 
1386  /* don't revisit leaves */
1387  *continue_walk = PT_STOP_WALK;
1388  break;
1389 
1390  case PT_SELECT:
1391  sc_info = bind_arg->sc_info;
1392 
1393  /* check for subquery in ON cond */
1394  sc_info->Oracle_outerjoin_subq_num++;
1395  break;
1396 
1397  case PT_DOT_:
1398  sc_info = bind_arg->sc_info;
1399 
1400  /* check for path expression in ON cond */
1401  sc_info->Oracle_outerjoin_path_num++;
1402  break;
1403 
1404  default:
1405  break;
1406  }
1407 
1408  return node;
1409 }
1410 
1411 /*
1412  * pt_clear_Oracle_outerjoin_spec_id () -
1413  * return:
1414  * parser(in):
1415  * node(in):
1416  * arg(in):
1417  * continue_walk(in/out):
1418  */
1419 static PT_NODE *
1420 pt_clear_Oracle_outerjoin_spec_id (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1421 {
1422  PT_BIND_NAMES_ARG *bind_arg = (PT_BIND_NAMES_ARG *) arg;
1423  SEMANTIC_CHK_INFO *sc_info;
1424 
1425  if (!node)
1426  {
1427  return node;
1428  }
1429 
1430  switch (node->node_type)
1431  {
1432  case PT_NAME:
1433  sc_info = bind_arg->sc_info;
1434 
1435  /* found node which is bound to the specified spec */
1436  if (node->node_type == PT_NAME)
1437  {
1438  /* clear spec_id to re-check outer join semantic */
1439  node->info.name.spec_id = 0;
1440  }
1441 
1442  /* don't revisit leaves */
1443  *continue_walk = PT_STOP_WALK;
1444  break;
1445 
1446  default:
1447  break;
1448  }
1449 
1450  return node;
1451 }
1452 
1453 void
1455 {
1456  if (node == NULL)
1457  {
1458  return;
1459  }
1460  if (node->node_type == PT_DOT_)
1461  {
1464  }
1465  else if (node->node_type == PT_NAME)
1466  {
1468 
1469  /* We also need to clear the spec id because this PT_NAME node might be a copy of a node that has been resolved
1470  * without filling in the default value. The parser_copy_tree() call in
1471  * fill_in_insert_default_function_arguments() is an example. We mark the current node as not resolved so that it
1472  * is resolved again, this time filling in the default value. */
1473  node->info.name.spec_id = 0;
1474  }
1475  else
1476  {
1477  assert (false);
1478  }
1479 }
1480 
1481 /*
1482  * fill_in_insert_default_function_arguments () - Fills in the argument of the
1483  * DEFAULT function when used
1484  * for INSERT, MERGE INSERT
1485  * parser(in):
1486  * node(in):
1487  * Note: When parsing statements such as "INSERT INTO tbl VALUES (1, DEFAULT)"
1488  * the column names corresponding to DEFAULT values are not yet known.
1489  * When performing name resolution the names and default values can be
1490  * filled in.
1491  */
1492 static void
1494 {
1495  PT_NODE *crt_attr = NULL;
1496  PT_NODE *crt_value = NULL;
1497  PT_NODE *crt_list = NULL;
1498  SM_CLASS *smclass = NULL;
1499  SM_ATTRIBUTE *attr = NULL;
1500  PT_NODE *cls_name = NULL;
1501  PT_NODE *values_list = NULL;
1502  PT_NODE *attrs_list = NULL;
1503 
1504  assert (node->node_type == PT_INSERT || node->node_type == PT_MERGE);
1505 
1506  /* if an attribute has a default expression as default value and that expression refers to the current date and time,
1507  * then we make sure that we mark this statement as one that needs the system datetime from the server */
1508  if (node->node_type == PT_INSERT)
1509  {
1510  cls_name = node->info.insert.spec->info.spec.entity_name;
1511  values_list = node->info.insert.value_clauses;
1512  attrs_list = node->info.insert.attr_list;
1513  }
1514  else
1515  {
1516  cls_name = node->info.merge.into->info.spec.entity_name;
1517  values_list = node->info.merge.insert.value_clauses;
1518  attrs_list = node->info.merge.insert.attr_list;
1519  }
1520 
1521  au_fetch_class_force (cls_name->info.name.db_object, &smclass, AU_FETCH_READ);
1522  if (smclass)
1523  {
1524  for (attr = smclass->attributes; attr != NULL; attr = (SM_ATTRIBUTE *) attr->header.next)
1525  {
1527  {
1528  node->flag.si_datetime = true;
1529  db_make_null (&parser->sys_datetime);
1530  break;
1531  }
1532  }
1533  }
1534 
1535  for (crt_list = values_list; crt_list != NULL; crt_list = crt_list->next)
1536  {
1537  /*
1538  * If the statement such as "INSERT INTO tbl DEFAULT" is given,
1539  * we rewrite it to "INSERT INTO tbl VALUES (DEFAULT, DEFAULT, ...)"
1540  * to support "server-side insertion" simply.
1541  * In this situation, the server will get "default value" from
1542  * "original_value" of the current representation, but sometimes
1543  * it is not the latest default value. (See the comment for sm_attribute
1544  * structure on class_object.h for more information.)
1545  * However, the client always knows it, so it's better for the server to
1546  * get the value from the client.
1547  */
1548  if (crt_list->info.node_list.list_type == PT_IS_DEFAULT_VALUE)
1549  {
1550  PT_NODE *crt_value_list = NULL;
1551 
1552  assert ((node->node_type == PT_INSERT && node->info.node_list.list == NULL)
1553  || (node->node_type == PT_MERGE && crt_list->info.node_list.list == NULL));
1554 
1555  for (crt_attr = attrs_list; crt_attr != NULL; crt_attr = crt_attr->next)
1556  {
1557  crt_value = parser_new_node (parser, PT_EXPR);
1558 
1559  if (crt_value == NULL)
1560  {
1561  if (crt_value_list != NULL)
1562  {
1563  parser_free_tree (parser, crt_value_list);
1564  }
1565  PT_ERROR (parser, node, "allocation error");
1566  return;
1567  }
1568 
1569  crt_value->info.expr.op = PT_DEFAULTF;
1570  crt_value->info.expr.arg1 = parser_copy_tree (parser, crt_attr);
1571 
1572  if (crt_value->info.expr.arg1 == NULL)
1573  {
1574  parser_free_node (parser, crt_value);
1575  if (crt_value_list != NULL)
1576  {
1577  parser_free_tree (parser, crt_value_list);
1578  }
1579  PT_ERROR (parser, node, "allocation error");
1580  return;
1581  }
1582 
1584 
1585  if (crt_value_list == NULL)
1586  {
1587  crt_value_list = crt_value;
1588  }
1589  else
1590  {
1591  crt_value_list = parser_append_node (crt_value, crt_value_list);
1592  }
1593  }
1594  crt_list->info.node_list.list = crt_value_list;
1595  crt_list->info.node_list.list_type = PT_IS_VALUE;
1596  }
1597  else
1598  {
1599  for (crt_attr = attrs_list, crt_value = crt_list->info.node_list.list; crt_attr != NULL && crt_value != NULL;
1600  crt_attr = crt_attr->next, crt_value = crt_value->next)
1601  {
1602  PT_NODE *crt_arg = NULL;
1603 
1604  if (crt_value->node_type != PT_EXPR)
1605  {
1606  continue;
1607  }
1608  if (crt_value->info.expr.op != PT_DEFAULTF)
1609  {
1610  continue;
1611  }
1612  if (crt_value->info.expr.arg1 != NULL)
1613  {
1614  continue;
1615  }
1616  crt_arg = parser_copy_tree (parser, crt_attr);
1617  if (crt_arg == NULL)
1618  {
1619  PT_ERROR (parser, node, "allocation error");
1620  return;
1621  }
1622  crt_value->info.expr.arg1 = crt_arg;
1624  }
1625  }
1626  }
1627 }
1628 
1629 /*
1630  * pt_bind_names () -
1631  * return:
1632  * parser(in):
1633  * node(in):
1634  * arg(in/out):
1635  * continue_walk(in/out):
1636  */
1637 static PT_NODE *
1638 pt_bind_names (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
1639 {
1640  PT_BIND_NAMES_ARG *bind_arg = (PT_BIND_NAMES_ARG *) arg;
1641  SCOPES scopestack;
1642  PT_NODE *node1 = NULL;
1643  PT_EXTRA_SPECS_FRAME spec_frame;
1644  PT_NODE *prev_attr = NULL, *attr = NULL, *next_attr = NULL, *as_attr = NULL;
1645  PT_NODE *resolved_attrs = NULL, *spec = NULL;
1646  PT_NODE *flat = NULL, *range_var = NULL;
1647  bool do_resolve = true;
1648  PT_NODE *seq = NULL;
1649  PT_NODE *cnf = NULL, *prev = NULL, *next = NULL, *last = NULL, *save = NULL;
1650  PT_NODE *lhs = NULL, *rhs = NULL, *lhs_spec = NULL, *rhs_spec = NULL;
1651  PT_NODE *p_spec = NULL;
1652  PT_NODE *result = NULL;
1653  short i, k, lhs_location, rhs_location, level;
1654  PT_JOIN_TYPE join_type;
1655  void *save_etc = NULL;
1656 
1657  *continue_walk = PT_CONTINUE_WALK;
1658 
1659  if (!node || !parser)
1660  {
1661  return node;
1662  }
1663 
1664  /* treat scopes as the next outermost scope */
1665  scopestack.next = bind_arg->scopes;
1666  scopestack.specs = NULL;
1667  scopestack.correlation_level = 0;
1668  scopestack.location = 0;
1669 
1670  /* prepend local scope to scopestack and then bind names */
1671  switch (node->node_type)
1672  {
1673  case PT_SELECT:
1674 
1675  scopestack.specs = node->info.query.q.select.from;
1676  spec_frame.next = bind_arg->spec_frames;
1677  spec_frame.extra_specs = NULL;
1678 
1679  /* break links to current scopes to bind_names in the WITH_CLAUSE */
1680  bind_arg->scopes = NULL;
1681  bind_arg->spec_frames = NULL;
1682  pt_bind_names_in_with_clause (parser, node, bind_arg);
1683 
1684  /* restore links to current scopes */
1685  bind_arg->scopes = &scopestack;
1686  bind_arg->spec_frames = &spec_frame;
1687 
1688  if (pt_has_error (parser))
1689  {
1690  /* name binding in WITH_CLAUSE have failed; this node will be registered to orphan list and freed later */
1691  node = NULL;
1692  goto select_end;
1693  }
1694 
1695  pt_bind_scope (parser, bind_arg);
1696 
1697  if (pt_has_error (parser))
1698  {
1699  /* this node will be registered to orphan list and freed later */
1700  node = NULL;
1701  goto select_end;
1702  }
1703 
1704  /* 0-step: check for hints that can affect name resolving. some hints are supposed to change the result type by
1705  * obtaining record information or page header information and so on. In these cases, names will be resolved to a
1706  * set of reserved names for each type of results. The query spec must be marked accordingly. NOTE: These hints
1707  * can be applied on single-spec queries. If this is a joined-spec query, just ignore the hints. */
1708  if (node->info.query.q.select.from != NULL && node->info.query.q.select.from->next == NULL)
1709  {
1711  {
1712  /* mark spec to scan for record info */
1713  node->info.query.q.select.from->info.spec.flag =
1715  }
1716  else if (node->info.query.q.select.hint & PT_HINT_SELECT_PAGE_INFO)
1717  {
1718  /* mark spec to scan for heap page headers */
1719  node->info.query.q.select.from->info.spec.flag =
1721  }
1722  else if (node->info.query.q.select.hint & PT_HINT_SELECT_KEY_INFO)
1723  {
1724  PT_NODE *using_index = node->info.query.q.select.using_index;
1725  if (using_index == NULL || !PT_IS_NAME_NODE (using_index))
1726  {
1727  assert (0);
1728  PT_INTERNAL_ERROR (parser, "Invalid usage of SELECT_KEY_INFO hint");
1729  parser_free_tree (parser, node);
1730  node = NULL;
1731  goto select_end;
1732  }
1733  /* using_index is just a name, mark as index name */
1734  using_index->info.name.meta_class = PT_INDEX_NAME;
1735  using_index->etc = (void *) PT_IDX_HINT_FORCE;
1736 
1737  /* mark spec to scan for index key info */
1738  node->info.query.q.select.from->info.spec.flag =
1740  }
1742  {
1743  PT_NODE *using_index = node->info.query.q.select.using_index;
1744  if (using_index == NULL || !PT_IS_NAME_NODE (using_index))
1745  {
1746  assert (0);
1747  PT_INTERNAL_ERROR (parser, "Invalid usage of SELECT_KEY_INFO hint");
1748  parser_free_tree (parser, node);
1749  node = NULL;
1750  goto select_end;
1751  }
1752  /* using_index is just a name, mark as index name */
1753  using_index->info.name.meta_class = PT_INDEX_NAME;
1754  using_index->etc = (void *) PT_IDX_HINT_FORCE;
1755 
1756  /* mark spec to scan for index key info */
1757  node->info.query.q.select.from->info.spec.flag =
1759  }
1760  }
1761 
1762  /* resolve '*' for rewritten multicolumn subquery during parsing STEP 1: remove sequence from select_list STEP 2:
1763  * resolve '*', if exists STEP 3: restore sequence */
1764 
1765  /* STEP 1 */
1766  seq = NULL;
1767  if (node->info.query.q.select.list->node_type == PT_VALUE
1770  {
1771  seq = node->info.query.q.select.list;
1772  node->info.query.q.select.list = seq->info.value.data_value.set;
1773  seq->info.value.data_value.set = NULL; /* cut-off link */
1774  }
1775 
1776  /* STEP 2 */
1777  if (node->info.query.q.select.list)
1778  { /* resolve "*" */
1779  if (node->info.query.q.select.list->node_type == PT_VALUE
1780  && node->info.query.q.select.list->type_enum == PT_TYPE_STAR)
1781  {
1782  PT_NODE *next = node->info.query.q.select.list->next;
1783 
1784  /* To consider 'select *, xxx ...', release "*" node only. */
1785  node->info.query.q.select.list->next = NULL;
1786  parser_free_node (parser, node->info.query.q.select.list);
1787 
1788  node->info.query.q.select.list = pt_resolve_star (parser, node->info.query.q.select.from, NULL);
1789 
1790  if (next != NULL)
1791  {
1792  parser_append_node (next, node->info.query.q.select.list);
1793  }
1794 
1795  if (!node->info.query.q.select.list)
1796  {
1797  unsigned int save_custom = parser->custom_print;
1798  PT_NODE *from = node->info.query.q.select.from;
1799 
1800  parser->custom_print = parser->custom_print | PT_SUPPRESS_RESOLVED;
1802  pt_short_print (parser, from));
1803  parser->custom_print = save_custom;
1804  parser_free_tree (parser, node);
1805  node = NULL;
1806  goto select_end;
1807  }
1808  }
1809  else
1810  { /* resolve "class_name.*" */
1811  prev_attr = NULL;
1812  attr = node->info.query.q.select.list;
1813 
1814  while (attr && do_resolve)
1815  {
1816  do_resolve = false;
1817 
1818  /* STEP 2-1) find "class_name.*" */
1819  while (attr)
1820  {
1821  if (attr->node_type == PT_NAME && attr->type_enum == PT_TYPE_STAR)
1822  {
1823  /* find "class_name.*" */
1824  do_resolve = true;
1825  break;
1826  }
1827 
1828  prev_attr = attr; /* save previous attr */
1829  attr = attr->next;
1830  }
1831 
1832  if (attr == NULL) /* consume attr list */
1833  {
1834  break;
1835  }
1836 
1837  /* STEP 2-2) do resolve */
1838  if (do_resolve == true)
1839  {
1840  /* STEP 2-2-1) assign spec_id into PT_NAME */
1841  for (spec = node->info.query.q.select.from; spec; spec = spec->next)
1842  {
1843  if (PT_SPEC_IS_ENTITY (spec))
1844  {
1845  /* entity spec */
1846  assert (!PT_SPEC_IS_DERIVED (spec) || !PT_SPEC_IS_CTE (spec));
1847  flat = spec->info.spec.flat_entity_list;
1848 
1849  if (pt_str_compare (attr->info.name.original, flat->info.name.resolved, CASE_INSENSITIVE)
1850  == 0)
1851  {
1852  /* find spec set attr's spec_id */
1853  attr->info.name.spec_id = flat->info.name.spec_id;
1854  break;
1855  }
1856  }
1857  else
1858  {
1859  /* derived table or cte */
1860  assert (PT_SPEC_IS_DERIVED (spec) || PT_SPEC_IS_CTE (spec));
1861  range_var = spec->info.spec.range_var;
1862  if (pt_str_compare (attr->info.name.original, range_var->info.name.original,
1863  CASE_INSENSITIVE) == 0)
1864  {
1865  break;
1866  }
1867  }
1868  } /* for */
1869 
1870  if (spec == NULL)
1871  { /* error */
1872  do_resolve = false;
1873  node->info.query.q.select.list = NULL;
1874  break;
1875  }
1876  else
1877  {
1878  /* STEP 2-2-2) recreate select_list */
1879  if (PT_SPEC_IS_ENTITY (spec))
1880  {
1881  resolved_attrs =
1882  parser_append_node (attr->next,
1883  pt_resolve_star (parser, node->info.query.q.select.from, attr));
1884  }
1885  else
1886  {
1887  for (as_attr = spec->info.spec.as_attr_list; as_attr; as_attr = as_attr->next)
1888  {
1889  as_attr->info.name.resolved = range_var->info.name.original;
1890  }
1891  resolved_attrs =
1892  parser_append_node (attr->next,
1893  parser_copy_tree_list (parser, spec->info.spec.as_attr_list));
1894  }
1895 
1896  if (prev_attr == NULL)
1897  {
1898  node->info.query.q.select.list = resolved_attrs;
1899  }
1900  else
1901  {
1902  prev_attr->next = NULL;
1903  node->info.query.q.select.list =
1904  parser_append_node (resolved_attrs, node->info.query.q.select.list);
1905  }
1906 
1907  if (resolved_attrs == NULL || node->info.query.q.select.list == NULL)
1908  {
1909  node->info.query.q.select.list = NULL;
1910  break;
1911  }
1912  }
1913  } /* if (do_resolve) */
1914 
1915  next_attr = attr->next;
1916  attr->next = NULL;
1917  parser_free_tree (parser, attr);
1918  attr = next_attr;
1919 
1920  /* reposition prev_attr */
1921  for (prev_attr = resolved_attrs; prev_attr->next != attr; prev_attr = prev_attr->next)
1922  {
1923  ;
1924  }
1925  }
1926  }
1927 
1928  if (!node->info.query.q.select.list)
1929  {
1930  unsigned int save_custom = parser->custom_print;
1931 
1932  parser->custom_print = (parser->custom_print | PT_SUPPRESS_RESOLVED);
1934  pt_short_print (parser, attr));
1935  parser->custom_print = save_custom;
1936  parser_free_tree (parser, node);
1937  node = NULL;
1938  goto select_end;
1939  }
1940  }
1941 
1942  /* STEP 3 */
1943  if (seq)
1944  {
1945  seq->info.value.data_value.set = node->info.query.q.select.list;
1946  node->info.query.q.select.list = seq;
1947  }
1948 
1949  (void) pt_resolve_hint (parser, node);
1950 
1951  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
1952 
1953  /* capture minimum correlation */
1954  if (!node->info.query.correlation_level)
1955  {
1956  node->info.query.correlation_level = scopestack.correlation_level;
1957  }
1958  else if (scopestack.correlation_level && (scopestack.correlation_level < node->info.query.correlation_level))
1959  {
1960  node->info.query.correlation_level = scopestack.correlation_level;
1961  }
1962 
1963  /* capture type enum and data_type from first column in select list */
1964  if (node && node->info.query.q.select.list)
1965  {
1966  node->type_enum = node->info.query.q.select.list->type_enum;
1967  if (node->info.query.q.select.list->data_type)
1968  {
1969  node->data_type = parser_copy_tree_list (parser, node->info.query.q.select.list->data_type);
1970  }
1971  }
1972 
1973  /* pop the extra spec frame and add any extra specs to the from list */
1974  node->info.query.q.select.from = parser_append_node (spec_frame.extra_specs, node->info.query.q.select.from);
1975 
1976  /*
1977  * Oracle style outer join support: convert to ANSI standard style
1978  * only permit the following predicate
1979  * 'single_column(+) op expression_'
1980  * 'expression_ op single_column(+)'
1981  * move outer join predicates from WHERE clause
1982  * to ON condition in FROM clause and set proper join type
1983  */
1984 
1986  {
1987  /* not found */
1988  goto select_end;
1989  }
1990 
1992  {
1993  /* can not specify the (+) operator in a query that also conatins FROM clause join syntax */
1994  PT_ERROR (parser, node, "can not specify '(+)' with ANSI join syntax");
1995  parser_free_tree (parser, node);
1996  node = NULL;
1997  goto select_end;
1998  }
1999 
2000 #if 0
2001  /* By default, support oracle_style_outerjoin */
2003  {
2004  PT_ERROR (parser, node, "Oracle outer join conversion not supported");
2005  parser_free_tree (parser, node);
2006  node = NULL;
2007  goto select_end;
2008  }
2009 #endif /* 0 */
2010 
2011  /* convert to CNF and tag taggable terms */
2012  node->info.query.q.select.where = pt_cnf (parser, node->info.query.q.select.where);
2013 
2014  /* list search twice one-pass: set outer join type, edge two-pass: set outer join sarg outer join sarg matrix:
2015  * X.i=Y.i and Y.i=Z.i and Y.j=1 case 1: X right Y right Z -> put Y(+)-sarg to Z case 2: X right Y left Z ->
2016  * meaningless Y(+)-sarg case 3: X left Y right Z -> syntax error at one-pass case 4: X left Y left Z -> put
2017  * Y(+)-sarg to Y */
2018 
2019  for (k = 1; k <= 2; k++)
2020  {
2021  prev = NULL; /* init */
2022  for (cnf = node->info.query.q.select.where; cnf; cnf = next)
2023  {
2024  next = cnf->next; /* save link */
2025 
2026  if (cnf->node_type != PT_EXPR)
2027  {
2028  prev = cnf;
2029  continue;
2030  }
2031 
2033  {
2034  join_type = PT_JOIN_LEFT_OUTER;
2035  }
2037  {
2038  join_type = PT_JOIN_RIGHT_OUTER;
2039  }
2040  else
2041  {
2042  prev = cnf;
2043  continue;
2044  }
2045 
2046  /* find left-hand side spec */
2047  lhs = cnf->info.expr.arg1;
2048  lhs_spec = NULL;
2049  lhs_location = 0; /* init */
2050  if (lhs)
2051  {
2052  if (pt_is_attr (lhs))
2053  {
2054  if (lhs->node_type == PT_DOT_)
2055  {
2056  /* check for path expression */
2058  pt_short_print (parser, node));
2059  parser_free_tree (parser, node);
2060  node = NULL;
2061  goto select_end;
2062  }
2063 
2064  /* find the class of the lhs from spec list */
2065  for (i = 0, spec = node->info.query.q.select.from; spec; i++, spec = spec->next)
2066  {
2067  /* found spec */
2068  if (spec->info.spec.id == lhs->info.name.spec_id)
2069  {
2070  lhs_spec = spec;
2071  lhs_location = i;
2072  break;
2073  }
2074  }
2075  }
2076  else if (!pt_is_const (lhs)) /* is_const : no nothing */
2077  {
2078  /* find the class of the lhs from spec list */
2079  last = save = NULL; /* init */
2080  do
2081  {
2082  for (i = -1, spec = node->info.query.q.select.from; spec && spec != last;
2083  i++, spec = spec->next)
2084  {
2085  save = spec;
2086  }
2087  last = save; /* set last spec */
2088 
2089  /* traverse tree to find spec */
2090  bind_arg->sc_info->Oracle_outerjoin_spec = last;
2091  bind_arg->sc_info->Oracle_outerjoin_attr_num = 0;
2092  bind_arg->sc_info->Oracle_outerjoin_subq_num = 0;
2093  bind_arg->sc_info->Oracle_outerjoin_path_num = 0;
2095  if (bind_arg->sc_info->Oracle_outerjoin_attr_num > 0)
2096  {
2097  lhs_spec = last;
2098  lhs_location = i;
2099  }
2100  /* check for subquery */
2101  if (bind_arg->sc_info->Oracle_outerjoin_subq_num > 0)
2102  {
2103  PT_ERRORm (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
2105  parser_free_tree (parser, node);
2106  node = NULL;
2107  goto select_end;
2108  }
2109  /* check for path expression */
2110  if (bind_arg->sc_info->Oracle_outerjoin_path_num > 0)
2111  {
2113  pt_short_print (parser, node));
2114  parser_free_tree (parser, node);
2115  node = NULL;
2116  goto select_end;
2117  }
2118  }
2119  while (lhs_spec == NULL && i > 0);
2120  }
2121  } /* if (lhs) */
2122 
2123  /* find right-hand side spec */
2124  rhs = cnf->info.expr.arg2;
2125  rhs_spec = NULL;
2126  rhs_location = 0; /* init */
2127  if (rhs)
2128  {
2129  if (pt_is_attr (rhs))
2130  {
2131  if (rhs->node_type == PT_DOT_)
2132  {
2133  /* check for path expression */
2135  pt_short_print (parser, node));
2136  parser_free_tree (parser, node);
2137  node = NULL;
2138  goto select_end;
2139  }
2140 
2141  /* find the class of the rhs from spec list */
2142  for (i = 0, spec = node->info.query.q.select.from; spec; i++, spec = spec->next)
2143  {
2144  /* found spec */
2145  if (spec->info.spec.id == rhs->info.name.spec_id)
2146  {
2147  rhs_spec = spec;
2148  rhs_location = i;
2149  break;
2150  }
2151  }
2152  }
2153  else if (!pt_is_const (rhs)) /* is_const : do nothing */
2154  {
2155  /* find the class of the rhs from spec list */
2156  last = save = NULL; /* init */
2157  do
2158  {
2159  for (i = -1, spec = node->info.query.q.select.from; spec && spec != last;
2160  i++, spec = spec->next)
2161  {
2162  save = spec;
2163  }
2164  last = save; /* set last spec */
2165 
2166  /* traverse tree to find spec */
2167  bind_arg->sc_info->Oracle_outerjoin_spec = last;
2168  bind_arg->sc_info->Oracle_outerjoin_attr_num = 0;
2169  bind_arg->sc_info->Oracle_outerjoin_subq_num = 0;
2170  bind_arg->sc_info->Oracle_outerjoin_path_num = 0;
2172  if (bind_arg->sc_info->Oracle_outerjoin_attr_num > 0)
2173  {
2174  rhs_spec = last;
2175  rhs_location = i;
2176  }
2177  /* check for subquery */
2178  if (bind_arg->sc_info->Oracle_outerjoin_subq_num > 0)
2179  {
2180  PT_ERRORm (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
2182  parser_free_tree (parser, node);
2183  node = NULL;
2184  goto select_end;
2185  }
2186  /* check for path expression */
2187  if (bind_arg->sc_info->Oracle_outerjoin_path_num > 0)
2188  {
2190  pt_short_print (parser, node));
2191  parser_free_tree (parser, node);
2192  node = NULL;
2193  goto select_end;
2194  }
2195  }
2196  while (rhs_spec == NULL && i > 0);
2197  }
2198  } /* if (rhs) */
2199 
2200  if (k == 1)
2201  {
2202  /* first search: only consider edges and skip sargs */
2203  if (lhs_spec && rhs_spec && lhs_spec->info.spec.id != rhs_spec->info.spec.id)
2204  {
2205  /* found edge: set join type and spec */
2206  if (lhs_location < rhs_location)
2207  {
2208  p_spec = lhs_spec;
2209  spec = rhs_spec;
2210  }
2211  else
2212  {
2213  /* converse join type of edge for example SELECT... FROM x, y WHERE y.i = x.i(+) */
2214  join_type = (join_type == PT_JOIN_LEFT_OUTER) ? PT_JOIN_RIGHT_OUTER : PT_JOIN_LEFT_OUTER;
2215  p_spec = rhs_spec;
2216  spec = lhs_spec;
2217  }
2218  }
2219  else
2220  {
2221  prev = cnf;
2222  continue;
2223  }
2224  }
2225  else
2226  {
2227  p_spec = NULL; /* useless */
2228  spec = (lhs_location < rhs_location) ? rhs_spec : lhs_spec;
2229  }
2230 
2231  /* error check */
2232  if (spec == NULL)
2233  {
2234  /* give up */
2235  PT_ERRORf (parser, node, "check outer join syntax at '%s'", pt_short_print (parser, cnf));
2236  parser_free_tree (parser, node);
2237  node = NULL;
2238  goto select_end;
2239  }
2240 
2241  if (k == 1)
2242  {
2243  /* first search: check outer join link set join type and edge */
2244 
2245  PT_NODE *tmp, *p_end, *s_end, *start, *end, *s_start;
2246 
2247  if (spec->info.spec.join_type == PT_JOIN_NONE)
2248  {
2249  /* case A, C */
2250  p_end = p_spec; /* init */
2251  for (tmp = p_end; tmp->next != spec; tmp = tmp->next)
2252  {
2253  /* found end of p_spec join_list */
2254  if (tmp->next->info.spec.join_type == PT_JOIN_NONE)
2255  {
2256  p_end = tmp;
2257  break;
2258  }
2259  else
2260  {
2261  p_end = tmp->next;
2262  }
2263  }
2264  for (tmp = p_end; tmp->next != spec; tmp = tmp->next)
2265  {
2266  ;
2267  }
2268  /* found before node of spec join list: cut-off link */
2269  tmp->next = NULL;
2270 
2271  for (tmp = spec; tmp->next; tmp = tmp->next)
2272  {
2273  ;
2274  }
2275  /* found end of spec list */
2276  s_end = tmp;
2277 
2278  s_end->next = p_end->next;
2279  p_end->next = spec;
2280  }
2281  else
2282  {
2283  for (tmp = p_spec->next; tmp != spec; tmp = tmp->next)
2284  {
2285  /* join_list disconnected */
2286  if (tmp->info.spec.join_type == PT_JOIN_NONE)
2287  {
2288  break;
2289  }
2290  }
2291  if (tmp != spec)
2292  { /* p_spec to spec join_list not exists */
2293  if (p_spec->info.spec.join_type == PT_JOIN_NONE)
2294  {
2295  /* case B */
2296  s_start = NULL; /* init */
2297  start = tmp; /* init */
2298  end = spec; /* init */
2299  do
2300  {
2301  for (tmp = start; tmp->next != end; tmp = tmp->next)
2302  {
2303  ;
2304  }
2305  if (tmp->info.spec.join_type == PT_JOIN_NONE)
2306  {
2307  /* found spec join_link start */
2308  s_start = tmp;
2309  for (tmp = node->info.query.q.select.from; tmp->next != s_start; tmp = tmp->next)
2310  {
2311  ;
2312  }
2313  /* found before node of spec join_list: cut-off link */
2314  tmp->next = NULL;
2315  }
2316  else
2317  {
2318  end = tmp;
2319  }
2320  }
2321  while (s_start == NULL); /* end do */
2322 
2323  for (tmp = spec; tmp->next; tmp = tmp->next)
2324  {
2325  ;
2326  }
2327  /* found end of spec list */
2328  s_end = tmp;
2329 
2330  s_end->next = node->info.query.q.select.from;
2331  node->info.query.q.select.from = s_start;
2332 
2333  /* swap p_spec, spec */
2334  save = p_spec;
2335  p_spec = spec;
2336  spec = save;
2337 
2338  /* converse join type */
2339  join_type = (join_type == PT_JOIN_LEFT_OUTER) ? PT_JOIN_RIGHT_OUTER : PT_JOIN_LEFT_OUTER;
2340  }
2341  else
2342  {
2343  /* case D: give up */
2344  PT_ERROR (parser, node, "a class may be outer joined to" " at most one other class");
2345  parser_free_tree (parser, node);
2346  node = NULL;
2347  goto select_end;
2348  }
2349  }
2350  }
2351  /* outer join_link handling end */
2352 
2353  /* set join type */
2354  if ((spec->info.spec.join_type == PT_JOIN_LEFT_OUTER
2355  || spec->info.spec.join_type == PT_JOIN_RIGHT_OUTER) && spec->info.spec.join_type != join_type)
2356  {
2357  /* give up */
2358  PT_ERROR (parser, node, "two classes cannot be " "outer-joined to each other");
2359  parser_free_tree (parser, node);
2360  node = NULL;
2361  goto select_end;
2362  }
2363  spec->info.spec.join_type = join_type;
2364  }
2365  else
2366  { /* k == 2 */
2367  /* second search: set sarg */
2368  if (spec->info.spec.join_type == PT_JOIN_RIGHT_OUTER && spec->next)
2369  {
2370  if (spec->next->info.spec.join_type == PT_JOIN_RIGHT_OUTER)
2371  {
2372  /* check for case 1: */
2373  spec = spec->next;
2374  }
2375  else if (spec->next->info.spec.join_type == PT_JOIN_LEFT_OUTER)
2376  {
2377  /* check for case 2: meaningless outer join sargs */
2378  prev = cnf;
2379  continue;
2380  }
2381  }
2382 
2383  /* check for case 4: do nothing and go ahead */
2384  }
2385 
2386  /* cut-off cnf from WHERE clause */
2387  if (prev == NULL)
2388  { /* the first cnf */
2389  node->info.query.q.select.where = next;
2390  }
2391  else
2392  {
2393  prev->next = next;
2394  }
2395  cnf->next = NULL; /* cut-off link */
2396 
2397  /* put cnf to the ON cond */
2398  spec->info.spec.on_cond = parser_append_node (cnf, spec->info.spec.on_cond);
2399  }
2400  }
2401 
2402  for (spec = node->info.query.q.select.from; spec; spec = spec->next)
2403  {
2404  if (spec->info.spec.on_cond)
2405  {
2406  /* check for case 3: */
2407  if (spec->info.spec.join_type == PT_JOIN_LEFT_OUTER && spec->next
2408  && spec->next->info.spec.join_type == PT_JOIN_RIGHT_OUTER)
2409  {
2410  PT_ERROR (parser, node, "a class may be outer joined to " "at most one other class");
2411  parser_free_tree (parser, node);
2412  node = NULL;
2413  goto select_end;
2414  }
2415  else if (spec->info.spec.join_type == PT_JOIN_RIGHT_OUTER)
2416  {
2417  for (save = node->info.query.q.select.from; save; save = save->next)
2418  {
2419  if (save->next == spec)
2420  {
2421  if (save->info.spec.join_type == PT_JOIN_LEFT_OUTER)
2422  {
2423  PT_ERROR (parser, node, "a class may be outer joined to " "at most one other class");
2424  parser_free_tree (parser, node);
2425  node = NULL;
2426  goto select_end;
2427  }
2428  }
2429  } /* for */
2430  }
2431 
2432 
2433  /* clear spec_id to re-check outer join semantic */
2434  bind_arg->sc_info->Oracle_outerjoin_spec = spec;
2435  parser_walk_tree (parser, spec->info.spec.on_cond, pt_clear_Oracle_outerjoin_spec_id, bind_arg,
2437  }
2438  }
2439 
2440  /* check outer join semantic of ON cond */
2441  bind_arg->scopes->specs = node->info.query.q.select.from; /* init */
2442  bind_arg->scopes->location = 0; /* init */
2443  parser_walk_tree (parser, node->info.query.q.select.from, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2444 
2445  /* meaningless outer join check */
2446  for (spec = node->info.query.q.select.from; spec; spec = spec->next)
2447  {
2448  if (spec->info.spec.join_type == PT_JOIN_NONE && spec->info.spec.on_cond)
2449  {
2450  /* meaningless outer join predicate for example SELECT... FROM x, y WHERE x.i(+) = 1 recover to WHERE
2451  * clause */
2452  node->info.query.q.select.where =
2453  parser_append_node (spec->info.spec.on_cond, node->info.query.q.select.where);
2454  spec->info.spec.on_cond = NULL;
2455  }
2456  } /* for */
2457 
2458  select_end:
2459  bind_arg->spec_frames = bind_arg->spec_frames->next;
2460 
2461  /* remove this level's scope */
2462  bind_arg->scopes = bind_arg->scopes->next;
2463 
2464  /* don't revisit leaves */
2465  *continue_walk = PT_LIST_WALK;
2466  break;
2467 
2468  case PT_UNION:
2469  case PT_INTERSECTION:
2470  case PT_DIFFERENCE:
2471  {
2472  int arg1_corr, arg2_corr, corr;
2473  PT_NODE *arg1, *arg2;
2474  PT_NODE *select_node = NULL, *order_by_link = NULL;
2475  int index_of_order_by_link = -1;
2476 
2477  /* treat this just like a select with no from, so that we can properly get correlation level of sub-queries. */
2478  bind_arg->scopes = &scopestack;
2479 
2480  pt_bind_names_in_with_clause (parser, node, bind_arg);
2481 
2482  /* change order by link in UNION/INTERSECTION/DIFFERENCE query into the tail of first select query's order by
2483  * list for bind names (It will be restored after bind names.) */
2484 
2485  if (node->info.query.order_by)
2486  {
2487  index_of_order_by_link = 0;
2488 
2489  select_node = node;
2490  while (select_node)
2491  {
2492  switch (select_node->node_type)
2493  {
2494  case PT_SELECT:
2495  goto l_select_node;
2496  break;
2497  case PT_UNION:
2498  case PT_INTERSECTION:
2499  case PT_DIFFERENCE:
2500  select_node = select_node->info.query.q.union_.arg1;
2501  break;
2502  default:
2503  select_node = NULL;
2504  break;
2505  }
2506  }
2507 
2508  l_select_node:
2509  if (select_node)
2510  {
2511  if (!select_node->info.query.order_by)
2512  {
2513  select_node->info.query.order_by = node->info.query.order_by;
2514  }
2515  else
2516  {
2517  index_of_order_by_link++;
2518  order_by_link = select_node->info.query.order_by;
2519  while (order_by_link->next)
2520  {
2521  order_by_link = order_by_link->next;
2522  index_of_order_by_link++;
2523  }
2524 
2525  order_by_link->next = node->info.query.order_by;
2526  }
2527 
2528  node->info.query.order_by = NULL;
2529  }
2530  }
2531 
2532  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2533 
2534  arg1 = node->info.query.q.union_.arg1;
2535  arg2 = node->info.query.q.union_.arg2;
2536 
2537  if (arg1 && arg2)
2538  {
2539  arg1_corr = arg1->info.query.correlation_level;
2540  arg2_corr = arg2->info.query.correlation_level;
2541  if (arg1_corr)
2542  {
2543  corr = arg1_corr;
2544  if (arg2_corr)
2545  {
2546  if (arg2_corr < corr)
2547  corr = arg2_corr;
2548  }
2549  }
2550  else
2551  {
2552  corr = arg2_corr;
2553  }
2554  /* must reduce the correlation level 1, for this level of scoping */
2555  if (corr)
2556  {
2557  corr--;
2558  }
2559  node->info.query.correlation_level = corr;
2560 
2561  /* capture type enum and data_type from arg1 */
2562  node->type_enum = arg1->type_enum;
2563  if (arg1->data_type)
2564  node->data_type = parser_copy_tree_list (parser, arg1->data_type);
2565  }
2566 
2567  /* Restore order by link */
2568  if (index_of_order_by_link >= 0)
2569  {
2570  if (order_by_link)
2571  {
2572  node->info.query.order_by = order_by_link->next;
2573  order_by_link->next = NULL;
2574  }
2575  else
2576  {
2577  node->info.query.order_by = select_node->info.query.order_by;
2578  select_node->info.query.order_by = NULL;
2579  }
2580  }
2581  }
2582 
2583  /* remove this level's scope */
2584  bind_arg->scopes = bind_arg->scopes->next;
2585 
2586  /* don't revisit leaves */
2587  *continue_walk = PT_LIST_WALK;
2588  break;
2589 
2590  case PT_UPDATE:
2591  scopestack.specs = node->info.update.spec;
2592  spec_frame.next = bind_arg->spec_frames;
2593  spec_frame.extra_specs = NULL;
2594 
2595  /* break links to current scopes to bind_names in the WITH_CLAUSE */
2596  bind_arg->scopes = NULL;
2597  bind_arg->spec_frames = NULL;
2598  pt_bind_names_in_with_clause (parser, node, bind_arg);
2599 
2600  bind_arg->spec_frames = spec_frame.next;
2601 
2602  /* restore links to current scopes */
2603  bind_arg->scopes = &scopestack;
2604  spec_frame.next = bind_arg->spec_frames;
2605  spec_frame.extra_specs = NULL;
2606  bind_arg->spec_frames = &spec_frame;
2607  pt_bind_scope (parser, bind_arg);
2608 
2609  (void) pt_resolve_hint (parser, node);
2610 
2611  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2612 
2613  /* pop the extra spec frame and add any extra specs to the from list */
2614  bind_arg->spec_frames = bind_arg->spec_frames->next;
2616 
2617  /* remove this level's scope */
2618  bind_arg->scopes = bind_arg->scopes->next;
2619 
2620  /* don't revisit leaves */
2621  *continue_walk = PT_LIST_WALK;
2622  break;
2623 
2624  case PT_DELETE:
2625  scopestack.specs = node->info.delete_.spec;
2626  spec_frame.next = bind_arg->spec_frames;
2627  spec_frame.extra_specs = NULL;
2628 
2629  /* break links to current scopes to bind_names in the WITH_CLAUSE */
2630  bind_arg->scopes = NULL;
2631  bind_arg->spec_frames = NULL;
2632  pt_bind_names_in_with_clause (parser, node, bind_arg);
2633 
2634  bind_arg->spec_frames = spec_frame.next;
2635 
2636  bind_arg->scopes = &scopestack;
2637  spec_frame.next = bind_arg->spec_frames;
2638  spec_frame.extra_specs = NULL;
2639  bind_arg->spec_frames = &spec_frame;
2640  pt_bind_scope (parser, bind_arg);
2641 
2642  (void) pt_resolve_hint (parser, node);
2643 
2644  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2645 
2646  /* pop the extra spec frame and add any extra specs to the from list */
2647  bind_arg->spec_frames = bind_arg->spec_frames->next;
2649 
2650  /* remove this level's scope */
2651  bind_arg->scopes = bind_arg->scopes->next;
2652 
2653  /* don't revisit leaves */
2654  *continue_walk = PT_LIST_WALK;
2655  break;
2656 
2657  case PT_INSERT:
2658  scopestack.specs = node->info.insert.spec;
2659  bind_arg->scopes = &scopestack;
2660  spec_frame.next = bind_arg->spec_frames;
2661  spec_frame.extra_specs = NULL;
2662  bind_arg->spec_frames = &spec_frame;
2663  pt_bind_scope (parser, bind_arg);
2664 
2665  result = pt_resolve_vclass_args (parser, node);
2666  if (!result)
2667  {
2668  /* error is handled */
2669  goto insert_end;
2670  }
2671  node = result;
2672 
2673  if (!node->info.insert.attr_list)
2674  {
2675  node->info.insert.attr_list = pt_resolve_star (parser, node->info.insert.spec, NULL);
2676  }
2677 
2679 
2680  /* Do not handle ON DUPLICATE KEY UPDATE yet, we need to resolve the other nodes first. */
2681  save = node->info.insert.odku_assignments;
2682  node->info.insert.odku_assignments = NULL;
2683 
2684  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2685 
2686  /* Check for double assignments */
2687  pt_no_double_insert_assignments (parser, node);
2688  if (pt_has_error (parser))
2689  {
2690  goto insert_end;
2691  }
2692 
2693  /* flag any "correlated" names as undefined. only names in subqueries and sub-inserts should be undefined. use
2694  * spec->etc to store the correlation level in value_clauses. */
2695  save_etc = node->info.insert.spec->etc;
2696  level = 0;
2697  node->info.insert.spec->etc = &level;
2700  node->info.insert.spec->etc = save_etc;
2701 
2702  if (save != NULL)
2703  {
2704  SCOPES extended_scope;
2705  PT_NODE *value_list = node->info.insert.value_clauses->info.node_list.list;
2706  extended_scope.next = NULL;
2707 
2708  /* restore ON DUPLICATE KEY UPDATE node */
2709  node->info.insert.odku_assignments = save;
2710 
2711  /* pt_undef_names_pre may have generated an error */
2712  if (pt_has_error (parser))
2713  {
2714  goto insert_end;
2715  }
2716 
2717  if (PT_IS_SELECT (value_list))
2718  {
2719  /* Some assignments may reference attributes from the select query that need to be resolved too. Add the
2720  * specs from the select statement as a scope in the stack. */
2721  extended_scope.next = bind_arg->scopes->next;
2722  extended_scope.specs = value_list->info.query.q.select.from;
2723  scopestack.correlation_level = 0;
2724  scopestack.location = 0;
2725  bind_arg->scopes->next = &extended_scope;
2726  }
2727 
2729  bind_arg);
2730 
2731  if (PT_IS_SELECT (value_list))
2732  {
2733  /* restore original scopes */
2734  bind_arg->scopes->next = extended_scope.next;
2735  }
2736  }
2737 
2738  if (!pt_has_error (parser))
2739  {
2740  /* make sure attributes were not bound to parameters */
2741  for (attr = node->info.insert.attr_list; attr; attr = attr->next)
2742  {
2743  if (attr->info.name.meta_class == PT_PARAMETER)
2744  {
2745  /* this is not an attribute of insert spec */
2747  attr->info.name.original,
2749  }
2750  }
2751  }
2752 
2753  insert_end:
2754  /* pop the extra spec frame and add any extra specs to the from list */
2755  bind_arg->spec_frames = bind_arg->spec_frames->next;
2757 
2758  /* remove this level's scope */
2759  bind_arg->scopes = bind_arg->scopes->next;
2760 
2761  /* don't revisit leaves */
2762  *continue_walk = PT_LIST_WALK;
2763  break;
2764 
2765  case PT_MERGE:
2766  if (node->info.merge.insert.value_clauses)
2767  {
2768  /* resolve missing attr_list as star */
2769  if (!node->info.merge.insert.attr_list)
2770  {
2771  node->info.merge.insert.attr_list = pt_resolve_star (parser, node->info.merge.into, NULL);
2772  }
2773  /* resolve DEFAULT clauses */
2774  if (node->info.merge.into->info.spec.entity_name)
2775  {
2777  }
2778  /* resolve insert attributes, values */
2779  pt_bind_names_merge_insert (parser, node, bind_arg, &scopestack, &spec_frame);
2780  if (pt_has_error (parser))
2781  {
2782  node = NULL;
2783  *continue_walk = PT_STOP_WALK;
2784  break;
2785  }
2786  }
2787 
2788  if (node->info.merge.update.assignment)
2789  {
2790  /* resolved update assignment list */
2791  pt_bind_names_merge_update (parser, node, bind_arg, &scopestack, &spec_frame);
2792  if (pt_has_error (parser))
2793  {
2794  node = NULL;
2795  *continue_walk = PT_STOP_WALK;
2796  break;
2797  }
2798  }
2799 
2800  assert (node->info.merge.into->next == NULL);
2801  node->info.merge.into->next = node->info.merge.using_clause;
2802 
2803  scopestack.specs = node->info.merge.into;
2804  bind_arg->scopes = &scopestack;
2805  spec_frame.next = bind_arg->spec_frames;
2806  spec_frame.extra_specs = NULL;
2807  bind_arg->spec_frames = &spec_frame;
2808  pt_bind_scope (parser, bind_arg);
2809  if (pt_has_error (parser))
2810  {
2811  node = NULL;
2812  *continue_walk = PT_STOP_WALK;
2813  break;
2814  }
2815 
2816  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2817  if (pt_has_error (parser))
2818  {
2819  node = NULL;
2820  *continue_walk = PT_STOP_WALK;
2821  break;
2822  }
2823 
2824  /* flag any "correlated" names as undefined. make sure etc is NULL. */
2825  save_etc = node->info.merge.into->etc;
2826  node->info.merge.into->etc = NULL;
2828  NULL);
2829  node->info.merge.into->etc = save_etc;
2830  if (pt_has_error (parser))
2831  {
2832  node = NULL;
2833  *continue_walk = PT_STOP_WALK;
2834  break;
2835  }
2836 
2837  bind_arg->spec_frames = bind_arg->spec_frames->next;
2838  bind_arg->scopes = bind_arg->scopes->next;
2839 
2840  /* don't revisit leaves */
2841  *continue_walk = PT_LIST_WALK;
2842 
2843  node->info.merge.into->next = NULL;
2844  break;
2845 
2846  case PT_CREATE_INDEX:
2847  case PT_ALTER_INDEX:
2848  case PT_DROP_INDEX:
2849  scopestack.specs = node->info.index.indexed_class;
2850  bind_arg->scopes = &scopestack;
2851  spec_frame.next = bind_arg->spec_frames;
2852  spec_frame.extra_specs = NULL;
2853  bind_arg->spec_frames = &spec_frame;
2854  pt_bind_scope (parser, bind_arg);
2855 
2856  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2857 
2858  bind_arg->spec_frames = bind_arg->spec_frames->next;
2859  bind_arg->scopes = bind_arg->scopes->next;
2860 
2861  *continue_walk = PT_LIST_WALK;
2862  break;
2863 
2864  case PT_METHOD_CALL:
2865  /*
2866  * We accept two different method call syntax:
2867  * 1) method_name(...) on target
2868  * 2) method_name(target, ...)
2869  * We need to normalize the second to the first so that we can do
2870  * resolution without special cases. We do this by moving the
2871  * first parameter to the on_call_target. If there is no parameter,
2872  * it will be caught in pt_semantic_check_local()
2873  */
2874  if (!node->info.method_call.on_call_target
2876  {
2879  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2880  /* don't revisit leaves */
2881  *continue_walk = PT_LIST_WALK;
2882  }
2883  else
2884  {
2886  {
2890  }
2891 
2892  /* make method name look resolved */
2895 
2896  /*
2897  * bind the names in the method arguments and target, their
2898  * scope will be the same as the method node's scope
2899  */
2900  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
2901  /* don't revisit leaves */
2902  *continue_walk = PT_LIST_WALK;
2903 
2904  /* find the type of the method here */
2905  if (!pt_resolve_method_type (parser, node) && (node->info.method_call.call_or_expr != PT_IS_CALL_STMT))
2906  {
2909  break;
2910  }
2911 
2912  /* if it is a call statement, we don't want to resolve method_name. also, if scopes is NULL we assume this
2913  * came from an evaluate call and we treat it like a call statement */
2914  if ((node->info.method_call.call_or_expr == PT_IS_CALL_STMT) || (bind_arg->scopes == NULL))
2915  {
2916  break;
2917  }
2918 
2919  /* resolve method name to entity where expansion will take place */
2922  {
2923  PT_NODE *entity = pt_find_entity_in_scopes (parser, bind_arg->scopes,
2925  /* no entity found will be caught as an error later. Probably an unresolvable target. */
2926  if (entity)
2927  {
2928  node->info.method_call.method_name->info.name.spec_id = entity->info.spec.id;
2929  }
2930  }
2931 
2932  }
2933 
2934  break;
2935 
2936  case PT_DATA_TYPE:
2937  /* don't visit leaves unless this is an object which might contain a name (i.e. CAST(value AS name) ) */
2938  if (node->type_enum != PT_TYPE_OBJECT)
2939  {
2940  *continue_walk = PT_LIST_WALK;
2941  }
2942  break;
2943 
2944  case PT_NAME:
2945  {
2946  PT_NODE *temp;
2947 
2948  if (node->type_enum == PT_TYPE_MAYBE)
2949  {
2950  /* reset spec_id to rebind the name/type */
2951  node->info.name.spec_id = 0;
2952  }
2953 
2954  temp = pt_bind_name_or_path_in_scope (parser, bind_arg, node);
2955  if (temp)
2956  {
2957  node = temp;
2958  /* don't visit leaves */
2959  *continue_walk = PT_LIST_WALK;
2960  }
2961  else
2962  {
2963  *continue_walk = PT_STOP_WALK;
2964  }
2965  }
2966  break;
2967 
2968  case PT_DOT_:
2969  {
2970  PT_NODE *temp;
2971  temp = pt_bind_name_or_path_in_scope (parser, bind_arg, node);
2972  if (temp)
2973  {
2974  node = temp;
2975  }
2976  else if (pt_has_error (parser))
2977  {
2978  return NULL;
2979  }
2980 
2981  if (!(node->node_type == PT_DOT_
2982  && (node->info.dot.arg2->node_type == PT_METHOD_CALL || node->info.dot.arg2->node_type == PT_FUNCTION)))
2983  {
2984  /* don't revisit leaves */
2985  *continue_walk = PT_LIST_WALK;
2986  }
2987 
2988  /* handle dot print format; do not print resolved name for arg2. for example: (CLASS_A, CLASS_B, CLASS_C is
2989  * class) CLASS_A.b.CLASS_B.c.CLASS_C.name; -> CLASS_A.b.c.name; */
2990  if (node->node_type == PT_DOT_)
2991  {
2992  PT_NODE *arg2;
2993 
2994  for (temp = node; temp->node_type == PT_DOT_; temp = temp->info.dot.arg1)
2995  {
2996  /* arg2 is PT_NAME node */
2997  arg2 = temp->info.dot.arg2;
2998  if (arg2 && arg2->node_type == PT_NAME)
2999  {
3001  }
3002  } /* for (temp = ...) */
3003  }
3004  }
3005  break;
3006 
3007  case PT_FUNCTION:
3008  if (node->info.function.function_type == PT_GENERIC)
3009  {
3011 
3012  if (node->info.function.function_type == PT_GENERIC)
3013  {
3014  /*
3015  * It may be a method call since they are parsed as
3016  * nodes PT_FUNCTION. If so, pt_make_method_call() will
3017  * translate it into a method_call.
3018  */
3019  node1 = pt_make_method_call (parser, node, bind_arg);
3020 
3021  if (node1->node_type == PT_METHOD_CALL)
3022  {
3023  PT_NODE_INIT_OUTERLINK (node);
3024  parser_free_tree (parser, node);
3025  node = node1; /* return the new node */
3026  /* don't revisit leaves */
3027  *continue_walk = PT_LIST_WALK;
3028  }
3029  else
3030  {
3031  /* It may be a generic function supported on the server. We put this case last so that user written
3032  * methods will resolve before trying to make it a server function. */
3033  if (!pt_type_generic_func (parser, node))
3034  {
3035  PT_NODE *top_node = NULL;
3036  int is_spec_attr = 0;
3037 
3038  /* get top node */
3039  if (bind_arg != NULL && bind_arg->sc_info != NULL)
3040  {
3041  top_node = bind_arg->sc_info->top_node;
3042  }
3043 
3044  if (top_node != NULL
3045  && (top_node->node_type == PT_CREATE_INDEX || top_node->node_type == PT_ALTER_INDEX
3046  || (top_node->node_type == PT_ALTER && (top_node->info.alter.create_index != NULL))))
3047  {
3048  /* check if function name is a spec attribute */
3049  if (pt_function_name_is_spec_attr (parser, node, bind_arg, &is_spec_attr) != NO_ERROR)
3050  {
3051  return NULL;
3052  }
3053  }
3054 
3055  /* show appropriate error message */
3056  if (is_spec_attr)
3057  {
3058  PT_ERRORm (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
3060  }
3061  else if (parser_function_code != PT_EMPTY)
3062  {
3063  PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
3065  }
3066  else
3067  {
3069  node->info.function.generic_name);
3070  }
3071 
3072  }
3073  }
3074  }
3075  else if (node->info.function.function_type < F_TOP_TABLE_FUNC)
3076  {
3077  PT_NODE *arg_list = node->info.function.arg_list;
3078 
3079  /* arg list must be a single subquery */
3080 
3081  if (arg_list->next
3082  || (arg_list->node_type != PT_SELECT && arg_list->node_type != PT_UNION
3083  && arg_list->node_type != PT_DIFFERENCE && arg_list->node_type != PT_INTERSECTION))
3084  {
3086  pt_short_print (parser, node));
3087  }
3088  }
3089  }
3090  break;
3091 
3092  case PT_SPEC:
3093  if (bind_arg->scopes)
3094  {
3095  node->info.spec.location = bind_arg->scopes->location++;
3096  }
3097  if (node->info.spec.on_cond)
3098  {
3099  switch (node->info.spec.join_type)
3100  {
3101  case PT_JOIN_INNER:
3102  case PT_JOIN_LEFT_OUTER:
3103  case PT_JOIN_RIGHT_OUTER:
3105  NULL);
3106  break;
3107  /* case PT_JOIN_FULL_OUTER: *//* not supported */
3108 
3109  case PT_JOIN_NONE:
3110  default:
3111  break;
3112  } /* switch (node->info.spec.join_type) */
3113  parser_walk_tree (parser, node->info.spec.on_cond, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
3114  }
3115  {
3116  PT_NODE *entity_name = node->info.spec.entity_name;
3117  if (entity_name && entity_name->node_type == PT_NAME)
3118  {
3119  entity_name->info.name.location = node->info.spec.location;
3120  if (entity_name->info.name.db_object && db_is_system_class (entity_name->info.name.db_object) > 0)
3121  {
3122  bind_arg->sc_info->system_class = true;
3123  }
3124  }
3125  }
3126 
3127  *continue_walk = PT_LIST_WALK;
3128  break;
3129 
3130  case PT_HOST_VAR:
3131  pt_bind_type_of_host_var (parser, node);
3132  break;
3133 
3134  case PT_SCOPE:
3135  scopestack.specs = node->info.scope.from;
3136  bind_arg->scopes = &scopestack;
3137  pt_bind_scope (parser, bind_arg);
3138  parser_walk_leaves (parser, node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
3139 
3140  /* remove this level's scope */
3141  bind_arg->scopes = bind_arg->scopes->next;
3142 
3143  /* don't revisit leaves */
3144  *continue_walk = PT_LIST_WALK;
3145  break;
3146 
3147  case PT_EXPR:
3148  if (node->info.expr.op == PT_NEXT_VALUE || node->info.expr.op == PT_CURRENT_VALUE)
3149  {
3150  /* don't walk leaves */
3151  *continue_walk = PT_LIST_WALK;
3152  }
3153  break;
3154 
3155  case PT_WITH_CLAUSE:
3156  /* WITH clause should be resolved from SELECT; don't walk leaves(cte_list) */
3157  *continue_walk = PT_LIST_WALK;
3158  break;
3159 
3160  case PT_CTE:
3161  pt_bind_names_in_cte (parser, node, bind_arg);
3162  if (pt_has_error (parser))
3163  {
3164  node = NULL;
3165  *continue_walk = PT_STOP_WALK;
3166  }
3167  else
3168  {
3169  /* don't walk leaves */
3170  *continue_walk = PT_LIST_WALK;
3171  }
3172  break;
3173 
3174  default:
3175  break;
3176  }
3177 
3178  return node;
3179 }
3180 
3181 /*
3182  * pt_bind_value_to_hostvar_local () -
3183  * return:
3184  * parser(in):
3185  * node(in):
3186  * arg(in):
3187  * continue_walk(in):
3188  */
3189 static PT_NODE *
3190 pt_bind_value_to_hostvar_local (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
3191 {
3192  DB_VALUE *value;
3193 
3194  if (node)
3195  {
3196  switch (node->node_type)
3197  {
3198  case PT_HOST_VAR:
3199  if (node->info.host_var.var_type != PT_HOST_IN)
3200  {
3201  break;
3202  }
3203 
3204  value = pt_value_to_db (parser, node);
3206  {
3207  /* change PT_NAME to PT_VALUE in order to optimize */
3208  /* return node ptr */
3209 
3210  PT_NODE *value_node;
3211 
3212  value_node = pt_dbval_to_value (parser, value);
3213  if (value_node)
3214  {
3215  PT_NODE_MOVE_NUMBER_OUTERLINK (value_node, node);
3216 
3217  parser_free_tree (parser, node);
3218 
3219  node = value_node;
3220  }
3221  }
3222  break;
3223  default:
3224  break;
3225  }
3226  }
3227 
3228  return node;
3229 } /* pt_bind_value_to_hostvar_local */
3230 
3231 /*
3232  * pt_bind_values_to_hostvars () -
3233  * return:
3234  * parser(in):
3235  * node(in):
3236  */
3237 PT_NODE *
3239 {
3240  if (!pt_has_error (parser))
3241  {
3242  node = parser_walk_tree (parser, node, pt_bind_value_to_hostvar_local, NULL, NULL, NULL);
3243  }
3244 
3245  if (pt_has_error (parser))
3246  {
3247  node = NULL;
3248  }
3249 
3250  return node;
3251 } /* pt_bind_values_to_hostvars */
3252 
3253 /*
3254  * pt_resolve_default_value () - Fills PT_NAME node with default value
3255  *
3256  * return : error code
3257  * parser (in) : parser context
3258  * name (in) : PT_NAME node
3259  *
3260  * NOTE: Filling with default value is forced. After setting default value,
3261  * PT_NAME_INFO_FILL_DEFAULT flag is set.
3262  * Name must be resolved first.
3263  */
3264 int
3266 {
3267  DB_ATTRIBUTE *att = NULL;
3268  const char *lang_str;
3269  int flag = 0;
3270  bool has_user_format;
3271 
3272  if (name->node_type != PT_NAME)
3273  {
3274  return NO_ERROR;
3275  }
3276 
3277  if (name->info.name.meta_class == PT_META_CLASS || name->info.name.meta_class == PT_OID_ATTR)
3278  {
3279  return NO_ERROR;
3280  }
3281 
3282  if (name->info.name.original == NULL || name->info.name.resolved == NULL)
3283  {
3284  /* cannot resolve */
3285  return NO_ERROR;
3286  }
3287 
3288  if (name->info.name.default_value != NULL)
3289  {
3290  /* default value was already set */
3291  return NO_ERROR;
3292  }
3293 
3295  if (att == NULL)
3296  {
3297  /* cannot resolve */
3298  return ER_FAILED;
3299  }
3300 
3302  {
3303  /* if the default value is an expression, make a node for it */
3304  PT_OP_TYPE op;
3305  PT_NODE *default_op_value_node;
3306 
3308  assert (op != (PT_OP_TYPE) 0);
3309  default_op_value_node = pt_expression_0 (parser, op);
3310 
3312  {
3313  name->info.name.default_value = default_op_value_node;
3314  }
3315  else
3316  {
3317  PT_NODE *arg1, *arg2, *arg3;
3318  arg1 = default_op_value_node;
3319  has_user_format = att->default_value.default_expr.default_expr_format ? 1 : 0;
3321  if (arg2 == NULL)
3322  {
3323  parser_free_tree (parser, default_op_value_node);
3325  return ER_FAILED;
3326  }
3327 
3328  arg3 = parser_new_node (parser, PT_VALUE);
3329  if (arg3 == NULL)
3330  {
3331  parser_free_tree (parser, default_op_value_node);
3332  parser_free_tree (parser, arg2);
3334  return ER_FAILED;
3335  }
3336  arg3->type_enum = PT_TYPE_INTEGER;
3338  lang_set_flag_from_lang (lang_str, has_user_format, 0, &flag);
3339  arg3->info.value.data_value.i = (long) flag;
3340 
3341  name->info.name.default_value = parser_make_expression (parser, PT_TO_CHAR, arg1, arg2, arg3);
3342  if (name->info.name.default_value == NULL)
3343  {
3344  parser_free_tree (parser, default_op_value_node);
3345  parser_free_tree (parser, arg2);
3346  parser_free_tree (parser, arg3);
3347  return ER_FAILED;
3348  }
3349  }
3350  }
3351  else
3352  {
3353  /* just set the default value */
3354  name->info.name.default_value = pt_dbval_to_value (parser, &att->default_value.value);
3355  if (name->info.name.default_value == NULL)
3356  {
3358  return ER_FAILED;
3359  }
3361  {
3363  }
3364  }
3365 
3367  return NO_ERROR;
3368 }
3369 
3370 /*
3371  * pt_find_attr_in_class_list () - trying to resolve X.attr
3372  * return: returns a PT_NAME list or NULL
3373  * parser(in):
3374  * flat(in): list of PT_NAME nodes (class names)
3375  * attr(in): a PT_NAME (an attribute name)
3376  */
3377 static int
3379 {
3380  DB_ATTRIBUTE *att = 0;
3381  DB_OBJECT *db = 0;
3382  PT_NODE *cname = flat;
3383  const char *lang_str;
3384  int flag = 0;
3385  bool has_user_format;
3386 
3387  if (!flat || !attr)
3388  {
3389  return 0;
3390  }
3391 
3392  if (attr->node_type != PT_NAME)
3393  {
3394  PT_INTERNAL_ERROR (parser, "resolution");
3395  return 0;
3396  }
3397 
3398  /* For Each class name on the list */
3399  while (cname)
3400  {
3401  if (cname->node_type != PT_NAME)
3402  {
3403  PT_INTERNAL_ERROR (parser, "resolution");
3404  return 0;
3405  }
3406 
3407  /* Get the object */
3408  db = cname->info.name.db_object;
3409  if (!db)
3410  {
3411  PT_INTERNAL_ERROR (parser, "resolution");
3412  return 0;
3413  }
3414 
3415  /* Does db have an attribute named 'name'? */
3416  att = (DB_ATTRIBUTE *) db_get_attribute_force (db, attr->info.name.original);
3417 
3418  if (!att || attr->info.name.meta_class == PT_META_CLASS || attr->info.name.meta_class == PT_OID_ATTR)
3419  {
3420  int db_err;
3421  db_err = er_errid ();
3422  if (db_err == ER_AU_SELECT_FAILURE || db_err == ER_AU_AUTHORIZATION_FAILURE)
3423  {
3424  PT_ERRORc (parser, attr, er_msg ());
3425  }
3426  return 0;
3427  }
3428 
3429  /* set its type */
3430  pt_get_attr_data_type (parser, att, attr);
3431 
3433  {
3434  if (attr->info.name.default_value != NULL)
3435  {
3436  /* default value was already set */
3437  return 1;
3438  }
3440  {
3441  /* if the default value is an expression, make a node for it */
3442  PT_OP_TYPE op;
3443  PT_NODE *default_op_value_node;
3444 
3446  assert (op != (PT_OP_TYPE) 0);
3447  default_op_value_node = pt_expression_0 (parser, op);
3448 
3450  {
3451  attr->info.name.default_value = default_op_value_node;
3452  }
3453  else
3454  {
3455  PT_NODE *arg1, *arg2, *arg3;
3456  arg1 = default_op_value_node;
3457  has_user_format = att->default_value.default_expr.default_expr_format ? 1 : 0;
3459  if (arg2 == NULL)
3460  {
3461  parser_free_tree (parser, default_op_value_node);
3463  return 0;
3464  }
3465 
3466  arg3 = parser_new_node (parser, PT_VALUE);
3467  if (arg3 == NULL)
3468  {
3469  parser_free_tree (parser, default_op_value_node);
3470  parser_free_tree (parser, arg2);
3472  return 0;
3473  }
3474  arg3->type_enum = PT_TYPE_INTEGER;
3476  lang_set_flag_from_lang (lang_str, has_user_format, 0, &flag);
3477  arg3->info.value.data_value.i = (long) flag;
3478 
3479  attr->info.name.default_value = parser_make_expression (parser, PT_TO_CHAR, arg1, arg2, arg3);
3480  if (attr->info.name.default_value == NULL)
3481  {
3482  parser_free_tree (parser, default_op_value_node);
3483  parser_free_tree (parser, arg2);
3484  parser_free_tree (parser, arg3);
3486  return 0;
3487  }
3488  }
3489  }
3490  else
3491  {
3492  /* just set the default value */
3493  attr->info.name.default_value = pt_dbval_to_value (parser, &att->default_value.value);
3494  if (attr->info.name.default_value == NULL)
3495  {
3496  PT_INTERNAL_ERROR (parser, "resolution");
3497  return 0;
3498  }
3500  {
3502  }
3503  }
3504  }
3505 
3506  cname = cname->next;
3507  }
3508  attr->info.name.spec_id = flat->info.name.spec_id;
3509 
3510  return 1;
3511 }
3512 
3513 /*
3514  * pt_find_class_attribute() - try to resolve attr as a class attribute of cls
3515  * return: 1 if all OK, 0 otherwise.
3516  * parser(in): the parser context
3517  * cls(in): the name of a class
3518  * attr(in/out): the name of an attribute
3519  */
3520 static int
3522 {
3523  DB_ATTRIBUTE *att;
3524  DB_OBJECT *db;
3525 
3526  if (!parser || !cls || cls->node_type != PT_NAME || !attr || attr->node_type != PT_NAME)
3527  return 0;
3528 
3529  db = cls->info.name.db_object;
3530 
3531  /* Does db have a class attribute named 'name'? */
3532  att = (DB_ATTRIBUTE *) db_get_class_attribute (db, attr->info.name.original);
3533 
3534  if (!att)
3535  {
3536  int db_err;
3537 
3538  db_err = er_errid ();
3539  if (!pt_has_error (parser))
3540  {
3541  if (db_err == ER_AU_SELECT_FAILURE || db_err == ER_AU_AUTHORIZATION_FAILURE)
3542  {
3543  PT_ERRORc (parser, cls, er_msg ());
3544  }
3545  }
3546  return 0;
3547  }
3548 
3549  attr->info.name.db_object = db;
3550 
3551  /* set its type */
3552  pt_get_attr_data_type (parser, att, attr);
3553 
3554  /* mark it as resolved */
3555  attr->info.name.spec_id = cls->info.name.spec_id;
3556  /* mark it as a class attribute */
3557  attr->info.name.meta_class = PT_META_ATTR;
3558 
3559  return 1;
3560 }
3561 
3562 /*
3563  * pt_find_name_in_spec () - Given a spec, see if name can be resolved to this
3564  * return: 0 if name is NOT an attribute of spec
3565  * parser(in):
3566  * spec(in):
3567  * name(in): a PT_NAME (an attribute name)
3568  */
3569 static int
3571 {
3572  int ok;
3573  PT_NODE *col;
3574  PT_NODE *range_var;
3575  const char *resolved_name;
3576 
3577  if (spec == NULL)
3578  {
3579  return 0;
3580  }
3581 
3582  if (name->info.name.meta_class == PT_CLASS)
3583  {
3584  /* should resolve to a class name later, don't search attributes */
3585  return 0;
3586  }
3587 
3588  resolved_name = name->info.name.resolved;
3589  range_var = spec->info.spec.range_var;
3590  if (resolved_name && range_var)
3591  {
3592  if (pt_str_compare (resolved_name, range_var->info.name.original, CASE_INSENSITIVE) != 0)
3593  {
3594  return 0;
3595  }
3596  }
3597 
3598  if (PT_SPEC_IS_ENTITY (spec))
3599  {
3600  if (spec->info.spec.meta_class == PT_META_CLASS)
3601  {
3602  ok = pt_find_class_attribute (parser, spec->info.spec.entity_name, name);
3603  }
3604  else
3605  {
3606  ok = pt_find_attr_in_class_list (parser, spec->info.spec.flat_entity_list, name);
3607  }
3608  }
3609  else
3610  {
3611  assert (PT_SPEC_IS_CTE (spec) || PT_SPEC_IS_DERIVED (spec));
3612  col = pt_is_on_list (parser, name, spec->info.spec.as_attr_list);
3613  ok = (col != NULL);
3614  if (col && !name->info.name.spec_id)
3615  {
3616  name->type_enum = col->type_enum;
3617  if (col->data_type)
3618  {
3619  name->data_type = parser_copy_tree_list (parser, col->data_type);
3620  }
3621  name->info.name.spec_id = spec->info.spec.id;
3622  name->info.name.meta_class = PT_NORMAL;
3623 
3625  {
3626  // calling default() on any json_table's columns should return NULL
3627  // set PT_NAME_DEFAULTF_ACCEPTS flag to pass pt_check_defaultf()
3628  DB_VALUE val;
3629  db_make_null (&val);
3630  name->info.name.default_value = pt_dbval_to_value (parser, &val);
3632  }
3633  }
3634  }
3635 
3636  return ok;
3637 }
3638 
3639 /*
3640  * pt_check_same_datatype() - All DATA_TYPE info fields are compared
3641  * SET_OF() types must match exactly
3642  * return: returns 1 if p & q have the same type
3643  * parser(in): the parser context
3644  * p(in): any PT_NODE
3645  * q(in): any PT_NODE
3646  *
3647  * Note :
3648  * OBJECT types must refer to the same class name.
3649  * Primitive types have to be IDENTICAL, not just compatible.
3650  */
3651 int
3653 {
3654  PT_NODE *s, *t, *v;
3655  PT_NODE *dt1, *dt2;
3656 
3657  if (!p || !q || !parser)
3658  {
3659  return 0;
3660  }
3661 
3662  /* primitive type match */
3663  if (p->type_enum != q->type_enum)
3664  {
3665  return 0;
3666  }
3667 
3668  if (p->node_type == PT_DATA_TYPE && q->node_type == PT_DATA_TYPE)
3669  {
3670  dt1 = (PT_NODE *) p;
3671  dt2 = (PT_NODE *) q;
3672  }
3673  else
3674  {
3675  dt1 = p->data_type;
3676  dt2 = q->data_type;
3677 
3678  if (dt1 && dt1->node_type != PT_DATA_TYPE)
3679  {
3680  return 0;
3681  }
3682  if (dt2 && dt2->node_type != PT_DATA_TYPE)
3683  {
3684  return 0;
3685  }
3686  }
3687 
3688  switch (p->type_enum)
3689  {
3690  case PT_TYPE_OBJECT: /* if type is object, check the names */
3691  if (dt1 == dt2)
3692  {
3693  return 1;
3694  }
3695 
3696  /* if both are "annonymous" object type, its ok */
3697  if (dt1 == NULL && dt2 == NULL)
3698  {
3699  return 1;
3700  }
3701 
3702  /* of only one is anonymous its not ok */
3703  if (dt1 == NULL || dt2 == NULL)
3704  {
3705  return 0;
3706  }
3707 
3708  if (dt1->info.data_type.entity == NULL && dt2->info.data_type.entity == NULL)
3709  {
3710  return 1;
3711  }
3712 
3713  /* Can't mix annonymous and non-annonymous (guards null pointers) */
3714  if (dt1->info.data_type.entity == NULL || dt2->info.data_type.entity == NULL)
3715  {
3716  return 0;
3717  }
3718 
3719  /* class objects must be the same */
3721  {
3722  return 0;
3723  }
3724  break;
3725 
3726  case PT_TYPE_SET:
3727  case PT_TYPE_MULTISET:
3728  case PT_TYPE_SEQUENCE:
3729  s = dt1;
3730  t = dt2;
3731 
3732  /* if sizes are different, sets can't match */
3733  if (pt_length_of_list (s) != pt_length_of_list (t))
3734  {
3735  return 0;
3736  }
3737 
3738  /* element types must match */
3739  while (s)
3740  {
3741  v = t;
3742  while (v)
3743  {
3744  if (pt_check_same_datatype (parser, s, v))
3745  {
3746  break; /* got match */
3747  }
3748  v = v->next;
3749  }
3750  if (!v)
3751  {
3752  return 0; /* s didn't match anything on t */
3753  }
3754  s = s->next;
3755  }
3756  break;
3757 
3758  default:
3759  if (dt1 && dt2)
3760  {
3761  if (dt1->info.data_type.precision != dt2->info.data_type.precision
3763  || dt1->info.data_type.units != dt2->info.data_type.units
3765  {
3766  return 0;
3767  }
3768  }
3769  break;
3770  }
3771 
3772  return 1;
3773 }
3774 
3775 /*
3776  * pt_check_unique_exposed () - make sure the exposed names in the
3777  * range_var field are all distinct
3778  * return: 1 if exposed names are all unique, 0 if duplicate name
3779  * parser(in):
3780  * p(in): a PT_SPEC node (list)
3781 
3782  * Note :
3783  * Assumes that the exposed name (range_var) is a PT_NAME node but
3784  * doesn't check this. Else, crash and burn.
3785  */
3786 static int
3788 {
3789  PT_NODE *q;
3790 
3791  while (p)
3792  {
3793  q = p->next; /* q = next spec */
3794  while (q)
3795  { /* check that p->range != q->range to the end of list */
3798  {
3801 
3802  if (p_type != q_type && (p_type == PT_META_CLASS || q_type == PT_META_CLASS))
3803  {
3804  /* this happens in statements like: SELECT class t, t.attr FROM t which are rewriten to: SELECT class
3805  * t, t.attr FROM t, class t In this context, t is different from class t and we should not flag an
3806  * error */
3807  q = q->next; /* check the next one inner loop */
3808  continue;
3809  }
3810 
3813  return 0;
3814  }
3815 
3816  q = q->next; /* check the next one inner loop */
3817  }
3818 
3819  p = p->next; /* go to next one outer loop */
3820  }
3821 
3822  return 1; /* OK */
3823 }
3824 
3825 /*
3826  * pt_check_unique_names () - make sure the spec names are different.
3827  *
3828  * return: 1 if names are all unique, 0 if duplicate name
3829  * parser(in):
3830  * p(in): a PT_SPEC node (list)
3831 
3832  * Note :
3833  * If names in range_var are resolved, use pt_check_unique_exposed () instead.
3834  * This was specially created for DELETE statement which needs to verify
3835  * that specs have unique names before calling pt_class_pre_fetch ();
3836  * otherwise it crashes.
3837  */
3838 int
3840 {
3841  PT_NODE *q;
3842 
3843  while (p)
3844  {
3845  const char *p_name = NULL;
3846  if (p->node_type != PT_SPEC)
3847  {
3848  p = p->next;
3849  continue;
3850  }
3852  {
3853  p_name = p->info.spec.range_var->info.name.original;
3854  }
3856  {
3857  p_name = p->info.spec.entity_name->info.name.original;
3858  }
3859  else
3860  {
3861  p = p->next;
3862  continue;
3863  }
3864  q = p->next; /* q = next spec */
3865  while (q)
3866  { /* check that p->range != q->range to the end of list */
3867  const char *q_name = NULL;
3868  if (q->node_type != PT_SPEC)
3869  {
3870  q = q->next;
3871  continue;
3872  }
3874  {
3875  q_name = q->info.spec.range_var->info.name.original;
3876  }
3878  {
3879  q_name = q->info.spec.entity_name->info.name.original;
3880  }
3881  else
3882  {
3883  q = q->next;
3884  continue;
3885  }
3886  if (!pt_str_compare (p_name, q_name, CASE_INSENSITIVE))
3887  {
3889  return 0;
3890  }
3891  q = q->next; /* check the next one inner loop */
3892  }
3893  p = p->next; /* go to next one outer loop */
3894  }
3895  return 1; /* OK */
3896 }
3897 
3898 /*
3899  * pt_common_attribute () - find the attributes that are identical
3900  * on both lists (i.e. the intersection)
3901  * return: returns a modified version of p
3902  * parser(in):
3903  * p(in/out): a list of PT_NAME nodes representing attributes
3904  * q(in): a list of PT_NAME nodes representing attributes
3905  *
3906  * Note :
3907  * This routine is called only from pt_resolve_star() above and should
3908  * not be used to take 'intersections' of general lists of names since
3909  * it modifies its argument.
3910  * WARNING: this routine must maintain the order of p.
3911  */
3912 static PT_NODE *
3914 {
3915  PT_NODE *temp, *result, *w;
3916 
3917  if (!p || !q)
3918  {
3919  return 0;
3920  }
3921  result = 0;
3922  while (p)
3923  {
3924  /* does the name match something on q? */
3925  w = pt_is_on_list (parser, p, q);
3926 
3927  /* if so, check that the data_types match */
3928  if (w && pt_check_same_datatype (parser, p, w))
3929  {
3930  /* OK, attach to result */
3931  temp = p->next;
3932  p->next = NULL;
3933  result = parser_append_node (p, result);
3934  p = temp;
3935  continue;
3936  }
3937  p = p->next;
3938  }
3939 
3940  return result;
3941 }
3942 
3943 /*
3944  * pt_add_class_to_entity_list () -
3945  * return:
3946  * parser(in):
3947  * class(in):
3948  * entity(in):
3949  * parent(in):
3950  * id(in):
3951  * meta_class(in):
3952  */
3953 PT_NODE *
3955  UINTPTR id, PT_MISC_TYPE meta_class)
3956 {
3957  PT_NODE *flat_list;
3958 
3959  flat_list = pt_make_subclass_list (parser, class_, parent->line_number, parent->column_number, id, meta_class, NULL);
3960  if (flat_list == NULL)
3961  {
3962  return NULL;
3963  }
3964 
3965  return pt_name_list_union (parser, entity, flat_list);
3966 }
3967 
3968 /*
3969  * pt_domain_to_data_type () - create and return a PT_DATA_TYPE node that
3970  * corresponds to a DB_DOMAIN dom
3971  * return: PT_NODE * to a data_type node
3972  * parser(in):
3973  * domain(in/out):
3974  *
3975  * Note : Won't work if type is OBJECT and class name is NULL
3976  */
3977 PT_NODE *
3979 {
3980  DB_DOMAIN *dom;
3981  DB_OBJECT *db;
3982  PT_NODE *result = NULL, *s, *result_last_node = NULL, *entity = NULL;
3983  PT_TYPE_ENUM t;
3984 
3985  t = pt_db_to_type_enum (TP_DOMAIN_TYPE (domain));
3986  switch (t)
3987  {
3988  case PT_TYPE_JSON:
3989  result = parser_new_node (parser, PT_DATA_TYPE);
3990  if (result == NULL)
3991  {
3992  return NULL;
3993  }
3994  result->type_enum = t;
3995  if (domain->json_validator != NULL)
3996  {
3997  result->info.data_type.json_schema =
4000  }
4001  else
4002  {
4003  result->info.data_type.json_schema = NULL;
4004  }
4005  break;
4006 
4007  case PT_TYPE_NUMERIC:
4008  case PT_TYPE_BIT:
4009  case PT_TYPE_VARBIT:
4010  case PT_TYPE_CHAR:
4011  case PT_TYPE_VARCHAR:
4012  case PT_TYPE_NCHAR:
4013  case PT_TYPE_VARNCHAR:
4014  result = parser_new_node (parser, PT_DATA_TYPE);
4015  if (result == NULL)
4016  {
4017  return NULL;
4018  }
4019  result->type_enum = t;
4020  /* some of these types won't have all of the three, but that's okay */
4021  result->info.data_type.precision = db_domain_precision (domain);
4022  result->info.data_type.dec_precision = db_domain_scale (domain);
4023  result->info.data_type.units = db_domain_codeset (domain);
4025  result->info.data_type.collation_flag = domain->collation_flag;
4026  assert (!PT_IS_CHAR_STRING_TYPE (t) || result->info.data_type.collation_id >= 0);
4027  break;
4028 
4029  case PT_TYPE_OBJECT:
4030  /* get the object */
4031  result = parser_new_node (parser, PT_DATA_TYPE);
4032  if (result == NULL)
4033  {
4034  return NULL;
4035  }
4036  result->type_enum = t;
4037  result->info.data_type.entity = NULL;
4039  while (domain)
4040  {
4041  db = db_domain_class (domain);
4042  if (db)
4043  {
4044  /* prim_type = PT_TYPE_OBJECT, attach db_object, attach name */
4045  entity =
4046  pt_add_class_to_entity_list (parser, db, result->info.data_type.entity, result, (UINTPTR) result,
4047  PT_CLASS);
4048  if (entity == NULL)
4049  {
4050  return NULL;
4051  }
4052  result->info.data_type.entity = entity;
4053  }
4054  domain = (DB_DOMAIN *) db_domain_next (domain);
4055  }
4056  break;
4057 
4058  case PT_TYPE_SET:
4059  case PT_TYPE_SEQUENCE:
4060  case PT_TYPE_MULTISET:
4061  case PT_TYPE_MIDXKEY:
4062  /* set of what? */
4063  dom = (DB_DOMAIN *) db_domain_set (domain);
4064  /* make list of types in set */
4065  while (dom)
4066  {
4067  s = pt_domain_to_data_type (parser, dom); /* recursion here */
4068 
4069  if (s)
4070  {
4071  if (result)
4072  {
4073  /*
4074  * We want to make sure that the flat name list
4075  * hanging off of the first PT_DATA_TYPE node is the
4076  * union of all flat name lists from all nodes in
4077  * this list; this makes certain things much easier
4078  * later on.
4079  * PRESERVE THE ORDER OF THESE LISTS!
4080  */
4081  result->info.data_type.entity =
4083  s->info.data_type.entity = NULL;
4084  result_last_node->next = s;
4085  result_last_node = s;
4086  }
4087  else
4088  {
4089  result = result_last_node = s;
4090  }
4091  }
4092 
4093  dom = (DB_DOMAIN *) db_domain_next (dom);
4094  }
4095  result_last_node = NULL;
4096 
4097  /*
4098  * Now run back over the flattened name list and ensure that
4099  * they all have the same spec id.
4100  */
4101  if (result)
4102  for (s = result->info.data_type.entity; s; s = s->next)
4103  {
4104  s->info.name.spec_id = (UINTPTR) result;
4105  }
4106  break;
4107 
4108  case PT_TYPE_ENUMERATION:
4109  {
4110  DB_ENUM_ELEMENT *db_enum = NULL;
4111  int idx;
4112 
4113  result = parser_new_node (parser, PT_DATA_TYPE);
4114  if (result == NULL)
4115  {
4116  return NULL;
4117  }
4118 
4119  result->type_enum = t;
4120  result->info.data_type.enumeration = NULL;
4121  for (idx = 1; idx <= DOM_GET_ENUM_ELEMS_COUNT (domain); idx++)
4122  {
4123  db_enum = &DOM_GET_ENUM_ELEM (domain, idx);
4124  s = pt_make_string_value (parser, DB_GET_ENUM_ELEM_STRING (db_enum));
4125  DB_SET_ENUM_ELEM_CODESET (&(DB_GET_ENUMERATION (&(s->info.value.db_value))),
4126  DB_GET_ENUM_ELEM_CODESET (db_enum));
4127  if (s == NULL)
4128  {
4129  return NULL;
4130  }
4132  }
4133 
4134  result->info.data_type.units = TP_DOMAIN_CODESET (domain);
4135  result->info.data_type.collation_id = TP_DOMAIN_COLLATION (domain);
4136  assert (result->info.data_type.collation_id >= 0);
4137  }
4138  break;
4139 
4140  default:
4141  result = parser_new_node (parser, PT_DATA_TYPE);
4142  if (result == NULL)
4143  {
4144  return NULL;
4145  }
4146  result->type_enum = t;
4147  break;
4148  }
4149 
4150  return result;
4151 }
4152 
4153 /*
4154  * pt_flat_spec_pre () - resolve the entity spec into a flat name list
4155  * and attach it
4156  * return:
4157  * parser(in):
4158  * node(in/out):
4159  * chk_parent(in):
4160  * continue_walk(in/out):
4161  */
4162 PT_NODE *
4163 pt_flat_spec_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
4164 {
4165  PT_NODE *q;
4166  PT_NODE *result = node;
4167  PT_FLAT_SPEC_INFO *info = (PT_FLAT_SPEC_INFO *) arg;
4168 
4169  *continue_walk = PT_CONTINUE_WALK;
4170 
4171  if (!node)
4172  {
4173  return 0;
4174  }
4175 
4176  /* if node type is entity_spec(list) process the list */
4177 
4178  switch (node->node_type)
4179  {
4180  case PT_INSERT:
4181  case PT_SELECT:
4182  case PT_UPDATE:
4183  case PT_DELETE:
4184  case PT_GRANT:
4185  case PT_REVOKE:
4186  case PT_MERGE:
4187  info->spec_parent = node;
4188  break;
4189  default:
4190  break;
4191  }
4192 
4193  if (node->node_type == PT_SPEC)
4194  {
4195  /* don't let parser_walk_tree go to rest of list. List is handled here */
4196  *continue_walk = PT_LEAF_WALK;
4197  while (node)
4198  {
4199  /* if a flat list has not been calculated, calculate it. */
4200  if (!node->info.spec.flat_entity_list && PT_SPEC_IS_ENTITY (node))
4201  {
4202  /* this sets the persistent entity_spec id. the address of the node may be changed through copying, but
4203  * this id won't. The number used is the address, just as an easy way to generate a unique number. */
4204  node->info.spec.id = (UINTPTR) node;
4205 
4206  q = pt_make_flat_name_list (parser, node, info->spec_parent, info->for_update);
4207 
4208  node->info.spec.flat_entity_list = q;
4209  }
4210 
4211  if (!PT_SPEC_IS_DERIVED (node) && PT_SPEC_IS_ENTITY (node))
4212  {
4213  /* entity_spec list are not allowed to have derived column names (for now) */
4214  if (node->info.spec.as_attr_list)
4215  {
4217  pt_short_print_l (parser, node->info.spec.as_attr_list));
4218  }
4219  }
4220  else if (PT_SPEC_IS_DERIVED (node))
4221  {
4222  PT_NODE *derived_table = node->info.spec.derived_table;
4223  if (!node->info.spec.id)
4224  {
4225  node->info.spec.id = (UINTPTR) node;
4226  }
4227 
4228  parser_walk_tree (parser, derived_table, pt_flat_spec_pre, info, pt_continue_walk, NULL);
4229  }
4230  else
4231  {
4232  PT_NODE *cte_def = NULL, *non_recursive_cte = NULL;
4233 
4234  assert (PT_SPEC_IS_CTE (node));
4235  cte_def = node->info.spec.cte_pointer->info.pointer.node;
4236  if (cte_def)
4237  {
4238  non_recursive_cte = cte_def->info.cte.non_recursive_part;
4239  }
4240 
4241  if (non_recursive_cte)
4242  {
4243  if (!node->info.spec.id)
4244  {
4245  node->info.spec.id = (UINTPTR) node;
4246  }
4247 
4248  parser_walk_tree (parser, non_recursive_cte, pt_flat_spec_pre, info, pt_continue_walk, NULL);
4249  }
4250  }
4251 
4252  node = node->next; /* next item on spec list */
4253  }
4254 
4255  /* and then do additional checks */
4256  if (result->node_type == PT_SPEC)
4257  {
4258  if (!pt_must_have_exposed_name (parser, result))
4259  {
4260  return 0;
4261  }
4262  if (!pt_check_unique_exposed (parser, result))
4263  {
4264  return 0;
4265  }
4266  }
4267  }
4268 
4269  return result;
4270 }
4271 
4272 /*
4273  * pt_get_all_attributes_and_types() -
4274  * return: cls' list of attributes if all OK, NULL otherwise.
4275  * parser(in): handle to parser context
4276  * cls(in): a PT_NAME node naming a class in the database
4277  * from(in): the entity_spec from which cls was derived
4278  * as a flat_entity_list item
4279  */
4280 static PT_NODE *
4282 {
4283  PT_NODE *result = NULL, *tail, *node;
4284  DB_ATTRIBUTE *att;
4285  DB_OBJECT *object;
4286  bool class_atts_only;
4287 
4288  if (cls == NULL || cls->node_type != PT_NAME || (object = cls->info.name.db_object) == NULL || from == NULL
4289  || from->node_type != PT_SPEC)
4290  {
4291  return NULL;
4292  }
4293 
4294  class_atts_only = (from->info.spec.meta_class == PT_META_CLASS);
4295  att = NULL;
4296  if (class_atts_only)
4297  {
4298  att = (DB_ATTRIBUTE *) db_get_class_attributes (object);
4299  }
4300  else
4301  {
4302  att = (DB_ATTRIBUTE *) db_get_attributes_force (object);
4303  }
4304 
4305  if (att != NULL)
4306  {
4307  /* make result anchor the list */
4308  result = tail = pt_name (parser, db_attribute_name (att));
4309  if (result == NULL)
4310  {
4311  return NULL;
4312  }
4313  result->line_number = from->line_number;
4314  result->column_number = from->column_number;
4315 
4316  /* set its type */
4317  pt_get_attr_data_type (parser, att, result);
4318  if (pt_has_error (parser))
4319  {
4320  goto on_error;
4321  }
4322 
4323  result->info.name.spec_id = from->info.spec.id;
4324  if (class_atts_only)
4325  {
4326  result->info.name.meta_class = PT_META_ATTR;
4328  }
4329 
4330  /* advance to next attribute */
4331  att = db_attribute_next (att);
4332 
4333  /* for the rest of the attributes do */
4334  while (att != NULL)
4335  {
4336  /* make new node & copy attribute name into it */
4337  node = pt_name (parser, db_attribute_name (att));
4338  if (node == NULL)
4339  {
4340  goto on_error;
4341  }
4342  node->line_number = from->line_number;
4343  node->column_number = from->column_number;
4344 
4345  /* set its type */
4346  pt_get_attr_data_type (parser, att, node);
4347  if (pt_has_error (parser))
4348  {
4349  goto on_error;
4350  }
4351 
4352  node->info.name.spec_id = from->info.spec.id;
4353  if (class_atts_only)
4354  {
4355  node->info.name.meta_class = PT_META_ATTR;
4356  node->info.name.db_object = from->info.spec.entity_name->info.name.db_object;
4357  }
4358 
4359  /* append to list */
4360  tail->next = node;
4361  tail = node;
4362 
4363  /* advance to next attribute */
4364  att = db_attribute_next (att);
4365  }
4366  }
4367 
4368  return result;
4369 
4370 on_error:
4371  if (result != NULL)
4372  {
4373  parser_free_tree (parser, result);
4374  }
4375 
4376  return NULL;
4377 }
4378 
4379 static PT_NODE *
4381 {
4382  PT_NODE **attribs = (PT_NODE **) args;
4383 
4384  if (json_table_column->node_type == PT_JSON_TABLE_COLUMN)
4385  {
4386  PT_NODE *next_attr = json_table_column->info.json_table_column_info.name;
4387  next_attr->type_enum = json_table_column->type_enum;
4388  next_attr->info.name.json_table_column_index = json_table_column->info.json_table_column_info.index;
4389  if (json_table_column->data_type != NULL)
4390  {
4391  next_attr->data_type = parser_copy_tree (parser, json_table_column->data_type);
4392  }
4393  *attribs = parser_append_node (next_attr, *attribs);
4394  }
4395 
4396  return json_table_column;
4397 }
4398 
4399 static PT_NODE *
4401  const char *json_table_alias)
4402 {
4403  PT_NODE *attribs = NULL;
4404  PT_NODE *copy_node = NULL;
4405 
4406  parser_walk_tree (parser, json_table_node, pt_json_table_gather_attribs, &attribs, NULL, NULL);
4407 
4408  if (attribs == NULL)
4409  {
4410  assert (false);
4411  return NULL;
4412  }
4413 
4414  // *INDENT-OFF*
4415  std::unordered_map<size_t, PT_NODE *> sorted_attrs;
4416  // *INDENT-ON*
4417 
4418  for (PT_NODE * attr = attribs; attr; attr = attr->next)
4419  {
4420  size_t index = attr->info.name.json_table_column_index;
4421  assert (strcmp (json_table_alias, attr->info.name.resolved) == 0);
4422 
4423  // we need copies of the actual names
4424  copy_node = pt_name (parser, attr->info.name.original);
4425  copy_node->type_enum = attr->type_enum;
4426  copy_node->info.name.resolved = json_table_alias;
4427  if (attr->data_type != NULL)
4428  {
4429  copy_node->data_type = parser_copy_tree (parser, attr->data_type);
4430  }
4431  sorted_attrs[index] = copy_node; // we have to copy, cannot use same node
4432  }
4433 
4434  size_t columns_nr = sorted_attrs.size ();
4435 
4436  for (unsigned int i = 0; i < columns_nr - 1; i++)
4437  {
4438  if (sorted_attrs[i] == NULL)
4439  {
4440  assert (false);
4441  return NULL;
4442  }
4443  sorted_attrs[i]->next = sorted_attrs[i + 1];
4444  }
4445  sorted_attrs[columns_nr - 1]->next = NULL;
4446 
4447  return sorted_attrs[0];
4448 }
4449 
4450 /*
4451  * pt_get_all_showstmt_attributes_and_types () -
4452  * return: show list attributes list if all OK, NULL otherwise.
4453  * parser(in): handle to parser context
4454  * derived_table(in): the entity_spec from which cls was derived
4455  * as a flat_entity_list item
4456  */
4457 static PT_NODE *
4459 {
4460  PT_NODE *result = NULL, *node;
4461  DB_ATTRIBUTE *att;
4462 
4463  if (derived_table == NULL || derived_table->node_type != PT_SHOWSTMT)
4464  {
4465  return NULL;
4466  }
4467 
4468  att = (DB_ATTRIBUTE *) showstmt_get_attributes (derived_table->info.showstmt.show_type);
4469  while (att != NULL)
4470  {
4471  /* make result anchor the list */
4472  node = pt_name (parser, db_attribute_name (att));
4473  if (node == NULL)
4474  {
4475  goto on_error;
4476  }
4477 
4478  /* set its type */
4479  pt_get_attr_data_type (parser, att, node);
4480 
4481  result = parser_append_node (node, result);
4482 
4483  /* advance to next attribute */
4484  att = db_attribute_next (att);
4485  }
4486 
4487  return result;
4488 
4489 on_error:
4490  if (result != NULL)
4491  {
4492  parser_free_tree (parser, result);
4493  }
4494  return NULL;
4495 }
4496 
4497 /*
4498  * pt_get_attr_data_type () - Given an attribute(att) whose name is in p,
4499  * find its data_type and attach the data-type to the name
4500  * return:
4501  * parser(in):
4502  * att(in): a db_attribute
4503  * attr(in/out): a PT_NAME node corresponding to att
4504  * db(in):
4505  */
4506 static void
4508 {
4509  DB_DOMAIN *dom;
4510  if (!attr || !att)
4511  {
4512  return;
4513  }
4514 
4515  dom = db_attribute_domain (att);
4516  attr->etc = dom; /* used for getting additional db-specific domain information in the Versant driver */
4518  switch (attr->type_enum)
4519  {
4520  case PT_TYPE_OBJECT:
4521  case PT_TYPE_SET:
4522  case PT_TYPE_SEQUENCE:
4523  case PT_TYPE_MULTISET:
4524  case PT_TYPE_NUMERIC:
4525  case PT_TYPE_BIT:
4526  case PT_TYPE_VARBIT:
4527  case PT_TYPE_CHAR:
4528  case PT_TYPE_VARCHAR:
4529  case PT_TYPE_NCHAR:
4530  case PT_TYPE_VARNCHAR:
4531  case PT_TYPE_ENUMERATION:
4532  case PT_TYPE_JSON:
4533  attr->data_type = pt_domain_to_data_type (parser, dom);
4534  break;
4535  default:
4536  break;
4537  }
4538 
4539  attr->info.name.meta_class = PT_NORMAL;
4540 
4541  /* set its shared attribute flag */
4542  if (db_attribute_is_shared (att))
4543  {
4544  attr->info.name.meta_class = PT_SHARED;
4545  }
4546 }
4547 
4548 
4549 /*
4550  * pt_unwhacked_spec () - Map to the real spec. Either identity,
4551  * or lookup of selector's path spec.
4552  * return:
4553  * parser(in):
4554  * scope(in):
4555  * spec(in):
4556  */
4557 static PT_NODE *
4559 {
4560  if (spec && spec->info.spec.derived_table_type == PT_IS_WHACKED_SPEC)
4561  {
4562  spec = pt_find_path_entity (parser, scope, spec);
4563  if (spec)
4564  {
4566  }
4567  }
4568  return spec;
4569 }
4570 
4571 
4572 /*
4573  * pt_resolve_correlation () - Given an exposed spec, return the name node
4574  * of its oid.
4575  * return:
4576  * parser(in):
4577  * in_node(in):
4578  * scope(in):
4579  * exposed_spec(in):
4580  * col_name(in):
4581  * p_entity(in):
4582  *
4583  * Note:
4584  * Also check for some semantic errors
4585  * - disallow OIDs of derived spec
4586  * - disallow selectors except inside path expression
4587  */
4588 static PT_NODE *
4590  int col_name, PT_NODE ** p_entity)
4591 {
4592  PT_NODE *corr_name = NULL;
4593 
4594  exposed_spec = pt_unwhacked_spec (parser, scope, exposed_spec);
4595 
4596  /* If so, name resolves to scope's flat list of entities */
4597  if (exposed_spec)
4598  {
4599  /* the exposed name of a derived table or a CTE may not be used alone, ie, "select e from (select a from c) e"
4600  * is disallowed. */
4601  if (col_name && (PT_SPEC_IS_DERIVED (exposed_spec) || PT_SPEC_IS_CTE (exposed_spec))
4602  && exposed_spec->info.spec.range_var != in_node)
4603  {
4605  {
4606  in_node->info.name.spec_id = exposed_spec->info.spec.id;
4607  return in_node;
4608  }
4609  else
4610  {
4612  pt_short_print (parser, in_node));
4613  return NULL;
4614  }
4615  }
4616 
4617  /* check for a selector variable in a perverse place */
4618  if ((in_node->node_type == PT_NAME && in_node->info.name.path_correlation)
4619  || (in_node->node_type == PT_DOT_
4620  && ((in_node->info.dot.arg1->node_type == PT_NAME && in_node->info.dot.arg2->info.name.path_correlation)
4621  || (in_node->info.dot.arg1->node_type == PT_NAME
4622  && in_node->info.dot.arg1->info.name.path_correlation))))
4623  {
4625  pt_short_print (parser, in_node));
4626  return NULL;
4627  }
4628 
4629  if (!exposed_spec->info.spec.range_var)
4630  {
4631  PT_INTERNAL_ERROR (parser, "resolution");
4632  return NULL;
4633  }
4634 
4635  corr_name = pt_name (parser, "");
4636  PT_NODE_COPY_NUMBER_OUTERLINK (corr_name, in_node);
4637  in_node->next = NULL;
4638  in_node->or_next = NULL;
4639  if (in_node->info.name.meta_class == PT_META_CLASS)
4640  {
4641  corr_name->info.name.meta_class = PT_META_CLASS;
4642  }
4643  else
4644  {
4645  corr_name->info.name.meta_class = PT_OID_ATTR;
4647  {
4649  }
4650  }
4652  {
4654  }
4656  {
4658  }
4659 
4660  parser_free_tree (parser, in_node);
4661 
4662  corr_name->info.name.spec_id = exposed_spec->info.spec.id;
4663  corr_name->info.name.resolved = exposed_spec->info.spec.range_var->info.name.original;
4664  if (PT_IS_SPEC_REAL_TABLE (exposed_spec))
4665  {
4667  }
4668 
4669  /* attach the data type */
4670  corr_name->type_enum = PT_TYPE_OBJECT;
4671  if (exposed_spec->info.spec.flat_entity_list)
4672  {
4673  corr_name->data_type = pt_object_to_data_type (parser, exposed_spec->info.spec.flat_entity_list);
4674  }
4675 
4676  *p_entity = exposed_spec;
4677  }
4678 
4679  return corr_name;
4680 }
4681 
4682 /*
4683  * pt_spec_in_domain() - determine if cls is in the domain specified by lst
4684  * return: true if cls is in the domain specified by lst
4685  * cls(in): a PT_SPEC node representing a class
4686  * lst(in): a list of PT_NAME nodes representing a data_type domain
4687  *
4688  * Note :
4689  * This function is used to check for well-formed selector variables. For
4690  * example, given the query
4691  * select room[x].size_in_sq_ft
4692  * from hotel, (all quarters (except cabin)) x, table(rooms) as t(room)
4693  * the selector variable 'x' is well-formed if the exposed spec 'x'
4694  * intersects the domain of attribute 'room'.
4695  */
4696 
4697 static int
4699 {
4700  PT_NODE *c;
4701 
4702  if (!cls || cls->node_type != PT_SPEC || !lst)
4703  {
4704  return 0; /* preconditions not met, so nothing doing. */
4705  }
4706 
4707  while (lst && lst->node_type == PT_NAME)
4708  {
4709  /* BEWARE! Do not use and assume that cls->info.spec.entity_name is a PT_NAME node because the code in sq.g
4710  * class_specification() and elsewhere uses cls->info.spec.entity_name to hold a list of PT_SPEC nodes. Instead,
4711  * use cls->info.spec.flat_entity_list as the parse tree representation of class_specs of the form 'select ...
4712  * from (c1 c2 ...) x' */
4713  c = cls->info.spec.flat_entity_list;
4714 
4715  /* cls is of the form '(c1 c2 ...) x' and we need to determine if any class in the hierarchy of (c1 c2 ...) is a
4716  * subclass of any class in lst. */
4717  while (c && c->node_type == PT_NAME && c->info.name.db_object)
4718  {
4719  if (c->info.name.db_object == lst->info.name.db_object)
4720  {
4721  return 1; /* cls is a subclass of a class in lst */
4722  }
4723  else
4724  {
4725  c = c->next; /* try the next c */
4726  }
4727  }
4728  lst = lst->next; /* try the next class in lst */
4729  }
4730  return 0; /* cls is not a subclass of any class in lst */
4731 }
4732 
4733 /*
4734  * pt_get_resolution() - try to resolve a name or path expr using this scope
4735  * return: if in_node is an X.Z with X an exposed name,
4736  * collapse it into Z, return Z
4737  * if in_node is an X that resolves to scope, return X
4738  * if in_node has no resolution in this scope, return NULL
4739  * parser(in): the parser context
4740  * bind_arg(in): a list of scopes for resolving method calls
4741  * scope(in): a list of PT_SPEC nodes (ie, a 'from' clause)
4742  * in_node(in/out): an attribute reference or path expression to be resolved
4743  * p_entity(out): entity_spec of X if in_node is an X.Z
4744  * col_name(in): true on top level call.
4745  */
4746 static PT_NODE *
4748  PT_NODE ** p_entity, int col_name)
4749 {
4750  PT_NODE *exposed_spec, *spec, *savespec, *arg1, *arg2, *arg1_name;
4751  PT_NODE *unique_entity, *path_correlation;
4752  PT_NODE *temp;
4753  PT_NODE *reserved_name = NULL;
4754  PT_FLAT_SPEC_INFO info;
4755 
4756  if (!in_node)
4757  {
4758  return NULL;
4759  }
4760 
4761  if (PT_SHOULD_BIND_RESERVED_NAME (scope))
4762  {
4763  /* Attempt to bind to reserved name */
4764  /* If scope should bind for record information, binding to table attribute is also allowed, so shouldn't stop if
4765  * binding to reserved names fails. */
4766  reserved_name = pt_bind_reserved_name (parser, in_node, scope);
4767  if (!PT_IS_SPEC_FLAG_SET (scope, PT_SPEC_FLAG_RECORD_INFO_SCAN) || reserved_name != NULL)
4768  {
4769  return reserved_name;
4770  }
4771  /* Couldn't bind to record info, attempt to bind to table attributes */
4772  /* Fall through */
4773  }
4774 
4775  if (in_node->node_type == PT_NAME)
4776  {
4777  /* Has this name been resolved? */
4778  if (in_node->info.name.spec_id)
4779  {
4780  *p_entity = NULL;
4781  if (in_node->type_enum == PT_TYPE_OBJECT && in_node->data_type)
4782  {
4783  temp = scope;
4784  while (temp && temp->info.spec.id != in_node->info.name.spec_id)
4785  {
4786  temp = temp->next;
4787  }
4788  if (temp)
4789  {
4790  *p_entity = temp;
4791  return in_node;
4792  }
4793  }
4794  return NULL;
4795  }
4796 
4797  /* Let's see if it is a parameter, possibly anchoring a path expr */
4798  if (in_node->info.name.meta_class == PT_PARAMETER)
4799  {
4800  *p_entity = NULL;
4801  return pt_bind_parameter (parser, in_node);
4802  }
4803 
4804  if (col_name)
4805  {
4806  if (in_node->info.name.path_correlation)
4807  {
4809  pt_short_print (parser, in_node));
4810  return NULL;
4811  }
4812  }
4813  else
4814  {
4815  /* We are on the left of a dot node. (because we are recursing) Here, correlation names have precedence over
4816  * column names. (for ANSI compatibility). For unqualified names, column names have precedence. For qualifier
4817  * names, correlation names have precedence. */
4818  exposed_spec = pt_is_correlation_name (parser, scope, in_node);
4819  if (exposed_spec)
4820  {
4821  return pt_resolve_correlation (parser, in_node, scope, exposed_spec, col_name, p_entity);
4822  }
4823  }
4824 
4825  /* Else, is this an attribute of a unique entity within scope? */
4826  for (savespec = NULL, spec = scope; spec; spec = spec->next)
4827  {
4828  if (pt_find_name_in_spec (parser, spec, in_node))
4829  {
4830  if (savespec)
4831  {
4833  in_node->info.name.original);
4834  return NULL;
4835  }
4836  savespec = spec;
4837  }
4838  }
4839 
4840  if (savespec)
4841  {
4842  /* if yes, set the resolution and the resolved name */
4843  in_node->info.name.resolved = savespec->info.spec.range_var->info.name.original;
4844  in_node->info.name.partition = savespec->info.spec.range_var->info.name.partition;
4845 
4846  if (PT_IS_SPEC_REAL_TABLE (savespec))
4847  {
4849  }
4850 
4851  savespec = pt_unwhacked_spec (parser, scope, savespec);
4852 
4853  *p_entity = savespec;
4854  return in_node;
4855  }
4856 
4857  if (col_name)
4858  {
4859  /* Failing finding a column name for a name NOT on the left of a dot, try and resolve it as a correlation
4860  * name (oid). For unqualified names, column names have precedence. For qualifier names, correlation names
4861  * have precedence. */
4862  exposed_spec = pt_is_correlation_name (parser, scope, in_node);
4863  if (exposed_spec)
4864  {
4865  return pt_resolve_correlation (parser, in_node, scope, exposed_spec, col_name, p_entity);
4866  }
4867  }
4868 
4869  if (in_node->info.name.meta_class == PT_META_CLASS)
4870  {
4871  DB_OBJECT *object;
4872  object = pt_find_users_class (parser, in_node);
4873  if (object == NULL)
4874  {
4875  return NULL; /* not an valid class */
4876  }
4877  in_node->info.name.db_object = object;
4878  if (bind_arg->spec_frames)
4879  {
4880  PT_NODE *class_spec, *node, *entity, *found = NULL;
4881  for (node = bind_arg->spec_frames->extra_specs; node != NULL; node = node->next)
4882  {
4883  if (node->node_type == PT_SPEC && (entity = node->info.spec.entity_name)
4884  && (entity->info.name.db_object == in_node->info.name.db_object))
4885  {
4886  found = node;
4887  break;
4888  }
4889  }
4890 
4891  if (found)
4892  {
4893  class_spec = found;
4894  }
4895  else
4896  {
4897  /* add the new spec to the extra scope */
4898  if ((class_spec = parser_new_node (parser, PT_SPEC)) == NULL)
4899  {
4900  return NULL;
4901  }
4902  class_spec->info.spec.id = (UINTPTR) class_spec;
4903  class_spec->info.spec.only_all = PT_ONLY;
4904  class_spec->info.spec.meta_class = PT_META_CLASS;
4905  if ((class_spec->info.spec.entity_name = pt_name (parser, in_node->info.name.original)) == NULL)
4906  {
4907  return NULL;
4908  }
4909  info.spec_parent = NULL;
4910  info.for_update = false;
4911  class_spec = parser_walk_tree (parser, class_spec, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
4912  bind_arg->spec_frames->extra_specs =
4913  parser_append_node (class_spec, bind_arg->spec_frames->extra_specs);
4914  }
4915 
4916  in_node->info.name.meta_class = PT_META_CLASS;
4917  in_node->info.name.spec_id = class_spec->info.spec.id;
4918  in_node->info.name.resolved = class_spec->info.spec.range_var->info.name.original;
4920  /* attach the data type */
4921  in_node->type_enum = PT_TYPE_OBJECT;
4922  if (class_spec->info.spec.flat_entity_list)
4923  {
4924  in_node->data_type = pt_object_to_data_type (parser, class_spec->info.spec.flat_entity_list);
4925  }
4926  *p_entity = class_spec;
4927  return in_node;
4928  }
4929  else
4930  {
4931  /* This is an object reference outside of a query */
4932  if (!in_node->info.name.resolved)
4933  {
4934  in_node->info.name.resolved = "";
4935  }
4936  in_node->info.name.spec_id = (UINTPTR) in_node->info.name.db_object;
4937  in_node->info.name.meta_class = PT_META_CLASS;
4938  in_node->type_enum = PT_TYPE_OBJECT;
4939  in_node->data_type = parser_new_node (parser, PT_DATA_TYPE);
4940 
4941  if (in_node->data_type == NULL)
4942  {
4943  PT_INTERNAL_ERROR (parser, "allocate new node");
4944  return NULL;
4945  }
4946 
4947  in_node->data_type->type_enum = PT_TYPE_OBJECT;
4948  in_node->data_type->info.data_type.entity = parser_copy_tree (parser, in_node);
4950  *p_entity = NULL; /* got no entity! */
4951  return in_node;
4952  }
4953  }
4954 
4955  /* no resolution in this scope */
4956  return NULL;
4957  }
4958 
4959  /* Is it a DOT expression X.Z? */
4960  if (in_node->node_type == PT_DOT_)
4961  {
4962  arg1 = in_node->info.dot.arg1;
4963  arg2 = in_node->info.dot.arg2;
4964  /* if bad arg2, OR if already resolved, then return same node */
4965  if (!arg2 || arg2->info.name.spec_id || arg2->node_type != PT_NAME)
4966  {
4967  *p_entity = NULL;
4968  return in_node;
4969  }
4970 
4971  if (col_name)
4972  {
4973  if (arg2->info.name.path_correlation)
4974  {
4976  pt_short_print (parser, in_node));
4977  return NULL;
4978  }
4979  }
4980 
4981  /* Check if this is an exposed name in the current scope. */
4982  exposed_spec = pt_is_correlation_name (parser, scope, in_node);
4983  if (exposed_spec)
4984  {
4985  return pt_resolve_correlation (parser, in_node, scope, exposed_spec, col_name, p_entity);
4986  }
4987 
4988  /* if arg1 not in scope, return NULL to indicate not in scope. */
4989  if (!(arg1 = pt_get_resolution (parser, bind_arg, scope, arg1, p_entity, 0)))
4990  {
4991  *p_entity = NULL;
4992  return NULL;
4993  }
4994 
4995  if (arg1->node_type == PT_NAME)
4996  {
4997  arg1_name = arg1;
4998  }
4999  else if (arg1->node_type == PT_METHOD_CALL)
5000  {
5001  arg1_name = arg1->info.method_call.method_name;
5002  }
5003  else
5004  {
5005  arg1_name = arg1->info.dot.arg2;
5006  }
5007  /* given X.Z, resolve (X) */
5008  in_node->info.dot.arg1 = arg1;
5009  /* Note : this should not get run, now that parameters are evaluated at run time, instead of converted to values
5010  * at compile time. We need to be careful here. We may have a path expression anchored by a parameter (PT_VALUE
5011  * node) or a class attribute object. If so, we evaluate the path expression here and return the appropriate
5012  * PT_VALUE node. */
5013  if (arg1->node_type == PT_VALUE && arg1->type_enum == PT_TYPE_OBJECT)
5014  {
5015  temp = pt_eval_value_path (parser, in_node);
5016  if (!temp)
5017  {
5018  return NULL;
5019  }
5020  temp->next = in_node->next;
5021  in_node->next = NULL;
5022  parser_free_tree (parser, temp);
5023  }
5024 
5025  if (arg1_name->info.name.meta_class == PT_PARAMETER)
5026  {
5027  /* if Parameter was undefined, we would already have raised an error in recursion on arg1 */
5028  return pt_bind_parameter_path (parser, in_node);
5029  }
5030 
5031  /* If arg1 is an exposed name, replace expr with resolved arg2 */
5032  if (arg1->node_type == PT_NAME && (arg1->info.name.meta_class == PT_OID_ATTR))
5033  {
5034  /* Arg1 was an exposed name */
5035  if (pt_find_name_in_spec (parser, *p_entity, arg2))
5036  {
5037  /* only mark it resolved if it was found! transfer the info from arg1 to arg2 */
5038  arg2->info.name.resolved = arg1->info.name.resolved;
5040  {
5042  }
5043  /* don't loose list */
5044  arg2->next = in_node->next;
5045  /* save alias */
5046  arg2->alias_print = in_node->alias_print;
5048  /* replace expr with resolved arg2 */
5049  in_node->info.dot.arg2 = NULL;
5050  in_node->next = NULL;
5051  parser_free_tree (parser, in_node);
5052  in_node = arg2;
5053  }
5054  else
5055  {
5056  temp = arg1->data_type;
5057  if (temp)
5058  {
5059  temp = temp->info.data_type.entity;
5060  }
5061  if (!temp)
5062  {
5063  /* resolution error */
5065  pt_short_print (parser, arg1), pt_short_print (parser, arg2));
5066  }
5067  else if (temp->next)
5068  {
5070  pt_short_print_l (parser, temp), pt_short_print (parser, arg2));
5071  }
5072  else
5073  {
5074  temp->info.name.resolved = NULL;
5076  pt_short_print_l (parser, temp), pt_short_print (parser, arg2));
5077  }
5078  /* signal as not resolved */
5079  return NULL;
5080  }
5081  }
5082  else if (arg1_name->info.name.meta_class == PT_META_CLASS)
5083  {
5084  if (arg1->data_type == NULL)
5085  {
5086  return NULL;
5087  }
5088 
5089  /* Arg1 was a meta class name */
5090  if (pt_find_class_attribute (parser, arg1->data_type->info.data_type.entity, arg2))
5091  {
5092  /* only mark it resolved if it was found! */
5093 
5094  /* A meta class attribute, transfer the class info from arg1 to arg2 */
5095  arg2->info.name.resolved = arg1->info.name.resolved;
5097  {
5099  }
5100  /* don't lose list */
5101  arg2->next = in_node->next;
5102  /* save alias */
5103  arg2->alias_print = in_node->alias_print;
5105  /* replace expr with resolved arg2 */
5106  in_node->info.dot.arg2 = NULL;
5107  in_node->next = NULL;
5108  parser_free_tree (parser, in_node);
5109  in_node = arg2;
5110  }
5111  else
5112  {
5113  temp = arg1->data_type;
5114  if (temp)
5115  {
5116  temp = temp->info.data_type.entity;
5117  }
5118  if (!temp)
5119  {
5120  /* resolution error */
5122  pt_short_print (parser, arg1), pt_short_print (parser, arg2));
5123  }
5124  else
5125  {
5126  temp->info.name.resolved = NULL;
5128  pt_short_print_l (parser, temp), pt_short_print (parser, arg2));
5129  }
5130  /* signal as not resolved */
5131  return NULL;
5132  }
5133  }
5134  else
5135  {
5136  /* This is NOT an exposed name, it must be an object attribute. It must also be a legitimate root for this
5137  * path expression. */
5138  if (arg1->type_enum != PT_TYPE_OBJECT)
5139  {
5141  pt_short_print (parser, arg1), pt_show_type_enum (arg1->type_enum));
5142  return NULL;
5143  }
5144  else if (!arg1->data_type)
5145  {
5146  PT_INTERNAL_ERROR (parser, "Resolution");
5147  return NULL;
5148  }
5149  else if (arg1_name->info.name.path_correlation)
5150  {
5151  path_correlation = arg1_name->info.name.path_correlation;
5152  /* there must be an exposed class spec in this scope */
5153  exposed_spec = pt_is_correlation_name (parser, scope, path_correlation);
5154  if (!exposed_spec)
5155  {
5156  PT_ERRORmf2 (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5158  pt_short_print (parser, scope));
5159  return NULL;
5160  }
5161  else if (exposed_spec->info.spec.derived_table)
5162  {
5163  PT_ERRORmf2 (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5165  pt_short_print (parser, exposed_spec));
5166  return NULL;
5167  }
5168  else
5169  {
5170  PT_NODE *test = arg1;
5171  PT_NODE *root_spec;
5172  PT_NODE *arg1dt;
5173  while (test->node_type == PT_DOT_)
5174  {
5175  test = test->info.dot.arg1;
5176  }
5177  if (exposed_spec->info.spec.id == test->info.name.spec_id)
5178  {
5179  PT_ERRORmf (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5181  return NULL;
5182  }
5183 
5184  /* test for circularly defined selectors */
5185  root_spec = scope;
5186  while (root_spec && (root_spec->info.spec.id != test->info.name.spec_id))
5187  {
5188  root_spec = root_spec->next;
5189  }
5190  if (root_spec)
5191  {
5192  temp = pt_find_entity (parser, exposed_spec->info.spec.path_entities, root_spec->info.spec.id);
5193  if (temp)
5194  {
5195  /* the selectors circularly define each other because this [sel] is the root of the
5196  * definition of the root of this selector. eg select x.a[y].b, y.a[x].b from x,y */
5197  PT_ERRORmf2 (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5199  test->info.name.resolved);
5200  return NULL;
5201  }
5202 
5203  if (exposed_spec->info.spec.derived_table_type == PT_IS_WHACKED_SPEC)
5204  {
5205  /* make sure the exposed spec is already on the root spec path entities. Otherwise we are
5206  * redefining it. */
5207  temp = pt_unwhacked_spec (parser, scope, exposed_spec);
5208  if (temp)
5209  {
5210  temp = temp->info.spec.path_conjuncts;
5211  if (temp)
5212  {
5213  temp = temp->info.expr.arg1;
5214  }
5215  if (temp && !pt_name_equal (parser, temp, arg1_name))
5216  {
5217  PT_ERRORmf2 (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5219  pt_short_print (parser, arg1));
5220  }
5221  }
5222  }
5223  }
5224  /* make sure the selector variable refers to an entity spec that is a subclass of the arg1->data_type
5225  * class. */
5226  if (!pt_has_error (parser) && arg1->data_type && arg1->data_type->node_type == PT_DATA_TYPE
5227  && (arg1dt = arg1->data_type->info.data_type.entity) && arg1dt->node_type == PT_NAME
5228  && !pt_spec_in_domain (exposed_spec, arg1dt))
5229  {
5230  PT_ERRORmf3 (parser, path_correlation, MSGCAT_SET_PARSER_SEMANTIC,
5232  pt_short_print_l (parser, exposed_spec->info.spec.flat_entity_list),
5233  pt_short_print_l (parser, arg1dt));
5234  return NULL;
5235  }
5236  }
5237 
5238  /* no cross product */
5240  parser_free_tree (parser, arg1->data_type->info.data_type.entity);
5241  arg1->data_type->info.data_type.entity =
5242  parser_copy_tree_list (parser, exposed_spec->info.spec.flat_entity_list);
5243  path_correlation->info.name.resolved = path_correlation->info.name.original;
5244  path_correlation->info.name.original = "";
5245  path_correlation->info.name.spec_id = exposed_spec->info.spec.id;
5246  path_correlation->info.name.meta_class = PT_OID_ATTR;
5247  path_correlation->type_enum = PT_TYPE_OBJECT;
5248  }
5249  else
5250  {
5251  exposed_spec = NULL;
5252  }
5253  if (!pt_find_attr_in_class_list (parser, arg1->data_type->info.data_type.entity, arg2))
5254  {
5255  temp = arg1->data_type;
5256  if (temp)
5257  {
5258  temp = temp->info.data_type.entity;
5259  }
5260  if (!temp)
5261  {
5262  /* resolution error */
5264  pt_short_print (parser, arg1), pt_short_print (parser, arg2));
5265  }
5266  else if (temp->next)
5267  {
5269  pt_short_print_l (parser, temp), pt_short_print (parser, arg2));
5270  }
5271  else
5272  {
5273  temp->info.name.resolved = NULL;
5275  pt_short_print_l (parser, temp), pt_short_print (parser, arg2));
5276  }
5277  *p_entity = NULL;
5278  return NULL; /* not bound */
5279  }
5280 
5281  /* we have a good path expression, find entity for arg2 in the path_entities of valid_entity, it may need to
5282  * be created */
5283 
5284  /* set the type of the dot node to the type of arg2 */
5285  in_node->type_enum = arg2->type_enum;
5286  if (arg2->data_type)
5287  {
5288  if (in_node->data_type)
5289  {
5290  parser_free_tree (parser, in_node->data_type);
5291  }
5292  in_node->data_type = parser_copy_tree_list (parser, arg2->data_type);
5293  }
5294 
5295  /* A normal path must be rooted in an entity spec However, we can have p_entity be NULL for some odd cases.
5296  * Eg insert into x values(meth(:p1).y) Don't get wigged out here, and it gets handled later. */
5297  if (*p_entity)
5298  {
5299  unique_entity = pt_insert_entity (parser, in_node, *p_entity, exposed_spec);
5300  *p_entity = unique_entity;
5301  }
5302  }
5303  return in_node;
5304  } /* end if-a-dot-expression */
5305 
5306  /* Is it a method call? Be careful, method calls that haven't been resolved masquerade as functions until we call
5307  * pt_bind_names() on the function node. */
5308  if ((in_node->node_type == PT_FUNCTION) || (in_node->node_type == PT_METHOD_CALL))
5309  {
5310  PT_NODE *new_node;
5311  if (in_node->node_type == PT_FUNCTION)
5312  {
5313  /* call pt_bind_names() to convert the function node into a method node as well as binding its arguments and
5314  * its target. */
5315  new_node = parser_walk_tree (parser, in_node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
5316  if (new_node->node_type != PT_METHOD_CALL)
5317  {
5318  return NULL;
5319  }
5320  else
5321  {
5322  /* remove wrong code this cause free memory(i.e., in_node) refer */
5323  in_node = new_node;
5324  }
5325  }
5326  /* Now, we have a PT_METHOD_CALL_NODE, and the target has been bound. */
5327  *p_entity = NULL;
5328  if (in_node->type_enum == PT_TYPE_OBJECT && in_node->data_type)
5329  {
5330  temp = scope;
5331  while (temp && (temp->info.spec.id != in_node->info.method_call.method_name->info.name.spec_id))
5332  {
5333  temp = temp->next;
5334  }
5335  *p_entity = temp;
5336  return in_node;
5337  }
5338  return NULL;
5339  } /* end if PT_FUNCTION || PT_METHOD_CALL */
5340 
5341  /* Else got some node type we shouldn't have */
5342  PT_INTERNAL_ERROR (parser, "Resolution");
5343  return NULL;
5344 }
5345 
5346 /*
5347  * pt_expand_external_path() - expand an attr with a path expression
5348  * return: if in_node is an X.Z with Z a external type, return X.Z.tdata
5349  * parser(in): the parser context
5350  * in_node(in): an attribute reference or path expression to be resolved
5351  * p_entity(out): entity_spec of X if in_node is an X.Z
5352  */
5353 static PT_NODE *
5355 {
5356 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
5357  PT_NODE *dot, *domain, *unique_entity;
5358 #endif /* ENABLE_UNUSED_FUNCTION */
5359  PT_NODE *attr, *entity;
5360  DB_ATTRIBUTE *attr_obj;
5361 
5362  /* if in_node is a path expr, get last attr in the in_node */
5363  attr = ((PT_IS_DOT_NODE (in_node)) ? in_node->info.dot.arg2 : in_node);
5364  if (!PT_IS_NAME_NODE (attr))
5365  {
5366  return NULL;
5367  }
5368 
5370  {
5371  entity = ((*p_entity) ? (*p_entity)->info.spec.entity_name : NULL);
5372  if (entity && entity->node_type == PT_NAME && entity->info.name.db_object)
5373  {
5374  attr_obj = (DB_ATTRIBUTE *) db_get_attribute_force (entity->info.name.db_object, attr->info.name.original);
5375 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
5376  /* check if the last attr is TEXT type */
5377  if (attr_obj && sm_has_text_domain (attr_obj, 0))
5378  {
5379  if ((domain = attr->data_type->info.data_type.entity) == NULL)
5380  {
5381  return NULL;
5382  }
5383  /* make a path expr like "attr.tdata" */
5384  if ((dot = parser_new_node (parser, PT_DOT_)) == NULL)
5385  {
5386  return NULL;
5387  }
5388  dot->info.dot.arg1 = attr;
5389  if ((dot->info.dot.arg2 = pt_name (parser, "tdata")) == NULL)
5390  {
5391  return NULL;
5392  }
5393  /* find "tdata" in the domain class, and attach the data type at "tdata" node */
5394  (void) pt_find_attr_in_class_list (parser, domain, dot->info.dot.arg2);
5395  dot->type_enum = dot->info.dot.arg2->type_enum;
5396  if ((dot->data_type = parser_copy_tree_list (parser, dot->info.dot.arg2->data_type)) == NULL)
5397  {
5398  return NULL;
5399  }
5400  /* insert the domain class into from class list */
5401  if (*p_entity)
5402  {
5403  unique_entity = pt_insert_entity (parser, dot, *p_entity, NULL);
5404  *p_entity = unique_entity;
5405  }
5406  /* merge in_node expr and "attr.tdata" */
5407  if (PT_IS_DOT_NODE (in_node))
5408  {
5409  dot->info.dot.arg1 = in_node->info.dot.arg1;
5410  }
5411  PT_NODE_COPY_NUMBER_OUTERLINK (dot, in_node);
5412  PT_NODE_INIT_OUTERLINK (in_node);
5413  dot->alias_print = pt_append_string (parser, NULL, attr->info.name.original);
5414  if (!dot->alias_print)
5415  {
5416  return NULL;
5417  }
5418  return dot;
5419  }
5420 #endif /* ENABLE_UNUSED_FUNCTION */
5421  }
5422  }
5423 
5424  return in_node;
5425 }
5426 
5427 /*
5428  * pt_is_correlation_name() - checks nam is an exposed name of some
5429  * entity_spec from scope
5430  * return: the entity spec of which nam is the correlation name.
5431  * Else 0 if not found or error.
5432  * parser(in/out): the parser context
5433  * scope(in): a list of PT_SPEC nodes
5434  * nam(in): a PT_NAME node
5435  */
5436 
5437 static PT_NODE *
5439 {
5440  PT_NODE *specs;
5441  PT_NODE *owner = NULL;
5442 
5443  assert (nam != NULL && (nam->node_type == PT_NAME || nam->node_type == PT_DOT_));
5444 
5445  if (nam->node_type == PT_DOT_)
5446  {
5447  owner = nam->info.dot.arg1;
5448  if (owner->node_type != PT_NAME)
5449  {
5450  /* could not be owner.correlation */
5451  return NULL;
5452  }
5453  nam = nam->info.dot.arg2;
5454  }
5455 
5456  if (nam->info.name.meta_class == PT_PARAMETER)
5457  {
5458  return NULL;
5459  }
5460 
5461  for (specs = scope; specs; specs = specs->next)
5462  {
5463  if (specs->node_type != PT_SPEC)
5464  {
5465  PT_INTERNAL_ERROR (parser, "resolution");
5466  return NULL;
5467  }
5468 
5469  if (specs->info.spec.range_var
5470  && ((nam->info.name.meta_class != PT_META_CLASS) || (specs->info.spec.meta_class == PT_META_CLASS))
5472  CASE_INSENSITIVE) == 0)
5473  {
5474  if (!owner)
5475  {
5476  return specs;
5477  }
5478  else
5479  {
5480  PT_NODE *entity_name;
5481 
5482  entity_name = specs->info.spec.entity_name;
5483  if (entity_name && entity_name->node_type == PT_NAME && entity_name->info.name.resolved
5484  /* actual class ownership test is done for spec no need to repeat that here. */
5485  && (pt_str_compare (entity_name->info.name.resolved, owner->info.name.original, CASE_INSENSITIVE) ==
5486  0))
5487  {
5488  return specs;
5489  }
5490  }
5491  }
5492  }
5493 
5494  return NULL;
5495 }
5496 
5497 /*
5498  * pt_find_entity () -
5499  * return: the entity spec of an entity of a spec in the scope with
5500  * an id matching the "match" spec
5501  * parser(in): the parser context
5502  * scope(in): a list of PT_SPEC nodes
5503  * id(in): of a PT_SPEC node
5504  */
5505 PT_NODE *
5507 {
5508  PT_NODE *spec, *path_spec;
5509  for (spec = (PT_NODE *) scope; spec; spec = spec->next)
5510  {
5511  if (spec->node_type != PT_SPEC)
5512  {
5513  PT_INTERNAL_ERROR (parser, "resolution");
5514  return NULL;
5515  }
5516  if (spec->info.spec.id == id)
5517  {
5518  return spec;
5519  }
5520  path_spec = pt_find_entity (parser, spec->info.spec.path_entities, id);
5521  if (path_spec)
5522  {
5523  return path_spec;
5524  }
5525  }
5526  return NULL;
5527 }
5528 
5529 /*
5530  * pt_find_path_entity () -
5531  * return: the entity spec of a path entity of a spec in the scope with
5532  * an id matching the whacked placeholder spec
5533  * parser(in): the parser context
5534  * scope(in): a list of PT_SPEC nodes
5535  * match(in): a PT_SPEC node that has been "whacked".
5536  */
5537 static PT_NODE *
5539 {
5540  PT_NODE *spec, *path_spec;
5541  UINTPTR id = match->info.spec.id;
5542 
5543  for (spec = scope; spec; spec = spec->next)
5544  {
5545  if (spec->node_type != PT_SPEC)
5546  {
5547  PT_INTERNAL_ERROR (parser, "resolution");
5548  return NULL;
5549  }
5550 
5551  path_spec = pt_find_entity (parser, spec->info.spec.path_entities, id);
5552  if (path_spec)
5553  {
5554  return path_spec;
5555  }
5556  }
5557 
5558  return NULL;
5559 }
5560 
5561 /*
5562  * pt_is_on_list () - check whether name node p is equal to
5563  * something on the list
5564  * return: Pointer to matching item or NULL
5565  * parser(in):
5566  * p(in): A PT_NAME node
5567  * list(in): A LIST of PT_NAME nodes
5568  *
5569  * Note :
5570  * two strings of length zero match
5571  * A NULL string does NOT match a zero length string
5572  */
5573 static PT_NODE *
5575 {
5576  if (p == NULL)
5577  {
5578  return NULL;
5579  }
5580  if (p->node_type != PT_NAME)
5581  {
5582  return NULL;
5583  }
5584 
5585  while (list)
5586  {
5587  if (list->node_type != PT_NAME)
5588  {
5589  PT_INTERNAL_ERROR (parser, "resolution");
5590  return NULL; /* this is an error */
5591  }
5592 
5594  {
5595  return (PT_NODE *) list; /* found a match */
5596  }
5597  list = list->next;
5598  }
5599 
5600  return NULL; /* no match */
5601 }
5602 
5603 /*
5604  * pt_name_list_union () -
5605  * return:
5606  * parser(in):
5607  * list(in/out): A list of PT_NAME nodes
5608  * additions(in): A list of PT_NAME nodes
5609  *
5610  * Note :
5611  * PT_NAME lists ( list1 union list2 )
5612  * PRESERVING ORDER OF LIST!
5613  */
5614 static PT_NODE *
5616 {
5617  PT_NODE *result, *temp;
5618 
5619  if (list == NULL)
5620  {
5621  return additions;
5622  }
5623  if (additions == NULL)
5624  {
5625  return list;
5626  }
5627 
5628  result = list;
5629  while (additions)
5630  {
5631  temp = additions;
5632  additions = additions->next;
5633  temp->next = NULL;
5634 
5635  if (!pt_is_on_list (parser, temp, list))
5636  {
5637  list = parser_append_node (temp, list);
5638  }
5639  else
5640  {
5641  parser_free_node (parser, temp);
5642  }
5643  }
5644 
5645  return result;
5646 }
5647 
5648 /*
5649  * pt_name_list_diff () -
5650  * return: Returns NULL if resulting list is empty
5651  * parser(in):
5652  * list(in): A list of PT_NAME nodes
5653  * deletions(in): A list of PT_NAME nodes
5654  *
5655  * Note :
5656  * PT_NAME lists (list1 - list2)
5657  * PRESERVING ORDER OF LIST!
5658  */
5659 static PT_NODE *
5661 {
5662  PT_NODE *result = NULL;
5663  PT_NODE *temp;
5664 
5665  if (list == NULL)
5666  {
5667  return NULL;
5668  }
5669  if (deletions == NULL)
5670  {
5671  return list;
5672  }
5673 
5674  while (list)
5675  {
5676  temp = list;
5677  list = list->next;
5678  temp->next = NULL;
5679 
5680  if (!pt_is_on_list (parser, temp, deletions))
5681  {
5682  result = parser_append_node (temp, result);
5683  }
5684  else
5685  {
5686  parser_free_node (parser, temp);
5687  }
5688  }
5689 
5690  parser_free_tree (parser, deletions);
5691 
5692  return result;
5693 }
5694 
5695 /*
5696  * pt_make_flat_name_list () - create a list of its name and all of its
5697  * subclass names, recursively
5698  * return: Returns a pointer to (list of) PT_NAME node(s)
5699  * parser(in):
5700  * db(in): db_object to find subclasses for
5701  * line_num(in): input line_num (for error messages)
5702  * col_num(in): input column num (for error messages)
5703  * id(in):
5704  * meta_class(in): parent class for pt_name nodes we create
5705  * names_mht(in): memory hash table used to avoid duplicates
5706  */
5707 
5708 static PT_NODE *
5709 pt_make_subclass_list (PARSER_CONTEXT * parser, DB_OBJECT * db, int line_num, int col_num, UINTPTR id,
5710  PT_MISC_TYPE meta_class, MHT_TABLE * names_mht)
5711 {
5712  PT_NODE *temp;
5713  const char *classname;
5714  PT_NODE *result = 0; /* will be returned */
5715  DB_OBJLIST *dbl; /* list of subclass objects */
5716  bool ismymht = false; /* Am I the one who created it? */
5717  SM_CLASS *smclass;
5718  int partition_skip;
5719 
5720 
5721  if (parser == NULL)
5722  {
5723  assert (parser != NULL);
5724  return NULL;
5725  }
5726 
5727  /* get the name of THIS class and put it in a PT_NAME node */
5728  if (db == NULL)
5729  {
5730  assert (db != NULL);
5731  return NULL;
5732  }
5733 
5734  classname = db_get_class_name (db);
5735  if (classname == NULL)
5736  {
5737  PT_INTERNAL_ERROR (parser, "resolution");
5738  return NULL;
5739  } /* not a class name (error) */
5740 
5741  /* Check to see if this classname is already known, and only add a (name) node if we have never seen it before. Note:
5742  * Even if we have visited it, we still need to recursively check its subclasses (see dbl below) in order to maintain
5743  * the correct ordering of classnames found via our depth-first search. */
5744  if (names_mht == NULL || !mht_get (names_mht, classname))
5745  {
5746  result = pt_name (parser, classname);
5747  if (result == NULL)
5748  {
5749  PT_INTERNAL_ERROR (parser, "allocate new node");
5750  return NULL;
5751  }
5752  result->line_number = line_num;
5753  result->column_number = col_num;
5754  result->info.name.db_object = db;
5755  result->info.name.spec_id = id;
5756  result->info.name.meta_class = meta_class;
5757  result->info.name.partition = NULL;
5758 
5759  if ((au_fetch_class_force (db, &smclass, AU_FETCH_READ) == NO_ERROR))
5760  {
5761  if (smclass->partition != NULL && smclass->partition->pname == NULL)
5762  {
5763  result->info.name.partition = smclass->partition;
5764  }
5765  }
5766  else
5767  {
5768  PT_ERRORc (parser, result, er_msg ());
5769  return NULL;
5770  }
5771 
5772  if (names_mht)
5773  {
5774  mht_put (names_mht, classname, (void *) true);
5775  }
5776  }
5777 
5778  /* get the list of immediate subclasses of db (may be NULL) */
5779  dbl = NULL;
5780  dbl = db_get_subclasses (db);
5781 
5782  /*
5783  * Build a hash table for all class and subclass names. This
5784  * helps us keep from building pt_name nodes for classes we
5785  * already know about. Also we only need to build the hash table if
5786  * there are in fact subclasses of the original class.
5787  */
5788  if (names_mht == NULL && dbl)
5789  {
5790  names_mht = mht_create ("Pt_Names_Hash_Table", PT_NAMES_HASH_SIZE, mht_4strhash, mht_compare_strings_are_equal);
5791  if (names_mht != NULL)
5792  {
5793  ismymht = true;
5794  /* Have to stick the first name node created above into the hash */
5795  mht_put (names_mht, classname, (void *) true);
5796  }
5797  else /* could not create hash table */
5798  {
5799  PT_ERRORc (parser, result, er_msg ());
5800  return NULL;
5801  }
5802  }
5803 
5804  /* for each subclass (dbl)...get the list(s) of its subclass names */
5805  while (dbl)
5806  {
5807  partition_skip = 0;
5808 
5809  if (au_fetch_class_force (dbl->op, &smclass, AU_FETCH_READ) == NO_ERROR)
5810  {
5811  if (smclass->partition != NULL && smclass->partition->pname != NULL)
5812  {
5813  partition_skip = 1; /* partitioned sub class */
5814  }
5815  }
5816  else
5817  {
5818  PT_ERRORc (parser, result, er_msg ());
5819  result = NULL;
5820  goto end;
5821  }
5822 
5823  if (!partition_skip)
5824  {
5825  /* here is the recursion */
5826  temp = pt_make_subclass_list (parser, dbl->op, line_num, col_num, id, meta_class, names_mht);
5827  /* when names_mht != NULL, it is possible that temp is NULL while no error happen. Such as: diamond problem
5828  * of multiple inheritance. So, check pt_has_error() is needed. */
5829  if (temp == NULL && pt_has_error (parser))
5830  {
5831  result = NULL;
5832  goto end;
5833  }
5834  /* and attach s to the tail of result. NOTE: ORDER IS IMPORTANT and MUST be maintained. This used to call
5835  * pt_name_list_union, but since we only add unique ones, we no longer need to do a set union operation. */
5836  result = parser_append_node (temp, result);
5837  }
5838 
5839  /* go to the next subclass */
5840  dbl = dbl->next;
5841  }
5842 end:
5843  /* Delete it only if we created it */
5844  if (ismymht && names_mht)
5845  {
5846  mht_destroy (names_mht);
5847  }
5848 
5849  return result;
5850 }
5851 
5852 
5853 /*
5854  * pt_make_flat_name_list () - Create flat name list from entity spec
5855  * return: returns a list of PT_NAME nodes representing the class(es)
5856  * referred to by the entity spec
5857  * parser(in):
5858  * spec(in): A PT_SPEC node representing a single entity spec
5859  * spec_parent(in):
5860 
5861  * Note :
5862  * Case (A == 'sub-list (A,B,..)'):
5863  * Set list(A)= set-theoretic union of the names list(A), list(B), ...
5864  * (There is no ONLY or ALL in this case)
5865  * Case (A == 'ONLY X' || A == 'X' (only is implied)):
5866  * Set list(A) = the name 'X' which must be an existing class name.
5867  * Attach the db_object * to the db_object field in the name node.
5868  * Case (A == 'ALL X'):
5869  * Set list(A) = the name 'X' as above union the names of all
5870  * subclasses of X (recursively).
5871  * Case (A == 'ALL X EXCEPT Y'):
5872  * Set list(A) = list(ALL X) - list(Y)
5873  * (set-theoretic difference of the lists)
5874  * Additionally:
5875  * list(Y) must be a subset of list(X), else error.
5876  * list(X)-list(Y) must be non-empty, else error.
5877  */
5878 static PT_NODE *
5879 pt_make_flat_name_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * spec_parent, bool for_update)
5880 {
5881  PT_NODE *result = 0; /* the list of names to return */
5882  PT_NODE *temp, *temp1, *temp2, *name;
5883  DB_OBJECT *db; /* a temp for class object */
5884  const char *class_name = NULL; /* a temp to extract name from class */
5885  PT_NODE *e_node;
5886  DB_AUTH type;
5887  AU_FETCHMODE fetchmode;
5888 
5889  if (!spec)
5890  {
5891  return 0;
5892  }
5893  if (spec->node_type != PT_SPEC)
5894  {
5895  PT_INTERNAL_ERROR (parser, "resolution");
5896  return NULL;
5897  }
5898 
5899  if (spec->info.spec.partition != NULL)
5900  {
5901  spec = pt_resolve_partition_spec (parser, spec, spec_parent, for_update);
5902  if (spec == NULL)
5903  {
5904  return spec;
5905  }
5906  return spec->info.spec.flat_entity_list;
5907  }
5908 
5909  name = spec->info.spec.entity_name;
5910  if (name == 0)
5911  {
5912  /* is a derived table */
5913  PT_INTERNAL_ERROR (parser, "resolution");
5914  return NULL;
5915  } /* internal error */
5916 
5917  /* If name field points to a name node (i.e. is not a sublist ) then .. */
5918  if (name->node_type == PT_NAME)
5919  {
5920  DB_OBJECT *classop;
5921  SM_CLASS *class_;
5922 
5923  class_name = name->info.name.original;
5924  classop = db_find_class_with_purpose (class_name, for_update);
5925  if (classop != NULL)
5926  {
5927  if (for_update)
5928  {
5929  fetchmode = AU_FETCH_UPDATE;
5930  type = AU_ALTER;
5931  }
5932  else
5933  {
5934  fetchmode = AU_FETCH_READ;
5935  type = AU_SELECT;
5936  }
5937 
5938  if (au_fetch_class (classop, &class_, fetchmode, type) == NO_ERROR)
5939  {
5940  if (class_->partition != NULL)
5941  {
5942  if (class_->partition->pname == NULL)
5943  {
5944  /* parent partition class */
5945  name->info.name.partition = class_->partition;
5946  }
5947  else
5948  {
5949  if (spec_parent && spec_parent->node_type != PT_SELECT
5950  && spec_parent->node_type != PT_CREATE_INDEX && spec_parent->node_type != PT_DROP_INDEX
5951  && spec_parent->node_type != PT_ALTER_INDEX && spec_parent->node_type != PT_MERGE
5952  && spec_parent->node_type != PT_DELETE && spec_parent->node_type != PT_UPDATE
5953  && spec_parent->node_type != PT_INSERT)
5954  {
5955  /* partition not allowed */
5956  PT_ERRORm (parser, spec, MSGCAT_SET_PARSER_SEMANTIC,
5958  return NULL;
5959  }
5960  }
5961  }
5962  }
5963  }
5964  else
5965  {
5966  PT_ERRORc (parser, spec, db_error_string (3));
5967  return NULL;
5968  }
5969 
5970  /* if ONLY... */
5971  if (spec->info.spec.only_all == PT_ONLY)
5972  {
5973  /* Get the name */
5974  name->info.name.spec_id = spec->info.spec.id;
5975  name->info.name.meta_class = spec->info.spec.meta_class;
5976  /* Make sure this is the name of a class */
5977  db = pt_find_users_class (parser, name);
5978  name->info.name.db_object = db;
5979  if (!db)
5980  {
5981  return 0; /* error already set */
5982  }
5983  /* an error. Isn't a class name */
5984  /* create a new name node with this class name on it. Return it. */
5985  result = pt_name (parser, class_name);
5986  result->line_number = spec->line_number;
5987  result->column_number = spec->column_number;
5988  result->info.name.db_object = db;
5989  result->info.name.spec_id = spec->info.spec.id;
5990  result->info.name.meta_class = spec->info.spec.meta_class;
5991  result->info.name.partition = name->info.name.partition;
5992  return result; /* there can be no except part */
5993  }
5994 
5995  /* if ALL... */
5996  if (spec->info.spec.only_all == PT_ALL)
5997  {
5998  /* get the entity_name as a string */
5999  name->info.name.spec_id = spec->info.spec.id;
6000  name->info.name.meta_class = spec->info.spec.meta_class;
6001  /* get the DB_OBJECT of which it is the name */
6002  db = pt_find_users_class (parser, name);
6003  name->info.name.db_object = db;
6004  if (!db)
6005  {
6006  return 0;
6007  }
6008  /* get list of this class name and all its subclass names */
6009  temp =
6010  pt_make_subclass_list (parser, db, spec->line_number, spec->column_number, spec->info.spec.id,
6011  spec->info.spec.meta_class, NULL);
6012  if (temp == NULL)
6013  {
6014  return NULL;
6015  }
6016  /* do the EXCEPT part if present */
6017  if (spec->info.spec.except_list == 0)
6018  {
6019  temp1 = 0;
6020  }
6021  else
6022  {
6023  temp1 = NULL;
6024  for (e_node = spec->info.spec.except_list; e_node; e_node = e_node->next)
6025  {
6026  /* recursion */
6027  temp2 = pt_make_flat_name_list (parser, e_node, spec_parent, false);
6028  if (!temp2)
6029  {
6030  return NULL;
6031  }
6032  temp1 = parser_append_node (temp2, temp1);
6033  }
6034  }
6035 
6036  /* check that each item on the EXCEPT flat-list is, in fact, a subclass name that is on the 'ALL' flat-list */
6037  temp2 = temp1;
6038  while (temp2)
6039  {
6040  if (!pt_is_on_list (parser, temp2, temp))
6041  {
6043  temp2->info.name.original);
6044  return 0;
6045  }
6046  temp2 = temp2->next;
6047  }
6048 
6049  /* return the difference of the two lists */
6050  result = pt_name_list_diff (parser, temp, temp1);
6051  if (!result)
6052  {
6054  }
6055  return result;
6056  }
6057  /* end if ALL */
6058 
6059  /* parser internal error, wasn't ONLY or ALL */
6060  PT_INTERNAL_ERROR (parser, "resolution");
6061  return 0;
6062  }
6063  /* end if not a sublist */
6064 
6065  /* If name field->ENTITY_SPEC node then we are dealing with a sublist: ( all A, B, all C except D, ...) There is no
6066  * ONLY/ALL/EXCEPT part for the sub-list as a whole. We take the union of all the names on the sub-list. */
6067  if (name->node_type == PT_SPEC)
6068  {
6069  result = 0;
6070  temp = name;
6071  /* for each (sub)entity_spec */
6072  while (temp)
6073  { /* recursion here */
6074  temp1 = pt_make_flat_name_list (parser, temp, spec_parent, for_update);
6075  result = pt_name_list_union (parser, result, temp1);
6076  temp = temp->next;
6077  }
6078 
6079  temp = result;
6080  while (temp)
6081  {
6082  temp->info.name.spec_id = spec->info.spec.id;
6083  temp->info.name.meta_class = spec->info.spec.meta_class;
6084  temp = temp->next;
6085  }
6086 
6087  return result;
6088  }
6089 
6090  PT_INTERNAL_ERROR (parser, "resolution");
6091  return 0; /* internal error, wasn't a name or a sublist */
6092 }
6093 
6094 
6095 /*
6096  * pt_must_have_exposed_name () - MUST assign a name (even a default one)
6097  * because later checks assume the range_var field is non-empty
6098  * return: 0 if error or can't assign a name. 1 if successful
6099  * parser(in):
6100  * p(in): a PT_SPEC node (list)
6101  *
6102  * Note :
6103  * For each item on the entity_spec list:
6104  * if not an entity spec, return 0
6105  * if .range_var already assigned, continue
6106  * if .range_var can be given the default (only class name) do it.
6107  * if can't assign name, return 0
6108  * Return 1 if every spec on list has a .range_var or can be given one
6109  * Set the .resolved field in each item in the flat list to
6110  * the corresponding exposed name. This is because in a query like:
6111  * select x.name,y.name from p x, p y both entity spec lists
6112  * generate the same flat list. We want to be able to tell them
6113  * apart later when we use them.
6114  */
6115 
6116 static int
6118 {
6119  PT_NODE *q = 0, *r;
6120  PT_NODE *spec_first = p;
6121 
6122  while (p)
6123  {
6124  if (p->node_type == PT_SPEC)
6125  {
6126  /* if needs a name */
6127  if (p->info.spec.range_var == NULL)
6128  {
6129  q = p->info.spec.entity_name;
6130  /* if an exposed name is not given, then exposed name is itself. */
6131  if (q && q->node_type == PT_NAME)
6132  { /* not a sub list */
6133  q->info.name.spec_id = p->info.spec.id;
6135  p->info.spec.range_var = parser_copy_tree (parser, q);
6137  }
6138  else if (p->info.spec.cte_name)
6139  {
6140  /* The name of the spec should be the name of the CTE */
6141  p->info.spec.range_var = parser_copy_tree (parser, p->info.spec.cte_name);
6142  }
6143  else
6144  {
6145  const char *unique_exposed_name;
6146  /*
6147  * Was sublist, they didn't give a correlation variable name so We generate a unique name and attach
6148  * it. */
6149  r = parser_new_node (parser, PT_NAME);
6150 
6151  if (r == NULL)
6152  {
6153  PT_INTERNAL_ERROR (parser, "allocate new node");
6154  return 0;
6155  }
6156 
6157  r->info.name.spec_id = p->info.spec.id;
6158  r->info.name.meta_class = p->info.spec.meta_class;
6159 
6160  unique_exposed_name = pt_get_unique_exposed_name (parser, spec_first);
6161 
6162  if (unique_exposed_name == NULL)
6163  {
6164  PT_INTERNAL_ERROR (parser, "allocate new table name");
6165  return 0;
6166  }
6167 
6168  r->info.name.original = unique_exposed_name;
6169  r->line_number = p->line_number;
6170  r->column_number = p->column_number;
6171  p->info.spec.range_var = r;
6172  }
6173  }
6175  /* If we get here, the item has a name. Copy name-pointer to the resolved field of each item on flat entity
6176  * list */
6177  q = p->info.spec.flat_entity_list;
6178  while (q)
6179  {
6181  if (PT_IS_SPEC_REAL_TABLE (p))
6182  {
6184  }
6185  q = q->next;
6186  }
6187  p = p->next;
6188  }
6189  } /* continue while() */
6190 
6191  return 1;
6192 }
6193 
6194 
6195 /*
6196  * pt_object_to_data_type () - create a PT_DATA_TYPE node that corresponds
6197  * to it and return it
6198  * return: PT_NODE * to a data_type node
6199  * parser(in):
6200  * class_list(in):
6201  */
6202 static PT_NODE *
6204 {
6205  PT_NODE *result;
6206  result = parser_new_node (parser, PT_DATA_TYPE);
6207  if (result == NULL)
6208  {
6209  PT_INTERNAL_ERROR (parser, "allocate new node");
6210  return NULL;
6211  }
6212 
6213  result->type_enum = PT_TYPE_OBJECT;
6214  result->info.data_type.entity = parser_copy_tree_list (parser, class_list);
6216  result->line_number = class_list->line_number;
6217  result->column_number = class_list->column_number;
6218  return result;
6219 }
6220 
6221 /*
6222  * pt_resolve_star_reserved_names () - Resolves '*' value in select list
6223  * when a hint that activates reserved
6224  * names is used.
6225  *
6226  * return : List of reserved names.
6227  * parser (in) : Parser context.
6228  * from (in) : Query spec.
6229  *
6230  * NOTE: The reserved names depend on the scan type flag on from node.
6231  */
6232 static PT_NODE *
6234 {
6235  PT_NODE *reserved_names = NULL;
6236  PT_NODE *new_name = NULL;
6237  int i, start, end;
6238  PT_RESERVED_NAME_TYPE reserved_name_type;
6239 
6240  if (parser == NULL || from == NULL || from->node_type != PT_SPEC)
6241  {
6242  assert (0);
6243  return NULL;
6244  }
6245 
6246  reserved_name_type = PT_SPEC_GET_RESERVED_NAME_TYPE (from);
6247  if (reserved_name_type == RESERVED_NAME_INVALID)
6248  {
6249  assert (0);
6250  return NULL;
6251  }
6252 
6253  PT_GET_RESERVED_NAME_FIRST_AND_LAST (reserved_name_type, start, end);
6254 
6255  for (i = start; i <= end; i++)
6256  {
6257  /* create a new node for each reserved name */
6258  new_name = pt_name (parser, pt_Reserved_name_table[i].name);
6259  if (new_name == NULL)
6260  {
6262  parser_free_tree (parser, reserved_names);
6263  return NULL;
6264  }
6265  /* mark the node as reserved */
6266  new_name->info.name.meta_class = PT_RESERVED;
6268  /* resolve name */
6269  new_name->info.name.spec_id = from->info.spec.id;
6270  new_name->info.name.resolved = from->info.spec.range_var->info.name.original;
6271  /* set type enum to the expected type */
6272  new_name->type_enum = pt_db_to_type_enum (pt_Reserved_name_table[i].type);
6273  if (new_name->type_enum == PT_TYPE_OBJECT)
6274  {
6275  new_name->data_type =
6276  pt_domain_to_data_type (parser,
6278  from->info.spec.entity_name->info.name.db_object, 0, 0, NULL,
6279  0));
6280  }
6281  /* append to name list */
6282  reserved_names = parser_append_node (new_name, reserved_names);
6283  }
6284  /* return reserved name list */
6285  return reserved_names;
6286 }
6287 
6288 /*
6289  * pt_resolve_star () - resolve the '*' as in a query
6290  * Replace the star with an equivalent list x.a, x.b, y.a, y.d ...
6291  * return:
6292  * parser(in):
6293  * from(in): a PT_SELECT node
6294  * attr(in): NULL if "*", non-NULL if "class_name.*"
6295  *
6296  * Note :
6297  * ASSUMES
6298  * Flat entity lists in the 'from' clause have already been created.
6299  * Items in from list all have or have been given an exposed name.
6300  */
6301 PT_NODE *
6303 {
6304  PT_NODE *flat_list;
6305  PT_NODE *flat, *spec_att, *class_att, *attr_name, *range, *result = NULL;
6306  PT_NODE *spec = from;
6307 
6308  if (PT_SHOULD_BIND_RESERVED_NAME (from))
6309  {
6310  return pt_resolve_star_reserved_names (parser, from);
6311  }
6312 
6313  while (spec)
6314  {
6315  if (attr)
6316  { /* resolve "class_name.*" */
6317  if (attr->info.name.spec_id != spec->info.spec.id)
6318  {
6319  spec = spec->next; /* skip to next spec */
6320  continue;
6321  }
6322  }
6323 
6324  /* spec_att := all attributes of this entity spec */
6325  spec_att = NULL;
6326 
6327  if (PT_SPEC_IS_DERIVED (spec) || PT_SPEC_IS_CTE (spec))
6328  {
6329  spec_att = parser_copy_tree_list (parser, spec->info.spec.as_attr_list);
6330  }
6331  else
6332  {
6333  /* spec_att := intersection of all attributes of spec's subclasses */
6334  assert (PT_SPEC_IS_ENTITY (spec));
6335  flat_list = spec->info.spec.flat_entity_list;
6336  for (flat = flat_list; flat; flat = flat->next)
6337  {
6338  /* get attribute list for this class flat */
6339  class_att = pt_get_all_attributes_and_types (parser, flat, spec);
6340  /* take intersection except first time */
6341  spec_att = ((flat == flat_list) ? class_att : pt_common_attribute (parser, spec_att, class_att));
6342 
6343  if (pt_has_error (parser))
6344  {
6345  return NULL;
6346  }
6347  }
6348  }
6349 
6350  attr_name = spec_att;
6351  range = spec->info.spec.range_var;
6352  while (attr_name)
6353  {
6354  if (range)
6355  {
6356  attr_name->info.name.resolved = range->info.name.original;
6357  }
6358 
6360  /* expand "attr" into "attr.tdata" if the attr is TEXT */
6361  if (attr_name->type_enum == PT_TYPE_OBJECT && !PT_NAME_INFO_IS_FLAGED (attr_name, PT_NAME_INFO_EXTERNAL))
6362  {
6363  DB_ATTRIBUTE *att = NULL;
6364  PT_NODE *entity_name = spec->info.spec.entity_name;
6365  if (entity_name && entity_name->node_type == PT_NAME && entity_name->info.name.db_object)
6366  {
6367  att = db_get_attribute (entity_name->info.name.db_object, attr_name->info.name.original);
6368  }
6369 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
6370  if (att && sm_has_text_domain (att, 0))
6371  {
6372  PT_NODE *prev_entity;
6373  PT_NODE *save_next = attr_name->next;
6374  PT_NODE *dot_arg1 = parser_copy_tree (parser, attr_name);
6375  PT_NODE *dot_arg2 = pt_name (parser, "tdata");
6376  if (!dot_arg1 || !dot_arg2)
6377  {
6378  return NULL;
6379  }
6380  else
6381  {
6382  parser_reinit_node (attr_name);
6383  attr_name->node_type = PT_DOT_;
6384  attr_name->info.dot.arg1 = dot_arg1;
6385  attr_name->info.dot.arg2 = dot_arg2;
6386  attr_name->alias_print = pt_append_string (parser, NULL, dot_arg1->info.name.original);
6387  if (!attr_name->alias_print)
6388  {
6389  return NULL;
6390  }
6391  attr_name = pt_get_resolution (parser, NULL, spec, attr_name, &prev_entity, 1);
6392  if (!attr_name)
6393  {
6394  return NULL;
6395  }
6396  attr_name->next = save_next;
6397  }
6398  }
6399 #endif /* ENABLE_UNUSED_FUNCTION */
6400  }
6401  attr_name = attr_name->next;
6402  }
6403 
6404  if (result)
6405  {
6406  /* attach spec_att to end of result */
6407  attr_name = result;
6408  while (attr_name->next)
6409  {
6410  attr_name = attr_name->next;
6411  }
6412  attr_name->next = spec_att;
6413  }
6414  else
6415  {
6416  result = spec_att;
6417  }
6418 
6419  if (attr)
6420  {
6421  break;
6422  }
6423  spec = spec->next;
6424  }
6425 
6426  return result;
6427 }
6428 
6429 /*
6430  * pt_resolve_vclass_args () - modifies the attribute list in the insert
6431  * statement by adding to the specified attributes the ones missing with
6432  * their default values (if not null). is applied only to views.
6433  *
6434  * return: the modified statement
6435  * parser(in):
6436  * statement(in): insert statement
6437  *
6438  * NOTE: this step is needed because all information on the view is lost after
6439  * translate (including default values for the missing attributes).
6440  */
6441 static PT_NODE *
6443 {
6444  PT_NODE *spec = NULL;
6445  PT_NODE *entity_name = NULL;
6446  PT_NODE *attr_list = NULL, *attr = NULL;
6447  PT_NODE *value_clauses = NULL, *value_list = NULL;
6448  PT_NODE *crt_node = NULL;
6449  PT_NODE *rest_attrs = NULL, *rest_values = NULL;
6450  DB_OBJECT *db_obj = NULL;
6451  SM_ATTRIBUTE *db_attributes = NULL, *db_attr = NULL;
6452  int is_values, is_vclass = 0;
6453  int is_subqery;
6454 
6455  if (!statement || statement->node_type != PT_INSERT)
6456  {
6457  /* do nothing */
6458  return statement;
6459  }
6460 
6461  spec = statement->info.insert.spec;
6462  entity_name = spec->info.spec.entity_name;
6463  if (!entity_name || entity_name->node_type != PT_NAME)
6464  {
6465  /* enitity_name should be resolved before going further */
6466  return statement;
6467  }
6468  db_obj = entity_name->info.name.db_object;
6469  if (!db_obj)
6470  {
6471  /* this applies only for views */
6472  return statement;
6473  }
6474  is_vclass = db_is_vclass (db_obj);
6475  if (is_vclass < 0)
6476  {
6477  PT_ERRORc (parser, statement, er_msg ());
6478  goto error;
6479  }
6480  if (!is_vclass)
6481  {
6482  return statement;
6483  }
6484 
6485  value_clauses = statement->info.insert.value_clauses;
6486  value_list = value_clauses->info.node_list.list;
6487  attr_list = statement->info.insert.attr_list;
6488  if (!attr_list)
6489  {
6490  return statement;
6491  }
6492 
6493  is_values = (value_clauses->info.node_list.list_type == PT_IS_VALUE);
6494  is_subqery = (value_clauses->info.node_list.list_type == PT_IS_SUBQUERY);
6495 
6496  db_attributes = db_get_attributes_force (db_obj);
6497  if (db_attributes == NULL)
6498  {
6499  return statement;
6500  }
6501 
6502  rest_attrs = NULL;
6503  rest_values = NULL;
6504 
6505  for (db_attr = db_attributes; db_attr; db_attr = db_attribute_next (db_attr))
6506  {
6507  const char *name = db_attr->header.name;
6508 
6509  if (db_attr->default_value.default_expr.default_expr_type == DB_DEFAULT_NONE
6510  && DB_IS_NULL (&db_attr->default_value.value))
6511  {
6512  continue;
6513  }
6514 
6515  for (attr = attr_list; attr; attr = attr->next)
6516  {
6517  if (pt_str_compare (name, attr->info.name.original, CASE_INSENSITIVE) == 0)
6518  {
6519  break;
6520  }
6521  }
6522  if (!attr)
6523  {
6524  /* create attribute & default value and update rest_lists */
6525  attr = parser_new_node (parser, PT_NAME);
6526  if (!attr)
6527  {
6528  PT_ERROR (parser, statement, "allocation error");
6529  goto error;
6530  }
6531  attr->info.name.original = pt_append_string (parser, NULL, name);
6532  if (attr->info.name.original == NULL)
6533  {
6534  PT_ERRORc (parser, statement, er_msg ());
6535  goto error;
6536  }
6537  if (rest_attrs)
6538  {
6539  rest_attrs = parser_append_node (attr, rest_attrs);
6540  }
6541  else
6542  {
6543  rest_attrs = attr;
6544  }
6545  if (is_values)
6546  {
6547  PT_NODE *val = parser_new_node (parser, PT_EXPR);
6548  if (!val)
6549  {
6550  PT_ERROR (parser, statement, "allocation error");
6551  goto error;
6552  }
6553  val->info.expr.op = PT_DEFAULTF;
6554  if (rest_values)
6555  {
6556  rest_values = parser_append_node (val, rest_values);
6557  }
6558  else
6559  {
6560  rest_values = val;
6561  }
6562  }
6563  if (is_subqery)
6564  {
6566  db_attr);
6567  if (!val)
6568  {
6569  /* error was already handled */
6570  goto error;
6571  }
6572 
6573  if (rest_values)
6574  {
6575  rest_values = parser_append_node (val, rest_values);
6576  }
6577  else
6578  {
6579  rest_values = val;
6580  }
6581  }
6582  }
6583  }
6584 
6585  if (!rest_attrs || !rest_values)
6586  {
6587  /* nothing to do */
6588  return statement;
6589  }
6590 
6591  statement->info.insert.attr_list = parser_append_node (rest_attrs, attr_list);
6592  if (is_values)
6593  {
6594  for (crt_node = value_clauses; crt_node; crt_node = crt_node->next)
6595  {
6596  /* a different copy of rest_values is needed for each node in the node list */
6597  PT_NODE *new_rest_values = parser_copy_tree_list (parser,
6598  rest_values);
6599  if (!new_rest_values)
6600  {
6601  goto error;
6602  }
6603  crt_node->info.node_list.list = parser_append_node (new_rest_values, crt_node->info.node_list.list);
6604  }
6605  /* only copied of rest_values are used, has to be freed */
6606  parser_free_tree (parser, rest_values);
6607  }
6608  if (is_subqery)
6609  {
6610  statement->info.insert.value_clauses->info.node_list.list =
6611  pt_append_query_select_list (parser, value_list, rest_values);
6612  }
6613 
6614  return statement;
6615 
6616 error:
6617  if (rest_attrs)
6618  {
6619  parser_free_tree (parser, rest_attrs);
6620  }
6621  if (rest_values)
6622  {
6623  parser_free_tree (parser, rest_values);
6624  }
6625  if (!pt_has_error (parser))
6626  {
6627  PT_ERRORm (parser, statement, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
6628  }
6629 
6630  return NULL;
6631 }
6632 
6633 /*
6634  * pt_resolve_hint_args () -
6635  * return: NO_ERROR on success, non-zero for ERROR
6636  * parser(in):
6637  * arg_list(in/out):
6638  * spec_list(in):
6639  * discard_no_match(in): remove unmatched node from arg_list
6640  */
6641 static int
6642 pt_resolve_hint_args (PARSER_CONTEXT * parser, PT_NODE ** arg_list, PT_NODE * spec_list, bool discard_no_match)
6643 {
6644 
6645  PT_NODE *arg, *spec, *range, *prev, *tmp;
6646 
6647  prev = NULL;
6648  arg = *arg_list;
6649 
6650  while (arg != NULL)
6651  {
6652  if (arg->node_type != PT_NAME || arg->info.name.original == NULL)
6653  {
6654  goto exit_on_error;
6655  }
6656 
6657  /* check if the specified class name exists in spec list */
6658  for (spec = spec_list; spec; spec = spec->next)
6659  {
6660  if (spec->node_type != PT_SPEC)
6661  {
6662  PT_INTERNAL_ERROR (parser, "resolution");
6663  goto exit_on_error;
6664  }
6665 
6666  if ((range = spec->info.spec.range_var)
6668  {
6669  /* found match */
6670  arg->info.name.spec_id = spec->info.spec.id;
6672  break;
6673  }
6674  }
6675 
6676  /* not found */
6677  if (spec == NULL)
6678  {
6679  if (discard_no_match)
6680  {
6681  tmp = arg;
6682  arg = arg->next;
6683  tmp->next = NULL;
6684  parser_free_node (parser, tmp);
6685 
6686  if (prev == NULL)
6687  {
6688  *arg_list = arg;
6689  }
6690  else
6691  {
6692  prev->next = arg;
6693  }
6694  }
6695  else
6696  {
6697  goto exit_on_error;
6698  }
6699  }
6700  else
6701  {
6702  prev = arg;
6703  arg = arg->next;
6704  }
6705  }
6706 
6707  return NO_ERROR;
6708 exit_on_error:
6709 
6710  return ER_FAILED;
6711 }
6712 
6713 /*
6714  * pt_resolve_hint () -
6715  * return:
6716  * parser(in):
6717  * node(in):
6718  */
6719 static int
6721 {
6722  PT_HINT_ENUM hint;
6723  PT_NODE **ordered = NULL, **use_nl = NULL, **use_idx = NULL;
6724  PT_NODE **use_merge = NULL, **index_ss = NULL, **index_ls = NULL;
6725  PT_NODE *spec_list = NULL;
6726 
6727  switch (node->node_type)
6728  {
6729  case PT_SELECT:
6730  hint = node->info.query.q.select.hint;
6731  ordered = &node->info.query.q.select.ordered;
6732  use_nl = &node->info.query.q.select.use_nl;
6733  use_idx = &node->info.query.q.select.use_idx;
6734  index_ss = &node->info.query.q.select.index_ss;
6735  index_ls = &node->info.query.q.select.index_ls;
6736  use_merge = &node->info.query.q.select.use_merge;
6737  spec_list = node->info.query.q.select.from;
6738  break;
6739  case PT_DELETE:
6740  hint = node->info.delete_.hint;
6741  ordered = &node->info.delete_.ordered_hint;
6742  use_nl = &node->info.delete_.use_nl_hint;
6743  use_idx = &node->info.delete_.use_idx_hint;
6744  use_merge = &node->info.delete_.use_merge_hint;
6745  spec_list = node->info.delete_.spec;
6746  break;
6747  case PT_UPDATE:
6748  hint = node->info.update.hint;
6749  ordered = &node->info.update.ordered_hint;
6750  use_nl = &node->info.update.use_nl_hint;
6751  use_idx = &node->info.update.use_idx_hint;
6752  use_merge = &node->info.update.use_merge_hint;
6753  spec_list = node->info.update.spec;
6754  break;
6755  default:
6756  PT_INTERNAL_ERROR (parser, "Invalid statement in hints resolving");
6757  return ER_FAILED;
6758  }
6759 
6760  if (hint & PT_HINT_ORDERED)
6761  {
6762  if (pt_resolve_hint_args (parser, ordered, spec_list, REQUIRE_ALL_MATCH) != NO_ERROR)
6763  {
6764  goto exit_on_error;
6765  }
6766  }
6767 
6768 #if 0
6769  if (hint & PT_HINT_Y)
6770  { /* not used */
6771  }
6772 #endif /* 0 */
6773 
6774  if (hint & PT_HINT_USE_NL)
6775  {
6776  if (pt_resolve_hint_args (parser, use_nl, spec_list, REQUIRE_ALL_MATCH) != NO_ERROR)
6777  {
6778  goto exit_on_error;
6779  }
6780  }
6781 
6782  if (hint & PT_HINT_USE_IDX)
6783  {
6784  if (pt_resolve_hint_args (parser, use_idx, spec_list, REQUIRE_ALL_MATCH) != NO_ERROR)
6785  {
6786  goto exit_on_error;
6787  }
6788  }
6789 
6790  /* *index_ss == NULL means apply index skip scan to each table */
6791  if ((hint & PT_HINT_INDEX_SS) && *index_ss != NULL)
6792  {
6793  if (pt_resolve_hint_args (parser, index_ss, spec_list, DISCARD_NO_MATCH) != NO_ERROR)
6794  {
6795  goto exit_on_error;
6796  }
6797 
6798  /* clear hint if no matched any item */
6799  if (*index_ss == NULL)
6800  {
6801  node->info.query.q.select.hint = (PT_HINT_ENUM) (node->info.query.q.select.hint & ~PT_HINT_INDEX_SS);
6802  }
6803  }
6804 
6805  /* *index_ls == NULL means apply loose index scan to each table */
6806  if ((hint & PT_HINT_INDEX_LS) && *index_ls != NULL)
6807  {
6808  if (pt_resolve_hint_args (parser, index_ls, spec_list, DISCARD_NO_MATCH) != NO_ERROR)
6809  {
6810  goto exit_on_error;
6811  }
6812 
6813  /* clear hint if no matched any item */
6814  if (*index_ls == NULL)
6815  {
6816  node->info.query.q.select.hint = (PT_HINT_ENUM) (node->info.query.q.select.hint & ~PT_HINT_INDEX_LS);
6817  }
6818  }
6819 
6820  if (hint & PT_HINT_USE_MERGE)
6821  {
6822  if (pt_resolve_hint_args (parser, use_merge, spec_list, REQUIRE_ALL_MATCH) != NO_ERROR)
6823  {
6824  goto exit_on_error;
6825  }
6826  }
6827 
6828 #if 0
6829  if (hint & PT_HINT_USE_HASH)
6830  { /* not used */
6831  }
6832 #endif /* 0 */
6833 
6834  return NO_ERROR;
6835 exit_on_error:
6836 
6837  /* clear hint info */
6838  node->info.query.q.select.hint = PT_HINT_NONE;
6839  if (*ordered != NULL)
6840  {
6841  parser_free_tree (parser, *ordered);
6842  }
6843  if (*use_nl != NULL)
6844  {
6845  parser_free_tree (parser, *use_nl);
6846  }
6847  if (*use_idx != NULL)
6848  {
6849  parser_free_tree (parser, *use_idx);
6850  }
6851  if (index_ss != NULL && *index_ss != NULL)
6852  {
6853  parser_free_tree (parser, *index_ss);
6854  }
6855  if (index_ls != NULL && *index_ls != NULL)
6856  {
6857  parser_free_tree (parser, *index_ls);
6858  }
6859  if (*use_merge != NULL)
6860  {
6861  parser_free_tree (parser, *use_merge);
6862  }
6863 
6864  switch (node->node_type)
6865  {
6866  case PT_SELECT:
6867  node->info.query.q.select.ordered = NULL;
6868  node->info.query.q.select.use_nl = NULL;
6869  node->info.query.q.select.use_idx = NULL;
6870  node->info.query.q.select.index_ss = NULL;
6871  node->info.query.q.select.index_ls = NULL;
6872  node->info.query.q.select.use_merge = NULL;
6873  break;
6874  case PT_DELETE:
6875  node->info.delete_.ordered_hint = NULL;
6876  node->info.delete_.use_nl_hint = NULL;
6877  node->info.delete_.use_idx_hint = NULL;
6878  node->info.delete_.use_merge_hint = NULL;
6879  break;
6880  case PT_UPDATE:
6881  node->info.update.ordered_hint = NULL;
6882  node->info.update.use_nl_hint = NULL;
6883  node->info.update.use_idx_hint = NULL;
6884  node->info.update.use_merge_hint = NULL;
6885  break;
6886  default:
6887  break;
6888  }
6889 
6890  return ER_FAILED;
6891 }
6892 
6893 /*
6894  * pt_resolve_using_index () -
6895  * return:
6896  * parser(in):
6897  * index(in):
6898  * from(in):
6899  */
6900 PT_NODE *
6902 {
6903  PT_NODE *spec, *range, *entity;
6904  DB_OBJECT *classop;
6905  SM_CLASS *class_;
6906  SM_CLASS_CONSTRAINT *cons;
6907  int found = 0;
6908  int errid;
6909 
6910  if (index == NULL || index->info.name.original == NULL)
6911  {
6912  if (index->etc != (void *) PT_IDX_HINT_CLASS_NONE)
6913  {
6914  /* the case of USING INDEX NONE */
6915  return index;
6916  }
6917  }
6918 
6919  assert (index != NULL);
6920 
6921  if (index->info.name.spec_id != 0) /* already resolved */
6922  {
6923  return index;
6924  }
6925  if (index->info.name.resolved != NULL)
6926  {
6927  /* index name is specified by class name as "class.index" */
6928 
6929  /* check if the specified class name exists in spec list */
6930  for (spec = from; spec; spec = spec->next)
6931  {
6932  if (spec->node_type != PT_SPEC)
6933  {
6934  PT_INTERNAL_ERROR (parser, "resolution");
6935  return NULL;
6936  }
6937 
6938  range = spec->info.spec.range_var;
6939  entity = spec->info.spec.entity_name;
6940  if (range && entity
6942  {
6943  classop = db_find_class (entity->info.name.original);
6944  if (au_fetch_class (classop, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
6945  {
6946  assert (er_errid () != NO_ERROR);
6947  errid = er_errid ();
6948  if (errid == ER_AU_SELECT_FAILURE || errid == ER_AU_AUTHORIZATION_FAILURE)
6949  {
6950  PT_ERRORc (parser, entity, er_msg ());
6951  }
6952  else
6953  {
6954  PT_INTERNAL_ERROR (parser, "resolution");
6955  }
6956 
6957  return NULL;
6958  }
6959  if (index->info.name.original != NULL)
6960  {
6961  cons = classobj_find_class_index (class_, index->info.name.original);
6962  if (cons == NULL)
6963  {
6964  /* error; the index is not for the specified class */
6966  pt_short_print (parser, index));
6967  return NULL;
6968  }
6970  || cons->index_status == SM_INVISIBLE_INDEX)
6971  {
6973  pt_short_print (parser, index));
6974  return NULL; // unusable index
6975  }
6976  }
6977  index->info.name.spec_id = spec->info.spec.id;
6978  index->info.name.meta_class = PT_INDEX_NAME;
6979  /* "class.index" is valid */
6980  return index;
6981  }
6982  }
6983 
6984  /* the specified class in "class.index" does not exist in spec list */
6986  pt_short_print (parser, index));
6987  return NULL;
6988  }
6989  else
6990  { /* if (index->info.name.resolved != NULL) */
6991  /* index name without class name specification */
6992 
6993  /* find the class of the index from spec list */
6994  for (spec = from; spec; spec = spec->next)
6995  {
6996  if (spec->node_type != PT_SPEC)
6997  {
6998  PT_INTERNAL_ERROR (parser, "resolution");
6999  return NULL;
7000  }
7001 
7002  range = spec->info.spec.range_var;
7003  entity = spec->info.spec.entity_name;
7004  if (range != NULL && entity != NULL && entity->info.name.original != NULL)
7005  {
7006  classop = db_find_class (entity->info.name.original);
7007  if (classop == NULL)
7008  {
7009  break;
7010  }
7011  if (au_fetch_class (classop, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
7012  {
7013  assert (er_errid () != NO_ERROR);
7014  errid = er_errid ();
7015  if (errid == ER_AU_SELECT_FAILURE || errid == ER_AU_AUTHORIZATION_FAILURE)
7016  {
7017  PT_ERRORc (parser, entity, er_msg ());
7018  }
7019  else
7020  {
7021  PT_INTERNAL_ERROR (parser, "resolution");
7022  }
7023 
7024  return NULL;
7025  }
7026  cons = classobj_find_class_index (class_, index->info.name.original);
7027  if (cons != NULL && (cons->index_status == SM_NORMAL_INDEX))
7028  {
7029  /* found the class; resolve index name */
7030  found++;
7031  index->info.name.resolved = range->info.name.original;
7032  index->info.name.spec_id = spec->info.spec.id;
7033  index->info.name.meta_class = PT_INDEX_NAME;
7034  }
7035  // TODO: raise an error for such indexes??
7036  }
7037  }
7038 
7039  if (found == 0)
7040  {
7041  /* error; can not find the class of the index */
7043  pt_short_print (parser, index));
7044  return NULL;
7045  }
7046  else if (found > 1)
7047  {
7048  index->info.name.resolved = NULL;
7049  /* we found more than one classes which have index of the same name */
7051  pt_short_print (parser, index));
7052  return NULL;
7053  }
7054 
7055  }
7056 
7057  return index;
7058 }
7059 
7060 /*
7061  * pt_str_compare () -
7062  * return: 0 if two strings are equal. 1 if not equal
7063  * p(in): A string
7064  * q(in): A string
7065  *
7066  * Note :
7067  * two NULL strings are considered a match.
7068  * two strings of length zero match
7069  * A NULL string does NOT match a zero length string
7070  */
7071 int
7072 pt_str_compare (const char *p, const char *q, CASE_SENSITIVENESS case_flag)
7073 {
7074  if (!p && !q)
7075  {
7076  return 0;
7077  }
7078  if (!p || !q)
7079  {
7080  return 1;
7081  }
7082 
7083  if (case_flag == CASE_INSENSITIVE)
7084  {
7085  return intl_identifier_casecmp (p, q);
7086  }
7087  else
7088  {
7089  return intl_identifier_cmp (p, q);
7090  }
7091 }
7092 
7093 /*
7094  * pt_get_unique_exposed_name () -
7095  * return:
7096  *
7097  * parser(in):
7098  * first_spec(in):
7099  */
7100 static const char *
7102 {
7103  char name_buf[32];
7104  int i = 1;
7105 
7106  if (first_spec->node_type != PT_SPEC)
7107  {
7108  assert (first_spec->node_type == PT_SPEC);
7109  return NULL;
7110  }
7111 
7112  while (1)
7113  {
7114  snprintf (name_buf, 32, "__t%u", i);
7115  if (pt_name_occurs_in_from_list (parser, name_buf, first_spec) == 0)
7116  {
7117  return pt_append_string (parser, NULL, name_buf);
7118  }
7119  i++;
7120  }
7121 
7122  return NULL;
7123 }
7124 
7125 /*
7126  * pt_quick_resolve_names () - resolve names in node_p based on the spec
7127  * spec_p
7128  * return : error code or NO_ERROR
7129  * parser (in) : parser context
7130  * spec_p (in/out) : PT_SPEC for the table containing the names in node_p
7131  * node_p (in/out) : the node to resolve
7132  * sc_info (in): semantic check info
7133  *
7134  * Note: Call this function to resolve the names in a node outside of a
7135  * statement context
7136  */
7137 int
7139 {
7140  PT_BIND_NAMES_ARG bind_arg;
7141  PT_NODE *spec = NULL, *node = NULL;
7142  int walk = 0;
7143  SCOPES scopestack;
7144  PT_EXTRA_SPECS_FRAME spec_frame;
7145  PT_FLAT_SPEC_INFO info;
7146 
7147  if (node_p == NULL || spec_p == NULL)
7148  {
7149  assert (false);
7150  return ER_FAILED;
7151  }
7152 
7153  spec = *spec_p;
7154  node = *node_p;
7155  if (spec == NULL || node == NULL)
7156  {
7157  assert (false);
7158  return ER_FAILED;
7159  }
7160 
7161  /* convert spec to a flat entity list */
7162  info.spec_parent = NULL;
7163  info.for_update = false;
7164  spec = pt_flat_spec_pre (parser, spec, &info, &walk);
7165 
7166  /* bind spec in scope */
7167  bind_arg.scopes = NULL;
7168  bind_arg.spec_frames = NULL;
7169  bind_arg.sc_info = sc_info;
7170 
7171  scopestack.next = bind_arg.scopes;
7172  scopestack.specs = spec;
7173  scopestack.correlation_level = 0;
7174  scopestack.location = 0;
7175 
7176  bind_arg.scopes = &scopestack;
7177  spec_frame.next = bind_arg.spec_frames;
7178  spec_frame.extra_specs = NULL;
7179  bind_arg.spec_frames = &spec_frame;
7180 
7181  *spec_p = spec;
7182  node = *node_p;
7183  /* resolve expression */
7184  node = parser_walk_tree (parser, node, pt_bind_names, &bind_arg, pt_bind_names_post, &bind_arg);
7185 
7186  node_p = &node;
7187  return NO_ERROR;
7188 }
7189 
7190 /*
7191  * natural_join_equal_attr () - If the two attributes have same name,
7192  * the function return true. We don't consider the type there.
7193  * Whether the join can be executed is dependent on whether the
7194  * two types are compatible. If not, the error will be threw by
7195  * subsequent process.
7196  * return:
7197  * lhs(in):
7198  * rhs(in):
7199  */
7200 static bool
7202 {
7203  const char *lhs_name;
7204  const char *rhs_name;
7205 
7206  assert (lhs != NULL && rhs != NULL);
7207 
7208  lhs_name = lhs->name;
7209  rhs_name = rhs->name;
7210 
7211  if (lhs_name == NULL || rhs_name == NULL)
7212  {
7213  return false;
7214  }
7215 
7216  if (intl_identifier_casecmp (lhs_name, rhs_name) == 0)
7217  {
7218  return true;
7219  }
7220 
7221  return false;
7222 }
7223 
7224 /*
7225  * free_natural_join_attrs () -
7226  * return:
7227  * attrs(in):
7228  */
7229 static void
7231 {
7232  NATURAL_JOIN_ATTR_INFO *attr_cur;
7233  NATURAL_JOIN_ATTR_INFO *attr_cur_next;
7234 
7235  attr_cur = attrs;
7236  while (attr_cur != NULL)
7237  {
7238  attr_cur_next = attr_cur->next;
7239  free (attr_cur);
7240  attr_cur = attr_cur_next;
7241  }
7242 }
7243 
7244 /*
7245  * generate_natural_join_attrs_from_subquery () -
7246  * return:
7247  * subquery_attrs_list(in):
7248  * attrs_p(out):
7249  */
7250 static int
7252 {
7253  PT_NODE *pt_cur;
7254  NATURAL_JOIN_ATTR_INFO *attr_head = NULL;
7255  NATURAL_JOIN_ATTR_INFO *attr_tail = NULL;
7256  NATURAL_JOIN_ATTR_INFO *attr_cur;
7257 
7258  for (pt_cur = subquery_attrs_list; pt_cur != NULL; pt_cur = pt_cur->next)
7259  {
7260  /*
7261  * We just deal the attributes which have name. It means we just
7262  * deal PT_NAME or other's pt_node have alias_name. For example,
7263  * select 1 from t1. The '1' is impossible to be used in natural
7264  * join, so we skip it.
7265  */
7266 
7267  if (pt_cur->alias_print == NULL && pt_cur->node_type != PT_NAME)
7268  {
7269  continue;
7270  }
7271 
7272  attr_cur = (NATURAL_JOIN_ATTR_INFO *) malloc (sizeof (NATURAL_JOIN_ATTR_INFO));
7273  if (attr_cur == NULL)
7274  {
7275  goto exit_on_error;
7276  }
7277 
7278  attr_cur->next = NULL;
7279 
7280  /*
7281  * Alias name have higher priority. select a as txx from ....
7282  * We consider txx as the attribute's name and ignore a.
7283  */
7284  if (pt_cur->alias_print)
7285  {
7286  attr_cur->name = (char *) pt_cur->alias_print;
7287  }
7288  else
7289  {
7290  if (pt_cur->node_type == PT_NAME)
7291  {
7292  attr_cur->name = (char *) pt_cur->info.name.original;
7293  }
7294  }
7295 
7296  attr_cur->type_enum = pt_cur->type_enum;
7297 
7298  attr_cur->meta_class = PT_NORMAL;
7299  if (pt_cur->node_type == PT_NAME)
7300  {
7301  attr_cur->meta_class = pt_cur->info.name.meta_class;
7302  }
7303 
7304  if (attr_head == NULL)
7305  {
7306  attr_head = attr_cur;
7307  attr_tail = attr_cur;
7308  }
7309  else
7310  {
7311  attr_tail->next = attr_cur;
7312  attr_tail = attr_cur;
7313  }
7314  }
7315 
7316  *attrs_p = attr_head;
7317  return NO_ERROR;
7318 
7319 exit_on_error:
7320  free_natural_join_attrs (attr_head);
7321  return ER_OUT_OF_VIRTUAL_MEMORY;
7322 }
7323 
7324 
7325 /*
7326  * generate_natural_join_attrs_from_db_attrs () -
7327  * return:
7328  * db_attrs(in):
7329  * attrs_p(out):
7330  */
7331 static int
7333 {
7334  DB_ATTRIBUTE *db_attr_cur;
7335  NATURAL_JOIN_ATTR_INFO *attr_head = NULL;
7336  NATURAL_JOIN_ATTR_INFO *attr_tail = NULL;
7337  NATURAL_JOIN_ATTR_INFO *attr_cur;
7338 
7339  for (db_attr_cur = db_attrs; db_attr_cur != NULL; db_attr_cur = db_attribute_next (db_attr_cur))
7340  {
7341  attr_cur = (NATURAL_JOIN_ATTR_INFO *) malloc (sizeof (NATURAL_JOIN_ATTR_INFO));
7342  if (attr_cur == NULL)
7343  {
7344  goto exit_on_error;
7345  }
7346 
7347  attr_cur->next = NULL;
7348  attr_cur->name = (char *) db_attribute_name (db_attr_cur);
7349  attr_cur->type_enum = pt_db_to_type_enum (db_attribute_type (db_attr_cur));
7350  attr_cur->meta_class = (db_attribute_is_shared (db_attr_cur) ? PT_SHARED : PT_NORMAL);
7351 
7352  if (attr_head == NULL)
7353  {
7354  attr_head = attr_cur;
7355  attr_tail = attr_cur;
7356  }
7357  else
7358  {
7359  attr_tail->next = attr_cur;
7360  attr_tail = attr_cur;
7361  }
7362  }
7363 
7364  *attrs_p = attr_head;
7365  return NO_ERROR;
7366 
7367 exit_on_error:
7368  free_natural_join_attrs (attr_head);
7369  return ER_OUT_OF_VIRTUAL_MEMORY;
7370 }
7371 
7372 /*
7373  * get_natural_join_attrs_from_pt_spec () - Get all attributes from a pt_spec
7374  * node that indicates an table or a subquery.
7375  * return:
7376  * parser(in):
7377  * node(in):
7378  */
7379 static NATURAL_JOIN_ATTR_INFO *
7381 {
7382  DB_OBJECT *cls;
7383  DB_ATTRIBUTE *db_attrs;
7384  NATURAL_JOIN_ATTR_INFO *natural_join_attrs;
7385  PT_NODE *derived_table;
7386  PT_NODE *subquery_attrs_list;
7387 
7388  assert (node != NULL && node->node_type == PT_SPEC);
7389 
7390  cls = NULL;
7391  db_attrs = NULL;
7392  natural_join_attrs = NULL;
7393 
7394  if (PT_SPEC_IS_ENTITY (node))
7395  {
7396  /* This is a table. */
7397  cls = node->info.spec.entity_name->info.name.db_object;
7398  if (cls == NULL)
7399  {
7400  return NULL;
7401  }
7402 
7403  db_attrs = db_get_attributes (cls);
7404  if (db_attrs == NULL)
7405  {
7406  return NULL;
7407  }
7408 
7409  if (generate_natural_join_attrs_from_db_attrs (db_attrs, &natural_join_attrs) != NO_ERROR)
7410  {
7412  goto exit_on_error;
7413  }
7414  }
7415  else if (PT_SPEC_IS_DERIVED (node) || PT_SPEC_IS_CTE (node))
7416  {
7417  /* This is a subquery or a CTE. */
7419  {
7420  derived_table = node->info.spec.derived_table;
7421 
7422  if (node->info.spec.as_attr_list != NULL)
7423  {
7424  subquery_attrs_list = node->info.spec.as_attr_list;
7425  }
7426  else if (derived_table->node_type == PT_SELECT)
7427  {
7428  subquery_attrs_list = derived_table->info.query.q.select.list;
7429  }
7430  else
7431  {
7432  subquery_attrs_list = NULL;
7433  }
7434  }
7435  else
7436  {
7437  subquery_attrs_list = node->info.spec.as_attr_list;
7438  }
7439 
7440  if (subquery_attrs_list == NULL)
7441  {
7442  return NULL;
7443  }
7444 
7445  if (generate_natural_join_attrs_from_subquery (subquery_attrs_list, &natural_join_attrs) != NO_ERROR)
7446  {
7448  goto exit_on_error;
7449  }
7450 
7451  }
7452  else
7453  {
7454  assert (false);
7455  }
7456 
7457  return natural_join_attrs;
7458 
7459 exit_on_error:
7460  return NULL;
7461 }
7462 
7463 /*
7464  * pt_create_pt_expr_equal_node () - The function creates the PT_expr
7465  * for natural join. The operator is " = ".
7466  * return:
7467  * parser(in):
7468  * arg1(in):
7469  * arg2(in):
7470  */
7471 static PT_NODE *
7473 {
7474  PT_NODE *expr = NULL;
7475 
7476  expr = parser_new_node (parser, PT_EXPR);
7477  if (expr == NULL)
7478  {
7479  return NULL;
7480  }
7481 
7482  expr->type_enum = PT_TYPE_LOGICAL;
7483  expr->info.expr.op = PT_EQ;
7484  expr->info.expr.arg1 = arg1;
7485  expr->info.expr.arg2 = arg2;
7486 
7487  return expr;
7488 }
7489 
7490 /*
7491  * pt_create_pt_name () - The function creates the PT_NAME name for natural
7492  * join. The pt_name node indicates an attribute in a table/subquery.
7493  * The spec indicates the table/subquery.
7494  * return:
7495  * parser(in):
7496  * spec(in):
7497  * attr(in):
7498  */
7499 static PT_NODE *
7501 {
7502  PT_NODE *name;
7503 
7504  assert (attr != NULL);
7505  assert (spec != NULL);
7506 
7507  name = parser_new_node (parser, PT_NAME);
7508  if (name == NULL)
7509  {
7510  return NULL;
7511  }
7512 
7513  name->info.name.original = pt_append_string (parser, NULL, attr->name);
7514  name->type_enum = attr->type_enum;
7515  name->info.name.meta_class = attr->meta_class;
7516  if (PT_SPEC_IS_ENTITY (spec))
7517  {
7519  }
7520  else if (PT_SPEC_IS_CTE (spec))
7521  {
7522  PT_NODE *cte = spec->info.spec.cte_pointer->info.pointer.node;
7523  name->info.name.resolved = pt_append_string (parser, NULL, cte->info.cte.name->info.name.original);
7524  }
7525  else
7526  {
7527  assert (PT_SPEC_IS_DERIVED (spec));
7528  }
7529 
7530  if (PT_IS_SPEC_REAL_TABLE (spec))
7531  {
7533  }
7534 
7535  name->info.name.spec_id = spec->info.spec.id;
7536 
7537  return name;
7538 
7539 }
7540 
7541 /*
7542  * pt_create_pt_expr_and_node () - The function create the PT_expr for natural
7543  * join. The operator is AND.
7544  * return:
7545  * parser(in):
7546  * arg1(in):
7547  * arg2(in):
7548  */
7549 static PT_NODE *
7551 {
7552  PT_NODE *expr = NULL;
7553 
7554  expr = parser_new_node (parser, PT_EXPR);
7555  if (expr == NULL)
7556  {
7557  return NULL;
7558  }
7559 
7560  expr->type_enum = PT_TYPE_LOGICAL;
7561  expr->info.expr.op = PT_AND;
7562  expr->info.expr.arg1 = arg1;
7563  expr->info.expr.arg2 = arg2;
7564 
7565  return expr;
7566 }
7567 
7568 /*
7569  * pt_resolve_natural_join_internal () - Resolve natural join into inner/outer join actually.
7570  * For t1 natural join t2, join_lhs is t1 and join_rhs is t2. The function adds on_cond
7571  * into t2. After the process, the join will become an inner/outer join.
7572  * return:
7573  * parser(in):
7574  * join_lhs(in):
7575  * join_rhs(in/out):
7576  */
7577 static void
7579 {
7580  NATURAL_JOIN_ATTR_INFO *lhs_attrs;
7581  NATURAL_JOIN_ATTR_INFO *rhs_attrs;
7582  NATURAL_JOIN_ATTR_INFO *lhs_attrs_cur, *rhs_attrs_cur;
7583  PT_NODE *on_cond_tail;
7584  PT_NODE *join_cond_expr;
7585  PT_NODE *join_cond_arg1;
7586  PT_NODE *join_cond_arg2;
7587  PT_NODE *on_cond_new;
7588 
7589  assert (join_lhs != NULL);
7590  assert (join_rhs != NULL);
7591 
7592  on_cond_tail = join_rhs->info.spec.on_cond;
7593 
7594  lhs_attrs = get_natural_join_attrs_from_pt_spec (parser, join_lhs);
7595  rhs_attrs = get_natural_join_attrs_from_pt_spec (parser, join_rhs);
7596 
7597  for (lhs_attrs_cur = lhs_attrs; lhs_attrs_cur != NULL; lhs_attrs_cur = lhs_attrs_cur->next)
7598  {
7599  for (rhs_attrs_cur = rhs_attrs; rhs_attrs_cur; rhs_attrs_cur = rhs_attrs_cur->next)
7600  {
7601  if (!natural_join_equal_attr (lhs_attrs_cur, rhs_attrs_cur))
7602  {
7603  continue;
7604  }
7605 
7606  /* step 1: we create pt_name for the first attribute */
7607  join_cond_arg1 = pt_create_pt_name (parser, join_lhs, lhs_attrs_cur);
7608  if (join_cond_arg1 == NULL)
7609  {
7611  goto exit_on_create_node_error;
7612  }
7613 
7614  /* step 2: we create pt_name for the second attribute */
7615  join_cond_arg2 = pt_create_pt_name (parser, join_rhs, rhs_attrs_cur);
7616  if (join_cond_arg2 == NULL)
7617  {
7619  goto exit_on_create_node_error;
7620  }
7621 
7622  /* step 3: we create the equal pt_expr node. like "join_cond_arg1 = join_cond_arg2" */
7623  join_cond_expr = pt_create_pt_expr_equal_node (parser, join_cond_arg1, join_cond_arg2);
7624  if (join_cond_expr == NULL)
7625  {
7627  goto exit_on_create_node_error;
7628  }
7629 
7630  /*
7631  * step4: If there is no on_cond, the new expr we created will be on_cond.
7632  * If not, it means there is old on_conds. So we will create a new expr
7633  * like "(old on_cond) and (new on_cond)".
7634  */
7635  if (on_cond_tail == NULL)
7636  {
7637  on_cond_tail = join_cond_expr;
7638  }
7639  else
7640  {
7641  on_cond_new = pt_create_pt_expr_and_node (parser, on_cond_tail, join_cond_expr);
7642  if (on_cond_new == NULL)
7643  {
7645  goto exit_on_create_node_error;
7646  }
7647 
7648  on_cond_tail = on_cond_new;
7649  }
7650  }
7651  }
7652 
7653  join_rhs->info.spec.on_cond = on_cond_tail;
7654 
7655  if (lhs_attrs != NULL)
7656  {
7657  free_natural_join_attrs (lhs_attrs);
7658  }
7659 
7660  if (rhs_attrs != NULL)
7661  {
7662  free_natural_join_attrs (rhs_attrs);
7663  }
7664 
7665  return;
7666 
7667 exit_on_create_node_error:
7668  if (lhs_attrs != NULL)
7669  {
7670  free_natural_join_attrs (lhs_attrs);
7671  }
7672 
7673  if (rhs_attrs != NULL)
7674  {
7675  free_natural_join_attrs (rhs_attrs);
7676  }
7677 
7678  return;
7679 }
7680 
7681 /*
7682  * pt_resolve_natural_join () - Resolve natural join into inner/outer join.
7683  * return:
7684  * parser(in):
7685  * node(in/out):
7686  * chk_parent(in):
7687  * continue_walk(in/out):
7688  */
7689 static PT_NODE *
7690 pt_resolve_natural_join (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk)
7691 {
7692  PT_NODE *join_lhs, *join_rhs;
7693 
7694  *continue_walk = PT_CONTINUE_WALK;
7695 
7696  if (node == NULL || node->node_type != PT_SPEC)
7697  {
7698  return node;
7699  }
7700 
7701  join_lhs = node;
7702  join_rhs = node->next;
7703 
7704  /* there is a natural join */
7705  if (join_rhs != NULL && join_rhs->node_type == PT_SPEC && join_rhs->info.spec.natural == true)
7706  {
7707  pt_resolve_natural_join_internal (parser, join_lhs, join_rhs);
7708  }
7709 
7710  return node;
7711 }
7712 
7713 /*
7714  * is_pt_name_in_group_having () -
7715  * return:
7716  * node(in):
7717  */
7718 static bool
7720 {
7721  if (node == NULL || node->node_type != PT_NAME || node->etc == NULL)
7722  {
7723  return false;
7724  }
7725 
7726  if (intl_identifier_casecmp ((char *) node->etc, CPTR_PT_NAME_IN_GROUP_HAVING) == 0)
7727  {
7728  return true;
7729  }
7730 
7731  return false;
7732 }
7733 
7734 /*
7735  * pt_mark_pt_name () -
7736  * return:
7737  * parser(in):
7738  * node(in/out):
7739  * chk_parent(in):
7740  * continue_walk(in/out):
7741  */
7742 static PT_NODE *
7743 pt_mark_pt_name (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk)
7744 {
7745  *continue_walk = PT_CONTINUE_WALK;
7746 
7747  if (node == NULL || node->node_type != PT_NAME)
7748  {
7749  return node;
7750  }
7751  node->etc = (void *) pt_append_string (parser, NULL, CPTR_PT_NAME_IN_GROUP_HAVING);
7752 
7753  return node;
7754 }
7755 
7756 /*
7757  * pt_mark_group_having_pt_name () - Mark the PT_NAME in group by / having.
7758  * return:
7759  * parser(in):
7760  * node(in/out):
7761  * chk_parent(in):
7762  * continue_walk(in/out):
7763  */
7764 static PT_NODE *
7765 pt_mark_group_having_pt_name (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk)
7766 {
7767  *continue_walk = PT_CONTINUE_WALK;
7768 
7769  if (node == NULL || node->node_type != PT_SELECT)
7770  {
7771  return node;
7772  }
7773 
7774  if (node->info.query.q.select.group_by != NULL)
7775  {
7776  node->info.query.q.select.group_by =
7778  }
7779 
7780  if (node->info.query.q.select.having != NULL)
7781  {
7782  node->info.query.q.select.having =
7784  }
7785 
7787  {
7788  if (node->info.query.order_by != NULL)
7789  {
7790  node->info.query.order_by =
7792  }
7793  }
7794 
7795  return node;
7796 }
7797 
7798 /*
7799  * pt_resolve_group_having_alias_pt_sort_spec () -
7800  * return:
7801  * parser(in):
7802  * node(in/out):
7803  * select_list(in):
7804  */
7805 static void
7807 {
7808  if (node != NULL && node->node_type == PT_SORT_SPEC)
7809  {
7810  pt_resolve_group_having_alias_internal (parser, &(node->info.sort_spec.expr), select_list);
7811  }
7812 }
7813 
7814 /*
7815  * pt_resolve_group_having_alias_pt_name () -
7816  * return:
7817  * parser(in):
7818  * node_p(in/out):
7819  * select_list(in):
7820  */
7821 static void
7823 {
7824  PT_NODE *col;
7825  char *n_str;
7826  PT_NODE *node;
7827 
7828  assert (node_p != NULL);
7829 
7830  node = *node_p;
7831 
7832  if (node == NULL || node->node_type != PT_NAME)
7833  {
7834  return;
7835  }
7836 
7837  /* It have been resolved. */
7838  if (node->info.name.resolved != NULL)
7839  {
7840  return;
7841  }
7842 
7843  n_str = (char *) node->info.name.original;
7844 
7845  for (col = select_list; col != NULL; col = col->next)
7846  {
7847  if (col->alias_print != NULL && intl_identifier_casecmp (n_str, col->alias_print) == 0)
7848  {
7849  parser_free_node (parser, *node_p);
7850  *node_p = parser_copy_tree (parser, col);
7851  if ((*node_p) != NULL)
7852  {
7853  (*node_p)->next = NULL;
7854  }
7855  break;
7856  }
7857  }
7858 
7859  /* We can not resolve the pt_name. */
7860  if (col == NULL)
7861  {
7863  pt_short_print (parser, (*node_p)));
7864  }
7865 }
7866 
7867 /*
7868  * pt_resolve_group_having_alias_pt_expr () -
7869  * return:
7870  * parser(in):
7871  * node(in/out):
7872  * select_list(in):
7873  */
7874 static void
7876 {
7877  if (node == NULL || node->node_type != PT_EXPR)
7878  {
7879  return;
7880  }
7881 
7882  /* Resolve arg1 */
7883  if (node->info.expr.arg1 != NULL && node->info.expr.arg1->node_type == PT_NAME)
7884  {
7885  pt_resolve_group_having_alias_pt_name (parser, &node->info.expr.arg1, select_list);
7886  }
7887  else if (node->info.expr.arg1 != NULL && node->info.expr.arg1->node_type == PT_EXPR)
7888  {
7889  pt_resolve_group_having_alias_pt_expr (parser, node->info.expr.arg1, select_list);
7890  }
7891  else
7892  {
7893 
7894  }
7895 
7896  /* Resolve arg2 */
7897  if (node->info.expr.arg2 != NULL && node->info.expr.arg2->node_type == PT_NAME)
7898  {
7899  pt_resolve_group_having_alias_pt_name (parser, &node->info.expr.arg2, select_list);
7900  }
7901  else if (node->info.expr.arg2 != NULL && node->info.expr.arg2->node_type == PT_EXPR)
7902  {
7903  pt_resolve_group_having_alias_pt_expr (parser, node->info.expr.arg2, select_list);
7904  }
7905  else
7906  {
7907 
7908  }
7909 
7910  /* Resolve arg3 */
7911  if (node->info.expr.arg3 != NULL && node->info.expr.arg3->node_type == PT_NAME)
7912  {
7913  pt_resolve_group_having_alias_pt_name (parser, &node->info.expr.arg3, select_list);
7914  }
7915  else if (node->info.expr.arg3 != NULL && node->info.expr.arg3->node_type == PT_EXPR)
7916  {
7917  pt_resolve_group_having_alias_pt_expr (parser, node->info.expr.arg3, select_list);
7918  }
7919  else
7920  {
7921 
7922  }
7923 }
7924 
7925 /*
7926  * pt_resolve_group_having_alias_internal () - Rosolve alias name in groupby and having clause.
7927  * return:
7928  * parser(in):
7929  * node_p(in/out):
7930  * select_list(in):
7931  */
7932 static void
7934 {
7935  assert (node_p != NULL);
7936  assert ((*node_p) != NULL);
7937 
7938  switch ((*node_p)->node_type)
7939  {
7940  case PT_NAME:
7941  pt_resolve_group_having_alias_pt_name (parser, node_p, select_list);
7942  break;
7943  case PT_EXPR:
7944  pt_resolve_group_having_alias_pt_expr (parser, *node_p, select_list);
7945  break;
7946  case PT_SORT_SPEC:
7947  pt_resolve_group_having_alias_pt_sort_spec (parser, *node_p, select_list);
7948  break;
7949  default:
7950  return;
7951  }
7952  return;
7953 }
7954 
7955 /*
7956  * pt_resolve_group_having_alias () - Resolve alias name in groupby and having clause. We
7957  * resolve groupby/having alias after bind_name, it means when the alias name is same
7958  * with table attribute, we choose table attribute firstly.
7959  * return:
7960  * parser(in):
7961  * node(in/out):
7962  * chk_parent(in):
7963  * continue_walk(in/out):
7964  */
7965 static PT_NODE *
7966 pt_resolve_group_having_alias (PARSER_CONTEXT * parser, PT_NODE * node, void *chk_parent, int *continue_walk)
7967 {
7968  PT_NODE *pt_cur;
7969 
7970  *continue_walk = PT_CONTINUE_WALK;
7971 
7972  if (node == NULL || node->node_type != PT_SELECT)
7973  {
7974  return node;
7975  }
7976 
7977  /* support for alias in GROUP BY */
7978  pt_cur = node->info.query.q.select.group_by;
7979  while (pt_cur != NULL)
7980  {
7981  pt_resolve_group_having_alias_internal (parser, &pt_cur, node->info.query.q.select.list);
7982  pt_cur = pt_cur->next;
7983  }
7984 
7985  /* support for alias in HAVING */
7986  pt_cur = node->info.query.q.select.having;
7987  while (pt_cur != NULL)
7988  {
7989  pt_resolve_group_having_alias_internal (parser, &pt_cur, node->info.query.q.select.list);
7990  pt_cur = pt_cur->next;
7991  }
7992 
7993  /* support for alias in ORDER BY */
7995  {
7996  pt_cur = node->info.query.order_by;
7997  while (pt_cur != NULL)
7998  {
7999  pt_resolve_group_having_alias_internal (parser, &pt_cur, node->info.query.q.select.list);
8000  pt_cur = pt_cur->next;
8001  }
8002  }
8003  return node;
8004 }
8005 
8006 /*
8007  * pt_resolve_names () -
8008  * return:
8009  * parser(in):
8010  * statement(in):
8011  * sc_info(in):
8012  */
8013 PT_NODE *
8015 {
8016  PT_BIND_NAMES_ARG bind_arg;
8017  PT_FLAT_SPEC_INFO info;
8018 
8019  bind_arg.scopes = NULL;
8020  bind_arg.spec_frames = NULL;
8021  bind_arg.sc_info = sc_info;
8022 
8023  assert (sc_info != NULL);
8024 
8025  if (statement != NULL && statement->node_type == PT_MERGE && statement->info.merge.into != NULL)
8026  {
8027  /* chain merge specs for flat name resolving */
8028  statement->info.merge.into->next = statement->info.merge.using_clause;
8029  statement->info.merge.using_clause = NULL;
8030  }
8031 
8032  /* Replace each Entity Spec with an Equivalent flat list */
8033  info.spec_parent = NULL;
8034  info.for_update = false;
8035  statement = parser_walk_tree (parser, statement, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
8036 
8037  if (statement != NULL && statement->node_type == PT_MERGE && statement->info.merge.into != NULL)
8038  {
8039  /* unchain merge specs */
8040  statement->info.merge.using_clause = statement->info.merge.into->next;
8041  statement->info.merge.into->next = NULL;
8042  }
8043 
8044  /* resolve names in search conditions, assignments, and assignations */
8045  if (!pt_has_error (parser))
8046  {
8047  PT_NODE *idx_name = NULL;
8048  if (statement->node_type == PT_CREATE_INDEX || statement->node_type == PT_ALTER_INDEX
8049  || statement->node_type == PT_DROP_INDEX)
8050  {
8051  /* backup the name of the index because it is not part of the table spec yet */
8052  idx_name = statement->info.index.index_name;
8053  statement->info.index.index_name = NULL;
8054  }
8055 
8056  /* Before pt_bind_name, we mark PT_NAME in group by/ having. */
8057  statement = parser_walk_tree (parser, statement, pt_mark_group_having_pt_name, NULL, NULL, NULL);
8058  if (pt_has_error (parser))
8059  {
8060  return NULL;
8061  }
8062 
8063  statement = parser_walk_tree (parser, statement, pt_bind_names, &bind_arg, pt_bind_names_post, &bind_arg);
8064  if (pt_has_error (parser))
8065  {
8066  return NULL;
8067  }
8068 
8069  if (statement
8070  && (statement->node_type == PT_CREATE_INDEX || statement->node_type == PT_ALTER_INDEX
8071  || statement->node_type == PT_DROP_INDEX))
8072  {
8073  statement->info.index.index_name = idx_name;
8074  }
8075 
8076  /* Resolve alias in group by/having. */
8077  statement = parser_walk_tree (parser, statement, pt_resolve_group_having_alias, NULL, NULL, NULL);
8078  if (pt_has_error (parser))
8079  {
8080  return NULL;
8081  }
8082 
8083  /*
8084  * The process converts natural join to inner/outer join.
8085  * The on_cond is added there.
8086  */
8087  statement = parser_walk_tree (parser, statement, NULL, NULL, pt_resolve_natural_join, NULL);
8088  if (pt_has_error (parser))
8089  {
8090  return NULL;
8091  }
8092  }
8093 
8094  /* Flag specs from FOR UPDATE clause with PT_SPEC_FLAG_FOR_UPDATE_CLAUSE and clear the for_update list. From now on
8095  * the specs from FOR UPDATE clause can be determined using this flag together with PT_SELECT_INFO_FOR_UPDATE flag */
8096  if (statement != NULL && statement->node_type == PT_SELECT
8098  {
8099  PT_NODE *node = statement->info.query.q.select.for_update;
8100  PT_NODE *spec = NULL;
8101 
8102  if (statement->info.query.q.select.for_update != NULL)
8103  {
8104  /* Flag only the specified specs */
8105  for (; node != NULL; node = node->next)
8106  {
8107  spec = pt_find_spec (parser, statement->info.query.q.select.from, node);
8108  if (spec == NULL)
8109  {
8111  node->info.name.original);
8112  return NULL;
8113  }
8115  }
8116  parser_free_tree (parser, statement->info.query.q.select.for_update);
8117  statement->info.query.q.select.for_update = NULL;
8118  }
8119  else
8120  {
8121  /* Flag all specs */
8122  for (spec = statement->info.query.q.select.from; spec != NULL; spec = spec->next)
8123  {
8125  }
8126  }
8127  }
8128 
8129  return statement;
8130 }
8131 
8132 /* pt_resolve_spec_to_cte - search for matches of node spec in each CTE from cte_defs list
8133  *
8134  * return:
8135  * parser(in):
8136  * node(in/out):
8137  * arg(in): cte_defs ( only the CTEs that can be referenced )
8138  * continue_walk(in/out):
8139  */
8140 static PT_NODE *
8141 pt_resolve_spec_to_cte (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
8142 {
8143  PT_NODE *cte_defs = (PT_NODE *) arg;
8144  PT_NODE *cte = NULL;
8145 
8146  if (node == NULL)
8147  {
8148  assert (false);
8149  return NULL;
8150  }
8151 
8152  if (node->node_type != PT_SPEC || !PT_SPEC_IS_ENTITY (node))
8153  {
8154  /* not interested in non-entity-specs */
8155  return node;
8156  }
8157 
8158  for (cte = cte_defs; cte != NULL; cte = cte->next)
8159  {
8160  PT_NODE *cte_name = cte->info.cte.name;
8161  assert (cte_name != NULL);
8162 
8163  if (pt_name_equal (parser, cte_name, node->info.spec.entity_name))
8164  {
8165  node->info.spec.cte_name = node->info.spec.entity_name;
8166  node->info.spec.entity_name = NULL;
8167  node->info.spec.cte_pointer = pt_point (parser, cte);
8168  node->info.spec.cte_pointer->info.pointer.do_walk = false;
8169  break;
8170  }
8171  }
8172 
8173  return node;
8174 }
8175 
8176 /* pt_resolve_spec_to_cte_and_count - search for matches of spec in each CTE from cte_defs list
8177  * and sets node->etc as counter if found
8178  *
8179  * return:
8180  * parser(in):
8181  * node(in/out):
8182  * arg(in): cte_defs ( only the CTEs that can be referenced )
8183  * continue_walk(in/out):
8184  *
8185  * Note: Must be paired with pt_count_ctes_post to ensure node->etc cleanup
8186  */
8187 static PT_NODE *
8188 pt_resolve_spec_to_cte_and_count (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
8189 {
8190  if (node == NULL)
8191  {
8192  assert (false);
8193  return NULL;
8194  }
8195 
8196  /* we are interested only in entity-specs that are transformed into cte-specs after pt_resolve_spec_to_cte */
8197  if (node->node_type != PT_SPEC || !PT_SPEC_IS_ENTITY (node))
8198  {
8199  return node;
8200  }
8201 
8202  node = pt_resolve_spec_to_cte (parser, node, arg, continue_walk);
8203  if (node == NULL || !PT_SPEC_IS_CTE (node))
8204  {
8205  /* spec was not found | error occured */
8206  return node;
8207  }
8208 
8209  /* spec was transformed into a CTE pointer spec */
8210  assert (node->node_type == PT_SPEC && PT_SPEC_IS_CTE (node));
8211 
8212  /* set node->etc to the number of occurences (one) */
8213  node->etc = malloc (sizeof (char));
8214  *((char *) node->etc) = 1;
8215 
8216  return node;
8217 }
8218 
8219 /* pt_count_ctes_post () - increase counter with current node cte occurrences
8220 * return:
8221 * parser(in):
8222 * node(in): the node to check, leave node unchanged except of node->etc
8223 * arg(out): count of CTEs
8224 * continue_walk(in):
8225 */
8226 static PT_NODE *
8227 pt_count_ctes_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
8228 {
8229  int *cnt = (int *) arg;
8230 
8231  /* check if node is a CTE SPEC with node->etc set */
8232  if (node != NULL && node->node_type == PT_SPEC && PT_SPEC_IS_CTE (node) && pt_node_etc (node) != NULL)
8233  {
8234  /* increment cnt argument and free etc */
8235  assert (*((char *) pt_node_etc (node)) == 1);
8236  (*cnt)++;
8237 
8238  /* cte_matches counter is no longer needed; pt_resolve_spec_to_cte expects to clean it here */
8239  free (pt_node_etc (node));
8240  pt_null_etc (node);
8241  }
8242 
8243  return node;
8244 }
8245 
8246 /* pt_resolve_cte_specs () - resolves all CTEs involved in a query
8247 * return:
8248 * parser(in):
8249 * node(in):
8250 * arg(out):
8251 * continue_walk(in):
8252 */
8253 PT_NODE *
8254 pt_resolve_cte_specs (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
8255 {
8256  PT_NODE *cte_list, *with = NULL, *saved_with = NULL;
8257  PT_NODE **with_p;
8258  PT_NODE *curr_cte, *previous_cte;
8259  PT_NODE *saved_curr_cte_next;
8260  int nested_with_count = 0;
8261 
8262  assert (parser != NULL);
8263  assert (node != NULL);
8264 
8265  switch (node->node_type)
8266  {
8267  case PT_SELECT:
8268  case PT_UNION:
8269  case PT_DIFFERENCE:
8270  case PT_INTERSECTION:
8271  with = node->info.query.with;
8272  with_p = &node->info.query.with;
8273  break;
8274  case PT_UPDATE:
8275  with = node->info.update.with;
8276  with_p = &node->info.update.with;
8277  break;
8278  case PT_DELETE:
8279  with = node->info.delete_.with;
8280  with_p = &node->info.delete_.with;
8281  break;
8282 
8283  default:
8284  return node;
8285  }
8286 
8287  if (with == NULL)
8288  {
8289  /* nothing to resolve to */
8290  return node;
8291  }
8292 
8293  cte_list = with->info.with_clause.cte_definition_list;
8294  if (cte_list == NULL)
8295  {
8296  PT_INTERNAL_ERROR (parser, "expecting cte definitions");
8297  return NULL;
8298  }
8299 
8300  /* check ambiguity in the names of CTEs */
8301  for (previous_cte = cte_list; previous_cte != NULL; previous_cte = previous_cte->next)
8302  {
8303  for (curr_cte = previous_cte->next; curr_cte != NULL; curr_cte = curr_cte->next)
8304  {
8305  if (pt_name_equal (parser, previous_cte->info.cte.name, curr_cte->info.cte.name))
8306  {
8307  /* ambiguity, two CTEs with the same name */
8309  curr_cte->info.cte.name->info.name.original);
8310  return NULL;
8311  }
8312  }
8313  }
8314 
8315  /* check if there are nested WITHs */
8316  cte_list = parser_walk_tree (parser, cte_list, pt_count_with_clauses, &nested_with_count, NULL, NULL);
8317  if (nested_with_count > 0)
8318  {
8320  return NULL;
8321  }
8322 
8323  /* STEP 1: Check if CTE is recursive - find if CTE definition contains self references and resolve them */
8324  for (curr_cte = cte_list; curr_cte != NULL; curr_cte = curr_cte->next)
8325  {
8326  if ((curr_cte->info.cte.non_recursive_part->node_type == PT_UNION) && (!curr_cte->info.cte.recursive_part))
8327  {
8328  PT_NODE *recursive_part = curr_cte->info.cte.non_recursive_part->info.query.q.union_.arg2;
8329  PT_NODE *non_recursive_part = curr_cte->info.cte.non_recursive_part->info.query.q.union_.arg1;
8330  PT_MISC_TYPE all_distinct = curr_cte->info.cte.non_recursive_part->info.query.all_distinct;
8331  PT_NODE *from;
8332  int curr_cte_count = 0;
8333 
8334  if (recursive_part->node_type != PT_SELECT)
8335  {
8336  /* SELECT only */
8337  continue;
8338  }
8339 
8340  /* isolate curr_cte to prevent resolving next CTEs in current recursive part */
8341  saved_curr_cte_next = curr_cte->next;
8342  curr_cte->next = NULL;
8343 
8344  /* look for self references in recursive query FROM */
8345  for (from = recursive_part->info.query.q.select.from; from != NULL; from = from->next)
8346  {
8347  if (from->node_type == PT_SPEC && PT_SPEC_IS_ENTITY (from))
8348  {
8349  (void) pt_resolve_spec_to_cte (parser, from, curr_cte, NULL);
8350  if (PT_SPEC_IS_CTE (from))
8351  {
8352  curr_cte_count++;
8353  }
8354  }
8355  }
8356 
8357  if (curr_cte_count == 0 && non_recursive_part->node_type == PT_SELECT)
8358  {
8359  /* no self references were found in arg2 from union; search in arg1 also, syntax allows this case */
8360  for (from = non_recursive_part->info.query.q.select.from; from != NULL; from = from->next)
8361  {
8362  if (from->node_type == PT_SPEC && PT_SPEC_IS_ENTITY (from))
8363  {
8364  (void) pt_resolve_spec_to_cte (parser, from, curr_cte, NULL);
8365  if (PT_SPEC_IS_CTE (from))
8366  {
8367  curr_cte_count++;
8368  }
8369  }
8370  }
8371 
8372  if (curr_cte_count > 0)
8373  {
8374  /* curr_cte is recursive but it was found in non-recursive part; swap non-recursive, recursive */
8375  PT_NODE *tmp = non_recursive_part;
8376  non_recursive_part = recursive_part;
8377  recursive_part = tmp;
8378  }
8379  }
8380 
8381  if (curr_cte_count > 0)
8382  {
8383  curr_cte->info.cte.non_recursive_part = non_recursive_part;
8384  curr_cte->info.cte.recursive_part = recursive_part;
8385  curr_cte->info.cte.only_all = all_distinct;
8386  if (curr_cte->info.cte.only_all != PT_ALL)
8387  {
8389  curr_cte->info.cte.name->info.name.original);
8390  return NULL;
8391  }
8392  }
8393 
8394  /* check if there are any unresolved self references of the cte, it would be incorrect */
8395  curr_cte_count = 0;
8396  curr_cte = parser_walk_tree (parser, curr_cte, pt_resolve_spec_to_cte_and_count, curr_cte,
8397  pt_count_ctes_post, &curr_cte_count);
8398  if (curr_cte == NULL)
8399  {
8400  /* error in walk */
8401  return NULL;
8402  }
8403  if (curr_cte_count > 0)
8404  {
8406  curr_cte->info.cte.name->info.name.original);
8407  return NULL;
8408  }
8409 
8410  /* restore next link */
8411  curr_cte->next = saved_curr_cte_next;
8412  }
8413 
8415  if (curr_cte->info.cte.recursive_part)
8416  {
8417  assert (curr_cte->info.cte.recursive_part->node_type == PT_SELECT);
8419  }
8420  }
8421 
8422  /* STEP 2: Resolve CTEs references within CTEs */
8423  for (previous_cte = cte_list, curr_cte = previous_cte->next; curr_cte != NULL;
8424  previous_cte = previous_cte->next, curr_cte = curr_cte->next)
8425  {
8426  /* disconect curr_cte from the list of CTEs that can be referenced in curr_cte */
8427  previous_cte->next = NULL;
8428 
8429  /* avoid following next links in parser_walk_tree */
8430  saved_curr_cte_next = curr_cte->next;
8431  curr_cte->next = NULL;
8432 
8433  /* cte_list keeps only the CTEs that precede curr_cte; resolve their references in curr_cte */
8434  curr_cte = parser_walk_tree (parser, curr_cte, pt_resolve_spec_to_cte, cte_list, NULL, NULL);
8435  if (curr_cte == NULL)
8436  {
8437  /* we expect error to be set */
8438  return NULL;
8439  }
8440 
8441  /* reconnect list, previous->next was curr_cte */
8442  previous_cte->next = curr_cte;
8443 
8444  /* restore next node */
8445  curr_cte->next = saved_curr_cte_next;
8446  }
8447 
8448  /* STEP 3: Resolve CTEs in the actual query */
8449  saved_with = *with_p;
8450  *with_p = NULL;
8451  node = parser_walk_tree (parser, node, pt_resolve_spec_to_cte, cte_list, NULL, NULL);
8452  *with_p = saved_with;
8453 
8454  /* all ok */
8455  return node;
8456 }
8457 
8458 /*
8459  * pt_copy_data_type_entity () -
8460  * return: A copy of the entity name represented by the data type
8461  * parser(in): parser environment
8462  * data_type(in): data type node
8463  */
8464 static PT_NODE *
8466 {
8467  PT_NODE *entity = NULL;
8468  if (data_type->node_type == PT_DATA_TYPE)
8469  {
8470  if (data_type->info.data_type.virt_object)
8471  {
8472  entity = pt_name (parser, db_get_class_name (data_type->info.data_type.virt_object));
8473  entity->info.name.db_object = data_type->info.data_type.virt_object;
8474  }
8475  else
8476  {
8477  entity = parser_copy_tree_list (parser, data_type->info.data_type.entity);
8478  }
8479  }
8480 
8481  return entity;
8482 }
8483 
8484 /*
8485  * pt_insert_entity() -
8486  * return: pointer to the entity spec, the parse tree is augmented with
8487  * the new entity spec if one is created.
8488  * parser(in): parser environment
8489  * path(in): expression that caused the generation of this entity_spec
8490  * prev_entity(in): the previous entity in the path expression
8491  * correlation_entity(in):
8492  */
8493 
8494 PT_NODE *
8495 pt_insert_entity (PARSER_CONTEXT * parser, PT_NODE * path, PT_NODE * prev_entity, PT_NODE * correlation_entity)
8496 {
8497  PT_NODE *entity = NULL;
8498  PT_NODE *res = NULL, *res1;
8499  PT_NODE *arg1;
8500  PT_NODE *arg1_name = NULL;
8501  PT_NODE *node;
8502 
8503  assert (path != NULL && prev_entity != NULL && path->node_type == PT_DOT_ && prev_entity->node_type == PT_SPEC);
8504 
8505  entity = pt_lookup_entity (parser, prev_entity->info.spec.path_entities, path);
8506  /* compute res */
8507  arg1 = path->info.dot.arg1;
8508  if ((arg1->node_type == PT_NAME) || (arg1->node_type == PT_METHOD_CALL))
8509  {
8510  res = arg1->data_type;
8511  arg1_name = arg1; /* what about method calls with selectors? */
8512  res1 = NULL;
8513  }
8514  else
8515  {
8516  res = arg1->info.dot.arg2->data_type;
8517  arg1_name = arg1->info.dot.arg2;
8518  res1 = arg1->data_type;
8519  }
8520 
8521  if (!res || !(res->node_type == PT_DATA_TYPE) || !res->info.data_type.entity)
8522  {
8523  /* if we have a path, it must be from a known entity list */
8524  PT_INTERNAL_ERROR (parser, "resolution");
8525  return NULL;
8526  }
8527 
8528  if (entity == NULL)
8529  {
8530  /* create new entity spec if we have a correlation spec, use it. Otherwise, make a new one */
8531  if (correlation_entity)
8532  {
8533  entity = parser_copy_tree (parser, correlation_entity);
8534  entity->info.spec.derived_table_type = (PT_MISC_TYPE) 0;
8535  entity->info.spec.meta_class = PT_PATH_INNER;
8536  parser_free_tree (parser, correlation_entity->info.spec.path_entities);
8537  correlation_entity->info.spec.path_entities = NULL;
8538  }
8539  else
8540  {
8541  if (!(entity = parser_new_node (parser, PT_SPEC)))
8542  {
8543  PT_ERROR (parser, path,
8546  return NULL;
8547  }
8548 
8549  /* use addr as entity_spec_id per convention */
8550  entity->info.spec.id = (UINTPTR) entity;
8551  entity->line_number = path->info.dot.arg2->line_number;
8552  entity->column_number = path->info.dot.arg2->column_number;
8553 
8554  /* mark if it is a pseudo entity for a method */
8555  if (arg1->node_type == PT_METHOD_CALL)
8556  {
8557  entity->info.spec.flavor = PT_METHOD_ENTITY;
8558  }
8559 
8560  entity->info.spec.entity_name = pt_copy_data_type_entity (parser, res);
8561 
8562  if (entity->info.spec.entity_name)
8563  {
8564  entity->info.spec.entity_name->info.name.spec_id = entity->info.spec.id;
8566  entity->info.spec.only_all = PT_ALL;
8567  entity->info.spec.range_var = parser_copy_tree (parser, entity->info.spec.entity_name);
8568  entity->info.spec.range_var->info.name.resolved = NULL;
8569  entity->info.spec.flat_entity_list = pt_make_flat_list_from_data_types (parser, res, entity);
8570  }
8571 
8572  /* We need to resolve the data type list to the newly created spec. */
8573  for (node = res; node; node = node->next)
8574  {
8575  if (node->info.data_type.entity)
8576  {
8577  node->info.data_type.entity->info.name.spec_id = entity->info.spec.id;
8578  }
8579  }
8580 
8581  /* The type of the DOT node is the same as the type of arg2 and so it must be resolved as well. */
8582  for (node = res1; node; node = node->next)
8583  {
8584  if (node->info.data_type.entity)
8585  {
8586  node->info.data_type.entity->info.name.spec_id = entity->info.spec.id;
8587  }
8588  }
8589  }
8590 
8591  /* add entity into path_entities list */
8592  entity->next = prev_entity->info.spec.path_entities;
8593  prev_entity->info.spec.path_entities = entity;
8594  entity = mq_regenerate_if_ambiguous (parser, entity, entity, entity);
8595  /* add the implicit conjunct */
8596  (void) pt_insert_conjunct (parser, path, entity);
8597  }
8598  if (correlation_entity && entity->info.spec.id != correlation_entity->info.spec.id)
8599  {
8600  const char *root = ""; /* safety net */
8601  if (arg1_name && arg1_name->node_type == PT_NAME)
8602  {
8603  root = arg1_name->info.name.original;
8604  }
8605 
8607  pt_short_print (parser, path), pt_short_print (parser, correlation_entity->info.spec.range_var),
8608  root);
8609  }
8610 
8611  /* Make sure the arg2 points to the correct entity */
8612  path->info.dot.arg2->info.name.spec_id = entity->info.spec.id;
8614  return entity;
8615 }
8616 
8617 
8618 /*
8619  * pt_insert_conjunct() -
8620  * return: parse tree that is augmented with the new conjunct
8621  * parser(in): parser environment
8622  * path_dot(in): path expression that caused this implicit conjunct
8623  * prev_entity(in): the previous entity in the path expression on which
8624  * we'll hang the new conjunct
8625  */
8626 
8627 static PT_NODE *
8629 {
8630  PT_NODE *conjunct;
8631  PT_NODE *arg1;
8632  PT_NODE *conj_name;
8633  PT_NODE *conj_res = NULL;
8634 
8635  assert (path_dot != NULL && path_dot->node_type == PT_DOT_ && prev_entity != NULL
8636  && prev_entity->node_type == PT_SPEC);
8637 
8638  arg1 = path_dot->info.dot.arg1;
8639  if ((arg1->node_type == PT_NAME) || (arg1->node_type == PT_METHOD_CALL))
8640  {
8641  conj_name = arg1;
8642  }
8643  else
8644  {
8645  conj_name = arg1->info.dot.arg2;
8646  /* comput conj_res to get exposed name from class data type of arg1 */
8647  arg1 = arg1->info.dot.arg1;
8648  if ((arg1->node_type == PT_NAME) || (arg1->node_type == PT_METHOD_CALL))
8649  {
8650  conj_res = arg1->data_type;
8651  }
8652  else
8653  {
8654  conj_res = arg1->info.dot.arg2->data_type;
8655  }
8656  if (conj_res)
8657  {
8658  conj_res = conj_res->info.data_type.entity;
8659  }
8660  }
8661 
8662  /* create new conjunct */
8663  if (!(conjunct = parser_new_node (parser, PT_EXPR)))
8664  {
8665  PT_ERROR (parser, path_dot,
8667  return NULL;
8668  }
8669  conjunct->info.expr.op = PT_EQ;
8670  conjunct->info.expr.arg1 = parser_copy_tree (parser, conj_name);
8671  if (conjunct->info.expr.arg1 == NULL)
8672  {
8673  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
8674  return NULL;
8675  }
8676 
8677  if (conj_name->node_type == PT_METHOD_CALL)
8678  {
8680  }
8681  if (conj_res)
8682  {
8683  conjunct->info.expr.arg1->info.name.resolved = conj_res->info.name.original;
8684  }
8685 
8686  conjunct->info.expr.arg2 = parser_copy_tree (parser, prev_entity->info.spec.flat_entity_list);
8687  if (conjunct->info.expr.arg2 == NULL)
8688  {
8689  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
8690  return NULL;
8691  }
8692 
8693  conjunct->info.expr.arg2->info.name.resolved = conjunct->info.expr.arg2->info.name.original;
8694  conjunct->info.expr.arg2->info.name.original = "";
8695  conjunct->info.expr.arg2->info.name.meta_class = PT_OID_ATTR;
8696  conjunct->info.expr.arg2->info.name.db_object = NULL;
8697  conjunct->info.expr.arg2->type_enum = conjunct->info.expr.arg1->type_enum;
8698  conjunct->info.expr.arg2->data_type = parser_copy_tree_list (parser, conjunct->info.expr.arg1->data_type);
8699  conjunct->line_number = path_dot->line_number;
8700  conjunct->column_number = path_dot->column_number;
8701  /* add conjunct into path_conjuncts list */
8702  conjunct->next = prev_entity->info.spec.path_conjuncts;
8703  prev_entity->info.spec.path_conjuncts = conjunct;
8704  return conjunct;
8705 } /* pt_insert_conjunct */
8706 
8707 
8708 /*
8709  * pt_lookup_entity () -
8710  * return: entity we are looking for
8711  * parser(in):
8712  * path_entities(in): entity list to look for entity
8713  * expr(in):
8714  */
8715 static PT_NODE *
8717 {
8718  PT_NODE *entity;
8719  int found = false;
8720  PT_NODE *arg1_of_conj;
8721  const char *name = NULL, *cname;
8722 
8723  for (entity = path_entities; (entity != NULL && !found);)
8724  { /* do nothing during increment step */
8725 
8726  arg1_of_conj = entity->info.spec.path_conjuncts->info.expr.arg1;
8727  if (expr->info.dot.arg1->node_type == PT_METHOD_CALL)
8728  {
8729  return NULL;
8730  }
8731  else
8732  {
8733  if (expr->info.dot.arg1->node_type == PT_DOT_)
8734  {
8735  name = expr->info.dot.arg1->info.dot.arg2->info.name.original;
8736  }
8737  else if (expr->info.dot.arg1->node_type == PT_NAME)
8738  {
8739  name = expr->info.dot.arg1->info.name.original;
8740  }
8741 
8742  if (arg1_of_conj->node_type == PT_NAME)
8743  {
8744  cname = arg1_of_conj->info.name.original;
8745  if (name != NULL && intl_identifier_casecmp (name, cname) == 0)
8746  {
8747  found = true;
8748  }
8749  }
8750  }
8751 
8752  if (!found)
8753  {
8754  entity = entity->next;
8755  }
8756  }
8757 
8758  return entity;
8759 }
8760 
8761 
8762 
8763 /*
8764  * pt_resolve_object () - gets the object to update either from a host var
8765  * or from a parameter. Once it has the object it creates an entity for
8766  * the object
8767  * return: none
8768  * parser(in):
8769  * node(in): an PT_UPDATE_INFO node representing an UPDATE OBJECT.. statement
8770  */
8771 void
8773 {
8774  DB_VALUE *val = NULL;
8775  PT_NODE *entity;
8776  DB_OBJECT *class_op = NULL;
8777  PT_NODE *obj_param = node->info.update.object_parameter;
8778  assert (obj_param != NULL);
8779  if (obj_param->node_type == PT_NAME)
8780  {
8781  if (obj_param->info.name.meta_class != PT_PARAMETER)
8782  {
8783  PT_INTERNAL_ERROR (parser, "resolution");
8784  return;
8785  }
8786 
8787  /* look it up as an interpreter parameter reference */
8788  val = pt_find_value_of_label (obj_param->info.name.original);
8789  if (!val) /* parameter not found */
8790  {
8792  obj_param->info.name.original);
8793  return;
8794  }
8795  }
8796  else if (obj_param->node_type == PT_HOST_VAR)
8797  {
8798  val = pt_value_to_db (parser, obj_param);
8799  }
8800 
8801  if (val == NULL) /* parameter not found */
8802  {
8804  return;
8805  }
8806 
8807  if (DB_VALUE_TYPE (val) != DB_TYPE_OBJECT)
8808  {
8810  return;
8811  }
8812  node->info.update.object = db_get_object (val);
8813  class_op = db_get_class (node->info.update.object);
8814  if (class_op == NULL)
8815  {
8817  return;
8818  }
8819 
8820  /* create an entity */
8821  entity = parser_new_node (parser, PT_SPEC);
8822  if (entity == NULL)
8823  {
8824  PT_INTERNAL_ERROR (parser, "allocate new node");
8825  return;
8826  }
8827 
8828  entity->info.spec.id = (UINTPTR) entity;
8829  entity->line_number = node->line_number;
8830  entity->column_number = node->column_number;
8831  entity->info.spec.entity_name = parser_new_node (parser, PT_NAME);
8832  if (entity->info.spec.entity_name == NULL)
8833  {
8834  PT_INTERNAL_ERROR (parser, "allocate new node");
8835  return;
8836  }
8837 
8838  entity->info.spec.entity_name->info.name.spec_id = entity->info.spec.id;
8840  entity->info.spec.entity_name->info.name.original = db_get_class_name (class_op);
8841  entity->info.spec.only_all = PT_ONLY;
8842  entity->info.spec.range_var = parser_copy_tree (parser, entity->info.spec.entity_name);
8843  if (entity->info.spec.range_var == NULL)
8844  {
8845  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
8846  return;
8847  }
8848 
8849  entity->info.spec.range_var->info.name.resolved = NULL;
8850  node->info.update.spec = entity;
8851 }
8852 
8853 
8854 /*
8855  * pt_resolve_method_type () - resolves the return type of the method call
8856  * and creates a data_type for it if it is needed
8857  * return:
8858  * parser(in):
8859  * node(in): an PT_METHOD_CALL node
8860  */
8861 static bool
8863 {
8864  PT_NODE *target;
8865  const char *method_name;
8866  DB_OBJECT *class_op;
8867  DB_METHOD *method = NULL;
8868  DB_DOMAIN *dom = NULL;
8869  if ((!node->info.method_call.method_name) || (!(target = node->info.method_call.on_call_target))
8870  || (!target->data_type) || (!target->data_type->info.data_type.entity)
8871  || (!(class_op = target->data_type->info.data_type.entity->info.name.db_object)))
8872  {
8873  return false; /* not a method */
8874  }
8875  method_name = node->info.method_call.method_name->info.name.original;
8876  method = NULL;
8877  method = db_get_method (class_op, method_name);
8878  if (method == NULL)
8879  {
8880  /* need to check if it is a class method */
8881  if (er_errid () == ER_OBJ_INVALID_METHOD)
8882  {
8883  er_clear ();
8884  }
8885  method = db_get_class_method (class_op, method_name);
8886  if (method == NULL)
8887  {
8888  return false; /* not a method */
8889  }
8891  }
8892  else
8893  {
8895  }
8896 
8897  /* look up the domain of the method's return type */
8898  if ((dom = db_method_arg_domain (method, 0)) == NULL)
8899  {
8900  /* only give error if it is a method expression */
8902  {
8904  }
8905  return false;
8906  }
8907 
8909  switch (node->type_enum)
8910  {
8911  case PT_TYPE_OBJECT:
8912  case PT_TYPE_SET:
8913  case PT_TYPE_SEQUENCE:
8914  case PT_TYPE_MULTISET:
8915  case PT_TYPE_NUMERIC:
8916  case PT_TYPE_BIT:
8917  case PT_TYPE_VARBIT:
8918  case PT_TYPE_CHAR:
8919  case PT_TYPE_VARCHAR:
8920  case PT_TYPE_NCHAR:
8921  case PT_TYPE_VARNCHAR:
8922  node->data_type = pt_domain_to_data_type (parser, dom);
8923  break;
8924  default:
8925  break;
8926  }
8927 
8928  /* finally resolve method id */
8929  node->info.method_call.method_id = (UINTPTR) node;
8930  return true;
8931 } /* pt_resolve_method_type */
8932 
8933 
8934 
8935 /*
8936  * pt_make_method_call () - determines if the function call is really a
8937  * method call and if so, creates a PT_METHOD_CALL to replace the node
8938  * resolves the method call
8939  * return:
8940  * parser(in):
8941  * node(in): an PT_FUNCTION node that may really be a method call
8942  * bind_arg(in):
8943  */
8944 static PT_NODE *
8946 {
8947  PT_NODE *new_node;
8948  int error = NO_ERROR;
8949 
8950  /* initialize the new node with the corresponding fields from the PT_FUNCTION node. */
8951  new_node = parser_new_node (parser, PT_METHOD_CALL);
8952  if (new_node == NULL)
8953  {
8954  PT_INTERNAL_ERROR (parser, "allocate new node");
8955  return NULL;
8956  }
8957 
8958  new_node->info.method_call.method_name = parser_new_node (parser, PT_NAME);
8959  if (new_node->info.method_call.method_name == NULL)
8960  {
8961  PT_INTERNAL_ERROR (parser, "allocate new node");
8962  return NULL;
8963  }
8964 
8965  PT_NODE_COPY_NUMBER_OUTERLINK (new_node, node);
8966 
8968 
8969  new_node->info.method_call.arg_list = parser_copy_tree_list (parser, node->info.function.arg_list);
8970 
8972 
8974  {
8975  TP_DOMAIN *d = NULL;
8976 
8977  new_node->info.method_call.method_name->info.name.spec_id = (UINTPTR) new_node->info.method_call.method_name;
8978 
8980 
8981  parser_walk_leaves (parser, new_node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
8982 
8983  /* returns either error or DB_TYPE... */
8985  if (error < 0)
8986  {
8987  PT_INTERNAL_ERROR (parser, "jsp_get_return_type");
8988  return NULL;
8989  }
8990  new_node->type_enum = pt_db_to_type_enum ((DB_TYPE) error);
8991 
8992  d = pt_type_enum_to_db_domain (new_node->type_enum);
8993  d = tp_domain_cache (d);
8994  new_node->data_type = pt_domain_to_data_type (parser, d);
8995 
8996  new_node->info.method_call.method_id = (UINTPTR) new_node;
8997 
8998  return new_node;
8999  }
9000  else
9001  {
9002  /* The first argument (which must be present), is the target of the method. Move it to the on_call_target. */
9003  if (!new_node->info.method_call.arg_list)
9004  {
9005  return node; /* return the function since it is not a method */
9006  }
9007  new_node->info.method_call.on_call_target = new_node->info.method_call.arg_list;
9008  new_node->info.method_call.arg_list = new_node->info.method_call.arg_list->next;
9009  new_node->info.method_call.on_call_target->next = NULL;
9010 
9011  /* make method name look resolved */
9012  new_node->info.method_call.method_name->info.name.spec_id = (UINTPTR) new_node->info.method_call.method_name;
9014 
9015  /* bind the names in the method arguments and target, their scope will be the same as the method node's scope */
9016  parser_walk_leaves (parser, new_node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
9017 
9018  /* find the type of the method here */
9019  if (!pt_resolve_method_type (parser, new_node))
9020  {
9021  return node; /* not a method call */
9022  }
9023  else
9024  {
9025  /* if scopes is NULL we assume this came from an evaluate call and we treat it like a call statement, that
9026  * is, we don't resolve method name. */
9027  if (bind_arg->scopes == NULL)
9028  {
9029  return new_node;
9030  }
9031  /* resolve method name to entity where expansion will take place */
9032  if ((new_node->info.method_call.on_call_target->node_type == PT_NAME)
9034  {
9035  PT_NODE *entity, *spec;
9036  entity = NULL; /* init */
9038  {
9039  for (spec = bind_arg->spec_frames->extra_specs; spec != NULL; spec = spec->next)
9040  {
9041  if (spec->node_type == PT_SPEC
9042  && (spec->info.spec.id == new_node->info.method_call.on_call_target->info.name.spec_id))
9043  {
9044  entity = spec;
9045  break;
9046  }
9047  }
9048  }
9049  else
9050  {
9051  entity =
9052  pt_find_entity_in_scopes (parser, bind_arg->scopes,
9054  }
9055  /* no entity found will be caught as an error later. Probably an unresolvable target. */
9056  if (entity)
9057  {
9058  new_node->info.method_call.method_name->info.name.spec_id = entity->info.spec.id;
9059  }
9060  }
9061 
9062  return new_node; /* it is a method call */
9063  }
9064  }
9065 } /* pt_make_method_call */
9066 
9067 
9068 /*
9069  * pt_find_entity_in_scopes () - looks up an entity spec in a scope list
9070  * return:
9071  * parser(in):
9072  * scopes(in):
9073  * spec_id(in):
9074  */
9075 static PT_NODE *
9077 {
9078  SCOPES *scope;
9079  PT_NODE *entity = NULL;
9080  for (scope = scopes; scope != NULL; scope = scope->next)
9081  {
9082  entity = pt_find_entity (parser, scope->specs, spec_id);
9083  if (entity)
9084  {
9085  break;
9086  }
9087  }
9088 
9089  return entity;
9090 }
9091 
9092 /*
9093  * pt_find_outer_entity_in_scopes () -
9094  * return:
9095  * parser(in):
9096  * scopes(in):
9097  * spec_id(in):
9098  * scope_location(in):
9099  */
9100 static PT_NODE *
9101 pt_find_outer_entity_in_scopes (PARSER_CONTEXT * parser, SCOPES * scopes, UINTPTR spec_id, short *scope_location)
9102 {
9103  PT_NODE *spec, *temp;
9104  int location = 0;
9105  if (scopes == NULL)
9106  {
9107  PT_INTERNAL_ERROR (parser, "resolution");
9108  return NULL;
9109  }
9110 
9111 
9112  for (spec = scopes->specs; spec; spec = spec->next)
9113  {
9114  if (spec->node_type != PT_SPEC)
9115  {
9116  PT_INTERNAL_ERROR (parser, "resolution");
9117  return NULL;
9118  }
9119  if (spec->info.spec.join_type == PT_JOIN_NONE)
9120  {
9121  location = spec->info.spec.location;
9122  }
9123  if (spec->info.spec.id == spec_id)
9124  {
9125  for (temp = spec; temp && temp->info.spec.location < *scope_location; temp = temp->next)
9126  {
9127  if (temp->info.spec.join_type == PT_JOIN_NONE)
9128  location = temp->info.spec.location;
9129  }
9130  *scope_location = location;
9131  return spec;
9132  }
9133  }
9134 
9135  return NULL;
9136 }
9137 
9138 
9139 /*
9140  * pt_make_flat_list_from_data_types
9141  *
9142  * description: For each node in the res_list, this routine appends that node's
9143  * entity list onto the flat list that is being created. The resulting
9144  * flat list is then normalized (correct spec_id, etc.)
9145  */
9146 
9147 /*
9148  * pt_make_flat_list_from_data_types () - For each node in the res_list,
9149  * this routine appends that node's entity list onto the flat list that
9150  * is being created. The resulting flat list is then normalized
9151  * return:
9152  * parser(in):
9153  * res_list(in):
9154  * entity(in):
9155  */
9156 static PT_NODE *
9158 {
9159  PT_NODE *node, *temp, *flat_list = NULL;
9160  for (node = res_list; node; node = node->next)
9161  {
9162  temp = pt_copy_data_type_entity (parser, node);
9163  flat_list = pt_name_list_union (parser, flat_list, temp);
9164  }
9165 
9166  /* set all ids on flat list */
9167  for (node = flat_list; node != NULL; node = node->next)
9168  {
9169  node->info.name.spec_id = entity->info.spec.id;
9170  node->info.name.resolved = entity->info.spec.entity_name->info.name.original;
9171  if (PT_IS_SPEC_REAL_TABLE (entity))
9172  {
9174  }
9175  node->info.name.meta_class = PT_CLASS;
9176  }
9177 
9178  return flat_list;
9179 }
9180 
9181 /*
9182  * pt_op_type_from_default_expr_type () - returns the corresponding PT_OP_TYPE
9183  * for the given default expression
9184  * return: a PT_OP_TYPE (the desired operation)
9185  * expr_type(in): a DB_DEFAULT_EXPR_TYPE (the default expression)
9186  */
9187 PT_OP_TYPE
9189 {
9190  switch (expr_type)
9191  {
9192  case DB_DEFAULT_SYSTIME:
9193  return PT_SYS_TIME;
9194 
9195  case DB_DEFAULT_SYSDATE:
9196  return PT_SYS_DATE;
9197 
9199  return PT_SYS_DATETIME;
9200 
9202  return PT_SYS_TIMESTAMP;
9203 
9205  return PT_UNIX_TIMESTAMP;
9206 
9207  case DB_DEFAULT_USER:
9208  return PT_USER;
9209 
9210  case DB_DEFAULT_CURR_USER:
9211  return PT_CURRENT_USER;
9212 
9214  return PT_CURRENT_DATETIME;
9215 
9217  return PT_CURRENT_TIMESTAMP;
9218 
9220  return PT_CURRENT_TIME;
9221 
9223  return PT_CURRENT_DATE;
9224 
9225  default:
9226  return (PT_OP_TYPE) 0;
9227  }
9228 }
9229 
9230 DB_OBJECT *
9232 {
9233  char *serial_name, *t;
9234  DB_OBJECT *serial_class_mop, *serial_mop;
9235  DB_IDENTIFIER serial_obj_id;
9236 
9237  if (serial_name_node == NULL || serial_name_node->node_type != PT_NAME)
9238  {
9239  return NULL;
9240  }
9241 
9242  serial_name = (char *) serial_name_node->info.name.original;
9243  t = strchr (serial_name, '.'); /* FIXME */
9244  serial_name = (t != NULL) ? (t + 1) : serial_name;
9245 
9246  serial_class_mop = sm_find_class (CT_SERIAL_NAME);
9247  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, serial_name);
9248  if (serial_mop == NULL)
9249  {
9251  }
9252 
9253  return serial_mop;
9254 }
9255 
9256 /*
9257  * pt_function_name_is_spec_attr () - checks if a generic function name is
9258  * actually an attribute name. It is used to distinguish between an error
9259  * caused by the wrong usage of a prefix length index or an function
9260  * index.
9261  *
9262  * return: NO_ERROR on success, non-zero for ERROR
9263  * parser(in): parser context
9264  * node(in): PT_FUNCTION node holding the function name to be searched
9265  * bind_arg(in): list of scopes
9266  * is_spec_attr(out): 1 if it is actually an attribute name, 0 otherwise
9267  */
9268 static int
9270 {
9271  SCOPES *scope = NULL;
9272  PT_NODE *spec = NULL;
9273  PT_NODE *attr = NULL;
9274 
9275  assert (node->node_type == PT_FUNCTION);
9276 
9277  *is_spec_attr = 0;
9278  attr = pt_name (parser, node->info.function.generic_name);
9279  if (attr == NULL)
9280  {
9282  return ER_FAILED;
9283  }
9284 
9285  /* walk scopes (might be unnecessary) */
9286  for (scope = bind_arg->scopes; scope; scope = scope->next)
9287  {
9288  /* walk specs */
9289  for (spec = scope->specs; spec; spec = spec->next)
9290  {
9291  if (pt_find_name_in_spec (parser, spec, attr) > 0)
9292  {
9293  *is_spec_attr = 1;
9294  break;
9295  }
9296  }
9297  if (*is_spec_attr == 1)
9298  {
9299  /* no need to continue */
9300  break;
9301  }
9302  }
9303 
9304  if (attr != NULL)
9305  {
9306  parser_free_node (parser, attr);
9307  }
9308 
9309  return NO_ERROR;
9310 }
9311 
9312 /*
9313  * pt_mark_function_index_expression () - mark function index expression
9314  * return:
9315  * parser(in): parser context
9316  * node(in): PT_EXPR node
9317  * bind_arg(in): list of scopes
9318  */
9319 static void
9321 {
9322  SCOPES *scope = NULL;
9323  PT_NODE *spec = NULL;
9324  MOP cls;
9325  SM_CLASS_CONSTRAINT *constraints;
9326  char *expr_str = NULL;
9327  PT_NODE *flat = NULL;
9328 
9329  if (expr->node_type != PT_EXPR)
9330  {
9331  return;
9332  }
9333 
9334  /* walk scopes */
9335  for (scope = bind_arg->scopes; scope; scope = scope->next)
9336  {
9337  /* walk specs */
9338  for (spec = scope->specs; spec; spec = spec->next)
9339  {
9340  if (spec->info.spec.meta_class == PT_CLASS && !spec->info.spec.derived_table
9341  && spec->info.spec.flat_entity_list)
9342  {
9343  flat = spec->info.spec.flat_entity_list;
9344  while (flat)
9345  {
9346  if (flat->node_type != PT_NAME)
9347  {
9348  PT_INTERNAL_ERROR (parser, "resolution");
9349  return;
9350  }
9351 
9352  /* Get the object */
9353  cls = flat->info.name.db_object;
9354  if (!cls)
9355  {
9356  PT_INTERNAL_ERROR (parser, "resolution");
9357  return;
9358  }
9359 
9360  constraints = sm_class_constraints (cls);
9361  while (constraints != NULL)
9362  {
9363  if (constraints->func_index_info)
9364  {
9365  if (expr_str == NULL)
9366  {
9367  expr_str = parser_print_function_index_expr (parser, expr);
9368  }
9369 
9370  if (!intl_identifier_casecmp (expr_str, constraints->func_index_info->expr_str))
9371  {
9373  return;
9374  }
9375  }
9376  constraints = constraints->next;
9377  }
9378 
9379  flat = flat->next;
9380  }
9381  }
9382  }
9383  }
9384 }
9385 
9386 /*
9387  * pt_bind_names_merge_insert () -
9388  * return:
9389  * parser(in):
9390  * node(in):
9391  * bind_arg(in):
9392  * scopestack(in):
9393  * spec_frame(in):
9394  */
9395 static void
9397  PT_EXTRA_SPECS_FRAME * spec_frame)
9398 {
9399  PT_NODE *temp_node, *node_list, *save_next, *prev_node = NULL;
9400  bool is_first_node;
9401 
9402  assert (node->node_type == PT_MERGE);
9403 
9404  /* bind names for insert attributes list */
9405  scopestack->specs = node->info.merge.into;
9406  bind_arg->scopes = scopestack;
9407  spec_frame->next = bind_arg->spec_frames;
9408  spec_frame->extra_specs = NULL;
9409  bind_arg->spec_frames = spec_frame;
9410  pt_bind_scope (parser, bind_arg);
9411  node->info.merge.insert.attr_list =
9412  parser_walk_tree (parser, node->info.merge.insert.attr_list, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
9413  if (pt_has_error (parser))
9414  {
9415  return;
9416  }
9417 
9418  /* bind names for default function in insert values list */
9419  node_list = node->info.merge.insert.value_clauses->info.node_list.list;
9420  for (temp_node = node_list, is_first_node = true; temp_node != NULL;
9421  temp_node = temp_node->next, is_first_node = false)
9422  {
9423  if (temp_node->node_type == PT_EXPR && temp_node->info.expr.op == PT_DEFAULTF)
9424  {
9425  scopestack->specs = node->info.merge.into;
9426  bind_arg->scopes = scopestack;
9427  spec_frame->next = bind_arg->spec_frames;
9428  spec_frame->extra_specs = NULL;
9429  bind_arg->spec_frames = spec_frame;
9430  pt_bind_scope (parser, bind_arg);
9431 
9432  save_next = temp_node->next;
9433  temp_node->next = NULL;
9434  temp_node = parser_walk_tree (parser, temp_node, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
9435  temp_node->next = save_next;
9436 
9437  if (is_first_node)
9438  {
9439  node->info.merge.insert.value_clauses->info.node_list.list = temp_node;
9440  }
9441  else
9442  {
9443  prev_node->next = temp_node;
9444  }
9445  }
9446  prev_node = temp_node;
9447  }
9448 
9449  if (pt_has_error (parser))
9450  {
9451  return;
9452  }
9453 
9454  /* bind names for the rest of insert values list */
9455  scopestack->specs = node->info.merge.using_clause;
9456  bind_arg->scopes = scopestack;
9457  spec_frame->next = bind_arg->spec_frames;
9458  spec_frame->extra_specs = NULL;
9459  bind_arg->spec_frames = spec_frame;
9460  pt_bind_scope (parser, bind_arg);
9461  node->info.merge.insert.value_clauses =
9463  bind_arg);
9464 
9465  if (pt_has_error (parser))
9466  {
9467  return;
9468  }
9469 
9470  /* bind names for insert search condition */
9471  scopestack->specs = node->info.merge.using_clause;
9472  bind_arg->scopes = scopestack;
9473  spec_frame->next = bind_arg->spec_frames;
9474  spec_frame->extra_specs = NULL;
9475  bind_arg->spec_frames = spec_frame;
9476  pt_bind_scope (parser, bind_arg);
9477  node->info.merge.insert.search_cond =
9479  bind_arg);
9480 }
9481 
9482 /*
9483  * pt_bind_names_merge_update () -
9484  * return:
9485  * parser(in):
9486  * node(in):
9487  * bind_arg(in):
9488  * scopestack(in):
9489  * spec_frame(in):
9490  */
9491 static void
9493  PT_EXTRA_SPECS_FRAME * spec_frame)
9494 {
9495  PT_NODE *assignment;
9496 
9497  /* resolve lhs with target spec only */
9498  scopestack->specs = node->info.merge.into;
9499  bind_arg->scopes = scopestack;
9500  spec_frame->next = bind_arg->spec_frames;
9501  spec_frame->extra_specs = NULL;
9502  bind_arg->spec_frames = spec_frame;
9503  pt_bind_scope (parser, bind_arg);
9504  for (assignment = node->info.merge.update.assignment; assignment; assignment = assignment->next)
9505  {
9506  if (PT_IS_N_COLUMN_UPDATE_EXPR (assignment->info.expr.arg1))
9507  {
9508  assignment->info.expr.arg1->info.expr.arg1 =
9509  parser_walk_tree (parser, assignment->info.expr.arg1->info.expr.arg1, pt_bind_names, bind_arg,
9510  pt_bind_names_post, bind_arg);
9511  if (assignment->info.expr.arg1->info.expr.arg1 == NULL)
9512  {
9513  assert (pt_has_error (parser));
9514  return;
9515  }
9516  }
9517  else
9518  {
9519  assignment->info.expr.arg1 =
9520  parser_walk_tree (parser, assignment->info.expr.arg1, pt_bind_names, bind_arg, pt_bind_names_post,
9521  bind_arg);
9522  if (assignment->info.expr.arg1 == NULL)
9523  {
9524  assert (pt_has_error (parser));
9525  return;
9526  }
9527  }
9528  }
9529 
9530  /* resolve rhs with both source and target specs */
9531  scopestack->specs = node->info.merge.into;
9532  node->info.merge.into->next = node->info.merge.using_clause;
9533  bind_arg->scopes = scopestack;
9534  spec_frame->next = bind_arg->spec_frames;
9535  spec_frame->extra_specs = NULL;
9536  bind_arg->spec_frames = spec_frame;
9537  pt_bind_scope (parser, bind_arg);
9538  for (assignment = node->info.merge.update.assignment; assignment; assignment = assignment->next)
9539  {
9540  assignment->info.expr.arg2 =
9541  parser_walk_tree (parser, assignment->info.expr.arg2, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
9542  if (assignment->info.expr.arg2 == NULL)
9543  {
9544  assert (pt_has_error (parser));
9545  return;
9546  }
9547  }
9548  node->info.merge.into->next = NULL;
9549 }
9550 
9551 /*
9552  * pt_resolve_partition_spec - resolve a spec specified with PARTITION keyword
9553  * to the actual partition spec
9554  * return: partition spec
9555  * parser (in) : parser context
9556  * spec (in) : spec
9557  * spec_parent (in) : spec parent
9558  * for_update (in): is update purpose?
9559  */
9560 static PT_NODE *
9561 pt_resolve_partition_spec (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * spec_parent, bool for_update)
9562 {
9563  const char *partition_suffix = NULL;
9564  const char *partition_name = NULL;
9565  DB_OBJECT *root_op, *partition_op = NULL;
9566  SM_CLASS *class_ = NULL;
9567  PT_NODE *entity_name = NULL, *partition_node = NULL;
9568  const char *root_name = NULL;
9569  AU_FETCHMODE fetchmode;
9570 
9571  if (spec == NULL || spec->info.spec.partition == NULL)
9572  {
9573  return spec;
9574  }
9575 
9576  entity_name = spec->info.spec.entity_name;
9577  root_name = entity_name->info.name.original;
9578  partition_node = spec->info.spec.partition;
9579  partition_suffix = partition_node->info.name.original;
9580  partition_name = pt_partition_name (parser, root_name, partition_suffix);
9581  if (partition_name == NULL)
9582  {
9583  return NULL;
9584  }
9585 
9586  /* set the actual partition name to the partition node */
9587  partition_node->info.name.original = partition_name;
9588 
9589  /* use partition name to make flat list */
9590  spec->info.spec.entity_name = partition_node;
9591  spec->info.spec.partition = NULL;
9592  spec->info.spec.flat_entity_list = pt_make_flat_name_list (parser, spec, spec_parent, for_update);
9593  if (spec->info.spec.flat_entity_list == NULL)
9594  {
9595  return NULL;
9596  }
9597 
9598  /* Verify if current spec is a partition of the saved entity name */
9599  root_op = db_find_class_with_purpose (root_name, for_update);
9600  if (root_op == NULL)
9601  {
9602  PT_ERRORc (parser, spec, er_msg ());
9603  return NULL;
9604  }
9605 
9606  partition_op = spec->info.spec.entity_name->info.name.db_object;
9607  if (partition_op == NULL)
9608  {
9609  /* We have successfully resolved it, it should not be null */
9610  PT_INTERNAL_ERROR (parser, "resolution");
9611  return NULL;
9612  }
9613 
9614  fetchmode = for_update ? AU_FETCH_UPDATE : AU_FETCH_READ;
9615 
9616  /* do not check authorization here */
9617  if (au_fetch_class_force (partition_op, &class_, fetchmode) != NO_ERROR)
9618  {
9619  PT_ERRORc (parser, spec, er_msg ());
9620  return NULL;
9621  }
9622 
9623  if (class_->partition == NULL)
9624  {
9625  /* no partition information */
9627  return NULL;
9628  }
9629 
9630  if (class_->users != NULL)
9631  {
9632  /* this is a partitioned class, it cannot be a partition of the specified class */
9634  return NULL;
9635  }
9636 
9637  /* class_ is a partition, we only have to verify that its superclass is root_op */
9638  if (class_->inheritance->op != root_op)
9639  {
9640  /* class_ is a partition of a different class */
9642  return NULL;
9643  }
9644 
9645  /* set root class name as alias for this spec */
9646  if (spec->info.spec.range_var == NULL)
9647  {
9648  spec->info.spec.range_var = entity_name;
9649  entity_name = NULL;
9650  }
9651 
9652  if (entity_name != NULL)
9653  {
9654  parser_free_tree (parser, entity_name);
9655  }
9656 
9657  return spec;
9658 }
9659 
9660 /*
9661  * pt_set_reserved_name_key_type () - When scanning for index key and node
9662  * info, keys are selected from index.
9663  * This function is supposed to resolve
9664  * data type for such attributes.
9665  *
9666  * return : Original node with updated type_enum.
9667  * parser (in) : Parser context.
9668  * node (in) : Parse tree node.
9669  * arg (in) : Index key data type.
9670  * continue_walk (in) : Continue walk.
9671  */
9672 static PT_NODE *
9673 pt_set_reserved_name_key_type (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9674 {
9676 
9677  if (node != NULL && node->node_type == PT_NAME && node->info.name.meta_class == PT_RESERVED
9680  {
9681  /* Set key type */
9682  node->data_type = parser_copy_tree_list (parser, key_type->data_type);
9683  if (node->data_type == NULL)
9684  {
9686  *continue_walk = PT_STOP_WALK;
9687  }
9688  node->type_enum = key_type->type_enum;
9689  }
9690  return node;
9691 }
9692 
9693 /*
9694  * pt_bind_names_in_with_clause () - resolve names in with clause of node
9695  *
9696  * return : void
9697  * parser (in) : Parser context.
9698  * node (in) : Parse tree node.
9699  * bind_arg (in) : Bind names arg.
9700  *
9701  * Note: The names from the with clause should be resolved before resolving the actual query;
9702  * Since CTEs may be referenced multiple times in a query, better resolve them separately
9703  * instead of resolving each occurence
9704  */
9705 static void
9707 {
9708  PT_NODE *with = NULL;
9709  PT_NODE *curr_cte;
9710 
9711  switch (node->node_type)
9712  {
9713  case PT_SELECT:
9714  case PT_UNION:
9715  case PT_DIFFERENCE:
9716  case PT_INTERSECTION:
9717  with = node->info.query.with;
9718  break;
9719  case PT_UPDATE:
9720  with = node->info.update.with;
9721  break;
9722  case PT_DELETE:
9723  with = node->info.delete_.with;
9724  break;
9725  default:
9726  assert (false);
9727  }
9728 
9729  if (with == NULL)
9730  {
9731  /* nothing to do */
9732  return;
9733  }
9734 
9735  for (curr_cte = with->info.with_clause.cte_definition_list; curr_cte != NULL; curr_cte = curr_cte->next)
9736  {
9737  /* isolate curr_cte and apply resolve names */
9738  PT_NODE *save_next_cte = curr_cte->next;
9739  curr_cte->next = NULL;
9740 
9741  pt_bind_names_in_cte (parser, curr_cte, bind_arg);
9742 
9743  curr_cte->next = save_next_cte;
9744  if (pt_has_error (parser))
9745  {
9746  return;
9747  }
9748  }
9749 }
9750 
9751 
9752 /*
9753  * pt_resolve_names_in_cte - resolve names in cte definition
9754  *
9755  * return : void
9756  * parser (in) : Parser context.
9757  * node (in) : Parse tree node.
9758  * bind_arg (in) : Bind names arg.
9759  */
9760 static void
9762 {
9763  PT_NODE *save_next_cte_def;
9764  PT_NODE *non_recursive_cte = cte_def->info.cte.non_recursive_part;
9765  PT_NODE *recursive_cte = cte_def->info.cte.recursive_part;
9766  bool save_donot_fold;
9767 
9768  assert (cte_def->node_type == PT_CTE);
9769 
9770  if (non_recursive_cte == NULL)
9771  {
9772  /* something went wrong, this shouldn't be possible */
9773  assert (0);
9774  return;
9775  }
9776 
9777  /* Evaluate the non-recursive part:
9778  * bind the names and the types from the non-recursive part and set cte->as_attr_list accordingly;
9779  * the recursive part(if it exists) will use the as_attr_list to bind its own names and types;
9780  */
9781  non_recursive_cte = parser_walk_tree (parser, non_recursive_cte, pt_bind_names, bind_arg,
9782  pt_bind_names_post, bind_arg);
9783 
9784  /* must bind any expr types in non recursive part; required for types binding */
9785  save_donot_fold = bind_arg->sc_info->donot_fold; /* save */
9786  bind_arg->sc_info->donot_fold = true; /* skip folding */
9787  non_recursive_cte = pt_semantic_type (parser, non_recursive_cte, bind_arg->sc_info);
9788  bind_arg->sc_info->donot_fold = save_donot_fold; /* restore */
9789  if (non_recursive_cte == NULL)
9790  {
9791  goto end;
9792  }
9793 
9794  /* build the cte as_attr_list according to the non_recursive part */
9795  if (cte_def->info.cte.as_attr_list == NULL)
9796  {
9797  cte_def->info.cte.as_attr_list =
9798  pt_get_attr_list_of_derived_table (parser, PT_IS_SUBQUERY, non_recursive_cte, cte_def->info.cte.name);
9799  }
9800  pt_set_attr_list_types (parser, cte_def->info.cte.as_attr_list, PT_IS_SUBQUERY, non_recursive_cte, cte_def);
9801 
9802  /* done with the non_recursive_part */
9803  cte_def->info.cte.non_recursive_part = non_recursive_cte;
9804 
9805  /* Evaluate the recursive part:
9806  * bind the names and the types of the recursive part, and unify them with the ones of the non-recursive part
9807  * pt_semantic_type will unify the types of the two parts considering that there is a UNION between them
9808  * cte->as_attr_list will be overwritten with the unified types
9809  */
9810  if (recursive_cte != NULL)
9811  {
9812  recursive_cte = parser_walk_tree (parser, recursive_cte, pt_bind_names, bind_arg, pt_bind_names_post, bind_arg);
9813  if (recursive_cte == NULL)
9814  {
9815  goto end;
9816  }
9817 
9818  cte_def->info.cte.recursive_part = recursive_cte;
9819 
9820  /* must bind any expr types in cte; required for types binding */
9821  save_donot_fold = bind_arg->sc_info->donot_fold;
9822  bind_arg->sc_info->donot_fold = true;
9823  save_next_cte_def = cte_def->next;
9824  cte_def->next = NULL;
9825  cte_def = pt_semantic_type (parser, cte_def, bind_arg->sc_info);
9826  if (!cte_def)
9827  {
9828  return; /* error in pt_semantic_type */
9829  }
9830 
9831  bind_arg->sc_info->donot_fold = save_donot_fold; /* restore */
9832  cte_def->next = save_next_cte_def;
9833 
9834  /* set final CTE attributes types */
9835  pt_set_attr_list_types (parser, cte_def->info.cte.as_attr_list, PT_IS_SUBQUERY, recursive_cte, cte_def);
9836 
9837  /* the attributes of cte self references specs can now be computed correctly */
9838  recursive_cte = parser_walk_tree (parser, recursive_cte, pt_bind_cte_self_references_types, NULL, NULL, NULL);
9839  }
9840 
9841 end:
9842  cte_def->info.cte.non_recursive_part = non_recursive_cte;
9843  cte_def->info.cte.recursive_part = recursive_cte;
9844 }
9845 
9846 /*
9847  * pt_bind_cte_self_references_types () - used to bind types of self reference specs in recursive cte part;
9848  * this can be done only after bind_names is complete and
9849  * final cte attributes types are set
9850  * return:
9851  * parser(in):
9852  * node(in):
9853  * arg(in/out):
9854  * continue_walk(in/out):
9855  */
9856 static PT_NODE *
9857 pt_bind_cte_self_references_types (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9858 {
9859  if (node == NULL || node->node_type != PT_SPEC || !PT_SPEC_IS_CTE (node))
9860  {
9861  /* interested only in CTE specs */
9862  return node;
9863  }
9864 
9865  pt_bind_spec_attrs (parser, node);
9866 
9867  *continue_walk = PT_LIST_WALK;
9868 
9869  return node;
9870 }
9871 
9872 
9873 /*
9874  * pt_get_attr_list_of_derived_table - determine the list of aliases of a derived table
9875  *
9876  * return : Computed as_attr_list
9877  * parser (in) : Parser context.
9878  * derived_table_type (in) : Provided by the spec that contains the derived table.
9879  * derived_table (in) : Derived table to be processed.
9880  * derived_alias (in) : The alias of the derived table (also comes from the spec).
9881  */
9882 static PT_NODE *
9884  PT_NODE * derived_alias)
9885 {
9886  PT_NODE *as_attr_list = NULL, *select_list;
9887  int i, id;
9888 
9889  switch (derived_table_type)
9890  {
9891  case PT_IS_SET_EXPR:
9892  /* if derived from a set expression, it better have a set type */
9893  if (derived_table->node_type == PT_NAME && derived_table->info.name.original != NULL
9894  && derived_table->info.name.original[0] != '\0')
9895  {
9896  as_attr_list = pt_name (parser, derived_table->info.name.original);
9897  }
9898  else
9899  { /* generate column name */
9900  id = 0;
9901  as_attr_list = pt_name (parser, mq_generate_name (parser, derived_alias->info.name.original, &id));
9902  }
9903  break;
9904 
9905  case PT_IS_SHOWSTMT:
9906  as_attr_list = pt_get_all_showstmt_attributes_and_types (parser, derived_table);
9907  if (as_attr_list == NULL)
9908  {
9909  PT_INTERNAL_ERROR (parser, "resolution");
9910  return NULL;
9911  }
9912  break;
9913 
9914  case PT_IS_SUBQUERY:
9915  /* must be a subquery derived table */
9916  /* select_list must have passed star expansion */
9917  PT_NODE * att, *col;
9918 
9919  select_list = pt_get_select_list (parser, derived_table);
9920  if (!select_list)
9921  {
9922  return NULL;
9923  }
9924 
9925  for (att = select_list, i = 0; att; att = att->next, i++)
9926  {
9927  if (att->alias_print)
9928  {
9929  col = pt_name (parser, att->alias_print);
9930  }
9931  else
9932  {
9933  if (att->node_type == PT_NAME && att->info.name.original != NULL && att->info.name.original[0] != '\0')
9934  {
9935  col = pt_name (parser, att->info.name.original);
9936  }
9937  else if (att->node_type == PT_VALUE && att->info.value.text != NULL && att->info.value.text[0] != '\0')
9938  {
9939  col = pt_name (parser, att->info.value.text);
9940  }
9941  else if (att->node_type == PT_EXPR || att->node_type == PT_FUNCTION)
9942  {
9943  PARSER_VARCHAR *alias;
9944  alias = pt_print_bytes (parser, att);
9945  col = pt_name (parser, (const char *) alias->bytes);
9946  }
9947  else
9948  { /* generate column name */
9949  id = i;
9950  col = pt_name (parser, mq_generate_name (parser, derived_alias->info.name.original, &id));
9951  }
9952  }
9953 
9954  col->type_enum = att->type_enum;
9955  if (att->data_type)
9956  {
9957  col->data_type = parser_copy_tree_list (parser, att->data_type);
9958  }
9959 
9960  as_attr_list = parser_append_node (col, as_attr_list);
9961  }
9962  break;
9963 
9964  case PT_DERIVED_JSON_TABLE:
9965  assert (derived_table->node_type == PT_JSON_TABLE);
9966 
9967  as_attr_list = pt_get_all_json_table_attributes_and_types (parser, derived_table->info.json_table_info.tree,
9968  derived_alias->info.name.original);
9969  break;
9970 
9971  default:
9972  /* this can't happen since we removed MERGE/CSELECT from grammar */
9973  assert (derived_table_type == PT_IS_CSELECT);
9974  PT_INTERNAL_ERROR (parser, "resolution");
9975  return NULL;
9976  }
9977 
9978  return as_attr_list;
9979 }
9980 
9981 /*
9982  * pt_set_attr_list_types - identify and set the types of attributes
9983  *
9984  * return : void
9985  * parser (in) : Parser context.
9986  * as_attr_list(in/out) : attr list to be processed.
9987  * derived_table_type (in) : Provided by the spec that contains the derived table.
9988  * derived_table (in) : Derived table to be processed.
9989  * parent_spec (in) : The spec where derived table resides.
9990  */
9991 static void
9992 pt_set_attr_list_types (PARSER_CONTEXT * parser, PT_NODE * as_attr_list, PT_MISC_TYPE derived_table_type,
9993  PT_NODE * derived_table, PT_NODE * parent_spec)
9994 {
9995  PT_NODE *elt_type, *select_list;
9996  int col_cnt = pt_length_of_list (as_attr_list), attr_cnt;
9997 
9998  switch (derived_table_type)
9999  {
10000  case PT_IS_SET_EXPR:
10001  /* if derived from a set expression, it better have a set type */
10002  if (!pt_is_set_type (derived_table))
10003  {
10005  pt_short_print (parser, derived_table));
10006  return;
10007  }
10008 
10009  elt_type = derived_table->data_type;
10010 
10011  /* Handle a derived table query on an empty set stored in a host variable (elt_type==NULL) the same way as a NULL
10012  * value. Note that derived table queries on sets of anything will also result in a null elt_type here */
10013  if (PT_IS_NULL_NODE (derived_table) || !elt_type)
10014  {
10015  /* this is to accept a NULL literal value consistently with NULL column values. Unfortunaltely, no type
10016  * information for the column may be deduced. */
10017  as_attr_list->type_enum = PT_TYPE_NULL;
10018  as_attr_list->data_type = NULL;
10019  }
10020  else
10021  {
10022  /*
10023  * Make sure that all elements on the data type list have the
10024  * same type_enum, e.g., that they all represent classes.
10025  */
10026  PT_TYPE_ENUM t = elt_type->type_enum;
10027  PT_NODE *p;
10028  for (p = elt_type->next; p; p = p->next)
10029  {
10030  if (p->type_enum != t)
10031  {
10032  elt_type = NULL;
10033  break;
10034  }
10035  }
10036  if (!elt_type)
10037  {
10039  pt_short_print (parser, derived_table));
10040  return;
10041  }
10042 
10043  /* it should have exactly one derived column */
10044  if (col_cnt > 1)
10045  {
10047  pt_short_print_l (parser, as_attr_list));
10048  return;
10049  }
10050  if (col_cnt < 1)
10051  {
10053  pt_short_print (parser, derived_table));
10054  return;
10055  }
10056 
10057  /* derived column assumes the set's element type */
10058  as_attr_list->type_enum = elt_type->type_enum;
10059  as_attr_list->data_type = parser_copy_tree_list (parser, elt_type);
10060  }
10061 
10062  break;
10063 
10064 
10065  case PT_IS_SHOWSTMT:
10066  {
10067  /* types are already set in pt_get_all_showstmt_attributes_and_types; */
10068  PT_NODE *col = as_attr_list;
10069  while (col)
10070  {
10071  col->line_number = parent_spec->line_number;
10072  col->column_number = parent_spec->column_number;
10073  col = col->next;
10074  }
10075  return;
10076  }
10077 
10078  case PT_IS_SUBQUERY:
10079  /* must be a subquery derived table */
10080  /* select_list must have passed star expansion */
10081  select_list = pt_get_select_list (parser, derived_table);
10082  if (!select_list)
10083  {
10084  return;
10085  }
10086 
10087  /* select_list attributes must match derived columns in number */
10088  attr_cnt = pt_length_of_select_list (select_list, INCLUDE_HIDDEN_COLUMNS);
10089  if (col_cnt != attr_cnt)
10090  {
10092  pt_short_print (parser, parent_spec), attr_cnt, col_cnt);
10093  return;
10094  }
10095  else
10096  {
10097  PT_NODE *col, *att;
10098  /* derived columns assume the type of their matching attributes */
10099  for (col = as_attr_list, att = select_list; col && att; col = col->next, att = att->next)
10100  {
10101  col->type_enum = att->type_enum;
10102  if (att->data_type)
10103  {
10104  col->data_type = parser_copy_tree_list (parser, att->data_type);
10105  }
10106  else
10107  {
10108  parser_free_tree (parser, col->data_type);
10109  col->data_type = NULL;
10110  }
10111  }
10112  }
10113  break;
10114 
10115  case PT_DERIVED_JSON_TABLE:
10116  // nothing to do? Types already set during pt_json_table_gather_attribs ()
10117  return;
10118 
10119  default:
10120  /* this can't happen since we removed MERGE/CSELECT from grammar */
10121  assert (derived_table_type == PT_IS_CSELECT);
10122  PT_INTERNAL_ERROR (parser, "resolution");
10123  return;
10124  }
10125 }
10126 
10127 /*
10128  * pt_count_with_clauses - find if node has WITH clause
10129  * return:
10130  * parser(in):
10131  * node(in): the node to check
10132  * arg(out): count of WITH clauses
10133  * continue_walk(in):
10134  */
10135 static PT_NODE *
10136 pt_count_with_clauses (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10137 {
10138  int *cnt = (int *) arg;
10139 
10140  if (node != NULL && PT_IS_QUERY_NODE_TYPE (node->node_type) && node->info.query.with != NULL)
10141  {
10142  /* node has WITH clause */
10143  (*cnt)++;
10144  }
10145 
10146  return node;
10147 }
10148 
10149 static PT_NODE *
10150 pt_bind_name_to_spec (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10151 {
10152  PT_NODE *spec = REINTERPRET_CAST (PT_NODE *, arg);
10153  if (spec->node_type != PT_SPEC)
10154  {
10155  assert (false);
10156  return node;
10157  }
10158 
10159  if (node->node_type != PT_NAME)
10160  {
10161  // not relevant
10162  return node;
10163  }
10164 
10165  if (pt_resolved (node))
10166  {
10167  assert (node->info.name.spec_id == spec->info.spec.id);
10168  return node;
10169  }
10170 
10171  node->info.name.spec_id = spec->info.spec.id;
10173  node->info.name.meta_class = PT_NORMAL; // so far, only normals are used.
10174  return node;
10175 }
PT_NODE * except_list
Definition: parse_tree.h:2133
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
#define MSGCAT_SEMANTIC_USING_INDEX_ERR_1
#define PT_NAME_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2575
int pt_check_unique_names(PARSER_CONTEXT *parser, const PT_NODE *p)
PT_NODE * pt_name(PARSER_CONTEXT *parser_ptr, const char *name)
PT_NODE * order_by
Definition: parse_tree.h:2769
PT_NODE * pt_resolve_using_index(PARSER_CONTEXT *parser, PT_NODE *index, PT_NODE *from)
DB_OBJECT * pt_resolve_serial(PARSER_CONTEXT *parser, PT_NODE *serial_name_node)
PT_NODE * next
Definition: parse_tree.h:3447
#define MSGCAT_SEMANTIC_IS_NOT_DEFINED
PT_NAME_INFO name
Definition: parse_tree.h:3318
static PT_NODE * pt_json_table_gather_attribs(PARSER_CONTEXT *parser, PT_NODE *json_table_node, void *args, int *continue_walk)
static void pt_resolve_group_having_alias_pt_expr(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_list)
PT_HINT_ENUM hint
Definition: parse_tree.h:2877
PT_NODE * arg_list
Definition: parse_tree.h:2258
short location
#define NO_ERROR
Definition: error_code.h:46
PT_UNION_INFO union_
Definition: parse_tree.h:2782
PT_NODE * pt_insert_entity(PARSER_CONTEXT *parser, PT_NODE *path, PT_NODE *prev_entity, PT_NODE *correlation_entity)
#define DB_GET_ENUM_ELEM_STRING(elem)
Definition: dbtype.h:103
int pt_quick_resolve_names(PARSER_CONTEXT *parser, PT_NODE **spec_p, PT_NODE **node_p, SEMANTIC_CHK_INFO *sc_info)
PT_METHOD_CALL_INFO method_call
Definition: parse_tree.h:3316
void er_stack_push(void)
#define PT_SELECT_INFO_IS_FLAGED(s, f)
Definition: parse_tree.h:2735
PT_NODE * class_specs
Definition: parse_tree.h:2332
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 * as_attr_list
Definition: parse_tree.h:1976
PT_NODE * specs
#define MSGCAT_SEMANTIC_NO_DERIVED_COL_NAM
static const char * pt_get_unique_exposed_name(PARSER_CONTEXT *parser, PT_NODE *first_spec)
#define MSGCAT_SEMANTIC_NO_ATTRIBUTES_IN_CLS
#define PT_IS_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:164
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
DB_OBJECT * object
Definition: parse_tree.h:2864
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
DB_OBJLIST * inheritance
Definition: class_object.h:718
PT_NODE * using_index
Definition: parse_tree.h:2693
#define MSGCAT_SEMANTIC_INCONSISTENT_PATH
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
int pt_resolve_default_value(PARSER_CONTEXT *parser, PT_NODE *name)
PT_MISC_TYPE var_type
Definition: parse_tree.h:2317
PT_NODE * assignment
Definition: parse_tree.h:2861
unsigned int mht_4strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:505
int db_domain_scale(const DB_DOMAIN *domain)
Definition: db_macro.c:4098
enum au_fetchmode AU_FETCHMODE
static int pt_must_have_exposed_name(PARSER_CONTEXT *parser, PT_NODE *p)
PT_NODE * pt_expression_0(PARSER_CONTEXT *parser_ptr, PT_OP_TYPE op)
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
#define MSGCAT_SEMANTIC_MUST_BE_SET_MSET_SEQ
int pt_instnum_compatibility(PT_NODE *expr)
static PT_NODE * pt_resolve_group_having_alias(PARSER_CONTEXT *parser, PT_NODE *node, void *chk_parent, int *continue_walk)
PT_MISC_TYPE call_or_expr
Definition: parse_tree.h:2367
short location
Definition: parse_tree.h:2577
static void pt_bind_type_of_host_var(PARSER_CONTEXT *parser, PT_NODE *hv)
DB_OBJECT * pt_find_users_class(PARSER_CONTEXT *parser, PT_NODE *name)
PT_JSON_TABLE_COLUMN_INFO json_table_column_info
Definition: parse_tree.h:3314
#define PT_EMPTY
Definition: parse_tree.h:616
size_t json_table_column_index
Definition: parse_tree.h:2582
DB_ATTRIBUTE * db_get_class_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:878
#define MSGCAT_SEMANTIC_DUPLICATE_CLASS_OR_ALIAS
static int pt_function_name_is_spec_attr(PARSER_CONTEXT *parser, PT_NODE *name, PT_BIND_NAMES_ARG *bind_arg, int *is_spec_attr)
PT_NODE * from
Definition: parse_tree.h:2678
int db_domain_precision(const DB_DOMAIN *domain)
Definition: db_macro.c:4079
DB_DOMAIN * pt_type_enum_to_db_domain(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:1549
static bool is_pt_name_in_group_having(PT_NODE *node)
PT_MISC_TYPE
Definition: parse_tree.h:983
#define PT_ERROR(parser, node, msg)
Definition: parse_tree.h:54
#define PT_NODE_INIT_OUTERLINK(n)
Definition: parse_tree.h:550
#define LC_DOESNOT_EXIST
static PT_NODE * pt_name_list_diff(PARSER_CONTEXT *parser, PT_NODE *list, PT_NODE *deletions)
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
PT_NODE * Oracle_outerjoin_spec
Definition: parse_tree.h:1708
DB_TYPE
Definition: dbtype_def.h:670
PT_NODE * assignment
Definition: parse_tree.h:2928
static void pt_resolve_natural_join_internal(PARSER_CONTEXT *parser, PT_NODE *join_lhs, PT_NODE *join_rhs)
static PT_NODE * pt_bind_reserved_name(PARSER_CONTEXT *parser, PT_NODE *in_node, PT_NODE *spec)
#define PT_NAME_INFO_FILL_DEFAULT
Definition: parse_tree.h:2565
CASE_SENSITIVENESS
Definition: parser.h:53
PT_RESERVED_NAME pt_Reserved_name_table[]
Definition: parse_tree.c:92
#define ER_FAILED
Definition: error_code.h:47
static int generate_natural_join_attrs_from_db_attrs(DB_ATTRIBUTE *db_attrs, NATURAL_JOIN_ATTR_INFO **attrs_p)
#define MSGCAT_SEMANTIC_OUT_OF_MEMORY
PT_RESERVED_NAME_TYPE
Definition: parse_tree.h:2387
short location
Definition: parse_tree.h:2152
#define PT_EXPR_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2239
static PT_NODE * pt_common_attribute(PARSER_CONTEXT *parser, PT_NODE *p, PT_NODE *q)
PT_MISC_TYPE flavor
Definition: parse_tree.h:2148
#define MSGCAT_SEMANTIC_PREFIX_IN_FUNC_INDX_NOT_ALLOWED
unsigned short correlation_level
PT_NODE * search_cond
Definition: parse_tree.h:2925
PT_NODE * arg3
Definition: parse_tree.h:2202
static int generate_natural_join_attrs_from_subquery(PT_NODE *subquery_attrs_list, NATURAL_JOIN_ATTR_INFO **attrs_p)
TP_DOMAIN * domain
Definition: class_object.h:444
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
PT_HINT_ENUM hint
Definition: parse_tree.h:2074
#define DB_GET_ENUMERATION(v)
Definition: dbtype.h:97
PT_NODE * pt_get_select_list(PARSER_CONTEXT *parser, PT_NODE *query)
Definition: query_result.c:404
#define LC_ERROR
struct extra_specs_frame * next
PT_NODE * arg2
Definition: parse_tree.h:2664
int correlation_level
Definition: parse_tree.h:2745
PT_EXTRA_SPECS_FRAME * spec_frames
static PT_NODE * pt_resolve_natural_join(PARSER_CONTEXT *parser, PT_NODE *node, void *chk_parent, int *continue_walk)
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
const void * mht_put(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1778
enum pt_type_enum PT_TYPE_ENUM
Definition: parse_tree.h:962
static PT_NODE * pt_get_attr_list_of_derived_table(PARSER_CONTEXT *parser, PT_MISC_TYPE derived_table_type, PT_NODE *derived_table, PT_NODE *derived_name)
SM_PARTITION * partition
Definition: class_object.h:760
DB_DOMAIN * db_domain_next(const DB_DOMAIN *domain)
Definition: db_macro.c:3974
#define PT_IS_SPEC_FLAG_SET(spec_, flags_)
Definition: parse_tree.h:653
static int pt_find_name_in_spec(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *name)
static PT_NODE * pt_resolve_correlation(PARSER_CONTEXT *parser, PT_NODE *in_node, PT_NODE *scope, PT_NODE *exposed_spec, int col_name, PT_NODE **p_entity)
#define pt_is_query(n)
Definition: parse_tree.h:258
PT_NODE * with
Definition: parse_tree.h:2075
PT_NODE * spec
Definition: parse_tree.h:2859
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
static void pt_bind_spec_attrs(PARSER_CONTEXT *parser, PT_NODE *spec)
FUNC_TYPE
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
DB_ATTRIBUTE * db_get_attribute_force(DB_OBJECT *obj, const char *name)
int db_domain_collation_id(const DB_DOMAIN *domain)
Definition: db_macro.c:4134
PT_TYPE_ENUM pt_db_to_type_enum(const DB_TYPE t)
Definition: parse_dbi.c:2595
DB_VALUE * pt_host_var_db_value(PARSER_CONTEXT *parser, PT_NODE *hv)
Definition: parse_dbi.c:3160
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
PT_NODE * pt_bind_type_from_dbval(PARSER_CONTEXT *parser, PT_NODE *node, DB_VALUE *val)
Definition: parse_dbi.c:3067
PT_NODE * partition
Definition: parse_tree.h:2142
PT_NODE * path_correlation
Definition: parse_tree.h:2550
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
#define MSGCAT_SEMANTIC_SPEC_EXCLUDES_ALL
unsigned int custom_print
Definition: parse_tree.h:2554
PT_SPEC_FLAG
Definition: parse_tree.h:1517
#define PT_SHOULD_BIND_RESERVED_NAME(spec_)
Definition: parse_tree.h:686
struct sm_component * next
Definition: class_object.h:384
union pt_query_info::@124 q
PT_NODE * class_specs
Definition: parse_tree.h:2062
#define MSGCAT_SEMANTIC_INVALID_PARTITION_REQUEST
PT_NODE * path_entities
Definition: parse_tree.h:2138
static PT_NODE * pt_resolve_spec_to_cte(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * node
Definition: parse_tree.h:3133
PT_SCOPE_INFO scope
Definition: parse_tree.h:3333
static int pt_find_class_attribute(PARSER_CONTEXT *parser, PT_NODE *cls, PT_NODE *attr)
struct pt_merge_info::@125 update
SM_FUNCTION_INFO * func_index_info
Definition: class_object.h:541
#define PT_IS_DOT_NODE(n)
Definition: parse_tree.h:302
const char * pname
Definition: class_object.h:694
unsigned int custom_print
Definition: parse_tree.h:3556
PT_NODE * pt_bind_values_to_hostvars(PARSER_CONTEXT *parser, PT_NODE *node)
#define PT_IS_NULL_NODE(e)
Definition: parse_tree.h:122
PT_NODE * group_by
Definition: parse_tree.h:2688
#define MSGCAT_SEMANTIC_CLASS_DOES_NOT_HAVE
PT_NODE * pt_flat_spec_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
struct sm_class_constraint * next
Definition: class_object.h:530
int er_errid(void)
SHOWSTMT_TYPE show_type
Definition: parse_tree.h:2815
PT_NODE * pt_append_query_select_list(PARSER_CONTEXT *parser, PT_NODE *query, PT_NODE *attrs)
#define PT_NAME_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2574
PT_NODE_LIST_INFO node_list
Definition: parse_tree.h:3320
NATURAL_JOIN_ATTR_INFO * next
static PT_NODE * pt_bind_parameter(PARSER_CONTEXT *parser, PT_NODE *parameter)
#define MSGCAT_SEMANTIC_ARG_IS_NOT_AN_OBJECT
static PT_NODE * pt_copy_data_type_entity(PARSER_CONTEXT *parser, PT_NODE *data_type)
static PT_NODE * pt_resolve_spec_to_cte_and_count(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_count_ctes_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void pt_set_fill_default_in_path_expression(PT_NODE *node)
PT_NODE * attr_list
Definition: parse_tree.h:2333
static PT_NODE * pt_mark_location(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_bind_parameter_path(PARSER_CONTEXT *parser, PT_NODE *path)
#define MSGCAT_SEMANTIC_AMBIGUOUS_REF_TO
DB_ATTRIBUTE * showstmt_get_attributes(SHOWSTMT_TYPE show_type)
Definition: show_meta.c:753
PT_WITH_CLAUSE_INFO with_clause
Definition: parse_tree.h:3362
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
#define MSGCAT_SEMANTIC_CYCLIC_SELECTOR
PT_NODE * class_specs
Definition: parse_tree.h:2860
int db_attribute_is_shared(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1429
#define AU_ALTER
Definition: authenticate.h:73
PT_NODE * data_type
Definition: parse_tree.h:3453
PT_NODE * pt_eval_value_path(PARSER_CONTEXT *parser, PT_NODE *path)
DB_ATTRIBUTE * db_get_attribute_by_name(const char *class_name, const char *attribute_name)
Definition: db_info.c:823
PT_NODE * for_update
Definition: parse_tree.h:2705
size_t json_table_column_count
static PT_NODE * pt_get_all_showstmt_attributes_and_types(PARSER_CONTEXT *parser, PT_NODE *derived_table)
PT_DOT_INFO dot
Definition: parse_tree.h:3287
PT_NODE * arg2
Definition: parse_tree.h:2086
SM_CLASS_CONSTRAINT * sm_class_constraints(MOP classop)
PT_RESERVED_NAME_ID id
Definition: parse_tree.h:2469
PT_NODE * index_ss
Definition: parse_tree.h:2698
static void fill_in_insert_default_function_arguments(PARSER_CONTEXT *parser, PT_NODE *const node)
#define PT_NODE_COPY_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:560
PT_JSON_TABLE_INFO json_table_info
Definition: parse_tree.h:3312
const char * name
PT_CTE_INFO cte
Definition: parse_tree.h:3282
#define REINTERPRET_CAST(dest_type, expr)
Definition: porting.h:1080
#define MSGCAT_SEMANTIC_AMBIGUOUS_EXPOSED_NM
#define MSGCAT_SEMANTIC_GT_1_DERIVED_COL_NAM
int jsp_is_exist_stored_procedure(const char *name)
Definition: jsp_cl.c:267
#define CT_SERIAL_NAME
Definition: transform.h:135
int Oracle_outerjoin_attr_num
Definition: parse_tree.h:1709
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
static int pt_spec_in_domain(PT_NODE *cls, PT_NODE *lst)
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
static PT_NODE * pt_make_flat_list_from_data_types(PARSER_CONTEXT *parser, PT_NODE *res_list, PT_NODE *entity)
PT_NODE * indexed_class
Definition: parse_tree.h:1927
PT_NODE * or_next
Definition: parse_tree.h:3448
const char * mq_generate_name(PARSER_CONTEXT *parser, const char *root, int *version)
PT_NODE * pt_resolve_star(PARSER_CONTEXT *parser, PT_NODE *from, PT_NODE *attr)
unsigned char bytes[1]
Definition: parse_tree.h:3431
PT_NODE * mq_regenerate_if_ambiguous(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *statement, PT_NODE *from)
#define PT_ERRORmf3(parser, node, setNo, msgNo, arg1, arg2, arg3)
Definition: parse_tree.h:66
#define MSGCAT_SEMANTIC_EXCEPTSPEC_NOT_HEIR
void mht_destroy(MHT_TABLE *ht)
Definition: memory_hash.c:1140
static void free_natural_join_attrs(NATURAL_JOIN_ATTR_INFO *attrs)
PT_MISC_TYPE class_or_inst
Definition: parse_tree.h:2368
static PT_NODE * pt_resolve_vclass_args(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
char * parser_print_function_index_expr(PARSER_CONTEXT *parser, const PT_NODE *expr)
static PT_NODE * pt_is_correlation_name(PARSER_CONTEXT *parser, PT_NODE *scope, PT_NODE *nam)
#define MSGCAT_SEMANTIC_OUTERJOIN_PATH_EXPR
static PT_NODE * pt_mark_group_having_pt_name(PARSER_CONTEXT *parser, PT_NODE *node, void *chk_parent, int *continue_walk)
void * pt_node_etc(const PT_NODE *col)
#define PT_NAME_DEFAULTF_ACCEPTS
Definition: parse_tree.h:2571
PT_MISC_TYPE derived_table_type
Definition: parse_tree.h:2147
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
PT_NODE * arg1
Definition: parse_tree.h:2663
static int pt_resolve_hint_args(PARSER_CONTEXT *parser, PT_NODE **arg_list, PT_NODE *spec_list, bool discard_no_match)
#define PT_IS_SELECT(n)
Definition: parse_tree.h:284
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
static PT_NODE * pt_make_subclass_list(PARSER_CONTEXT *parser, DB_OBJECT *db, int line_num, int col_num, UINTPTR id, PT_MISC_TYPE meta_class, MHT_TABLE *names_mht)
PT_ALTER_INFO alter
Definition: parse_tree.h:3268
PT_HINT_ENUM
Definition: parse_tree.h:1161
PT_NODE * arg2
Definition: parse_tree.h:2198
static void pt_bind_scope(PARSER_CONTEXT *parser, PT_BIND_NAMES_ARG *bind_arg)
#define PT_EXPR_INFO_RIGHT_OUTER
Definition: parse_tree.h:2219
PT_NODE * index_name
Definition: parse_tree.h:1929
PT_NODE * cte_definition_list
Definition: parse_tree.h:3221
PT_FUNCTION_INFO function
Definition: parse_tree.h:3301
#define MSGCAT_SEMANTIC_IS_NOT_OBJECT_TYPE
#define ER_QPROC_SERIAL_NOT_FOUND
Definition: error_code.h:965
static PT_NODE * pt_count_with_clauses(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
DB_OBJECT * db_object
Definition: parse_tree.h:2546
#define NULL_DEFAULT_EXPRESSION_OPERATOR
Definition: dbtype_def.h:659
PT_OP_TYPE pt_op_type_from_default_expr_type(DB_DEFAULT_EXPR_TYPE expr_type)
PARSER_VARCHAR * json_schema
Definition: parse_tree.h:2054
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)
static void pt_resolve_group_having_alias_pt_name(PARSER_CONTEXT *parser, PT_NODE **node_p, PT_NODE *select_list)
int Oracle_outerjoin_subq_num
Definition: parse_tree.h:1710
PT_NODE * use_nl_hint
Definition: parse_tree.h:2871
PT_NODE * pt_find_spec(PARSER_CONTEXT *parser, const PT_NODE *from, const PT_NODE *name)
#define PT_IS_QUERY_NODE_TYPE(x)
Definition: parse_tree.h:115
PT_NODE * parser_walk_leaves(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE_WALK_FUNCTION pre_function, void *pre_argument, PT_NODE_WALK_FUNCTION post_function, void *post_argument)
PT_SPEC_FLAG flag
Definition: parse_tree.h:2155
PT_POINTER_INFO pointer
Definition: parse_tree.h:3359
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define PT_SPEC_IS_ENTITY(spec_)
Definition: parse_tree.h:698
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
PT_TYPE_ENUM virt_type_enum
Definition: parse_tree.h:2042
static int pt_find_attr_in_class_list(PARSER_CONTEXT *parser, PT_NODE *flat, PT_NODE *attr)
PT_NODE * odku_assignments
Definition: parse_tree.h:2341
#define MSGCAT_SEMANTIC_INCORRECT_UNION_IN_CTE
#define PT_NAME_ALLOW_REUSABLE_OID
Definition: parse_tree.h:2568
const char * pt_show_type_enum(PT_TYPE_ENUM t)
PT_NODE * cte_pointer
Definition: parse_tree.h:2132
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
PT_NODE * on_cond
Definition: parse_tree.h:2149
PT_NODE * entity
Definition: parse_tree.h:2038
static PT_NODE * pt_resolve_partition_spec(PARSER_CONTEXT *parser, PT_NODE *partition_spec, PT_NODE *spec_parent, bool fo_update)
bool pt_eval_path_expr(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *val)
const char * db_json_get_schema_raw_from_validator(JSON_VALIDATOR *val)
Definition: db_json.cpp:2310
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
PT_NODE * recursive_part
Definition: parse_tree.h:1978
static void pt_get_attr_data_type(PARSER_CONTEXT *parser, DB_ATTRIBUTE *att, PT_NODE *attr)
DB_DOMAIN * db_method_arg_domain(DB_METHOD *method, int arg)
Definition: db_info.c:1671
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
PT_NODE * top_node
Definition: parse_tree.h:1707
PT_MISC_TYPE all_distinct
Definition: parse_tree.h:2746
int intl_identifier_cmp(const char *str1, const char *str2)
PT_NODE * method_name
Definition: parse_tree.h:2363
static FUNC_TYPE pt_find_function_type(const char *name)
static void pt_set_attr_list_types(PARSER_CONTEXT *parser, PT_NODE *as_attr_list, PT_MISC_TYPE derived_table_type, PT_NODE *derived_table, PT_NODE *parent_spec)
const char * original
Definition: parse_tree.h:2544
PT_HINT_ENUM hint
Definition: parse_tree.h:2707
int intl_identifier_casecmp(const char *str1, const char *str2)
#define PT_NAME_INFO_STAR
Definition: parse_tree.h:2560
PT_NODE * pt_make_string_value(PARSER_CONTEXT *parser, const char *value_string)
#define PT_NAME_INFO_DOT_STAR
Definition: parse_tree.h:2561
#define DOM_GET_ENUM_ELEM(dom, idx)
Definition: object_domain.h:44
int pt_name_occurs_in_from_list(PARSER_CONTEXT *parser, const char *name, PT_NODE *from_list)
Definition: compile.c:1545
PT_NODE * cte_name
Definition: parse_tree.h:2131
#define TP_DOMAIN_COLLATION(dom)
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
#define PT_GET_RESERVED_NAME_FIRST_AND_LAST(type, first, last)
Definition: parse_tree.h:2501
static PT_NODE * pt_set_reserved_name_key_type(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
const char * db_error_string(int level)
Definition: db_admin.c:2116
DB_OBJECT * db_domain_class(const DB_DOMAIN *domain)
Definition: db_macro.c:4030
PT_NODE * parser_copy_tree(PARSER_CONTEXT *parser, const PT_NODE *tree)
#define DOM_GET_ENUM_ELEMS_COUNT(dom)
Definition: object_domain.h:42
PT_NODE * pt_semantic_type(PARSER_CONTEXT *parser, PT_NODE *tree, SEMANTIC_CHK_INFO *sc_info)
static PT_NODE * pt_object_to_data_type(PARSER_CONTEXT *parser, PT_NODE *class_list)
PT_NODE * pt_sm_attribute_default_value_to_node(PARSER_CONTEXT *parser, const SM_ATTRIBUTE *sm_attr)
Definition: parse_dbi.c:516
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
PT_SHOWSTMT_INFO showstmt
Definition: parse_tree.h:3342
PT_NODE * having
Definition: parse_tree.h:2692
DB_OBJECT * db_get_object(const DB_VALUE *value)
PT_NODE * from
Definition: parse_tree.h:2686
#define PT_SELECT_INFO_COLS_SCHEMA
Definition: parse_tree.h:2721
PT_NODE * enumeration
Definition: parse_tree.h:2039
UINTPTR spec_id
Definition: parse_tree.h:2543
PT_NODE * use_merge_hint
Definition: parse_tree.h:2873
PT_NODE * value_clauses
Definition: parse_tree.h:2938
#define PT_IS_SPEC_REAL_TABLE(spec_)
Definition: parse_tree.h:707
#define TP_DOMAIN_TYPE(dom)
static PT_NODE * pt_expand_external_path(PARSER_CONTEXT *parser, PT_NODE *in_node, PT_NODE **p_entity)
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
void * mht_get(MHT_TABLE *ht, const void *key)
Definition: memory_hash.c:1419
int pt_str_compare(const char *p, const char *q, CASE_SENSITIVENESS case_flag)
SP_PARSER_CTX * parser
PT_NODE * arg1
Definition: parse_tree.h:2197
PT_NODE * pt_find_entity(PARSER_CONTEXT *parser, const PT_NODE *scope, UINTPTR id)
static NATURAL_JOIN_ATTR_INFO * get_natural_join_attrs_from_pt_spec(PARSER_CONTEXT *parser, PT_NODE *node)
SEMANTIC_CHK_INFO * sc_info
#define NULL
Definition: freelistheap.h:34
PT_NODE * as_attr_list
Definition: parse_tree.h:2136
int db_domain_codeset(const DB_DOMAIN *domain)
Definition: db_macro.c:4116
static PT_NODE * pt_find_outer_entity_in_scopes(PARSER_CONTEXT *parser, SCOPES *scopes, UINTPTR spec_id, short *scope_location)
#define MSGCAT_SEMANTIC_NESTED_WITH
static int pt_check_unique_exposed(PARSER_CONTEXT *parser, const PT_NODE *p)
PT_NODE * use_nl_hint
Definition: parse_tree.h:2069
const char * er_msg(void)
#define DB_IS_DATETIME_DEFAULT_EXPR(v)
Definition: dbtype_def.h:661
#define LC_EXIST
DB_OBJECT * db_get_class(MOP obj)
Definition: db_info.c:589
PT_NODE * value_clauses
Definition: parse_tree.h:2334
static PT_NODE * pt_create_pt_name(PARSER_CONTEXT *parser, PT_NODE *spec, NATURAL_JOIN_ATTR_INFO *attr)
PT_MISC_TYPE is_subquery
Definition: parse_tree.h:2747
if(extra_options)
Definition: dynamic_load.c:958
PT_INDEX_INFO index
Definition: parse_tree.h:3308
#define PT_NAMES_HASH_SIZE
#define MSGCAT_SEMANTIC_UNDEFINED_ARGUMENT
#define PT_SPEC_IS_DERIVED(spec_)
Definition: parse_tree.h:690
char * pt_append_string(const PARSER_CONTEXT *parser, const char *old_string, const char *new_tail)
Definition: parse_tree.c:980
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
PARSER_VARCHAR * pt_print_bytes(PARSER_CONTEXT *parser, const PT_NODE *node)
#define PT_ERRORc(parser, node, msg)
Definition: parse_tree.h:55
static PT_NODE * pt_check_Oracle_outerjoin(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_insert_conjunct(PARSER_CONTEXT *parser, PT_NODE *path_dot, PT_NODE *prev_entity)
#define MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST
#define MSGCAT_SEMANTIC_SELECTOR_TO_NON_CLS
#define MSGCAT_SEMANTIC_INVALID_INTERNAL_FUNCTION
#define MSGCAT_SEMANTIC_WANT_NO_DERIVED_COLS
MHT_TABLE * mht_create(const char *name, int est_size, unsigned int(*hash_func)(const void *key, unsigned int ht_size), int(*cmp_func)(const void *key1, const void *key2))
Definition: memory_hash.c:894
static PT_NODE * pt_get_all_json_table_attributes_and_types(PARSER_CONTEXT *parser, PT_NODE *json_table_node, const char *json_table_alias)
void pt_null_etc(PT_NODE *node)
#define MSGCAT_SEMANTIC_WANT_NO_REF_TO_DRVTB
#define PT_SPEC_IS_CTE(spec_)
Definition: parse_tree.h:694
PT_NODE * pt_continue_walk(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * with
Definition: parse_tree.h:2778
int pt_check_same_datatype(const PARSER_CONTEXT *parser, const PT_NODE *p, const PT_NODE *q)
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
short location
Definition: parse_tree.h:2243
int db_is_system_class(MOP op)
Definition: db_info.c:502
PT_NODE * use_idx
Definition: parse_tree.h:2697
struct db_objlist * next
Definition: dbtype_def.h:442
static PT_NODE * pt_bind_cte_self_references_types(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_make_flat_name_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *spec_parent, bool for_update)
static void pt_mark_function_index_expression(PARSER_CONTEXT *parser, PT_NODE *expr, PT_BIND_NAMES_ARG *bind_arg)
PT_NODE * with
Definition: parse_tree.h:2878
int btree_get_index_key_type(BTID btid, TP_DOMAIN **key_type_p)
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
#define MSGCAT_CATALOG_CUBRID
const char * text
Definition: parse_tree.h:3056
#define MSGCAT_SEMANTIC_PARTITION_DOES_NOT_EXIST
PT_NODE * use_idx_hint
Definition: parse_tree.h:2872
#define PT_NAME_INFO_EXTERNAL
Definition: parse_tree.h:2563
PT_NODE * pt_add_class_to_entity_list(PARSER_CONTEXT *parser, DB_OBJECT *class_, PT_NODE *entity, const PT_NODE *parent, UINTPTR id, PT_MISC_TYPE meta_class)
DB_DOMAIN * db_attribute_domain(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1165
#define MSGCAT_SEMANTIC_OUTERJOIN_SCOPE
DB_VALUE * pt_find_value_of_label(const char *label)
PT_NODE * set
Definition: parse_tree.h:3047
void er_stack_pop(void)
int pt_resolved(const PT_NODE *expr)
DB_METHOD * db_get_method(DB_OBJECT *obj, const char *name)
Definition: db_info.c:1454
unsigned si_datetime
Definition: parse_tree.h:3464
PT_NODE * parser_append_node(PT_NODE *node, PT_NODE *list)
struct db_object * op
Definition: dbtype_def.h:443
char * pt_short_print(PARSER_CONTEXT *parser, const PT_NODE *node)
TP_DOMAIN_COLL_ACTION collation_flag
Definition: object_domain.h:94
const char * generic_name
Definition: parse_tree.h:2261
PT_NODE * parser_new_node(PARSER_CONTEXT *parser, PT_NODE_TYPE node_type)
static void error(const char *msg)
Definition: gencat.c:331
static PT_NODE * pt_find_path_entity(PARSER_CONTEXT *parser, PT_NODE *scope, PT_NODE *match)
#define PT_NODE_MOVE_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:572
static PT_NODE * pt_bind_name_to_spec(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_CTE_NAME_AMBIGUITY
void parser_free_node(const PARSER_CONTEXT *parser, PT_NODE *node)
Definition: parse_tree.c:869
static const char * CPTR_PT_NAME_IN_GROUP_HAVING
#define MSGCAT_SEMANTIC_CLASSES_HAVE_NO_ATTR
PT_NODE * name
Definition: parse_tree.h:1975
SM_CLASS_CONSTRAINT * classobj_find_class_index(SM_CLASS *class_, const char *name)
int locator_does_exist_object(MOP mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:3242
#define AU_SELECT
Definition: authenticate.h:69
#define MSGCAT_SET_ERROR
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
PT_NODE * index_ls
Definition: parse_tree.h:2699
bool pt_name_equal(PARSER_CONTEXT *parser, const PT_NODE *name1, const PT_NODE *name2)
const char * pt_partition_name(PARSER_CONTEXT *parser, const char *class_name, const char *partition)
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
const char * default_expr_format
Definition: dbtype_def.h:1206
static PT_NODE * pt_get_all_attributes_and_types(PARSER_CONTEXT *parser, PT_NODE *cls, PT_NODE *from)
#define PT_NAME_INFO_GENERATED_OID
Definition: parse_tree.h:2566
#define ER_AU_SELECT_FAILURE
Definition: error_code.h:221
DB_ATTRIBUTE * db_get_attributes_force(DB_OBJECT *obj)
PT_NODE * ordered_hint
Definition: parse_tree.h:2068
static int pt_resolve_hint(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_resolve_names(PARSER_CONTEXT *parser, PT_NODE *statement, SEMANTIC_CHK_INFO *sc_info)
PT_NODE * pt_resolve_cte_specs(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * use_idx_hint
Definition: parse_tree.h:2070
PT_NODE * into
Definition: parse_tree.h:2923
#define MSGCAT_SET_PARSER_SEMANTIC
PT_NODE * pt_set_is_view_spec(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_UNKNOWN_FUNCTION
static PT_NODE * pt_find_entity_in_scopes(PARSER_CONTEXT *parser, SCOPES *scopes, UINTPTR spec_id)
#define PT_SELECT_INFO_ANSI_JOIN
Definition: parse_tree.h:2714
static PT_NODE * pt_make_method_call(PARSER_CONTEXT *parser, PT_NODE *node, PT_BIND_NAMES_ARG *bind_arg)
SM_PARTITION * partition
Definition: parse_tree.h:2549
static PT_NODE * pt_bind_value_to_hostvar_local(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_SELECTOR_DEFINE_SELF
#define DB_SET_ENUM_ELEM_CODESET(elem, cs)
Definition: dbtype.h:111
static PT_NODE * pt_unwhacked_spec(PARSER_CONTEXT *parser, PT_NODE *scope, PT_NODE *spec)
DB_VALUE sys_datetime
Definition: parse_tree.h:3580
struct pt_merge_info::@126 insert
#define strlen(s1)
Definition: intl_support.c:43
int Oracle_outerjoin_path_num
Definition: parse_tree.h:1711
char * prm_get_string_value(PARAM_ID prm_id)
void pt_no_double_insert_assignments(PARSER_CONTEXT *parser, PT_NODE *stmt)
static void pt_bind_names_in_with_clause(PARSER_CONTEXT *parser, PT_NODE *node, PT_BIND_NAMES_ARG *bind_arg)
PT_NODE * default_value
Definition: parse_tree.h:2553
DB_METHOD * db_get_class_method(DB_OBJECT *obj, const char *name)
Definition: db_info.c:1484
SM_COMPONENT header
Definition: class_object.h:441
PT_NODE * pt_point(PARSER_CONTEXT *parser, const PT_NODE *in_tree)
PT_NODE * non_recursive_part
Definition: parse_tree.h:1977
PT_NODE * attr_list
Definition: parse_tree.h:2937
static PT_NODE * pt_mark_pt_name(PARSER_CONTEXT *parser, PT_NODE *node, void *chk_parent, int *continue_walk)
#define PT_SELECT_INFO_ORACLE_OUTER
Definition: parse_tree.h:2715
#define MSGCAT_SEMANTIC_WANT_SINGLE_TABLE_IN
PT_OP_TYPE
Definition: parse_tree.h:1320
static void pt_bind_names_in_cte(PARSER_CONTEXT *parser, PT_NODE *node, PT_BIND_NAMES_ARG *bind_arg)
static void pt_bind_names_merge_insert(PARSER_CONTEXT *parser, PT_NODE *node, PT_BIND_NAMES_ARG *bind_arg, SCOPES *scopestack, PT_EXTRA_SPECS_FRAME *specs_frame)
#define PT_SELECT_FULL_INFO_COLS_SCHEMA
Definition: parse_tree.h:2722
DB_OBJECT * virt_object
Definition: parse_tree.h:2040
void pt_resolve_object(PARSER_CONTEXT *parser, PT_NODE *node)
#define PT_NAME_FOR_UPDATE
Definition: parse_tree.h:2570
int lang_set_flag_from_lang(const char *lang_str, bool has_user_format, bool has_user_lang, int *flag)
bool prm_get_bool_value(PARAM_ID prm_id)
int jsp_get_return_type(const char *name)
Definition: jsp_cl.c:287
JSON_VALIDATOR * json_validator
int intl_mbs_casecmp(const char *mbs1, const char *mbs2)
Definition: intl_support.c:358
int pt_is_attr(PT_NODE *node)
PT_RESERVED_NAME_ID reserved_id
Definition: parse_tree.h:2581
PT_MISC_TYPE only_all
Definition: parse_tree.h:2145
#define MSGCAT_SEMANTIC_ATT_CNT_NE_DERIVED_C
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
void er_clear(void)
#define PT_IS_N_COLUMN_UPDATE_EXPR(n)
Definition: parse_tree.h:422
static PT_NODE * pt_create_pt_expr_and_node(PARSER_CONTEXT *parser, PT_NODE *arg1, PT_NODE *arg2)
static PT_NODE * pt_is_on_list(PARSER_CONTEXT *parser, const PT_NODE *p, const PT_NODE *list)
PT_DELETE_INFO delete_
Definition: parse_tree.h:3285
static PT_NODE * pt_lookup_entity(PARSER_CONTEXT *parser, PT_NODE *path_entities, PT_NODE *expr)
void * etc
Definition: parse_tree.h:3450
#define MSGCAT_SEMANTIC_USING_INDEX_ERR_2
DB_TYPE db_attribute_type(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1000
#define MSGCAT_SEMANTIC_SELECTOR_UNRESOLVED
#define MSGCAT_SEMANTIC_OUTERJOIN_JOIN_COND_SUBQ
#define PT_CHECK_RESERVED_NAME_BIND(spec_, reserved_id)
Definition: parse_tree.h:2528
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
DB_ATTRIBUTE * db_get_class_attributes(DB_OBJECT *obj)
Definition: db_info.c:939
PT_NODE * spec
Definition: parse_tree.h:2061
PT_NODE * ordered
Definition: parse_tree.h:2695
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
PT_VALUE_INFO value
Definition: parse_tree.h:3358
int pt_length_of_select_list(PT_NODE *list, int hidden_col)
int db_make_null(DB_VALUE *value)
char * msgcat_message(int cat_id, int set_id, int msg_id)
static PT_NODE * pt_create_pt_expr_equal_node(PARSER_CONTEXT *parser, PT_NODE *arg1, PT_NODE *arg2)
static PT_NODE * pt_bind_names(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
SCOPES * next
PT_NODE * list
Definition: parse_tree.h:2685
PT_NODE * use_merge
Definition: parse_tree.h:2700
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define MSGCAT_SEMANTIC_USING_INDEX_ERR_3
PT_OP_TYPE op
Definition: parse_tree.h:2200
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
unsigned short correlation_level
Definition: parse_tree.h:2555
#define pt_is_set_type(n)
Definition: parse_tree.h:267
static WHEN_DESC on_error
PT_NODE * path_conjuncts
Definition: parse_tree.h:2139
#define PT_SPEC_SPECIAL_INDEX_SCAN(spec_)
Definition: parse_tree.h:656
#define MSGCAT_SEMANTIC_SELECTOR_REDEFINED
TP_DOMAIN * tp_domain_resolve(DB_TYPE domain_type, DB_OBJECT *class_obj, int precision, int scale, TP_DOMAIN *setdomain, int collation)
PT_NODE * parser_reinit_node(PT_NODE *node)
PT_JOIN_TYPE
Definition: parse_tree.h:1149
SM_INDEX_STATUS index_status
Definition: class_object.h:544
#define PT_EXPR_INFO_LEFT_OUTER
Definition: parse_tree.h:2218
#define MSGCAT_SEMANTIC_DOM_OBJ_HASNO_ATT_X
PT_NODE * create_index
Definition: parse_tree.h:1826
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
#define MSGCAT_SEMANTIC_PATH_CORR_OUTSIDE
PT_NODE * pt_cnf(PARSER_CONTEXT *parser, PT_NODE *node)
Definition: cnf.c:941
#define ER_AU_AUTHORIZATION_FAILURE
Definition: error_code.h:220
#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_domain_to_data_type(PARSER_CONTEXT *parser, DB_DOMAIN *domain)
static bool pt_resolve_method_type(PARSER_CONTEXT *parser, PT_NODE *node)
#define MSGCAT_SEMANTIC_GT_1_SET_ELEM_TYPE
const char * resolved
Definition: parse_tree.h:2545
#define PT_SELECT_INFO_FOR_UPDATE
Definition: parse_tree.h:2730
static PT_NODE * pt_undef_names_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_METH_DOESNT_EXIST
PT_NODE * using_clause
Definition: parse_tree.h:2924
#define TP_DOMAIN_CODESET(dom)
int parser_function_code
static PT_NODE * pt_get_resolution(PARSER_CONTEXT *parser, PT_BIND_NAMES_ARG *bind_arg, PT_NODE *scope, PT_NODE *in_node, PT_NODE **p_entity, int col_name)
int pt_type_generic_func(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_bind_param_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_undef_names_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * use_nl
Definition: parse_tree.h:2696
static void pt_resolve_group_having_alias_internal(PARSER_CONTEXT *parser, PT_NODE **node_p, PT_NODE *select_list)
static PT_NODE * pt_clear_Oracle_outerjoin_spec_id(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * pt_dbval_to_value(PARSER_CONTEXT *parser, const DB_VALUE *val)
Definition: parse_dbi.c:574
#define DB_GET_ENUM_ELEM_CODESET(elem)
Definition: dbtype.h:108
static void pt_bind_names_merge_update(PARSER_CONTEXT *parser, PT_NODE *node, PT_BIND_NAMES_ARG *bind_arg, SCOPES *scopestack, PT_EXTRA_SPECS_FRAME *specs_frame)
#define MSGCAT_SEMANTIC_SELECTOR_NOT_SUBCLASS
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
static bool natural_join_equal_attr(NATURAL_JOIN_ATTR_INFO *lhs, NATURAL_JOIN_ATTR_INFO *rhs)
#define MSGCAT_SEMANTIC_METH_NOT_TYPED
PT_NODE * object_parameter
Definition: parse_tree.h:2865
MOP do_get_serial_obj_id(DB_IDENTIFIER *serial_obj_id, DB_OBJECT *serial_class_mop, const char *serial_name)
PT_NODE * ordered_hint
Definition: parse_tree.h:2870
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
#define pt_is_const(n)
Definition: parse_tree.h:271
int mht_compare_strings_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:767
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
#define PT_SPEC_GET_RESERVED_NAME_TYPE(spec_)
Definition: parse_tree.h:661
PT_HOST_VAR_INFO host_var
Definition: parse_tree.h:3307
#define PT_NAME_INFO_DOT_NAME
Definition: parse_tree.h:2559
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)
TP_DOMAIN_COLL_ACTION collation_flag
Definition: parse_tree.h:2048
#define PT_EXPR_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2238
PT_NODE * spec_parent
Definition: parse_tree.h:3421
#define PT_ERRORf(parser, node, msg, arg1)
Definition: parse_tree.h:57
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
#define ER_OBJ_INVALID_METHOD
Definition: error_code.h:279
static void pt_resolve_group_having_alias_pt_sort_spec(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_list)
PT_NODE * parser_copy_tree_list(PARSER_CONTEXT *parser, PT_NODE *tree)
PT_RESERVED_NAME_ID
Definition: parse_tree.h:2397
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
static PT_NODE * pt_resolve_star_reserved_names(PARSER_CONTEXT *parser, PT_NODE *from)
const char ** p
Definition: dynamic_load.c:945
cubxasl::json_table::column json_table_column
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
DB_DEFAULT_EXPR_TYPE
Definition: dbtype_def.h:1181
PT_JOIN_TYPE join_type
Definition: parse_tree.h:2151
DB_DOMAIN * db_domain_set(const DB_DOMAIN *domain)
Definition: db_macro.c:4060
static PT_NODE * pt_name_list_union(PARSER_CONTEXT *parser, PT_NODE *list, PT_NODE *additions)
DB_OBJECT * db_find_class_with_purpose(const char *name, bool for_update)
Definition: db_info.c:153
PT_NODE * on_call_target
Definition: parse_tree.h:2365
PT_NODE * derived_table
Definition: parse_tree.h:2134
#define MSGCAT_SEMANTIC_NOT_ATTRIBUTE_OF
static PT_NODE * pt_bind_names_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_INCORRECT_RECURSIVE_CTE
static PT_NODE * pt_bind_name_or_path_in_scope(PARSER_CONTEXT *parser, PT_BIND_NAMES_ARG *bind_arg, PT_NODE *in_node)
PT_NODE * range_var
Definition: parse_tree.h:2135
char * pt_short_print_l(PARSER_CONTEXT *parser, const PT_NODE *node)
#define MSGCAT_SEMANTIC_CLASS_HAS_NO_ATTR
DB_OBJLIST * db_get_subclasses(DB_OBJECT *obj)
Definition: db_info.c:659
PT_MISC_TYPE only_all
Definition: parse_tree.h:1979