CUBRID Engine  latest
semantic_check.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  * semantic_check.c - semantic checking functions
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <assert.h>
28 
29 #include "authenticate.h"
30 #include "error_manager.h"
31 #include "parser.h"
32 #include "parser_message.h"
33 #include "semantic_check.h"
34 #include "memory_alloc.h"
35 #include "jsp_cl.h"
36 #include "execute_schema.h"
37 #include "set_object.h"
38 #include "schema_manager.h"
39 #include "release_string.h"
40 #include "dbi.h"
41 #include "xasl_generation.h"
42 #include "view_transform.h"
43 #include "show_meta.h"
44 #include "partition.h"
45 #include "db_json.hpp"
46 #include "object_primitive.h"
47 
48 #include "dbtype.h"
49 #define PT_CHAIN_LENGTH 10
50 
51 typedef enum
53 
54 typedef enum
58 
59 typedef struct seman_compatible_info
60 {
61  int idx;
63  int prec;
64  int scale;
65  bool force_cast;
67  const PT_NODE *ref_att; /* column node having current compat info */
69 
70 typedef enum
71 {
72  RANGE_MIN = 0,
75 
76 typedef struct PT_VALUE_LINKS
77 {
81 
82 typedef struct db_value_plist
83 {
87 
88 typedef struct
89 {
94  UINTPTR spec_id;
96 
101 static int pt_is_real_class_of_vclass (PARSER_CONTEXT * parser, const PT_NODE * s_class, const PT_NODE * d_class);
102 static int pt_objects_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_class_dt, const PT_NODE * s_class);
103 static int pt_class_compatible (PARSER_CONTEXT * parser, const PT_NODE * class1, const PT_NODE * class2,
104  bool view_definition_context);
105 static bool pt_vclass_compatible (PARSER_CONTEXT * parser, const PT_NODE * att, const PT_NODE * qcol);
106 static int pt_type_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_type, const PT_NODE * s_type);
107 static int pt_collection_compatible (PARSER_CONTEXT * parser, const PT_NODE * col1, const PT_NODE * col2,
108  bool view_definition_context);
110  bool view_definition_context, bool * is_object_type);
112  bool * is_cast_allowed);
114  int num_cinfo);
115 static void pt_get_compatible_info_from_node (const PT_NODE * att, SEMAN_COMPATIBLE_INFO * cinfo);
117  SEMAN_COMPATIBLE_INFO * cinfo, int idx, bool * need_cast);
119  PT_NODE * stmt_node, const char *class_name,
120  const char *attr_name, PT_NODE * attr);
121 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
122 static PT_NODE *pt_append_statements_on_change_default (PARSER_CONTEXT * parser, PT_NODE * statement_list,
123  PT_NODE * stmt_node, const char *class_name,
124  const char *attr_name, PT_NODE * value);
125 static PT_NODE *pt_append_statements_on_drop_attributes (PARSER_CONTEXT * parser, PT_NODE * statement_list,
126  const char *class_name_list);
127 #endif
129  SEMAN_COMPATIBLE_INFO * cinfo, int num_cinfo);
131  SEMAN_COMPATIBLE_INFO * cinfo, bool * new_cast_added);
133  bool * need_cast);
135  PT_NODE * select_list2, bool * need_cast);
137  SEMAN_COMPATIBLE_INFO * cinfo2, PT_NODE * att1, PT_NODE * att2, int index);
139  SEMAN_COMPATIBLE_INFO * att1_info, SEMAN_COMPATIBLE_INFO * att2_info);
140 
141 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
142 static PT_NODE *pt_make_parameter (PARSER_CONTEXT * parser, const char *name, int is_out_parameter);
143 static PT_NODE *pt_append_statements_on_insert (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
144  const char *attr_name, PT_NODE * value, PT_NODE * parameter);
145 static PT_NODE *pt_append_statements_on_update (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
146  const char *attr_name, const char *alias_name, PT_NODE * value,
147  PT_NODE ** where_ptr);
148 static PT_NODE *pt_append_statements_on_delete (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
149  const char *attr_name, const char *alias_name, PT_NODE ** where_ptr);
150 static void pt_resolve_insert_external (PARSER_CONTEXT * parser, PT_NODE * insert);
151 static void pt_resolve_update_external (PARSER_CONTEXT * parser, PT_NODE * update);
152 static void pt_resolve_delete_external (PARSER_CONTEXT * parser, PT_NODE * delete);
153 static PT_NODE *pt_make_default_value (PARSER_CONTEXT * parser, const char *class_name, const char *attr_name);
154 #endif /* ENABLE_UNUSED_FUNCTION */
156 static PT_NODE *pt_check_data_default (PARSER_CONTEXT * parser, PT_NODE * data_default_list);
157 static PT_NODE *pt_find_query (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
158 static PT_NODE *pt_find_default_expression (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
159 static PT_NODE *pt_find_aggregate_function (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
160 static PT_NODE *pt_find_aggregate_analytic_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
162  int *continue_walk);
165  const char *self, const bool reuse_oid, PT_NODE * stmt);
166 static void pt_check_mutable_attributes (PARSER_CONTEXT * parser, DB_OBJECT * cls, PT_NODE * attr_defs);
167 static void pt_check_alter (PARSER_CONTEXT * parser, PT_NODE * alter);
168 static const char *attribute_name (PARSER_CONTEXT * parser, PT_NODE * att);
169 static int is_shared_attribute (PARSER_CONTEXT * parser, PT_NODE * att);
170 static int pt_find_partition_column_count_func (PT_NODE * func, PT_NODE ** name_node);
171 static int pt_find_partition_column_count (PT_NODE * expr, PT_NODE ** name_node);
172 static int pt_value_links_add (PARSER_CONTEXT * parser, PT_NODE * val, PT_NODE * parts, PT_VALUE_LINKS * ptl);
173 
175  PT_VALUE_LINKS * ptl, PT_NODE * parts);
176 static void pt_check_partitions (PARSER_CONTEXT * parser, PT_NODE * stmt, MOP dbobj);
177 static int partition_range_min_max (DB_VALUE ** dest, DB_VALUE * inval, int min_max);
178 static int db_value_list_add (DB_VALUE_PLIST ** ptail, DB_VALUE * val);
179 static int db_value_list_find (const DB_VALUE_PLIST * phead, const DB_VALUE * val);
180 static int db_value_list_finddel (DB_VALUE_PLIST ** phead, DB_VALUE * val);
182 static bool pt_attr_refers_to_self (PARSER_CONTEXT * parser, PT_NODE * attr, const char *self);
183 static bool pt_is_compatible_type (const PT_TYPE_ENUM arg1_type, const PT_TYPE_ENUM arg2_type);
185  PT_NODE * col);
186 static PT_NODE *pt_check_vclass_query_spec (PARSER_CONTEXT * parser, PT_NODE * qry, PT_NODE * attrs, const char *self,
187  const bool do_semantic_check);
191 static void pt_check_create_entity (PARSER_CONTEXT * parser, PT_NODE * node);
192 static void pt_check_create_user (PARSER_CONTEXT * parser, PT_NODE * node);
193 static void pt_check_create_index (PARSER_CONTEXT * parser, PT_NODE * node);
194 static void pt_check_drop (PARSER_CONTEXT * parser, PT_NODE * node);
195 static void pt_check_grant_revoke (PARSER_CONTEXT * parser, PT_NODE * node);
196 static void pt_check_method (PARSER_CONTEXT * parser, PT_NODE * node);
197 static void pt_check_truncate (PARSER_CONTEXT * parser, PT_NODE * node);
198 static void pt_check_kill (PARSER_CONTEXT * parser, PT_NODE * node);
199 static PT_NODE *pt_check_single_valued_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
201  int *continue_walk);
202 static void pt_check_into_clause (PARSER_CONTEXT * parser, PT_NODE * qry);
203 static int pt_normalize_path (PARSER_CONTEXT * parser, REFPTR (char, c));
204 static int pt_json_str_codeset_normalization (PARSER_CONTEXT * parser, REFPTR (char, c));
205 static int pt_check_json_table_node (PARSER_CONTEXT * parser, PT_NODE * node);
206 static PT_NODE *pt_semantic_check_local (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
207 static PT_NODE *pt_gen_isnull_preds (PARSER_CONTEXT * parser, PT_NODE * pred, PT_CHAIN_INFO * chain);
208 static PT_NODE *pt_path_chain (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
209 static PT_NODE *pt_expand_isnull_preds_helper (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
210 static PT_NODE *pt_expand_isnull_preds (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
211 static PT_NODE *pt_check_and_replace_hostvar (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
212 static PT_NODE *pt_check_with_clause (PARSER_CONTEXT * parser, PT_NODE * node);
213 static PT_NODE *pt_check_with_info (PARSER_CONTEXT * parser, PT_NODE * node, SEMANTIC_CHK_INFO * info);
214 static DB_OBJECT *pt_find_class (PARSER_CONTEXT * parser, PT_NODE * p, bool for_update);
215 static void pt_check_unique_attr (PARSER_CONTEXT * parser, const char *entity_name, PT_NODE * att,
216  PT_NODE_TYPE att_type);
217 static void pt_check_function_index_expr (PARSER_CONTEXT * parser, PT_NODE * node);
218 static PT_NODE *pt_check_function_index_expr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg,
219  int *continue_walk);
220 static void pt_check_assignments (PARSER_CONTEXT * parser, PT_NODE * stmt);
222 static PT_NODE *pt_replace_referenced_attributes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg,
223  int *continue_walk);
225 static void pt_check_xaction_list (PARSER_CONTEXT * parser, PT_NODE * node);
226 static PT_NODE *pt_count_iso_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
227 static PT_NODE *pt_count_time_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
228 static PT_NODE *pt_check_isolation_lvl (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
229 static PT_NODE *pt_check_constraint (PARSER_CONTEXT * parser, const PT_NODE * create, const PT_NODE * constraint);
230 static PT_NODE *pt_check_constraints (PARSER_CONTEXT * parser, const PT_NODE * create);
231 static int pt_check_auto_increment_table_option (PARSER_CONTEXT * parser, PT_NODE * create);
232 static DB_OBJECT *pt_check_user_exists (PARSER_CONTEXT * parser, PT_NODE * cls_ref);
233 static int pt_collection_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_col, const PT_NODE * s_col);
234 static int pt_assignment_class_compatible (PARSER_CONTEXT * parser, PT_NODE * lhs, PT_NODE * rhs);
235 static PT_NODE *pt_assignment_compatible (PARSER_CONTEXT * parser, PT_NODE * lhs, PT_NODE * rhs);
236 static int pt_check_defaultf (PARSER_CONTEXT * parser, PT_NODE * node);
237 static PT_NODE *pt_check_vclass_union_spec (PARSER_CONTEXT * parser, PT_NODE * qry, PT_NODE * attrds);
238 static int pt_check_group_concat_order_by (PARSER_CONTEXT * parser, PT_NODE * func);
239 static bool pt_has_parameters (PARSER_CONTEXT * parser, PT_NODE * stmt);
240 static PT_NODE *pt_is_parameter_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
241 static PT_NODE *pt_resolve_sort_spec_expr (PARSER_CONTEXT * parser, PT_NODE * sort_spec, PT_NODE * select_list);
242 static bool pt_compare_sort_spec_expr (PARSER_CONTEXT * parser, PT_NODE * expr1, PT_NODE * expr2);
243 static PT_NODE *pt_find_matching_sort_spec (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * spec_list,
244  PT_NODE * select_list);
246 static PT_NODE *pt_check_analytic_function (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
247 static PT_NODE *pt_check_filter_index_expr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
248 static PT_NODE *pt_check_filter_index_expr_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg,
249  int *continue_walk);
250 static void pt_check_filter_index_expr (PARSER_CONTEXT * parser, PT_NODE * atts, PT_NODE * node, MOP db_obj);
251 static PT_NODE *pt_check_sub_insert (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk);
252 static PT_NODE *pt_get_assignments (PT_NODE * node);
255  SEMAN_COMPATIBLE_INFO * cinfo, int num_cinfo);
257  SEMAN_COMPATIBLE_INFO * cinfo, int num_cinfo);
258 static PT_NODE *pt_mark_union_leaf_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
259 
260 static void pt_check_vacuum (PARSER_CONTEXT * parser, PT_NODE * node);
261 
262 static PT_NODE *pt_check_where (PARSER_CONTEXT * parser, PT_NODE * node);
263 
265  PT_NODE * part_next, PT_NODE * column_dt);
267 
268 /* pt_combine_compatible_info () - combine two cinfo into cinfo1
269  * return: true if compatible, else false
270  * cinfo1(in);
271  * cinfo2(in):
272  * att1(in):
273  * att2(in):
274  * index(in): for update the idx of cinfo1
275  */
276 static bool
278  PT_NODE * att1, PT_NODE * att2, int index)
279 {
280  PT_TYPE_ENUM common_type;
281  bool is_compatible = false;
282 
283  assert (parser != NULL && cinfo1 != NULL && cinfo2 != NULL);
284  assert (att1 != NULL && att2 != NULL);
285 
286  /* init cinfo before combine */
287  if (cinfo1->idx == -1 && cinfo2->idx == -1)
288  {
289  return true;
290  }
291 
292  if (cinfo1->idx == -1)
293  {
294  cinfo1->idx = index;
295  pt_get_compatible_info_from_node (att1, cinfo1);
296  }
297 
298  if (cinfo2->idx == -1)
299  {
300  cinfo2->idx = index;
301  pt_get_compatible_info_from_node (att2, cinfo2);
302  }
303 
304  common_type = pt_common_type (cinfo1->type_enum, cinfo2->type_enum);
305  is_compatible = pt_update_compatible_info (parser, cinfo1, common_type, cinfo1, cinfo2);
306 
307  return is_compatible;
308 }
309 
310 /* pt_update_compatible_info () - update cinfo after get common type for cast
311  * return: true if compatible, else false
312  * cinfo(in);
313  * common_type(in):
314  * int p1, s1, p2, s2: prec1,scale1,prec2 and scale2
315  */
316 static bool
318  SEMAN_COMPATIBLE_INFO * att1_info, SEMAN_COMPATIBLE_INFO * att2_info)
319 {
320  bool is_compatible = false;
321 
322  assert (parser != NULL && cinfo != NULL);
323  assert (att1_info != NULL && att2_info != NULL);
324 
325  switch (common_type)
326  {
327  case PT_TYPE_CHAR:
328  case PT_TYPE_VARCHAR:
329  case PT_TYPE_NCHAR:
330  case PT_TYPE_VARNCHAR:
331  case PT_TYPE_BIT:
332  case PT_TYPE_VARBIT:
333  is_compatible = true;
334 
335  if (common_type == PT_TYPE_CHAR || common_type == PT_TYPE_VARCHAR)
336  {
337  cinfo->type_enum = PT_TYPE_VARCHAR;
338  }
339  else if (common_type == PT_TYPE_NCHAR || common_type == PT_TYPE_VARNCHAR)
340  {
341  cinfo->type_enum = PT_TYPE_VARNCHAR;
342  }
343  else
344  {
345  cinfo->type_enum = PT_TYPE_VARBIT;
346  }
347 
348  if (att1_info->prec == DB_DEFAULT_PRECISION || att2_info->prec == DB_DEFAULT_PRECISION)
349  {
350  cinfo->prec = DB_DEFAULT_PRECISION;
351  }
352  else
353  {
354  cinfo->prec = MAX (att1_info->prec, att2_info->prec);
355  if (cinfo->prec == 0)
356  {
357  cinfo->prec = DB_DEFAULT_PRECISION;
358  }
359  }
360  break;
361 
362  case PT_TYPE_NUMERIC:
363  is_compatible = true;
364 
365  cinfo->type_enum = common_type;
366 
367  cinfo->scale = MAX (att1_info->scale, att2_info->scale);
368  cinfo->prec = MAX ((att1_info->prec - att1_info->scale), (att2_info->prec - att2_info->scale)) + cinfo->scale;
369 
370  if (cinfo->prec > DB_MAX_NUMERIC_PRECISION)
371  { /* overflow */
372  cinfo->scale -= (cinfo->prec - DB_MAX_NUMERIC_PRECISION);
373  if (cinfo->scale < 0)
374  {
375  cinfo->scale = 0;
376  }
378  }
379  break;
380 
381  case PT_TYPE_SET:
382  case PT_TYPE_MULTISET:
383  case PT_TYPE_SEQUENCE:
384  /* NEVER try to fix set types */
385  is_compatible = true;
386  break;
387  case PT_TYPE_NONE:
388  is_compatible = false;
389  break;
390 
391  default:
392  is_compatible = true;
393  cinfo->type_enum = common_type;
394  break;
395  }
396 
397  return is_compatible;
398 }
399 
400 /* pt_values_query_to_compatible_cast () - cast select list with cinfo
401  * return:
402  * parser(in):
403  * node(in):
404  * cinfo(in):
405  */
406 static PT_NODE *
408  int num_cinfo)
409 {
410  PT_NODE *node_list, *result = node;
411  int i;
412  PT_NODE *attrs, *att;
413  PT_NODE *prev_att, *next_att, *new_att = NULL;
414  bool new_cast_added;
415  bool need_to_cast;
416  PT_NODE_LIST_INFO *cur_node_list_info;
417  bool is_select_data_type_set = false;
418 
419  assert (parser != NULL && node != NULL && cinfo != NULL);
420  assert (node->node_type == PT_SELECT && PT_IS_VALUE_QUERY (node));
421 
422  node_list = node->info.query.q.select.list;
423  assert (node_list);
424 
425  for (; node_list; node_list = node_list->next)
426  {
427  cur_node_list_info = &node_list->info.node_list;
428  attrs = cur_node_list_info->list;
429 
430  prev_att = NULL;
431  for (att = attrs, i = 0; i < num_cinfo && att != NULL; ++i, att = next_att)
432  {
433  bool is_cast_allowed = true;
434 
435  new_cast_added = false;
436  next_att = att->next;
437  need_to_cast = false;
438  if (cinfo[i].idx == i)
439  {
440  if (!pt_is_compatible_without_cast (parser, &(cinfo[i]), att, &is_cast_allowed))
441  {
442  need_to_cast = true;
443  if ((PT_IS_STRING_TYPE (att->type_enum) || att->type_enum == PT_TYPE_NUMERIC)
444  && att->data_type == NULL)
445  {
446  result = NULL;
447  goto end;
448  }
449  }
450  }
451 
452  if (need_to_cast)
453  {
454  if (!is_cast_allowed)
455  {
456  result = NULL;
457  goto end;
458  }
459 
460  new_att = pt_make_cast_with_compatible_info (parser, att, next_att, cinfo + i, &new_cast_added);
461  if (new_att == NULL)
462  {
463  goto out_of_mem;
464  }
465 
466  if (new_cast_added)
467  {
468  att = new_att;
469  }
470 
471  if (prev_att == NULL)
472  {
473  cur_node_list_info->list = att;
474  if (is_select_data_type_set == false)
475  {
476  node->type_enum = att->type_enum;
477  if (node->data_type)
478  {
479  parser_free_tree (parser, node->data_type);
480  }
481  node->data_type = parser_copy_tree_list (parser, att->data_type);
482  is_select_data_type_set = true;
483  }
484  }
485  else
486  {
487  prev_att->next = att;
488  }
489  }
490  prev_att = att;
491  }
492  }
493 
494 end:
495  return result;
496 
497 out_of_mem:
499  return NULL;
500 }
501 
502 /*
503  * pt_get_compatible_info () -
504  * return: return a pointer of SEMAN_COMPATIBLE_INFO array or null on error
505  * parser(in): parser context
506  * node(in): values query node or union
507  * select_list1(in):
508  * select_list2(in):
509  * need_cast(in/out):
510  * current_row(in): for value query error info
511  * note: the return pointer must be freed by free_and_init
512  */
513 static SEMAN_COMPATIBLE_INFO *
514 pt_get_compatible_info (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * select_list1, PT_NODE * select_list2,
515  bool * need_cast)
516 {
517  PT_NODE *att1, *att2, *p, *q;
518  PT_UNION_COMPATIBLE compatible;
519  SEMAN_COMPATIBLE_INFO *cinfo = NULL, *result = NULL;
520  bool is_object_type;
521  int i, k;
522  int cnt1, cnt2;
523  bool need_cast_tmp = false;
524 
525  assert (parser != NULL && node != NULL && select_list1 != NULL && select_list2 != NULL && need_cast != NULL);
526 
527  *need_cast = false;
528 
529  p = select_list1;
530  q = select_list2;
531 
532  if (p->node_type == PT_NODE_LIST)
533  {
534  assert (q->node_type == PT_NODE_LIST);
535 
536  select_list1 = p->info.node_list.list;
537  select_list2 = q->info.node_list.list;
538  }
539 
540  cnt1 = pt_length_of_select_list (select_list1, EXCLUDE_HIDDEN_COLUMNS);
541  cnt2 = pt_length_of_select_list (select_list2, EXCLUDE_HIDDEN_COLUMNS);
542 
543  if (cnt1 != cnt2)
544  {
545  if (select_list1->node_type == PT_NODE_LIST)
546  {
548  pt_short_print (parser, p), cnt2, pt_short_print (parser, q));
549  }
550  else
551  {
552  PT_ERRORmf2 (parser, select_list1, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_ARITY_MISMATCH, cnt1, cnt2);
553  }
554  goto end;
555  }
556 
557  /* compare the columns */
558  for (i = 0, att1 = select_list1, att2 = select_list2; i < cnt1; ++i, att1 = att1->next, att2 = att2->next)
559  {
560  compatible = pt_union_compatible (parser, att1, att2, false, &is_object_type);
561  if (compatible == PT_UNION_INCOMP)
562  {
563  /* alloc compatible info array */
564  if (cinfo == NULL)
565  {
566  cinfo = (SEMAN_COMPATIBLE_INFO *) malloc (cnt1 * sizeof (SEMAN_COMPATIBLE_INFO));
567  if (cinfo == NULL)
568  {
569  goto out_of_mem;
570  }
571 
572  for (k = 0; k < cnt1; ++k)
573  {
574  cinfo[k].idx = -1;
575  cinfo[k].type_enum = PT_TYPE_NONE;
576  cinfo[k].prec = DB_DEFAULT_PRECISION;
577  cinfo[k].scale = DB_DEFAULT_SCALE;
578  cinfo[k].force_cast = false;
582  cinfo[k].coll_infer.can_force_cs = false;
583  cinfo[k].ref_att = NULL;
584  }
585  }
586 
587  if (pt_get_common_type_for_union (parser, att1, att2, &cinfo[i], i, &need_cast_tmp) == NULL)
588  {
589  goto end;
590  }
591  *need_cast |= need_cast_tmp;
592  }
593  else if (compatible == PT_UNION_INCOMP_CANNOT_FIX || compatible == PT_UNION_ERROR)
594  {
595  if (!is_object_type)
596  {
598  pt_short_print (parser, att1), pt_short_print (parser, att2));
599  goto end;
600  }
601  }
602  }
603 
604  result = cinfo;
605 
606 end:
607  if (result != cinfo && cinfo != NULL)
608  {
609  free_and_init (cinfo);
610  }
611  return result;
612 
613 out_of_mem:
615  return NULL;
616 }
617 
618 /*
619  * pt_make_cast_with_compatible_info () -
620  * return: return a pointer to PT_EXPR node (cast)
621  * parser(in): parser context
622  * att(in): current attribute
623  * next_att(in): next attribute
624  * cinfo(in): compatible info
625  * new_cast_added(out): true if a new PT_EXPR node for cast if allocated, else false
626  */
627 static PT_NODE *
629  SEMAN_COMPATIBLE_INFO * cinfo, bool * new_cast_added)
630 {
631  PT_EXPR_INFO *temp_expr;
632  PT_DATA_TYPE_INFO *temp_data_type;
633  PT_NODE *new_att = NULL, *new_dt = NULL;
634 
635  assert (parser != NULL && att != NULL && cinfo != NULL && new_cast_added != NULL);
636 
637  *new_cast_added = false;
638  if (att->node_type == PT_EXPR && att->info.expr.op == PT_CAST && att->etc != NULL)
639  {
640  /* system added cast operator */
641  temp_expr = &att->info.expr;
642  temp_expr->cast_type->type_enum = cinfo->type_enum;
643 
644  temp_data_type = &temp_expr->cast_type->info.data_type;
645  temp_data_type->precision = cinfo->prec;
646  temp_data_type->dec_precision = cinfo->scale;
647  if (PT_HAS_COLLATION (cinfo->type_enum))
648  {
649  temp_data_type->collation_id = cinfo->coll_infer.coll_id;
650  temp_data_type->units = (int) cinfo->coll_infer.codeset;
651  }
652 
653  att->type_enum = att->info.expr.cast_type->type_enum;
654  att->data_type->type_enum = cinfo->type_enum;
655  temp_data_type = &att->data_type->info.data_type;
656  temp_data_type->precision = cinfo->prec;
657  temp_data_type->dec_precision = cinfo->scale;
658  if (PT_HAS_COLLATION (cinfo->type_enum))
659  {
660  temp_data_type->collation_id = cinfo->coll_infer.coll_id;
661  temp_data_type->units = (int) cinfo->coll_infer.codeset;
662  }
663 
664  new_att = att;
665  }
666  else
667  {
668  /* create new cast node */
669  att->next = NULL;
670 
671  new_att = parser_new_node (parser, PT_EXPR);
672  new_dt = parser_new_node (parser, PT_DATA_TYPE);
673  if (new_att == NULL || new_dt == NULL)
674  {
675  if (new_att)
676  {
677  parser_free_tree (parser, new_att);
678  new_att = NULL;
679  }
680  if (new_dt)
681  {
682  parser_free_tree (parser, new_dt);
683  new_dt = NULL;
684  }
685 
686  goto out_of_mem;
687  }
688 
689  /* move alias */
690  new_att->line_number = att->line_number;
691  new_att->column_number = att->column_number;
692  if (att->alias_print == NULL && att->node_type == PT_NAME)
693  {
694  new_att->alias_print = att->info.name.original;
695  }
696  else
697  {
698  new_att->alias_print = att->alias_print;
699  }
700  att->alias_print = NULL;
701 
702  new_dt->type_enum = cinfo->type_enum;
703  temp_data_type = &new_dt->info.data_type;
704  temp_data_type->precision = cinfo->prec;
705  temp_data_type->dec_precision = cinfo->scale;
706  if (PT_HAS_COLLATION (cinfo->type_enum))
707  {
708  temp_data_type->collation_id = cinfo->coll_infer.coll_id;
709  temp_data_type->units = (int) cinfo->coll_infer.codeset;
710  }
711 
712  new_att->type_enum = new_dt->type_enum;
713  temp_expr = &new_att->info.expr;
714  temp_expr->op = PT_CAST;
715  temp_expr->cast_type = new_dt;
716  temp_expr->arg1 = att;
717  new_att->next = next_att;
718  new_att->etc = cinfo; /* to make this as system added */
719  new_att->flag.is_value_query = att->flag.is_value_query;
720 
721  new_att->data_type = parser_copy_tree_list (parser, new_dt);
723 
724  *new_cast_added = true;
725  }
726 
727  return new_att;
728 
729 out_of_mem:
730  /* the error msg will be set in the caller */
731  return NULL;
732 }
733 
734 /*
735  * pt_get_values_query_compatible_info () -
736  * return: return a pointer of SEMAN_COMPATIBLE_INFO array or null on error
737  * parser(in): parser context
738  * node(in): values query node
739  * need_cast(in/out):
740  *
741  * note: the return pointer must be freed by free_and_init
742  */
743 static SEMAN_COMPATIBLE_INFO *
744 pt_get_values_query_compatible_info (PARSER_CONTEXT * parser, PT_NODE * node, bool * need_cast)
745 {
746  PT_NODE *attrs1, *attrs2, *att1, *att2, *node_list, *next_node_list;
747  SEMAN_COMPATIBLE_INFO *cinfo = NULL, *cinfo_cur = NULL, *result = NULL;
748  int i, count;
749  bool is_compatible, need_cast_cond = false;
750 
751  assert (parser);
752 
753  *need_cast = false;
754 
755  if (node == NULL || node->node_type != PT_SELECT || !PT_IS_VALUE_QUERY (node))
756  {
757  return NULL;
758  }
759 
760  node_list = node->info.query.q.select.list;
761  if (node_list == NULL)
762  {
763  return NULL;
764  }
765  attrs1 = node_list->info.node_list.list;
766 
767  next_node_list = node_list->next;
768  /* only one row */
769  if (next_node_list == NULL)
770  {
771  return NULL;
772  }
773  attrs2 = next_node_list->info.node_list.list;
774 
776 
777  /* get compatible_info for cast */
778  while (next_node_list != NULL)
779  {
780  cinfo_cur = pt_get_compatible_info (parser, node, node_list, next_node_list, &need_cast_cond);
781  if (cinfo_cur == NULL && need_cast_cond)
782  {
783  goto end;
784  }
785 
786  if (cinfo == NULL)
787  {
788  cinfo = cinfo_cur;
789  *need_cast = need_cast_cond;
790  cinfo_cur = NULL; /* do not free */
791  }
792  else
793  {
794  /* compare cinfo[i].type_enum and cinfo_cur[i].type_enum and save the compatible type_enum in cinfo[i] */
795  if (need_cast_cond)
796  {
797  is_compatible = true;
798  for (i = 0, att1 = attrs1, att2 = attrs2; i < count; ++i, att1 = att1->next, att2 = att2->next)
799  {
800  if (cinfo_cur[i].idx == -1)
801  {
802  continue;
803  }
804 
805  if (cinfo[i].idx == -1)
806  {
807  cinfo[i] = cinfo_cur[i];
808  *need_cast = true;
809  continue;
810  }
811 
812  /* if equal, skip the following steps */
813  if (cinfo[i].type_enum == cinfo_cur[i].type_enum && cinfo[i].prec == cinfo_cur[i].prec
814  && cinfo[i].scale == cinfo_cur[i].scale
815  && cinfo[i].coll_infer.coll_id == cinfo_cur[i].coll_infer.coll_id)
816  {
817  assert (cinfo[i].idx == cinfo_cur[i].idx);
818  continue;
819  }
820 
821  /* combine the two cinfos */
822  is_compatible = pt_combine_compatible_info (parser, cinfo + i, cinfo_cur + i, att1, att2, i);
823  if (!is_compatible)
824  {
825  break;
826  }
827 
828  *need_cast = true;
829  }
830 
831  if (!is_compatible)
832  {
834  pt_short_print (parser, att1), pt_short_print (parser, att2));
835  goto end;
836  }
837  }
838  }
839 
840  attrs1 = attrs2;
841  node_list = next_node_list;
842  next_node_list = next_node_list->next;
843  if (next_node_list != NULL)
844  {
845  attrs2 = next_node_list->info.node_list.list;
846  }
847 
848  /* free cinfo_cur */
849  free_and_init (cinfo_cur);
850  }
851 
852  /* assign cinfo to return value */
853  result = cinfo;
854 
855 end:
856  if (cinfo_cur != NULL)
857  {
858  free_and_init (cinfo_cur);
859  }
860  if (result != cinfo && cinfo != NULL)
861  {
862  free_and_init (cinfo);
863  }
864  return result;
865 }
866 
867 /*
868  * pt_check_compatible_node_for_orderby ()
869  */
870 bool
872 {
873  PT_NODE *arg1, *cast_type;
874  PT_TYPE_ENUM type1, type2;
875 
876  if (order == NULL || column == NULL || order->node_type != PT_EXPR || order->info.expr.op != PT_CAST)
877  {
878  return false;
879  }
880 
881  arg1 = order->info.expr.arg1;
882  if (arg1->node_type != column->node_type)
883  {
884  return false;
885  }
886 
887  if (arg1->node_type != PT_NAME && arg1->node_type != PT_DOT_)
888  {
889  return false;
890  }
891 
892  if (pt_check_path_eq (parser, arg1, column) != 0)
893  {
894  return false;
895  }
896 
897  cast_type = order->info.expr.cast_type;
898  assert (cast_type != NULL);
899 
900  type1 = arg1->type_enum;
901  type2 = cast_type->type_enum;
902 
903  if (PT_IS_NUMERIC_TYPE (type1) && PT_IS_NUMERIC_TYPE (type2))
904  {
905  return true;
906  }
907 
908  /* Only string type : Do not consider 'CAST (enum_col as VARCHAR)' equal to 'enum_col' */
909  if (PT_IS_STRING_TYPE (type1) && PT_IS_STRING_TYPE (type2))
910  {
911  int c1, c2;
912 
913  c1 = arg1->data_type->info.data_type.collation_id;
914  c2 = cast_type->info.data_type.collation_id;
915  return c1 == c2;
916  }
917 
918  if (PT_IS_DATE_TIME_TYPE (type1) && PT_IS_DATE_TIME_TYPE (type2))
919  {
920  if ((type1 == PT_TYPE_TIME && type2 != PT_TYPE_TIME) || (type1 != PT_TYPE_TIME && type2 == PT_TYPE_TIME))
921  {
922  return false;
923  }
924  return true;
925  }
926 
927  return false;
928 }
929 
930 /*
931  * pt_check_cast_op () - Checks to see if the cast operator is well-formed
932  * return: none
933  * parser(in):
934  * node(in): the node to check
935  */
936 bool
938 {
939  PT_NODE *arg1;
940  PT_TYPE_ENUM cast_type = PT_TYPE_NONE, arg_type;
941  PT_CAST_VAL cast_is_valid = PT_CAST_VALID;
942 
943  if (node == NULL || node->node_type != PT_EXPR || node->info.expr.op != PT_CAST)
944  {
945  /* this should not happen, but don't crash and burn if it does */
946  assert (false);
947  return false;
948  }
949 
950  /* check special CAST : COLLATE modifier */
952  {
953  LANG_COLLATION *lc;
954  PT_NODE *arg_dt = NULL;
955 
956  if (node->info.expr.arg1 != NULL && node->info.expr.arg1->type_enum != PT_TYPE_NONE
957  && !PT_HAS_COLLATION (node->info.expr.arg1->type_enum))
958  {
960  return false;
961  }
962  /* arg1 may have been set NULL due to previous semantic errors */
963  arg_dt = (node->info.expr.arg1 != NULL) ? node->info.expr.arg1->data_type : NULL;
964 
966  if (arg_dt != NULL && lc->codeset != arg_dt->info.data_type.units)
967  {
968  /* cannot change codeset with COLLATE */
971  return false;
972  }
973  }
974 
975  /* get cast type */
976  if (node->info.expr.cast_type != NULL)
977  {
978  cast_type = node->info.expr.cast_type->type_enum;
979  }
980  else
981  {
983  {
984  PT_INTERNAL_ERROR (parser, "null cast type");
985  }
986  return false;
987  }
988 
989  /* get argument */
990  arg1 = node->info.expr.arg1;
991  if (arg1 == NULL)
992  {
993  /* a parse error might have occurred lower in the parse tree of arg1; don't register another error unless no
994  * error has been set */
995 
996  if (!pt_has_error (parser))
997  {
999  pt_show_type_enum (cast_type));
1000  }
1001  return false;
1002  }
1003 
1004  /* CAST (arg_type AS cast_type) */
1005  if (arg1->node_type == PT_EXPR && arg1->info.expr.op == PT_CAST)
1006  {
1007  /* arg1 is a cast, so arg1.type_enum is not yet set; pull type from expression's cast type */
1008  arg_type = arg1->info.expr.cast_type->type_enum;
1009  }
1010  else
1011  {
1012  /* arg1 is not a cast */
1013  arg_type = arg1->type_enum;
1014  }
1015 
1016  switch (arg_type)
1017  {
1018  case PT_TYPE_INTEGER:
1019  case PT_TYPE_BIGINT:
1020  case PT_TYPE_FLOAT:
1021  case PT_TYPE_DOUBLE:
1022  case PT_TYPE_SMALLINT:
1023  case PT_TYPE_MONETARY:
1024  case PT_TYPE_NUMERIC:
1025  switch (cast_type)
1026  {
1027  case PT_TYPE_BIT:
1028  case PT_TYPE_VARBIT:
1029  case PT_TYPE_DATE:
1030  /* allow numeric to TIME and TIMESTAMP conversions */
1031  case PT_TYPE_DATETIME:
1032  case PT_TYPE_DATETIMETZ:
1033  case PT_TYPE_DATETIMELTZ:
1034  case PT_TYPE_SET:
1035  case PT_TYPE_MULTISET:
1036  case PT_TYPE_SEQUENCE:
1037  case PT_TYPE_BLOB:
1038  case PT_TYPE_CLOB:
1039  case PT_TYPE_OBJECT:
1040  cast_is_valid = PT_CAST_INVALID;
1041  break;
1042  default:
1043  break;
1044  }
1045  break;
1046  case PT_TYPE_DATE:
1047  switch (cast_type)
1048  {
1049  case PT_TYPE_INTEGER:
1050  case PT_TYPE_BIGINT:
1051  case PT_TYPE_FLOAT:
1052  case PT_TYPE_DOUBLE:
1053  case PT_TYPE_SMALLINT:
1054  case PT_TYPE_MONETARY:
1055  case PT_TYPE_NUMERIC:
1056  case PT_TYPE_BIT:
1057  case PT_TYPE_VARBIT:
1058  case PT_TYPE_TIME:
1059  case PT_TYPE_SET:
1060  case PT_TYPE_MULTISET:
1061  case PT_TYPE_SEQUENCE:
1062  case PT_TYPE_BLOB:
1063  case PT_TYPE_CLOB:
1064  case PT_TYPE_OBJECT:
1065  cast_is_valid = PT_CAST_INVALID;
1066  break;
1067  default:
1068  break;
1069  }
1070  break;
1071  case PT_TYPE_TIME:
1072  switch (cast_type)
1073  {
1074  case PT_TYPE_INTEGER:
1075  case PT_TYPE_BIGINT:
1076  case PT_TYPE_FLOAT:
1077  case PT_TYPE_DOUBLE:
1078  case PT_TYPE_SMALLINT:
1079  case PT_TYPE_MONETARY:
1080  case PT_TYPE_NUMERIC:
1081  case PT_TYPE_BIT:
1082  case PT_TYPE_VARBIT:
1083  case PT_TYPE_DATE:
1084  case PT_TYPE_SET:
1085  case PT_TYPE_MULTISET:
1086  case PT_TYPE_SEQUENCE:
1087  case PT_TYPE_BLOB:
1088  case PT_TYPE_CLOB:
1089  case PT_TYPE_OBJECT:
1090  cast_is_valid = PT_CAST_INVALID;
1091  break;
1092  case PT_TYPE_TIMESTAMP:
1093  case PT_TYPE_TIMESTAMPLTZ:
1094  case PT_TYPE_TIMESTAMPTZ:
1095  case PT_TYPE_DATETIME:
1096  case PT_TYPE_DATETIMELTZ:
1097  case PT_TYPE_DATETIMETZ:
1098  cast_is_valid = PT_CAST_UNSUPPORTED;
1099  break;
1100  default:
1101  break;
1102  }
1103  break;
1104  case PT_TYPE_TIMESTAMP:
1105  case PT_TYPE_TIMESTAMPTZ:
1106  case PT_TYPE_TIMESTAMPLTZ:
1107  switch (cast_type)
1108  {
1109  case PT_TYPE_INTEGER:
1110  case PT_TYPE_BIGINT:
1111  case PT_TYPE_FLOAT:
1112  case PT_TYPE_DOUBLE:
1113  case PT_TYPE_SMALLINT:
1114  case PT_TYPE_MONETARY:
1115  case PT_TYPE_NUMERIC:
1116  case PT_TYPE_BIT:
1117  case PT_TYPE_VARBIT:
1118  case PT_TYPE_SET:
1119  case PT_TYPE_MULTISET:
1120  case PT_TYPE_SEQUENCE:
1121  case PT_TYPE_BLOB:
1122  case PT_TYPE_CLOB:
1123  case PT_TYPE_OBJECT:
1124  cast_is_valid = PT_CAST_INVALID;
1125  break;
1126  default:
1127  break;
1128  }
1129  break;
1130  case PT_TYPE_DATETIME:
1131  case PT_TYPE_DATETIMETZ:
1132  case PT_TYPE_DATETIMELTZ:
1133  switch (cast_type)
1134  {
1135  case PT_TYPE_INTEGER:
1136  case PT_TYPE_FLOAT:
1137  case PT_TYPE_DOUBLE:
1138  case PT_TYPE_SMALLINT:
1139  case PT_TYPE_MONETARY:
1140  case PT_TYPE_NUMERIC:
1141  case PT_TYPE_BIT:
1142  case PT_TYPE_VARBIT:
1143  case PT_TYPE_SET:
1144  case PT_TYPE_MULTISET:
1145  case PT_TYPE_SEQUENCE:
1146  case PT_TYPE_BLOB:
1147  case PT_TYPE_CLOB:
1148  case PT_TYPE_OBJECT:
1149  cast_is_valid = PT_CAST_INVALID;
1150  break;
1151  default:
1152  break;
1153  }
1154  break;
1155  case PT_TYPE_CHAR:
1156  case PT_TYPE_VARCHAR:
1157  case PT_TYPE_NCHAR:
1158  case PT_TYPE_VARNCHAR:
1159  if ((PT_IS_NATIONAL_CHAR_STRING_TYPE (arg_type) && PT_IS_SIMPLE_CHAR_STRING_TYPE (cast_type))
1160  || (PT_IS_SIMPLE_CHAR_STRING_TYPE (arg_type) && PT_IS_NATIONAL_CHAR_STRING_TYPE (cast_type)))
1161  {
1162  cast_is_valid = PT_CAST_INVALID;
1163  break;
1164  }
1165 
1166  switch (cast_type)
1167  {
1168  case PT_TYPE_SET:
1169  case PT_TYPE_MULTISET:
1170  case PT_TYPE_SEQUENCE:
1171  cast_is_valid = PT_CAST_UNSUPPORTED;
1172  break;
1173  case PT_TYPE_OBJECT:
1174  cast_is_valid = PT_CAST_INVALID;
1175  break;
1176  default:
1177  break;
1178  }
1179  break;
1180  case PT_TYPE_BIT:
1181  case PT_TYPE_VARBIT:
1182  switch (cast_type)
1183  {
1184  case PT_TYPE_INTEGER:
1185  case PT_TYPE_BIGINT:
1186  case PT_TYPE_FLOAT:
1187  case PT_TYPE_DOUBLE:
1188  case PT_TYPE_SMALLINT:
1189  case PT_TYPE_MONETARY:
1190  case PT_TYPE_NUMERIC:
1191  case PT_TYPE_DATE:
1192  case PT_TYPE_TIME:
1193  case PT_TYPE_TIMESTAMP:
1194  case PT_TYPE_TIMESTAMPTZ:
1195  case PT_TYPE_TIMESTAMPLTZ:
1196  case PT_TYPE_DATETIME:
1197  case PT_TYPE_DATETIMELTZ:
1198  case PT_TYPE_DATETIMETZ:
1199  case PT_TYPE_SET:
1200  case PT_TYPE_MULTISET:
1201  case PT_TYPE_SEQUENCE:
1202  case PT_TYPE_OBJECT:
1203  cast_is_valid = PT_CAST_INVALID;
1204  break;
1205  case PT_TYPE_CLOB:
1206  cast_is_valid = PT_CAST_UNSUPPORTED;
1207  break;
1208  default:
1209  break;
1210  }
1211  break;
1212  case PT_TYPE_OBJECT:
1213  /* some functions like DECODE, CASE perform wrap with CAST, allow it */
1215  {
1216  cast_is_valid = PT_CAST_UNSUPPORTED;
1217  }
1218  break;
1219  case PT_TYPE_SET:
1220  case PT_TYPE_MULTISET:
1221  case PT_TYPE_SEQUENCE:
1222  switch (cast_type)
1223  {
1224  case PT_TYPE_INTEGER:
1225  case PT_TYPE_BIGINT:
1226  case PT_TYPE_FLOAT:
1227  case PT_TYPE_DOUBLE:
1228  case PT_TYPE_SMALLINT:
1229  case PT_TYPE_MONETARY:
1230  case PT_TYPE_NUMERIC:
1231  case PT_TYPE_BIT:
1232  case PT_TYPE_VARBIT:
1233  case PT_TYPE_DATE:
1234  case PT_TYPE_TIME:
1235  case PT_TYPE_TIMESTAMP:
1236  case PT_TYPE_TIMESTAMPTZ:
1237  case PT_TYPE_TIMESTAMPLTZ:
1238  case PT_TYPE_DATETIME:
1239  case PT_TYPE_DATETIMETZ:
1240  case PT_TYPE_DATETIMELTZ:
1241  case PT_TYPE_BLOB:
1242  case PT_TYPE_CLOB:
1243  case PT_TYPE_OBJECT:
1244  cast_is_valid = PT_CAST_INVALID;
1245  break;
1246  case PT_TYPE_CHAR:
1247  case PT_TYPE_VARCHAR:
1248  case PT_TYPE_NCHAR:
1249  case PT_TYPE_VARNCHAR:
1250  cast_is_valid = PT_CAST_UNSUPPORTED;
1251  break;
1252  default:
1253  break;
1254  }
1255  break;
1256  case PT_TYPE_BLOB:
1257  switch (cast_type)
1258  {
1259  case PT_TYPE_BIT:
1260  case PT_TYPE_VARBIT:
1261  case PT_TYPE_BLOB:
1262  case PT_TYPE_ENUMERATION:
1263  break;
1264  case PT_TYPE_CLOB:
1265  cast_is_valid = PT_CAST_UNSUPPORTED;
1266  break;
1267  default:
1268  cast_is_valid = PT_CAST_INVALID;
1269  break;
1270  }
1271  break;
1272  case PT_TYPE_CLOB:
1273  switch (cast_type)
1274  {
1275  case PT_TYPE_CHAR:
1276  case PT_TYPE_VARCHAR:
1277  case PT_TYPE_NCHAR:
1278  case PT_TYPE_VARNCHAR:
1279  case PT_TYPE_CLOB:
1280  case PT_TYPE_ENUMERATION:
1281  break;
1282  case PT_TYPE_BLOB:
1283  cast_is_valid = PT_CAST_UNSUPPORTED;
1284  break;
1285  default:
1286  cast_is_valid = PT_CAST_INVALID;
1287  break;
1288  }
1289  break;
1290  default:
1291  break;
1292  }
1293 
1294  switch (cast_is_valid)
1295  {
1296  case PT_CAST_VALID:
1297  break;
1298  case PT_CAST_INVALID:
1300  pt_short_print (parser, node->info.expr.arg1), pt_show_type_enum (cast_type));
1301  break;
1302  case PT_CAST_UNSUPPORTED:
1304  pt_short_print (parser, node->info.expr.arg1), pt_show_type_enum (cast_type));
1305  break;
1306  }
1307 
1308  return (cast_is_valid == PT_CAST_VALID) ? true : false;
1309 }
1310 
1311 /*
1312  * pt_check_user_exists () - given 'user.class', check that 'user' exists
1313  * return: db_user instance if user exists, NULL otherwise.
1314  * parser(in): the parser context used to derive cls_ref
1315  * cls_ref(in): a PT_NAME node
1316  *
1317  * Note :
1318  * this routine is needed only in the context of checking create stmts,
1319  * ie, in checking 'create vclass usr.cls ...'.
1320  * Otherwise, pt_check_user_owns_class should be used.
1321  */
1322 static DB_OBJECT *
1324 {
1325  const char *usr;
1326  DB_OBJECT *result;
1327 
1328  assert (parser != NULL);
1329 
1330  if (!cls_ref || cls_ref->node_type != PT_NAME || (usr = cls_ref->info.name.resolved) == NULL || usr[0] == '\0')
1331  {
1332  return NULL;
1333  }
1334 
1335  result = db_find_user (usr);
1336  if (!result)
1337  {
1339  }
1340 
1341  return result;
1342 }
1343 
1344 /*
1345  * pt_check_user_owns_class () - given user.class, check that user owns class
1346  * return: db_user instance if 'user' exists & owns 'class', NULL otherwise
1347  * parser(in): the parser context used to derive cls_ref
1348  * cls_ref(in): a PT_NAME node
1349  */
1350 DB_OBJECT *
1352 {
1353  DB_OBJECT *result, *cls, *owner;
1354 
1355  if ((result = pt_check_user_exists (parser, cls_ref)) == NULL || (cls = cls_ref->info.name.db_object) == NULL)
1356  {
1357  return NULL;
1358  }
1359 
1360  owner = db_get_owner (cls);
1361  result = (ws_is_same_object (owner, result) ? result : NULL);
1362  if (!result)
1363  {
1365  cls_ref->info.name.resolved, cls_ref->info.name.original);
1366  }
1367 
1368  return result;
1369 }
1370 
1371 /*
1372  * pt_derive_attribute () - derive a new ATTR_DEF node from a query_spec
1373  * column
1374  * return: a new ATTR_DEF node derived from c if all OK, NULL otherwise.
1375  * parser(in): the parser context to use for creating the ATTR_DEF node
1376  * c(in): a query_spec column
1377  */
1378 static PT_NODE *
1380 {
1381  PT_NODE *attr = NULL;
1382  PT_NODE *cname = NULL;
1383 
1384  assert (parser != NULL);
1385 
1386  if (c == NULL)
1387  {
1388  return NULL;
1389  }
1390 
1391  if (c->alias_print != NULL)
1392  {
1393  cname = pt_name (parser, c->alias_print);
1394  }
1395  else if (c->node_type == PT_NAME)
1396  {
1398  && (c->info.name.original == NULL || strlen (c->info.name.original) == 0))
1399  {
1400  cname = pt_name (parser, c->info.name.resolved);
1401  }
1402  else
1403  {
1404  cname = pt_name (parser, c->info.name.original);
1405  }
1406  }
1407  else
1408  {
1409  return NULL;
1410  }
1411 
1412  if (cname == NULL)
1413  {
1414  return NULL;
1415  }
1416 
1417  attr = parser_new_node (parser, PT_ATTR_DEF);
1418  if (attr == NULL)
1419  {
1420  return NULL;
1421  }
1422 
1423  attr->data_type = NULL;
1424  attr->info.attr_def.attr_name = cname;
1425  attr->info.attr_def.attr_type = PT_NORMAL;
1426 
1427  return attr;
1428 }
1429 
1430 /*
1431  * pt_get_attributes () - get & return the attribute list of
1432  * a {class|vclass|view}
1433  * return: c's attribute list if successful, NULL otherwise.
1434  * parser(in): the parser context to use for creating the list
1435  * c(in): a {class|vclass|view} object
1436  */
1437 /* TODO modify the function so that we can distinguish between a class having
1438  * no attributes and an execution error.
1439  */
1440 static PT_NODE *
1442 {
1443  DB_ATTRIBUTE *attributes;
1444  const char *class_name;
1445  PT_NODE *i_attr, *name, *typ, *types, *list = NULL;
1446  DB_OBJECT *cls;
1447  DB_DOMAIN *dom;
1448 
1449  assert (parser != NULL);
1450 
1451  if (!c || !(class_name = db_get_class_name ((DB_OBJECT *) c)))
1452  {
1453  return list;
1454  }
1455 
1456  attributes = db_get_attributes ((DB_OBJECT *) c);
1457  while (attributes)
1458  {
1459  /* create a new attribute node */
1460  i_attr = parser_new_node (parser, PT_ATTR_DEF);
1461  if (i_attr == NULL)
1462  {
1463  PT_INTERNAL_ERROR (parser, "allocate new node");
1464  return NULL;
1465  }
1466 
1467  /* its name is class_name.attribute_name */
1468  i_attr->info.attr_def.attr_name = name = pt_name (parser, db_attribute_name (attributes));
1469  name->info.name.resolved = pt_append_string (parser, NULL, class_name);
1471  name->info.name.meta_class = (db_attribute_is_shared (attributes) ? PT_SHARED : PT_NORMAL);
1472 
1473  /* set its data type */
1474  i_attr->type_enum = pt_db_to_type_enum (db_attribute_type (attributes));
1475  switch (i_attr->type_enum)
1476  {
1477  case PT_TYPE_OBJECT:
1478  cls = db_domain_class (db_attribute_domain (attributes));
1479  if (cls)
1480  {
1481  name = pt_name (parser, db_get_class_name (cls));
1482  name->info.name.meta_class = PT_CLASS;
1483  name->info.name.db_object = cls;
1484  name->info.name.spec_id = (UINTPTR) name;
1485  i_attr->data_type = typ = parser_new_node (parser, PT_DATA_TYPE);
1486  if (typ)
1487  {
1488  typ->info.data_type.entity = name;
1489  }
1490  }
1491  break;
1492 
1493  case PT_TYPE_SET:
1494  case PT_TYPE_SEQUENCE:
1495  case PT_TYPE_MULTISET:
1496  types = NULL;
1497  dom = db_domain_set (db_attribute_domain (attributes));
1498  while (dom)
1499  {
1500  typ = pt_domain_to_data_type (parser, dom);
1501  if (typ)
1502  {
1503  typ->next = types;
1504  }
1505  types = typ;
1506  dom = db_domain_next (dom);
1507  }
1508  i_attr->data_type = types;
1509  break;
1510 
1511  default:
1512  dom = attributes->domain;
1513  typ = pt_domain_to_data_type (parser, dom);
1514  i_attr->data_type = typ;
1515  break;
1516  }
1517 
1518  list = parser_append_node (i_attr, list);
1519 
1520  /* advance to next attribute */
1521  attributes = db_attribute_next (attributes);
1522  }
1523  return list;
1524 }
1525 
1526 /*
1527  * pt_get_class_type () - return a class instance's type
1528  * return: PT_CLASS, PT_VCLASS, or PT_MISC_DUMMY
1529  * cls(in): a class instance
1530  */
1531 static PT_MISC_TYPE
1533 {
1534  if (!cls)
1535  {
1536  return PT_MISC_DUMMY;
1537  }
1538 
1539  if (db_is_vclass ((DB_OBJECT *) cls) > 0)
1540  {
1541  return PT_VCLASS;
1542  }
1543 
1544  if (db_is_class ((DB_OBJECT *) cls) > 0)
1545  {
1546  return PT_CLASS;
1547  }
1548 
1549  return PT_MISC_DUMMY;
1550 }
1551 
1552 /*
1553  * pt_number_of_attributes () - determine the number of attributes
1554  * of the new class to be created by a create_vclass statement,
1555  * or the number of attributes of the new definition of a view
1556  * in the case of "ALTER VIEW xxx AS SELECT ...".
1557  * return: number of attributes of the new class to be created by stmt
1558  * parser(in): the parser context used to derive stmt
1559  * stmt(in): a create_vclass statement
1560  * attrs(out): the attributes of the new class to be created by stmt
1561  *
1562  * Note :
1563  * non-inherited class_attributes are excluded from the attribute count.
1564  */
1565 static int
1567 {
1568  int count = 0;
1569  PT_NODE *crt_attr = NULL;
1570  PT_NODE *crt_parent = NULL;
1571  PT_NODE *t_attr = NULL;
1572  PT_NODE *inherited_attrs = NULL;
1573  PT_NODE *r = NULL;
1574  PT_NODE *i_attr = NULL;
1575  PT_NODE *next_node = NULL;
1576 
1577  if (stmt == NULL || attrs == NULL)
1578  {
1579  return count;
1580  }
1581 
1582  if ((stmt->node_type == PT_ALTER) && (stmt->info.alter.code == PT_RESET_QUERY))
1583  {
1584  *attrs = stmt->info.alter.alter_clause.query.attr_def_list;
1585  count = pt_length_of_list (*attrs);
1586  return count;
1587  }
1588 
1589  assert (stmt->node_type == PT_CREATE_ENTITY);
1590  if (stmt->node_type != PT_CREATE_ENTITY)
1591  {
1592  return count;
1593  }
1594 
1595  *attrs = stmt->info.create_entity.attr_def_list;
1596  count = pt_length_of_list (*attrs);
1597 
1598  /* Exclude class_attributes from count but keep them in the attrs list. */
1599  for (crt_attr = *attrs; crt_attr != NULL; crt_attr = crt_attr->next)
1600  {
1601  if (crt_attr->info.attr_def.attr_type == PT_META_ATTR)
1602  {
1603  count--;
1604  }
1605  }
1606 
1607  /* collect into one list all inherited attributes from all parents */
1608  inherited_attrs = NULL;
1609  for (crt_parent = stmt->info.create_entity.supclass_list; crt_parent != NULL; crt_parent = crt_parent->next)
1610  {
1611  /* get this parent's attributes & append them to the list */
1612  PT_NODE *const parent_attrs = pt_get_attributes (parser, crt_parent->info.name.db_object);
1613 
1614  inherited_attrs = parser_append_node (parent_attrs, inherited_attrs);
1615  }
1616 
1617  /* Rule 2: If two or more superclasses have attributes with the same name and domain but different origins, the class
1618  * may inherit one or more of the attributes, but the user needs to specify inheritance. Implementation: scan through
1619  * the inheritance list and do any attribute renaming specified by the user. */
1620  for (r = stmt->info.create_entity.resolution_list; r != NULL; r = r->next)
1621  {
1622  PT_NODE *const new_name = r->info.resolution.as_attr_mthd_name;
1623  PT_NODE *const resolv_class = r->info.resolution.of_sup_class_name;
1624  PT_NODE *const resolv_attr = r->info.resolution.attr_mthd_name;
1625 
1626  if (new_name == NULL)
1627  {
1628  continue;
1629  }
1630 
1631  for (i_attr = inherited_attrs; i_attr != NULL; t_attr = i_attr, i_attr = i_attr->next)
1632  {
1633  PT_NODE *const name = i_attr->info.attr_def.attr_name;
1634 
1635  if (pt_str_compare (resolv_attr->info.name.original, name->info.name.original, CASE_INSENSITIVE) == 0
1636  && pt_str_compare (resolv_class->info.name.original, name->info.name.resolved, CASE_INSENSITIVE) == 0)
1637  {
1638  name->info.name.original = new_name->info.name.original;
1639  }
1640  }
1641  }
1642 
1643  /* Rule 2 implementation continued: remove from inherited_attrs all inherited attributes that conflict with any
1644  * user-specified inheritance. */
1645  for (r = stmt->info.create_entity.resolution_list; r != NULL; r = r->next)
1646  {
1647  PT_NODE *const resolv_class = r->info.resolution.of_sup_class_name;
1648  PT_NODE *const resolv_attr = r->info.resolution.attr_mthd_name;
1649 
1651  {
1652  continue;
1653  }
1654 
1655  /* user wants class to inherit this attribute without renaming */
1656  for (i_attr = inherited_attrs; i_attr != NULL; i_attr = i_attr->next)
1657  {
1658  PT_NODE *const name = i_attr->info.attr_def.attr_name;
1659 
1660  if (pt_str_compare (resolv_attr->info.name.original, name->info.name.original, CASE_INSENSITIVE) != 0)
1661  {
1662  /* i_attr is a keeper so advance t_attr. */
1663  t_attr = i_attr;
1664  }
1665  else
1666  {
1667  if (pt_str_compare (resolv_class->info.name.original, name->info.name.resolved, CASE_INSENSITIVE) == 0)
1668  {
1669  /* i_attr is a keeper. keep the user-specified inherited attribute */
1670  t_attr = i_attr;
1671  continue;
1672  }
1673  /* delete inherited attribute that conflicts with resolv_attr */
1674  if (i_attr == inherited_attrs)
1675  {
1676  inherited_attrs = i_attr->next;
1677  }
1678  else
1679  {
1680  t_attr->next = i_attr->next;
1681  }
1682  /* i_attr is a goner. do NOT advance t_attr! */
1683  }
1684  }
1685  }
1686 
1687  /*
1688  * At this point, the conflicting attributes that the user wants us to keep have been safely preserved and renamed in
1689  * inherited_attrs. It is now safe to start weeding out remaining attribute conflicts. */
1690 
1691  /*
1692  * Rule 1: If the name of an attribute in a class C conflicts (i.e., is the same as) with that of an attribute in a
1693  * superclass S, the name in class C is used; that is, the attribute is not inherited. Implementation: remove from
1694  * inherited_attrs each attribute whose name matches some non-inherited attribute name. */
1695  for (crt_attr = stmt->info.create_entity.attr_def_list; crt_attr != NULL; crt_attr = crt_attr->next)
1696  {
1697  for (i_attr = inherited_attrs; i_attr; i_attr = i_attr->next)
1698  {
1701  {
1702  /* i_attr is a keeper. */
1703  t_attr = i_attr;
1704  }
1705  else
1706  {
1707  /* delete it from inherited_attrs */
1708  if (i_attr == inherited_attrs)
1709  {
1710  inherited_attrs = i_attr->next;
1711  }
1712  else
1713  {
1714  t_attr->next = i_attr->next;
1715  }
1716  /* i_attr is a goner. do NOT advance t_attr! */
1717  }
1718  }
1719  }
1720 
1721  /*
1722  * Rule 2 continued: If the user does not specify the attributes (to be inherited), the system will pick one
1723  * arbitrarily, and notify the user. Jeff probably knows how to 'pick one arbitrarily', but until we learn how, the
1724  * following will do for TPR. We lump together Rules 2 & 3 and implement them as: given a group of attributes with
1725  * the same name, keep the first and toss the rest. */
1726  for (i_attr = inherited_attrs, next_node = i_attr ? i_attr->next : NULL; i_attr != NULL;
1727  i_attr = next_node, next_node = i_attr ? i_attr->next : NULL)
1728  {
1729  for (r = i_attr->next; r != NULL; r = r->next)
1730  {
1733  {
1734  /* r is a keeper so advance t_attr. */
1735  t_attr = r;
1736  }
1737  else
1738  {
1739  if (r == i_attr->next)
1740  {
1741  i_attr->next = r->next;
1742  }
1743  else
1744  {
1745  t_attr->next = r->next;
1746  }
1747  /* r is a goner. do NOT advance t_attr! */
1748  }
1749  }
1750  }
1751 
1752  /* Append the non-inherited attributes to the inherited attributes. */
1753  if (inherited_attrs != NULL)
1754  {
1755  count += pt_length_of_list (inherited_attrs);
1756  *attrs = parser_append_node (*attrs, inherited_attrs);
1757  }
1758 
1759  return count;
1760 }
1761 
1762 /*
1763  * pt_is_real_class_of_vclass () - determine if s_class is a
1764  * real class of d_class
1765  * return: 1 if s_class is a real class of the view d_class
1766  * parser(in): the parser context
1767  * s_class(in): a PT_DATA_TYPE node whose type_enum is PT_TYPE_OBJECT
1768  * d_class(in): a PT_DATA_TYPE node whose type_enum is PT_TYPE_OBJECT
1769  */
1770 static int
1771 pt_is_real_class_of_vclass (PARSER_CONTEXT * parser, const PT_NODE * s_class, const PT_NODE * d_class)
1772 {
1773  if (!d_class || d_class->node_type != PT_DATA_TYPE || !s_class || s_class->node_type != PT_DATA_TYPE)
1774  {
1775  return 0;
1776  }
1777 
1778  return mq_is_real_class_of_vclass (parser, s_class->info.data_type.entity, d_class->info.data_type.entity);
1779 }
1780 
1781 /*
1782  * pt_objects_assignable () - determine if src is assignable to data_type dest
1783  * return: 1 iff src is assignable to dest, 0 otherwise
1784  * parser(in): the parser context
1785  * d_class_dt(in): data_type of target attribute
1786  * s_class(in): source PT_NODE
1787  */
1788 static int
1789 pt_objects_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_class_dt, const PT_NODE * s_class)
1790 {
1791  PT_NODE *s_class_type, *d_class_dt_type = NULL;
1792 
1793  if (!s_class || s_class->type_enum != PT_TYPE_OBJECT)
1794  {
1795  return 0;
1796  }
1797 
1798  if (!d_class_dt || (d_class_dt->node_type == PT_DATA_TYPE && !(d_class_dt_type = d_class_dt->info.data_type.entity)))
1799  {
1800  /* a wildcard destination object matches any other object type */
1801  return 1;
1802  }
1803 
1804  else if ((d_class_dt && d_class_dt->node_type != PT_DATA_TYPE) || !s_class->data_type
1805  || s_class->data_type->node_type != PT_DATA_TYPE)
1806  {
1807  /* weed out structural errors as failures */
1808  return 0;
1809  }
1810  else
1811  {
1812  /* s_class is assignable to d_class_dt if s_class is a subclass of d_class_dt this is what it should be: return
1813  * pt_is_subset_of(parser, s_class_type, d_class_dt_type); but d_class_dt->info.data_type.entity does not have
1814  * ALL the subclasses of the type, ie, if d_class_dt's type is "glo", it shows only "glo" instead of: "glo,
1815  * audio, etc." so we do this instead: */
1816  if (!(s_class_type = s_class->data_type->info.data_type.entity))
1817  {
1818  return 1; /* general object type */
1819  }
1820  else
1821  {
1822  return ((s_class_type->info.name.db_object == d_class_dt_type->info.name.db_object)
1823  || (db_is_subclass (s_class_type->info.name.db_object, d_class_dt_type->info.name.db_object) > 0));
1824  }
1825  }
1826 }
1827 
1828 /*
1829  * pt_class_assignable () - determine if s_class is assignable to d_class_dt
1830  * return: 1 if s_class is assignable to d_class
1831  * parser(in): the parser context
1832  * d_class_dt(in): a PT_DATA_TYPE node whose type_enum is PT_TYPE_OBJECT
1833  * s_class(in): a PT_NODE whose type_enum is PT_TYPE_OBJECT
1834  */
1835 int
1836 pt_class_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_class_dt, const PT_NODE * s_class)
1837 {
1838 
1839  /* a wildcard destination object accepts any other object type */
1840  if (!d_class_dt || (d_class_dt->node_type == PT_DATA_TYPE && !d_class_dt->info.data_type.entity))
1841  {
1842  return 1;
1843  }
1844 
1845  /* weed out structural errors as failures */
1846  if (!s_class || (d_class_dt && d_class_dt->node_type != PT_DATA_TYPE))
1847  {
1848  return 0;
1849  }
1850 
1851  /* NULL is assignable to any class type */
1852  if (s_class->type_enum == PT_TYPE_NA || s_class->type_enum == PT_TYPE_NULL)
1853  {
1854  return 1;
1855  }
1856 
1857  /* make sure we are dealing only with object types */
1858  if (s_class->type_enum != PT_TYPE_OBJECT)
1859  {
1860  return 0;
1861  }
1862 
1863  return (pt_objects_assignable (parser, d_class_dt, s_class)
1864  || pt_is_real_class_of_vclass (parser, s_class->data_type, d_class_dt)
1865  || pt_is_real_class_of_vclass (parser, d_class_dt, s_class->data_type));
1866 }
1867 
1868 /*
1869  * pt_class_compatible () - determine if two classes have compatible domains
1870  * return: 1 if class1 and class2 have compatible domains
1871  * parser(in): the parser context
1872  * class1(in): a PT_NODE whose type_enum is PT_TYPE_OBJECT
1873  * class2(in): a PT_NODE whose type_enum is PT_TYPE_OBJECT
1874  * view_definition_context(in):
1875  */
1876 static int
1877 pt_class_compatible (PARSER_CONTEXT * parser, const PT_NODE * class1, const PT_NODE * class2,
1878  bool view_definition_context)
1879 {
1880  if (!class1 || class1->type_enum != PT_TYPE_OBJECT || !class2 || class2->type_enum != PT_TYPE_OBJECT)
1881  {
1882  return 0;
1883  }
1884 
1885  if (view_definition_context)
1886  {
1887  return pt_class_assignable (parser, class1->data_type, class2);
1888  }
1889  else
1890  {
1891  return (pt_class_assignable (parser, class1->data_type, class2)
1892  || pt_class_assignable (parser, class2->data_type, class1));
1893  }
1894 }
1895 
1896 /*
1897  * pt_vclass_compatible () - determine if att is vclass compatible with qcol
1898  * return: true if att is vclass compatible with qcol
1899  * parser(in): the parser context
1900  * att(in): PT_DATA_TYPE node of a vclass attribute def
1901  * qcol(in): a query spec column
1902  */
1903 static bool
1904 pt_vclass_compatible (PARSER_CONTEXT * parser, const PT_NODE * att, const PT_NODE * qcol)
1905 {
1906  PT_NODE *entity, *qcol_entity, *qcol_typ;
1907  DB_OBJECT *vcls = NULL;
1908  const char *clsnam = NULL, *qcol_typnam = NULL, *spec, *qs_clsnam;
1909  DB_QUERY_SPEC *specs;
1910 
1911  /* a wildcard object accepts any other object type but is not vclass_compatible with any other object */
1912  if (!att || (att->node_type == PT_DATA_TYPE && !att->info.data_type.entity))
1913  {
1914  return false;
1915  }
1916 
1917  /* weed out structural errors as failures */
1918  if (!qcol || (att && att->node_type != PT_DATA_TYPE) || (entity = att->info.data_type.entity) == NULL
1919  || entity->node_type != PT_NAME || ((vcls = entity->info.name.db_object) == NULL
1920  && (clsnam = entity->info.name.original) == NULL))
1921  {
1922  return false;
1923  }
1924 
1925  /* make sure we are dealing only with object types that can be union vclass_compatible with vcls. */
1926  if (qcol->type_enum != PT_TYPE_OBJECT || (qcol_typ = qcol->data_type) == NULL || qcol_typ->node_type != PT_DATA_TYPE
1927  || (qcol_entity = qcol_typ->info.data_type.entity) == NULL || qcol_entity->node_type != PT_NAME
1928  || (qcol_typnam = qcol_entity->info.name.original) == NULL)
1929  {
1930  return false;
1931  }
1932 
1933  /* make sure we have the vclass */
1934  if (!vcls)
1935  {
1936  vcls = db_find_class (clsnam);
1937  }
1938  if (!vcls)
1939  {
1940  return false;
1941  }
1942 
1943  /* return true iff att is a vclass & qcol is in att's query_spec list */
1944  for (specs = db_get_query_specs (vcls); specs && (spec = db_query_spec_string (specs));
1945  specs = db_query_spec_next (specs))
1946  {
1947  qs_clsnam = pt_get_proxy_spec_name (spec);
1948  if (qs_clsnam && intl_identifier_casecmp (qs_clsnam, qcol_typnam) == 0)
1949  {
1950  return true; /* att is vclass_compatible with qcol */
1951  }
1952  }
1953 
1954  return false; /* att is not vclass_compatible with qcol */
1955 }
1956 
1957 /*
1958  * pt_type_assignable () - determine if s_type is assignable to d_type
1959  * return: 1 if s_type is assignable to d_type
1960  * parser(in): the parser context
1961  * d_type(in): a PT_DATA_TYPE node whose type_enum is PT_TYPE_OBJECT
1962  * s_type(in): a PT_DATA_TYPE node whose type_enum is PT_TYPE_OBJECT
1963  */
1964 static int
1965 pt_type_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_type, const PT_NODE * s_type)
1966 {
1967  PT_NODE *src_type, *dest_type = NULL;
1968 
1969  /* a wildcard destination object accepts any other object type */
1970  if (!d_type || (d_type->node_type == PT_DATA_TYPE && !d_type->info.data_type.entity))
1971  {
1972  return 1;
1973  }
1974 
1975  /* weed out structural errors as failures */
1976  if (!s_type || (d_type && d_type->node_type != PT_DATA_TYPE))
1977  {
1978  return 0;
1979  }
1980 
1981  /* make sure we are dealing only with object types */
1982  if (s_type->type_enum != PT_TYPE_OBJECT)
1983  {
1984  return 0;
1985  }
1986 
1987  dest_type = d_type->info.data_type.entity;
1988  src_type = s_type->info.data_type.entity;
1989  if (!dest_type || !src_type)
1990  {
1991  return 0;
1992  }
1993 
1994  /* If the destination isn't resolved, resolve it. */
1995  if (!dest_type->info.name.db_object)
1996  {
1997  dest_type->info.name.db_object = db_find_class (dest_type->info.name.original);
1998  dest_type->info.name.meta_class = PT_CLASS;
1999  }
2000 
2001  return (src_type->info.name.db_object == dest_type->info.name.db_object
2002  || (db_is_subclass (src_type->info.name.db_object, dest_type->info.name.db_object) > 0)
2003  || mq_is_real_class_of_vclass (parser, src_type, dest_type));
2004 }
2005 
2006 /*
2007  * pt_collection_assignable () - determine if s_col is assignable to d_col
2008  * return: 1 if s_col is assignable to d_col
2009  * parser(in): the parser context
2010  * d_col(in): a PT_NODE whose type_enum is a PT_IS_COLLECTION_TYPE
2011  * s_col(in): a PT_NODE whose type_enum is a PT_IS_COLLECTION_TYPE
2012  */
2013 static int
2014 pt_collection_assignable (PARSER_CONTEXT * parser, const PT_NODE * d_col, const PT_NODE * s_col)
2015 {
2016  int assignable = 1; /* innocent until proven guilty */
2017 
2018  if (!d_col || !s_col || !PT_IS_COLLECTION_TYPE (d_col->type_enum))
2019  {
2020  return 0;
2021  }
2022 
2023  /* NULL is assignable to any class type */
2024  if (s_col->type_enum == PT_TYPE_NA || s_col->type_enum == PT_TYPE_NULL)
2025  {
2026  return 1;
2027  }
2028 
2029  /* make sure we are dealing only with collection types */
2030  if (!PT_IS_COLLECTION_TYPE (s_col->type_enum))
2031  {
2032  return 0;
2033  }
2034 
2035  /* can't assign a multiset or a sequence to a set, or a multiset to a sequence */
2036  if (((d_col->type_enum == PT_TYPE_SET)
2037  && ((s_col->type_enum == PT_TYPE_MULTISET) || (s_col->type_enum == PT_TYPE_SEQUENCE)))
2038  || ((d_col->type_enum == PT_TYPE_SEQUENCE) && (s_col->type_enum == PT_TYPE_MULTISET)))
2039  {
2040  assignable = 0;
2041  }
2042  else if (!d_col->data_type)
2043  {
2044  /* the wildcard set (set of anything) can be assigned a set of any type. */
2045  assignable = 1;
2046  }
2047  else if (!s_col->data_type)
2048  {
2049  /* in this case, we have a wild card set being assigned to a non-wildcard set. */
2050  assignable = 0;
2051  }
2052  else
2053  {
2054  /* Check to see that every type in the source collection is in the destination collection. That is, the source
2055  * types must be a subset of the destination types. There is no coercion allowed. */
2056  PT_NODE *st, *dt;
2057  int found;
2058 
2059  for (st = s_col->data_type; st != NULL; st = st->next)
2060  {
2061  found = 0;
2062  for (dt = d_col->data_type; dt != NULL; dt = dt->next)
2063  {
2064  if (st->type_enum == dt->type_enum)
2065  {
2066  if ((st->type_enum != PT_TYPE_OBJECT) || (pt_type_assignable (parser, dt, st)))
2067  {
2068  found = 1;
2069  break;
2070  }
2071  }
2072  }
2073 
2074  if (!found)
2075  {
2076  assignable = 0;
2077  break;
2078  }
2079  }
2080  }
2081 
2082  return assignable;
2083 } /* pt_collection_assignable */
2084 
2085 /*
2086  * pt_collection_compatible () - determine if two collections
2087  * have compatible domains
2088  * return: 1 if c1 and c2 have compatible domains
2089  * parser(in): the parser context
2090  * col1(in): a PT_NODE whose type_enum is PT_TYPE_OBJECT
2091  * col2(in): a PT_NODE whose type_enum is PT_TYPE_OBJECT
2092  * view_definition_context(in):
2093  */
2094 static int
2095 pt_collection_compatible (PARSER_CONTEXT * parser, const PT_NODE * col1, const PT_NODE * col2,
2096  bool view_definition_context)
2097 {
2098  if (!col1 || !PT_IS_COLLECTION_TYPE (col1->type_enum) || !col2 || !PT_IS_COLLECTION_TYPE (col2->type_enum))
2099  {
2100  return 0;
2101  }
2102 
2103  if (view_definition_context)
2104  {
2105  return pt_collection_assignable (parser, col1, col2);
2106  }
2107  else
2108  {
2109  return (col1->type_enum == col2->type_enum
2110  && (pt_collection_assignable (parser, col1, col2) || pt_collection_assignable (parser, col2, col1)));
2111  }
2112 }
2113 
2114 /*
2115  * pt_union_compatible () - determine if two select_list items are
2116  * union compatible
2117  * return: 1 if item1 and item2 are union compatible.
2118  * parser(in): the parser context
2119  * item1(in): an element of a select_list or attribute_list
2120  * item2(in): an element of a select_list or attribute_list
2121  * view_definition_context(in):
2122  * is_object_type(in):
2123  *
2124  * Note :
2125  * return 1 if:
2126  * - item1 or item2 is "NA", or
2127  * - item1 and item2 have identical types, or
2128  * - item1 is a literal that can be coerced to item2's type, or
2129  * - item2 is a literal that can be coerced to item1's type.
2130  */
2131 
2132 static PT_UNION_COMPATIBLE
2133 pt_union_compatible (PARSER_CONTEXT * parser, PT_NODE * item1, PT_NODE * item2, bool view_definition_context,
2134  bool * is_object_type)
2135 {
2136  PT_TYPE_ENUM typ1, typ2, common_type;
2137  PT_NODE *dt1, *dt2, *data_type;
2138  int r;
2139 
2140  typ1 = item1->type_enum;
2141  typ2 = item2->type_enum;
2142  *is_object_type = false;
2143 
2144  if (typ1 == typ2 && typ1 != PT_TYPE_OBJECT && !PT_IS_COLLECTION_TYPE (typ1))
2145  {
2146  if (typ1 == PT_TYPE_NONE) /* is not compatible with anything */
2147  {
2149  }
2150 
2151  if (typ1 == PT_TYPE_MAYBE)
2152  {
2153  /* assume hostvars are compatible */
2154  return PT_UNION_COMP;
2155  }
2156 
2157  if (!view_definition_context)
2158  {
2159  dt1 = item1->data_type;
2160  dt2 = item2->data_type;
2161  common_type = typ1;
2162 
2163  if (dt1 && dt2)
2164  {
2165  /* numeric type, fixed size string type */
2166  if (common_type == PT_TYPE_NUMERIC || PT_IS_STRING_TYPE (common_type))
2167  {
2168  if ((dt1->info.data_type.precision != dt2->info.data_type.precision)
2170  || (dt1->info.data_type.units != dt2->info.data_type.units))
2171  {
2172  /* different numeric and fixed size string types are incompatible */
2173  return PT_UNION_INCOMP;
2174  }
2175  }
2176  }
2177  else
2178  {
2179  return PT_UNION_INCOMP;
2180  }
2181  }
2182  return PT_UNION_COMP;
2183  }
2184 
2185  if (typ2 == PT_TYPE_NA || typ2 == PT_TYPE_NULL)
2186  {
2187  /* NA is compatible with any type except PT_TYPE_NONE */
2188  return ((typ1 != PT_TYPE_NONE) ? PT_UNION_COMP : PT_UNION_INCOMP_CANNOT_FIX);
2189  }
2190 
2191  if (typ1 == PT_TYPE_NA || typ1 == PT_TYPE_NULL)
2192  {
2193  /* NA is compatible with any type except PT_TYPE_NONE */
2194  return ((typ2 != PT_TYPE_NONE) ? PT_UNION_COMP : PT_UNION_INCOMP_CANNOT_FIX);
2195  }
2196 
2197  if (view_definition_context)
2198  {
2199  common_type = typ1;
2200  }
2201  else
2202  {
2203  common_type = pt_common_type (typ1, typ2);
2204  }
2205 
2206  if (common_type == PT_TYPE_NONE) /* not union compatible */
2207  {
2209  }
2210 
2211  if (item1->node_type == PT_VALUE || item2->node_type == PT_VALUE)
2212  {
2213  data_type = NULL;
2214  if (common_type == PT_TYPE_NUMERIC)
2215  {
2216  SEMAN_COMPATIBLE_INFO ci1, ci2;
2217 
2218  pt_get_compatible_info_from_node (item1, &ci1);
2219  pt_get_compatible_info_from_node (item2, &ci2);
2220 
2221  data_type = parser_new_node (parser, PT_DATA_TYPE);
2222  if (data_type == NULL)
2223  {
2224  return PT_UNION_ERROR;
2225  }
2226  data_type->info.data_type.precision =
2227  MAX ((ci1.prec - ci1.scale), (ci2.prec - ci2.scale)) + MAX (ci1.scale, ci2.scale);
2228  data_type->info.data_type.dec_precision = MAX (ci1.scale, ci2.scale);
2229 
2231  {
2232  data_type->info.data_type.dec_precision =
2234  if (data_type->info.data_type.dec_precision < 0)
2235  {
2236  data_type->info.data_type.dec_precision = 0;
2237  }
2239  }
2240  }
2241 
2242  if (item1->type_enum == common_type && item2->type_enum == common_type)
2243  {
2244  return PT_UNION_COMP;
2245  }
2246  else
2247  {
2248  return PT_UNION_INCOMP;
2249  }
2250  }
2251  else if (common_type == PT_TYPE_OBJECT)
2252  {
2253  *is_object_type = true;
2254  if ((item1->node_type == PT_NAME && item1->info.name.meta_class == PT_VID_ATTR)
2255  || (item2->node_type == PT_NAME && item2->info.name.meta_class == PT_VID_ATTR))
2256  {
2257  /* system-added OID */
2258  return PT_UNION_COMP;
2259  }
2260  else
2261  {
2262  r = pt_class_compatible (parser, item1, item2, view_definition_context);
2263  return ((r == 1) ? PT_UNION_COMP : PT_UNION_INCOMP_CANNOT_FIX);
2264  }
2265  }
2266  else if (PT_IS_COLLECTION_TYPE (common_type))
2267  {
2268  r = pt_collection_compatible (parser, item1, item2, view_definition_context);
2269  return ((r == 1) ? PT_UNION_COMP : PT_UNION_INCOMP_CANNOT_FIX);
2270  }
2271 
2272  return PT_UNION_INCOMP; /* not union compatible */
2273 }
2274 
2275 /*
2276  * pt_is_compatible_without_cast () -
2277  * return: true/false
2278  * parser(in):
2279  * dest_type_enum(in):
2280  * dest_prec(in):
2281  * dest_scale(in):
2282  * src(in):
2283  */
2284 static bool
2286  bool * is_cast_allowed)
2287 {
2288  assert (dest_sci != NULL);
2289  assert (src != NULL);
2290  assert (is_cast_allowed != NULL);
2291 
2292  *is_cast_allowed = true;
2293 
2294  if (dest_sci->force_cast && dest_sci->type_enum == PT_TYPE_JSON)
2295  {
2296  return false;
2297  }
2298 
2299  if (dest_sci->type_enum != src->type_enum)
2300  {
2301  return false;
2302  }
2303 
2304  if (PT_HAS_COLLATION (src->type_enum))
2305  {
2306  if (src->data_type != NULL && src->data_type->info.data_type.collation_id != dest_sci->coll_infer.coll_id)
2307  {
2308  INTL_CODESET att_cs;
2309 
2310  att_cs = (INTL_CODESET) src->data_type->info.data_type.units;
2311 
2312  if (!INTL_CAN_COERCE_CS (att_cs, dest_sci->coll_infer.codeset))
2313  {
2314  *is_cast_allowed = false;
2315  }
2316 
2317  return false;
2318  }
2319  }
2320 
2321  if (PT_IS_STRING_TYPE (dest_sci->type_enum))
2322  {
2323  assert_release (dest_sci->prec != 0);
2324  if (src->data_type && dest_sci->prec == src->data_type->info.data_type.precision)
2325  {
2326  return true;
2327  }
2328  else
2329  {
2330  return false;
2331  }
2332  }
2333  else if (dest_sci->type_enum == PT_TYPE_NUMERIC)
2334  {
2335  assert_release (dest_sci->prec != 0);
2336  if (src->data_type && dest_sci->prec == src->data_type->info.data_type.precision
2337  && dest_sci->scale == src->data_type->info.data_type.dec_precision)
2338  {
2339  return true;
2340  }
2341  else
2342  {
2343  return false;
2344  }
2345  }
2346  else if (dest_sci->type_enum == PT_TYPE_ENUMERATION)
2347  {
2348  /* enumerations might not have the same domain */
2349  return false;
2350  }
2351  else if (PT_IS_COLLECTION_TYPE (dest_sci->type_enum))
2352  {
2353  /* collections might not have the same domain */
2354  return false;
2355  }
2356 
2357  return true; /* is compatible, no need to cast */
2358 }
2359 
2360 /*
2361  * pt_to_compatible_cast () -
2362  * return:
2363  * parser(in):
2364  * node(in):
2365  * cinfo(in):
2366  */
2367 static PT_NODE *
2368 pt_to_compatible_cast (PARSER_CONTEXT * parser, PT_NODE * node, SEMAN_COMPATIBLE_INFO * cinfo, int num_cinfo)
2369 {
2370  PT_NODE *attrs, *att;
2371  PT_NODE *prev_att, *next_att, *new_att = NULL, *new_dt = NULL;
2372  int i;
2373  bool new_cast_added;
2374  bool need_to_cast;
2375 
2376  assert (parser != NULL);
2377 
2378  if (!node || !pt_is_query (node))
2379  {
2380  return NULL;
2381  }
2382 
2383  if (pt_is_select (node))
2384  {
2385  if (PT_IS_VALUE_QUERY (node))
2386  {
2387  node = pt_values_query_to_compatible_cast (parser, node, cinfo, num_cinfo);
2388  }
2389  else
2390  {
2391  attrs = pt_get_select_list (parser, node);
2392  if (attrs == NULL)
2393  {
2394  return NULL;
2395  }
2396 
2397  prev_att = NULL;
2398  for (att = attrs, i = 0; i < num_cinfo && att; att = next_att, i++)
2399  {
2400  bool is_cast_allowed = true;
2401 
2402  new_cast_added = false;
2403 
2404  next_att = att->next; /* save next link */
2405 
2406  need_to_cast = false;
2407  /* find incompatible attr */
2408  if (cinfo[i].idx == i)
2409  {
2410  if (!pt_is_compatible_without_cast (parser, &(cinfo[i]), att, &is_cast_allowed))
2411  {
2412  need_to_cast = true;
2413 
2414  /* assertion check */
2415  if (need_to_cast)
2416  {
2417  if (PT_IS_STRING_TYPE (att->type_enum) || att->type_enum == PT_TYPE_NUMERIC)
2418  {
2419  if (att->data_type == NULL)
2420  {
2421  assert_release (att->data_type != NULL);
2422  return NULL;
2423  }
2424  }
2425  }
2426  }
2427  }
2428 
2429  if (need_to_cast)
2430  {
2431  SEMAN_COMPATIBLE_INFO att_cinfo;
2432 
2433  if (!is_cast_allowed)
2434  {
2435  return NULL;
2436  }
2437 
2438  memcpy (&att_cinfo, &(cinfo[i]), sizeof (att_cinfo));
2439 
2440  if (PT_HAS_COLLATION (att->type_enum) && att->data_type != NULL)
2441  {
2442  /* use collation and codeset of original attribute the values from cinfo are not usable */
2443  att_cinfo.coll_infer.coll_id = att->data_type->info.data_type.collation_id;
2444  att_cinfo.coll_infer.codeset = (INTL_CODESET) att->data_type->info.data_type.units;
2445  }
2446 
2447  new_att = pt_make_cast_with_compatible_info (parser, att, next_att, &att_cinfo, &new_cast_added);
2448  if (new_att == NULL)
2449  {
2450  goto out_of_mem;
2451  }
2452 
2453  if (new_cast_added)
2454  {
2455  att = new_att;
2456  }
2457 
2458  if (prev_att == NULL)
2459  {
2460  node->info.query.q.select.list = att;
2461  node->type_enum = att->type_enum;
2462  if (node->data_type)
2463  {
2464  parser_free_tree (parser, node->data_type);
2465  }
2466  node->data_type = parser_copy_tree_list (parser, att->data_type);
2467  }
2468  else
2469  {
2470  prev_att->next = att;
2471  }
2472  }
2473 
2474  prev_att = att;
2475  }
2476  }
2477  }
2478  else
2479  { /* PT_UNION, PT_DIFFERENCE, PT_INTERSECTION */
2480  if (!pt_to_compatible_cast (parser, node->info.query.q.union_.arg1, cinfo, num_cinfo)
2481  || !pt_to_compatible_cast (parser, node->info.query.q.union_.arg2, cinfo, num_cinfo))
2482  {
2483  return NULL;
2484  }
2485 
2486  if (node->data_type)
2487  {
2488  parser_free_tree (parser, node->data_type);
2489  }
2490  node->data_type = parser_copy_tree_list (parser, node->info.query.q.union_.arg1->data_type);
2491  }
2492 
2493  return node;
2494 
2495 out_of_mem:
2496  if (new_att)
2497  {
2498  parser_free_tree (parser, new_att);
2499  }
2500 
2501  if (new_dt)
2502  {
2503  parser_free_tree (parser, new_dt);
2504  }
2505 
2507  return NULL;
2508 }
2509 
2510 /*
2511  * pt_get_compatible_info_from_node () -
2512  * return:
2513  * att(in):
2514  * cinfo(out):
2515  */
2516 static void
2518 {
2519  assert (cinfo != NULL);
2520 
2521  cinfo->coll_infer.coll_id = -1;
2524  cinfo->coll_infer.can_force_cs = false;
2525  cinfo->prec = cinfo->scale = 0;
2526  cinfo->ref_att = att;
2527  cinfo->force_cast = false;
2528 
2529  cinfo->type_enum = att->type_enum;
2530 
2531  switch (att->type_enum)
2532  {
2533  case PT_TYPE_SMALLINT:
2534  cinfo->prec = 6;
2535  cinfo->scale = 0;
2536  break;
2537  case PT_TYPE_INTEGER:
2538  cinfo->prec = 10;
2539  cinfo->scale = 0;
2540  break;
2541  case PT_TYPE_BIGINT:
2542  cinfo->prec = 19;
2543  cinfo->scale = 0;
2544  break;
2545  case PT_TYPE_NUMERIC:
2546  cinfo->prec = (att->data_type) ? att->data_type->info.data_type.precision : 0;
2547  cinfo->scale = (att->data_type) ? att->data_type->info.data_type.dec_precision : 0;
2548  break;
2549  case PT_TYPE_CHAR:
2550  case PT_TYPE_VARCHAR:
2551  case PT_TYPE_NCHAR:
2552  case PT_TYPE_VARNCHAR:
2553  cinfo->prec = (att->data_type) ? att->data_type->info.data_type.precision : 0;
2554  cinfo->scale = 0;
2555  break;
2556  default:
2557  break;
2558  }
2559 
2560  if (PT_HAS_COLLATION (att->type_enum))
2561  {
2562  (void) pt_get_collation_info ((PT_NODE *) att, &(cinfo->coll_infer));
2563  }
2564 }
2565 
2566 /*
2567  * pt_get_common_type_for_union () -
2568  * return:
2569  * parser(in):
2570  * att1(in):
2571  * att2(in):
2572  * cinfo(out):
2573  * idx(in):
2574  * need_cast(out):
2575  */
2576 static PT_NODE *
2578  int idx, bool * need_cast)
2579 {
2580  PT_NODE *dt1, *dt2;
2581  PT_TYPE_ENUM common_type;
2582  bool is_compatible = false;
2583 
2584  dt1 = att1->data_type;
2585  dt2 = att2->data_type;
2586 
2587  if ((PT_IS_STRING_TYPE (att1->type_enum) && att2->type_enum == PT_TYPE_MAYBE)
2588  || (PT_IS_STRING_TYPE (att2->type_enum) && att1->type_enum == PT_TYPE_MAYBE))
2589  {
2590  common_type = (att1->type_enum == PT_TYPE_MAYBE ? att2->type_enum : att1->type_enum);
2591  }
2592  else
2593  {
2594  common_type = pt_common_type (att1->type_enum, att2->type_enum);
2595  }
2596 
2597  if (common_type != PT_TYPE_NONE)
2598  {
2599  SEMAN_COMPATIBLE_INFO att1_info, att2_info;
2600  /* save attr idx and compatible type */
2601  cinfo->idx = idx;
2602 
2603  pt_get_compatible_info_from_node (att1, &att1_info);
2604  pt_get_compatible_info_from_node (att2, &att2_info);
2605 
2606  is_compatible = pt_update_compatible_info (parser, cinfo, common_type, &att1_info, &att2_info);
2607 
2608  if (is_compatible)
2609  {
2610  *need_cast = true;
2611  }
2612  }
2613 
2614  if (!is_compatible)
2615  {
2617  pt_short_print (parser, att1), pt_short_print (parser, att2));
2618  return NULL;
2619  }
2620 
2621  return att1;
2622 }
2623 
2624 /*
2625  * pt_check_union_compatibility () - check two query_specs for
2626  * union compatibility
2627  * return: node on success, NULL otherwise.
2628  * parser(in): the parser context used to derive qry1 and qry2
2629  * node(in): a query node
2630  *
2631  * Note :
2632  * the definition of union compatible is: same number of pairwise
2633  * union-compatible attributes from the two query_specs.
2634  * two vclass compatible attributes are considered union-compatible.
2635  */
2636 
2637 PT_NODE *
2639 {
2640  PT_NODE *attrs1, *attrs2, *result = node;
2641  PT_NODE *arg1, *arg2;
2642  int cnt1, cnt2;
2643  SEMAN_COMPATIBLE_INFO *cinfo = NULL;
2644  bool need_cast;
2645 
2646  assert (parser != NULL);
2647 
2648  if (node == NULL
2649  || (node->node_type != PT_UNION && node->node_type != PT_INTERSECTION && node->node_type != PT_DIFFERENCE
2650  && node->node_type != PT_CTE))
2651  {
2652  return NULL;
2653  }
2654 
2655  if (node->node_type == PT_CTE)
2656  {
2657  arg1 = node->info.cte.non_recursive_part;
2658  arg2 = node->info.cte.recursive_part;
2659  }
2660  else
2661  {
2662  arg1 = node->info.query.q.union_.arg1;
2663  arg2 = node->info.query.q.union_.arg2;
2664  }
2665 
2666  attrs1 = pt_get_select_list (parser, arg1);
2667  if (attrs1 == NULL)
2668  {
2669  return NULL;
2670  }
2671  attrs2 = pt_get_select_list (parser, arg2);
2672  if (attrs2 == NULL)
2673  {
2674  return NULL;
2675  }
2676 
2679 
2680  if (cnt1 != cnt2)
2681  {
2683  return NULL;
2684  }
2685 
2686  /* get compatible info */
2687  cinfo = pt_get_compatible_info (parser, node, attrs1, attrs2, &need_cast);
2688  if (cinfo == NULL && need_cast)
2689  {
2690  result = NULL;
2691  }
2692 
2693  /* convert attrs type to compatible type */
2694  if (result && need_cast == true)
2695  {
2696  if (!pt_to_compatible_cast (parser, arg1, cinfo, cnt1) || !pt_to_compatible_cast (parser, arg2, cinfo, cnt1))
2697  {
2698  result = NULL;
2699  }
2700  else
2701  {
2702  /* copy the new data_type to the actual UNION node */
2703  if (node->data_type != NULL)
2704  {
2705  parser_free_tree (parser, node->data_type);
2706  }
2707 
2708  node->data_type = parser_copy_tree (parser, arg1->data_type);
2709  }
2710  }
2711 
2712  if (cinfo)
2713  {
2714  free_and_init (cinfo);
2715  }
2716 
2717  return result;
2718 }
2719 
2720 /*
2721  * pt_check_type_compatibility_of_values_query () - check rows for
2722  * values query compatibility
2723  * return: node on success, NULL otherwise.
2724  * parser(in): the parser context used to derive qry1 and qry2
2725  * node(in): a query node
2726  *
2727  * Note :
2728  * the definition of values query compatible is: same number of
2729  * attributes from rows.
2730  * every two rows' compatible attributes are considered union-compatible.
2731  */
2732 PT_NODE *
2734 {
2735  PT_NODE *node_list, *result = node;
2736  SEMAN_COMPATIBLE_INFO *cinfo = NULL;
2737  bool need_cast = false;
2738  PT_NODE *attrs;
2739  int count;
2740 
2741  assert (parser);
2742 
2743  if (node == NULL || node->node_type != PT_SELECT || !PT_IS_VALUE_QUERY (node))
2744  {
2745  return NULL;
2746  }
2747 
2748  node_list = node->info.query.q.select.list;
2749  if (node_list == NULL)
2750  {
2751  return NULL;
2752  }
2753  attrs = node_list->info.node_list.list;
2754 
2755  node_list = node_list->next;
2756  /* only one row */
2757  if (node_list == NULL)
2758  {
2759  return result;
2760  }
2761 
2763 
2764  /* get compatible_info for cast */
2765  cinfo = pt_get_values_query_compatible_info (parser, node, &need_cast);
2766 
2767  if (cinfo == NULL && need_cast)
2768  {
2769  result = NULL;
2770  goto end;
2771  }
2772 
2773  /* convert attrs type to compatible type */
2774  if (need_cast && cinfo != NULL)
2775  {
2776  result = pt_values_query_to_compatible_cast (parser, node, cinfo, count);
2777  }
2778 
2779 end:
2780  if (cinfo)
2781  {
2782  free_and_init (cinfo);
2783  }
2784 
2785  return result;
2786 }
2787 
2788 /*
2789  * pt_check_union_values_query_compatibility () - check compatibility
2790  * when union values query
2791  * return: node on success, NULL otherwise.
2792  * parser(in): the parser context used to derive qry1 and qry2
2793  * node(in): a query node
2794  *
2795  * Note :
2796  * please see pt_check_union_compatibility
2797  * and pt_check_type_compatibility_of_values_query
2798  */
2799 PT_NODE *
2801 {
2802  PT_NODE *attrs1, *attrs2, *att1, *att2, *result = node;
2803  int cnt1, cnt2, i;
2804  SEMAN_COMPATIBLE_INFO *cinfo = NULL;
2805  SEMAN_COMPATIBLE_INFO *cinfo_arg1 = NULL;
2806  SEMAN_COMPATIBLE_INFO *cinfo_arg2 = NULL;
2807  SEMAN_COMPATIBLE_INFO *cinfo_arg3 = NULL;
2808  bool need_cast;
2809  PT_NODE *arg1, *arg2, *tmp;
2810  bool is_compatible;
2811 
2812  assert (parser != NULL);
2813 
2814  if (!node
2815  || !(node->node_type == PT_UNION || node->node_type == PT_INTERSECTION || node->node_type == PT_DIFFERENCE
2816  || node->node_type == PT_CTE))
2817  {
2818  return NULL;
2819  }
2820 
2821  if (node->node_type == PT_CTE)
2822  {
2823  arg1 = node->info.cte.non_recursive_part;
2824  arg2 = node->info.cte.recursive_part;
2825  }
2826  else
2827  {
2828  arg1 = node->info.query.q.union_.arg1;
2829  arg2 = node->info.query.q.union_.arg2;
2830  }
2831 
2832  if (!arg1 || !arg2 || !(attrs1 = pt_get_select_list (parser, arg1)) || !(attrs2 = pt_get_select_list (parser, arg2)))
2833  {
2834  return NULL;
2835  }
2836 
2839  if (cnt1 != cnt2)
2840  {
2842  return NULL;
2843  }
2844 
2845  if (PT_IS_VALUE_QUERY (arg1) && PT_IS_VALUE_QUERY (arg2)) /* two values query */
2846  {
2847  need_cast = false;
2848  cinfo_arg1 = pt_get_values_query_compatible_info (parser, arg1, &need_cast);
2849  if (cinfo_arg1 == NULL && need_cast)
2850  {
2851  result = NULL;
2852  goto end;
2853  }
2854 
2855  need_cast = false;
2856  cinfo_arg2 = pt_get_values_query_compatible_info (parser, arg2, &need_cast);
2857  if (cinfo_arg2 == NULL && need_cast)
2858  {
2859  result = NULL;
2860  goto end;
2861  }
2862 
2863  /* compare cinfo_arg1 and cinfo_arg2 save the compatible cinfo in cinfo_arg1 */
2864  if (cinfo_arg1 != NULL && cinfo_arg2 != NULL)
2865  {
2866  is_compatible = true;
2867 
2868  for (i = 0, att1 = attrs1, att2 = attrs2; i < cnt1; ++i, att1 = att1->next, att2 = att2->next)
2869  {
2870  is_compatible = pt_combine_compatible_info (parser, cinfo_arg1 + i, cinfo_arg2 + i, att1, att2, i);
2871  if (!is_compatible)
2872  {
2873  result = NULL;
2874  goto end;
2875  }
2876  }
2877  }
2878  else if (cinfo_arg2 != NULL)
2879  {
2880  cinfo_arg1 = cinfo_arg2;
2881  cinfo_arg2 = NULL;
2882  }
2883 
2884  /* compare the select list */
2885  cinfo_arg3 = pt_get_compatible_info (parser, node, attrs1, attrs2, &need_cast);
2886  if (cinfo_arg3 == NULL && need_cast)
2887  {
2888  result = NULL;
2889  goto end;
2890  }
2891 
2892  if (need_cast)
2893  {
2894  if (cinfo_arg1 != NULL)
2895  {
2896  is_compatible = true;
2897  for (i = 0, att1 = attrs1, att2 = attrs2; i < cnt1; ++i, att1 = att1->next, att2 = att2->next)
2898  {
2899  is_compatible = pt_combine_compatible_info (parser, cinfo_arg1 + i, cinfo_arg3 + i, att1, att2, i);
2900  if (!is_compatible)
2901  {
2902  result = NULL;
2903  goto end;
2904  }
2905  }
2906  }
2907  else
2908  {
2909  cinfo_arg1 = cinfo_arg3;
2910  cinfo_arg3 = NULL;
2911  }
2912  }
2913 
2914  cinfo = cinfo_arg1;
2915  }
2916  else if (PT_IS_VALUE_QUERY (arg1) || PT_IS_VALUE_QUERY (arg2)) /* one values query, one select */
2917  {
2918  /* make arg1->is_value_query==1 */
2919  if (PT_IS_VALUE_QUERY (arg2))
2920  {
2921  tmp = arg1;
2922  arg1 = arg2;
2923  arg2 = tmp;
2924  }
2925 
2926  /* arg1 is the values query */
2927  need_cast = false;
2928  cinfo_arg1 = pt_get_values_query_compatible_info (parser, arg1, &need_cast);
2929  if (cinfo_arg1 == NULL && need_cast)
2930  {
2931  result = NULL;
2932  goto end;
2933  }
2934 
2935  /* get the cinfo of select */
2936  attrs1 = pt_get_select_list (parser, arg1);
2937  attrs2 = pt_get_select_list (parser, arg2);
2938  cinfo_arg2 = pt_get_compatible_info (parser, node, attrs1, attrs2, &need_cast);
2939  if (cinfo_arg2 == NULL && need_cast)
2940  {
2941  result = NULL;
2942  goto end;
2943  }
2944 
2945  if (need_cast)
2946  {
2947  /* compare cinfo_arg1 and cinfo_arg2 save the compatible cinfo in cinfo_arg1 */
2948  if (cinfo_arg1 != NULL)
2949  {
2950  is_compatible = true;
2951  for (i = 0, att1 = attrs1, att2 = attrs2; i < cnt1; ++i, att1 = att1->next, att2 = att2->next)
2952  {
2953  is_compatible = pt_combine_compatible_info (parser, cinfo_arg1 + i, cinfo_arg2 + i, att1, att2, i);
2954  if (!is_compatible)
2955  {
2956  result = NULL;
2957  goto end;
2958  }
2959  }
2960  }
2961  else
2962  {
2963  cinfo_arg1 = cinfo_arg2;
2964  cinfo_arg2 = NULL;
2965  }
2966  cinfo = cinfo_arg1;
2967  }
2968  }
2969  else
2970  {
2971  /* should not be here */
2972  assert (false);
2973  }
2974 
2975  /* make the cast */
2976  if (cinfo != NULL)
2977  {
2978  if (pt_to_compatible_cast (parser, arg1, cinfo, cnt1) == NULL
2979  || pt_to_compatible_cast (parser, arg2, cinfo, cnt1) == NULL)
2980  {
2981  result = NULL;
2982  }
2983  }
2984 
2985 end:
2986  if (cinfo_arg1)
2987  {
2988  free_and_init (cinfo_arg1);
2989  }
2990  if (cinfo_arg2)
2991  {
2992  free_and_init (cinfo_arg2);
2993  }
2994  if (cinfo_arg3)
2995  {
2996  free_and_init (cinfo_arg3);
2997  }
2998 
2999  return result;
3000 }
3001 
3002 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
3003 /*
3004  * pt_make_default_value () -
3005  * return: return a PT_NODE for the default value
3006  * parser(in): parser context
3007  * class_name(in): class name of the attr to be defined a default value
3008  * attr_name(in): name of attr to be defined a default value
3009  */
3010 static PT_NODE *
3011 pt_make_default_value (PARSER_CONTEXT * parser, const char *class_name, const char *attr_name)
3012 {
3013  DB_OBJECT *class_obj;
3014  DB_ATTRIBUTE *attr_obj;
3015  DB_VALUE *value;
3016  PT_NODE *node = NULL;
3017  char *value_string;
3018 
3019  class_obj = db_find_class (class_name);
3020  if (class_obj)
3021  {
3022  attr_obj = db_get_attribute (class_obj, attr_name);
3023  if (attr_obj)
3024  {
3025  value = db_attribute_default (attr_obj);
3026  if (value)
3027  {
3028  value_string = db_get_string (value);
3029  node = pt_make_string_value (parser, value_string);
3030  }
3031  }
3032  }
3033  return node;
3034 }
3035 
3036 /*
3037  * pt_make_parameter () -
3038  * return: return a PT_NODE for the parameter name
3039  * parser(in): parser context
3040  * name(in): parameter name to make up a PT_NODE
3041  * is_out_parameter(in): whether input or output parameter
3042  */
3043 
3044 static PT_NODE *
3045 pt_make_parameter (PARSER_CONTEXT * parser, const char *name, int is_out_parameter)
3046 {
3047  PT_NODE *node;
3048 
3049  node = parser_new_node (parser, PT_NAME);
3050  if (node)
3051  {
3052  node->info.name.original = pt_append_string (parser, NULL, name);
3053  node->info.name.meta_class = PT_PARAMETER;
3054  if (is_out_parameter)
3055  { /* to skip parameter binding */
3056  node->info.name.spec_id = (UINTPTR) node;
3057  node->info.name.resolved = pt_append_string (parser, NULL, "out parameter");
3058  }
3059  }
3060  return node;
3061 }
3062 
3063 /*
3064  * pt_append_statements_on_add_attribute () -
3065  * return: return a list of statement string or null on error
3066  * parser(in): parser context
3067  * statement_list(in,out): statement strings to be created internally
3068  * stmt_node(in): parse tree for a create or alter statement
3069  * class_name(in): class name to add a attr
3070  * attr_name(in): attr name to add
3071  * attr(in/out): attr definition to add
3072  *
3073  * Note :
3074  * rewrite rule is like this.
3075  * create class c (..., a text constraint, ...);
3076  * => (pre) create class c_text_a_ under db_text;
3077  * => (main) create class c (..., a c_text_a_, ...);
3078  * => (post) alter class c_text_a_ add tid c unique, tdata string constraint;
3079  * => (post) create unique index on c(a);
3080  * => (post) grant select on c to user;
3081  */
3082 
3083 static PT_NODE *
3084 pt_append_statements_on_add_attribute (PARSER_CONTEXT * parser, PT_NODE * statement_list, PT_NODE * stmt_node,
3085  const char *class_name, const char *attr_name, PT_NODE * attr)
3086 {
3087  PT_NODE *s1, *s2, *s3, *s4;
3088  char *text_class_name = NULL, *stmt = NULL;
3089  char *constraint_name = NULL;
3090 
3091  text_class_name = pt_append_string (parser, NULL, class_name);
3092  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3093  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3094 
3095  constraint_name = pt_append_string (parser, NULL, TEXT_CONSTRAINT_PREFIX);
3096  constraint_name = pt_append_string (parser, constraint_name, attr_name);
3097 
3098  if (db_find_class (text_class_name))
3099  {
3100  PT_ERRORmf (parser, stmt_node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_EXISTS, text_class_name);
3101  return NULL;
3102  }
3103 
3104  stmt = pt_append_string (parser, NULL, "CREATE CLASS ");
3105  stmt = pt_append_string (parser, stmt, text_class_name);
3106  stmt = pt_append_string (parser, stmt, " UNDER db_text;");
3107  s1 = pt_make_string_value (parser, stmt);
3108 
3109  stmt = pt_append_string (parser, NULL, "ALTER CLASS ");
3110  stmt = pt_append_string (parser, stmt, text_class_name);
3111  stmt = pt_append_string (parser, stmt, " ADD tid ");
3112  stmt = pt_append_string (parser, stmt, class_name);
3113  stmt = pt_append_string (parser, stmt, ", tdata STRING ");
3114  stmt = pt_append_string (parser, stmt, ((attr->info.attr_def.data_default)
3115  ? parser_print_tree (parser, attr->info.attr_def.data_default) : ""));
3116  stmt = pt_append_string (parser, stmt, " ");
3117  stmt = pt_append_string (parser, stmt, ((attr->info.attr_def.constrain_not_null) ? "NOT NULL" : ""));
3118  stmt = pt_append_string (parser, stmt, ", CONSTRAINT ");
3119  stmt = pt_append_string (parser, stmt, constraint_name);
3120  stmt = pt_append_string (parser, stmt, " UNIQUE(tid)");
3121  stmt = pt_append_string (parser, stmt, ";");
3122  s2 = pt_make_string_value (parser, stmt);
3123 
3124  stmt = pt_append_string (parser, NULL, "CREATE UNIQUE INDEX ");
3125  stmt = pt_append_string (parser, stmt, constraint_name);
3126  stmt = pt_append_string (parser, stmt, " ON ");
3127  stmt = pt_append_string (parser, stmt, class_name);
3128  stmt = pt_append_string (parser, stmt, "([");
3129  stmt = pt_append_string (parser, stmt, attr_name);
3130  stmt = pt_append_string (parser, stmt, "]);");
3131  s3 = pt_make_string_value (parser, stmt);
3132 
3133  stmt = pt_append_string (parser, NULL, "GRANT SELECT ON ");
3134  stmt = pt_append_string (parser, stmt, text_class_name);
3135  stmt = pt_append_string (parser, stmt, " TO ");
3136  stmt = pt_append_string (parser, stmt, au_get_user_name (Au_user));
3137  stmt = pt_append_string (parser, stmt, " WITH GRANT OPTION");
3138  s4 = pt_make_string_value (parser, stmt);
3139 
3140  /* redefine the attribute definition */
3141  attr->type_enum = PT_TYPE_OBJECT;
3142  attr->data_type->type_enum = attr->type_enum;
3143  attr->data_type->info.data_type.entity = pt_name (parser, text_class_name);
3144  if (attr->data_type->info.data_type.entity == NULL)
3145  {
3147  return NULL;
3148  }
3149 
3150  attr->data_type->info.data_type.units = 1;
3151  attr->data_type->info.data_type.precision = 0;
3152 
3153  parser_free_tree (parser, attr->info.attr_def.data_default);
3154  attr->info.attr_def.data_default = NULL;
3155  attr->info.attr_def.constrain_not_null = 0;
3156 
3157  /* indicate the time of doing statement, 'etc' points to the statement to do previously */
3158  s1->etc = NULL;
3159  s2->etc = stmt_node;
3160  s3->etc = stmt_node;
3161  s1->next = s2;
3162  s2->next = s3;
3163  s3->next = s4;
3164 
3165  if (statement_list)
3166  {
3167  s4->next = statement_list;
3168  }
3169  statement_list = s1;
3170 
3171  return statement_list;
3172 }
3173 
3174 /*
3175  * pt_append_statements_on_change_default () -
3176  * return: return a list of statement string or null on error
3177  * parser(in): parser context
3178  * statement_list(in,out): statement strings to be created internally
3179  * stmt_node(in): parse tree for a alter default statement
3180  * class_name(in): class name of a attr to redefine the default value
3181  * attr_name(in): attr name to redefine the default value
3182  * value(in/out): default value of the attr
3183  *
3184  * Note :
3185  * rewrite rule is like this.
3186  * alter class c change ..., a default value, ...;
3187  * => (pre) alter class c_text_a_ change data default value;
3188  * => (main) alter class c change ..., a default null, ...;
3189  */
3190 static PT_NODE *
3191 pt_append_statements_on_change_default (PARSER_CONTEXT * parser, PT_NODE * statement_list, PT_NODE * stmt_node,
3192  const char *class_name, const char *attr_name, PT_NODE * value)
3193 {
3194  PT_NODE *s1, *save_next;
3195  char *text_class_name = NULL, *stmt = NULL;
3196 
3197  text_class_name = pt_append_string (parser, NULL, class_name);
3198  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3199  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3200 
3201  if (!db_find_class (text_class_name))
3202  {
3203  PT_ERRORmf (parser, stmt_node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST, text_class_name);
3204  return NULL;
3205  }
3206 
3207  stmt = pt_append_string (parser, NULL, "ALTER CLASS ");
3208  stmt = pt_append_string (parser, stmt, text_class_name);
3209  stmt = pt_append_string (parser, stmt, " CHANGE tdata DEFAULT ");
3210  stmt = pt_append_string (parser, stmt, parser_print_tree (parser, value));
3211  s1 = pt_make_string_value (parser, stmt);
3212 
3213  /* redefine the default value */
3214  save_next = value->next;
3215  parser_free_subtrees (parser, value);
3216  parser_reinit_node (value);
3217  value->type_enum = PT_TYPE_NULL;
3218  value->next = save_next;
3219 
3220  s1->etc = NULL;
3221 
3222  if (statement_list)
3223  {
3224  s1->next = statement_list;
3225  }
3226  statement_list = s1;
3227 
3228  return statement_list;
3229 }
3230 
3231 /*
3232  * pt_append_statements_on_drop_attributes () -
3233  * return: return a list of statement string or null on error
3234  * parser(in): parser context
3235  * statement_list(in/out): statement strings to be created internally
3236  * class_name_list(in): a list of class name to drop
3237  *
3238  * Note :
3239  * rewrite rule is like this.
3240  * alter class c drop ..., a, ...;
3241  * => (pre) drop class c_text_a_;
3242  * => (main) alter class c drop ..., a, ...;
3243  * drop class c;
3244  * => (pre) drop class c_text_a_;
3245  * => (main) drop class c;
3246  */
3247 
3248 static PT_NODE *
3249 pt_append_statements_on_drop_attributes (PARSER_CONTEXT * parser, PT_NODE * statement_list, const char *class_name_list)
3250 {
3251  PT_NODE *s1;
3252  char *stmt = NULL;
3253 
3254  stmt = pt_append_string (parser, NULL, "DROP CLASS ");
3255  stmt = pt_append_string (parser, stmt, class_name_list);
3256  s1 = pt_make_string_value (parser, stmt);
3257 
3258  s1->etc = NULL;
3259 
3260  if (statement_list)
3261  {
3262  s1->next = statement_list;
3263  }
3264  statement_list = s1;
3265 
3266  return statement_list;
3267 }
3268 
3269 /*
3270  * pt_append_statements_on_insert () -
3271  * return: return a list of statement string or null on error
3272  * parser(in): parser context
3273  * stmt_node(in): parse tree for a insert statement
3274  * class_name(in): class name to do insert
3275  * attr_name(in): attr name to do insert
3276  * value(in/out): value to do insert at the attr
3277  * parameter(in): output parameter for the insert statement
3278  *
3279  * Note :
3280  * rewrite rule is like this.
3281  * insert into c (..., a, ...) values (..., v, ...);
3282  * => (main) insert into c (..., a.object, ...) values (..., null, ...)
3283  * into :obj1;
3284  * => (post) insert into c_text_a_ values (:obj1, v) into :obj2;
3285  * => (post) update c set a.object = :obj2 where c = :obj1;
3286  */
3287 static PT_NODE *
3288 pt_append_statements_on_insert (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
3289  const char *attr_name, PT_NODE * value, PT_NODE * parameter)
3290 {
3291  PT_NODE *s1, *s2, *list;
3292  PT_NODE *save_next;
3293  char *text_class_name = NULL, *stmt = NULL;
3294  char param1_name[256], param2_name[256];
3295  char alias1_name[256];
3296  unsigned int save_custom;
3297 
3298  text_class_name = pt_append_string (parser, NULL, class_name);
3299  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3300  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3301 
3302  if (!db_find_class (text_class_name))
3303  {
3304  PT_ERRORmf (parser, stmt_node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST, text_class_name);
3305  return NULL;
3306  }
3307 
3308  if (parameter && parameter->info.name.original)
3309  {
3310  sprintf (param1_name, "%s", parameter->info.name.original);
3311  }
3312  else
3313  {
3314  sprintf (param1_name, "%s_%p", "p1", stmt_node);
3315  }
3316  sprintf (param2_name, "%s_%p", "p2", stmt_node);
3317  sprintf (alias1_name, "%s_%p", "c1", stmt_node);
3318 
3319  save_custom = parser->custom_print;
3320  parser->custom_print = parser->custom_print | PT_INTERNAL_PRINT;
3321 
3322  stmt = pt_append_string (parser, NULL, "INSERT INTO ");
3323  stmt = pt_append_string (parser, stmt, text_class_name);
3324  stmt = pt_append_string (parser, stmt, " VALUES (:");
3325  stmt = pt_append_string (parser, stmt, param1_name);
3326  stmt = pt_append_string (parser, stmt, ", ");
3327  stmt = pt_append_string (parser, stmt, parser_print_tree (parser, value));
3328  stmt = pt_append_string (parser, stmt, ") INTO :");
3329  stmt = pt_append_string (parser, stmt, param2_name);
3330  stmt = pt_append_string (parser, stmt, "; ");
3331  s1 = pt_make_string_value (parser, stmt);
3332 
3333  parser->custom_print = save_custom;
3334 
3335  stmt = pt_append_string (parser, NULL, "UPDATE ");
3336  stmt = pt_append_string (parser, stmt, class_name);
3337  stmt = pt_append_string (parser, stmt, " ");
3338  stmt = pt_append_string (parser, stmt, alias1_name);
3339  stmt = pt_append_string (parser, stmt, " SET [");
3340  stmt = pt_append_string (parser, stmt, attr_name);
3341  stmt = pt_append_string (parser, stmt, "].OBJECT = :");
3342  stmt = pt_append_string (parser, stmt, param2_name);
3343  stmt = pt_append_string (parser, stmt, " WHERE ");
3344  stmt = pt_append_string (parser, stmt, alias1_name);
3345  stmt = pt_append_string (parser, stmt, ".OBJECT = :");
3346  stmt = pt_append_string (parser, stmt, param1_name);
3347  s2 = pt_make_string_value (parser, stmt);
3348 
3349  /* redefine the insert value */
3350  save_next = value->next;
3351  parser_free_subtrees (parser, value);
3352  parser_reinit_node (value);
3353  value->node_type = PT_VALUE;
3354  value->type_enum = PT_TYPE_NULL;
3355  value->next = save_next;
3356 
3357  s1->etc = stmt_node;
3358  s2->etc = stmt_node;
3359  s1->next = s2;
3360 
3361  list = stmt_node->info.insert.internal_stmts;
3362  if (list == NULL)
3363  {
3364  stmt_node->info.insert.internal_stmts = s1;
3365  }
3366  else
3367  {
3368  while (list->next != NULL)
3369  {
3370  list = list->next;
3371  }
3372  list->next = s1;
3373  }
3374  list = s1;
3375 
3376  return list;
3377 }
3378 
3379 
3380 /*
3381  * pt_append_statements_on_update () -
3382  * return: return a list of statement string or null on error
3383  * parser(in): parser context
3384  * stmt_node(in): parse tree for a update statement
3385  * class_name(in): class name to do update
3386  * attr_name(in): attr name to do update
3387  * alias_name(in): alias for the class name
3388  * value(in/out): value to do update at the attr
3389  * where_ptr(in/out): pointer of a parse tree for the where clause of
3390  * the update statement
3391  *
3392  * Note :
3393  * rewrite rule is like this.
3394  * update c set ..., a = v, ... where condtion
3395  * => (pre) select (select sum(set{a.object}) from c where condition)
3396  * into :obj1 from db_root
3397  * => (pre) update c_text_a_ set tdata = v where tid in
3398  * (select c from c where a.object in :obj1)
3399  * => (main) update c set ..., a.object = a.object, ...
3400  * where a.object in :obj1
3401  */
3402 static PT_NODE *
3403 pt_append_statements_on_update (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
3404  const char *attr_name, const char *alias_name, PT_NODE * value, PT_NODE ** where_ptr)
3405 {
3406  PT_NODE *s1, *s2, *list;
3407  PT_NODE *save_next;
3408  DB_VALUE *param1_dbvalp;
3409  char *text_class_name = NULL, *stmt = NULL;
3410  char param1_name[256];
3411  char alias1_name[256];
3412  unsigned int save_custom;
3413 
3414  text_class_name = pt_append_string (parser, NULL, class_name);
3415  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3416  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3417 
3418  if (!db_find_class (text_class_name))
3419  {
3420  PT_ERRORmf (parser, stmt_node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST, text_class_name);
3421  return NULL;
3422  }
3423 
3424  sprintf (param1_name, "%s_%p", "p1", attr_name);
3425  sprintf (alias1_name, "%s_%p", "c1", attr_name);
3426 
3427  save_custom = parser->custom_print;
3428  parser->custom_print = parser->custom_print | PT_INTERNAL_PRINT;
3429 
3430  stmt = pt_append_string (parser, NULL, "SELECT {null}+(SELECT SUM(SET{[");
3431  stmt = pt_append_string (parser, stmt, attr_name);
3432  stmt = pt_append_string (parser, stmt, "].OBJECT}) FROM ");
3433  stmt = pt_append_string (parser, stmt, class_name);
3434  stmt = pt_append_string (parser, stmt, " ");
3435  stmt = pt_append_string (parser, stmt, alias_name);
3436  if (*where_ptr)
3437  {
3438  stmt = pt_append_string (parser, stmt, " WHERE ");
3439  stmt = pt_append_string (parser, stmt, parser_print_tree (parser, *where_ptr));
3440  }
3441  stmt = pt_append_string (parser, stmt, ") INTO :");
3442  stmt = pt_append_string (parser, stmt, param1_name);
3443  stmt = pt_append_string (parser, stmt, " FROM db_root;");
3444  s1 = pt_make_string_value (parser, stmt);
3445 
3446  /* To resolve out parameter at compile time, put the parameter into the label table with null value */
3447  param1_dbvalp = db_value_create ();
3448  if (param1_dbvalp == NULL)
3449  {
3450  parser->custom_print = save_custom;
3451  return NULL;
3452  }
3453  else
3454  {
3455  db_make_set (param1_dbvalp, db_set_create_basic (NULL, NULL));
3456  if (pt_associate_label_with_value (param1_name, param1_dbvalp) != NO_ERROR)
3457  {
3458  parser->custom_print = save_custom;
3459  return NULL;
3460  }
3461  }
3462 
3463  stmt = pt_append_string (parser, NULL, "UPDATE ");
3464  stmt = pt_append_string (parser, stmt, text_class_name);
3465  stmt = pt_append_string (parser, stmt, " SET tdata = ");
3466  stmt = pt_append_string (parser, stmt, ((value->node_type == PT_NAME && value->info.name.meta_class == PT_NORMAL)
3467  ? "tid." : ""));
3468  stmt = pt_append_string (parser, stmt, parser_print_tree (parser, value));
3469  stmt = pt_append_string (parser, stmt, " WHERE tid IN (SELECT ");
3470  stmt = pt_append_string (parser, stmt, alias1_name);
3471  stmt = pt_append_string (parser, stmt, " FROM ");
3472  stmt = pt_append_string (parser, stmt, class_name);
3473  stmt = pt_append_string (parser, stmt, " ");
3474  stmt = pt_append_string (parser, stmt, alias1_name);
3475  stmt = pt_append_string (parser, stmt, " WHERE [");
3476  stmt = pt_append_string (parser, stmt, attr_name);
3477  stmt = pt_append_string (parser, stmt, "].OBJECT IN :");
3478  stmt = pt_append_string (parser, stmt, param1_name);
3479  stmt = pt_append_string (parser, stmt, ")");
3480  s2 = pt_make_string_value (parser, stmt);
3481 
3482  parser->custom_print = save_custom;
3483 
3484  /* redefine where clause if the clause is redefined at first */
3485  if ((*where_ptr) == NULL || (*where_ptr)->etc != (*where_ptr))
3486  {
3487  if (*where_ptr)
3488  {
3489  parser_free_tree (parser, *where_ptr);
3490  }
3491  *where_ptr = parser_new_node (parser, PT_EXPR);
3492  if (*where_ptr == NULL)
3493  {
3494  return NULL;
3495  }
3496  (*where_ptr)->info.expr.op = PT_IS_IN;
3497  (*where_ptr)->info.expr.arg1 = pt_name (parser, attr_name);
3498  (*where_ptr)->info.expr.arg2 = pt_make_parameter (parser, param1_name, 0);
3499  (*where_ptr)->etc = (*where_ptr); /* mark to prevent multiple rewrite */
3500  PT_NAME_INFO_SET_FLAG ((*where_ptr)->info.expr.arg1, PT_NAME_INFO_EXTERNAL);
3501  }
3502 
3503  /* redefine the assignment value */
3504  save_next = value->next;
3505  parser_free_subtrees (parser, value);
3506  parser_reinit_node (value);
3507  value->node_type = PT_NAME;
3508  value->info.name.original = pt_append_string (parser, NULL, attr_name);
3510  value->next = save_next;
3511 
3512  s1->etc = NULL;
3513  s2->etc = NULL;
3514  s1->next = s2;
3515 
3516  list = stmt_node->info.update.internal_stmts;
3517  if (list == NULL)
3518  {
3519  stmt_node->info.insert.internal_stmts = s1;
3520  }
3521  else
3522  {
3523  while (list->next != NULL)
3524  list = list->next;
3525  list->next = s1;
3526  }
3527  list = s1;
3528 
3529  parser->custom_print = save_custom;
3530 
3531  return list;
3532 }
3533 
3534 /*
3535  * pt_append_statements_on_delete () -
3536  * return: return a list of statement string or null on error
3537  * parser(in): parser context
3538  * stmt_node(in): parse tree for a delete statement
3539  * class_name(in): class name to do delete
3540  * attr_name(in): attr name to do delete
3541  * alias_name(in): alias for the class name
3542  * where_ptr(in/out): pointer of a parse tree for the where clause of
3543  * the delete statement
3544  *
3545  * Note :
3546  * rewrite rule is like this.
3547  * delete from c where condition;
3548  * => (pre) select (select sum(set{a.object}) from c where condition)
3549  * into :obj1 from db_root
3550  * => (pre) delete from c_text_a_ where tid in (select c from c where
3551  * a.object in :obj1)
3552  * => (main) delete from c where a.object in :obj1
3553  */
3554 
3555 static PT_NODE *
3556 pt_append_statements_on_delete (PARSER_CONTEXT * parser, PT_NODE * stmt_node, const char *class_name,
3557  const char *attr_name, const char *alias_name, PT_NODE ** where_ptr)
3558 {
3559  PT_NODE *s1, *s2, *list;
3560  DB_VALUE *param1_dbvalp;
3561  char *text_class_name = NULL, *stmt = NULL;
3562  char param1_name[256];
3563  char alias1_name[256];
3564  unsigned int save_custom;
3565 
3566  text_class_name = pt_append_string (parser, NULL, class_name);
3567  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3568  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3569 
3570  if (!db_find_class (text_class_name))
3571  {
3572  PT_ERRORmf (parser, stmt_node, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST, text_class_name);
3573  return NULL;
3574  }
3575 
3576  sprintf (param1_name, "%s_%p", "p1", attr_name);
3577  sprintf (alias1_name, "%s_%p", "c1", attr_name);
3578 
3579  save_custom = parser->custom_print;
3580  parser->custom_print = parser->custom_print | PT_INTERNAL_PRINT;
3581 
3582  stmt = pt_append_string (parser, NULL, "SELECT {null}+(SELECT SUM(SET{[");
3583  stmt = pt_append_string (parser, stmt, attr_name);
3584  stmt = pt_append_string (parser, stmt, "].OBJECT}) FROM ");
3585  stmt = pt_append_string (parser, stmt, class_name);
3586  stmt = pt_append_string (parser, stmt, " ");
3587  stmt = pt_append_string (parser, stmt, alias_name);
3588  if (*where_ptr)
3589  {
3590  stmt = pt_append_string (parser, stmt, " WHERE ");
3591  stmt = pt_append_string (parser, stmt, parser_print_tree (parser, *where_ptr));
3592  }
3593  stmt = pt_append_string (parser, stmt, ") INTO :");
3594  stmt = pt_append_string (parser, stmt, param1_name);
3595  stmt = pt_append_string (parser, stmt, " FROM db_root;");
3596  s1 = pt_make_string_value (parser, stmt);
3597 
3598  parser->custom_print = save_custom;
3599 
3600  /* To resolve out parameter at compile time, put the parameter into the label table with null value */
3601  param1_dbvalp = db_value_create ();
3602  if (param1_dbvalp == NULL)
3603  {
3604  return NULL;
3605  }
3606  else
3607  {
3608  db_make_set (param1_dbvalp, db_set_create_basic (NULL, NULL));
3609  if (pt_associate_label_with_value (param1_name, param1_dbvalp) != NO_ERROR)
3610  {
3611  return NULL;
3612  }
3613  }
3614  stmt = pt_append_string (parser, NULL, "DELETE FROM ");
3615  stmt = pt_append_string (parser, stmt, text_class_name);
3616  stmt = pt_append_string (parser, stmt, " WHERE tid IN (SELECT ");
3617  stmt = pt_append_string (parser, stmt, alias1_name);
3618  stmt = pt_append_string (parser, stmt, " FROM ");
3619  stmt = pt_append_string (parser, stmt, class_name);
3620  stmt = pt_append_string (parser, stmt, " ");
3621  stmt = pt_append_string (parser, stmt, alias1_name);
3622  stmt = pt_append_string (parser, stmt, " WHERE [");
3623  stmt = pt_append_string (parser, stmt, attr_name);
3624  stmt = pt_append_string (parser, stmt, "].OBJECT IN :");
3625  stmt = pt_append_string (parser, stmt, param1_name);
3626  stmt = pt_append_string (parser, stmt, ")");
3627  s2 = pt_make_string_value (parser, stmt);
3628 
3629  /* redefine where clause if the clause is redefined at first */
3630  if ((*where_ptr) == NULL || (*where_ptr)->etc != (*where_ptr))
3631  {
3632  if (*where_ptr)
3633  {
3634  parser_free_tree (parser, *where_ptr);
3635  }
3636  if ((*where_ptr = parser_new_node (parser, PT_EXPR)) == NULL)
3637  {
3638  return NULL;
3639  }
3640  (*where_ptr)->info.expr.op = PT_IS_IN;
3641  (*where_ptr)->info.expr.arg1 = pt_name (parser, attr_name);
3642  (*where_ptr)->info.expr.arg2 = pt_make_parameter (parser, param1_name, 0);
3643  (*where_ptr)->etc = (*where_ptr); /* mark to prevent multiple rewrite */
3644  PT_NAME_INFO_SET_FLAG ((*where_ptr)->info.expr.arg1, PT_NAME_INFO_EXTERNAL);
3645  }
3646 
3647  s1->etc = NULL;
3648  s2->etc = NULL;
3649  s1->next = s2;
3650 
3651  list = stmt_node->info.delete_.internal_stmts;
3652  if (list == NULL)
3653  {
3654  stmt_node->info.insert.internal_stmts = s1;
3655  }
3656  else
3657  {
3658  while (list->next != NULL)
3659  list = list->next;
3660  list->next = s1;
3661  }
3662  list = s1;
3663 
3664  return list;
3665 }
3666 
3667 /*
3668  * pt_resolve_insert_external () - create internal statements and
3669  * rewrite a value to insert for TEXT typed attrs on into clause
3670  * of a insert statement
3671  * return: none
3672  * parser(in): parser context
3673  * insert(in): parse tree of a insert statement
3674  */
3675 static void
3676 pt_resolve_insert_external (PARSER_CONTEXT * parser, PT_NODE * insert)
3677 {
3678  PT_NODE *a, *v, *lhs, *rhs, *save_next;
3679  PT_NODE *spec, *entity, *value;
3680  const char *class_name, *attr_name;
3681  char *text_class_name = NULL, param1_name[256];
3682 
3683  spec = insert->info.insert.spec;
3684  entity = (spec ? spec->info.spec.entity_name : NULL);
3685  class_name = (entity ? entity->info.name.original : NULL);
3686  if (class_name == NULL)
3687  {
3688  return;
3689  }
3690 
3691  a = insert->info.insert.attr_list;
3692 
3693  if (insert->info.insert.is_value == PT_IS_SUBQUERY)
3694  {
3695  for (; a != NULL; a = a->next)
3696  {
3697  if (PT_IS_DOT_NODE (a))
3698  {
3699  PT_ERRORmf2 (parser, a, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CANT_COERCE_TO, "subquery", "text");
3700  return;
3701  }
3702  }
3703  }
3704  else if (insert->info.insert.is_value == PT_IS_DEFAULT_VALUE)
3705  {
3706  for (; a != NULL; a = a->next)
3707  {
3708  if (PT_IS_DOT_NODE (a))
3709  {
3710  /* replace "attr.tdata" with "attr" */
3711  save_next = a->next;
3712  lhs = a->info.expr.arg1;
3713  rhs = a->info.expr.arg2;
3714  *a = *lhs;
3715  a->next = save_next;
3716  parser_reinit_node (lhs); /* not to free subtrees */
3717  parser_free_tree (parser, lhs);
3718  parser_free_tree (parser, rhs);
3719 
3720  /* make a default value */
3721  attr_name = a->info.name.original;
3722  text_class_name = pt_append_string (parser, NULL, class_name);
3723  text_class_name = pt_append_string (parser, text_class_name, "_text_");
3724  text_class_name = pt_append_string (parser, text_class_name, attr_name);
3725 
3726  if ((value = pt_make_default_value (parser, text_class_name, "tdata")) == NULL)
3727  {
3728  goto exit_on_error;
3729  }
3730 
3731  if (insert->info.insert.into_var == NULL)
3732  {
3733  sprintf (param1_name, "p1_%p", insert);
3734  insert->info.insert.into_var = pt_make_parameter (parser, param1_name, 1);
3735  }
3736  if (pt_append_statements_on_insert (parser, insert, class_name, attr_name, value,
3737  insert->info.insert.into_var) == NULL)
3738  {
3739  goto exit_on_error;
3740  }
3741  }
3742  }
3743  }
3744  else
3745  {
3746  v = insert->info.insert.value_clause;
3747  for (; a != NULL && v != NULL; a = a->next, v = v->next)
3748  {
3749  if (PT_IS_DOT_NODE (a))
3750  {
3751  /* replace "attr.tdata" to "attr" */
3752  save_next = a->next;
3753  lhs = a->info.expr.arg1;
3754  rhs = a->info.expr.arg2;
3755  *a = *lhs;
3756  a->next = save_next;
3757  parser_reinit_node (lhs); /* not to free subtrees */
3758  parser_free_tree (parser, lhs);
3759  parser_free_tree (parser, rhs);
3760 
3761  /* if (pt_assignment_compatible(parser, attr, v)) */
3762  attr_name = a->info.name.original;
3763  if (a->type_enum != v->type_enum)
3764  {
3765  if (insert->info.insert.into_var == NULL)
3766  {
3767  sprintf (param1_name, "p1_%p", insert);
3768  insert->info.insert.into_var = pt_make_parameter (parser, param1_name, 1);
3769  }
3770  if (pt_append_statements_on_insert (parser, insert, class_name, attr_name, v,
3771  insert->info.insert.into_var) == NULL)
3772  {
3773  goto exit_on_error;
3774  }
3775  }
3776  }
3777  }
3778  }
3779  return;
3780 
3781 exit_on_error:
3782 
3784  return;
3785 }
3786 
3787 /*
3788  * pt_resolve_update_external () - create internal statements and redefine
3789  * a value to do update for TEXT typed attrs on assignment clause of
3790  * a update statement
3791  * return: none
3792  * parser(in): parser context
3793  * update(in): parse tree of a update statement
3794  */
3795 static void
3796 pt_resolve_update_external (PARSER_CONTEXT * parser, PT_NODE * update)
3797 {
3798  PT_NODE *a, *lhs, *rhs;
3799  PT_NODE *spec, *entity, *alias;
3800  DB_OBJECT *db_obj;
3801  DB_ATTRIBUTE *db_att;
3802  const char *class_name, *attr_name, *alias_name;
3803 
3804  spec = update->info.update.spec;
3805  entity = (spec ? spec->info.spec.entity_name : NULL);
3806  class_name = (entity ? entity->info.name.original : NULL);
3807  alias = (spec ? spec->info.spec.range_var : NULL);
3808  alias_name = (alias ? alias->info.name.original : NULL);
3809 
3810  if (class_name && (db_obj = db_find_class (class_name)))
3811  {
3812  for (a = update->info.update.assignment; a; a = a->next)
3813  {
3814  if (PT_IS_ASSIGN_NODE (a) && (lhs = a->info.expr.arg1) != NULL && (rhs = a->info.expr.arg2) != NULL)
3815  {
3817  {
3818  attr_name = lhs->info.name.original;
3819  db_att = db_get_attribute (db_obj, attr_name);
3820 
3821  if (db_att && sm_has_text_domain (db_att, 0))
3822  {
3824  if (pt_append_statements_on_update (parser, update, class_name, attr_name, alias_name, rhs,
3825  &update->info.update.search_cond) == NULL)
3826  {
3827  goto exit_on_error;
3828  }
3829  }
3830  }
3831  }
3832  }
3833  }
3834 
3835  return;
3836 
3837 exit_on_error:
3838 
3840  return;
3841 }
3842 
3843 /*
3844  * pt_resolve_delete_external () - create internal statements
3845  * for TEXT typed attrs defined in class to do delete statement
3846  * return: none
3847  * parser(in): parser context
3848  * delete(in): parse tree of a delete statement
3849  */
3850 static void
3851 pt_resolve_delete_external (PARSER_CONTEXT * parser, PT_NODE * delete)
3852 {
3853  PT_NODE *spec, *entity, *alias;
3854  DB_OBJECT *db_obj;
3855  DB_ATTRIBUTE *db_att;
3856  const char *class_name, *alias_name;
3857 
3858  spec = delete->info.delete_.spec;
3859  entity = (spec ? spec->info.spec.entity_name : NULL);
3860  class_name = (entity ? entity->info.name.original : NULL);
3861  alias = (spec ? spec->info.spec.range_var : NULL);
3862  alias_name = (alias ? alias->info.name.original : NULL);
3863 
3864  if (class_name && (db_obj = db_find_class (class_name)))
3865  {
3866  db_att = db_get_attributes_force (db_obj);
3867  while (db_att)
3868  {
3869  if (sm_has_text_domain (db_att, 0))
3870  {
3871  if (pt_append_statements_on_delete (parser, delete, class_name, db_attribute_name (db_att), alias_name,
3872  &delete->info.delete_.search_cond) == NULL)
3873  {
3874  goto exit_on_error;
3875  }
3876  }
3877  db_att = db_attribute_next (db_att);
3878  }
3879  }
3880 
3881  return;
3882 
3883 exit_on_error:
3884 
3886  return;
3887 }
3888 #endif /* ENABLE_UNUSED_FUNCTION */
3889 
3890 /*
3891  * pt_resolve_default_external () - create internal statements
3892  * for a TEXT typed attr to alter the default value
3893  * return: none
3894  * parser(in): parser context
3895  * alter(in): parse tree of a alter statement
3896  */
3897 static void
3899 {
3900  PT_NODE *attr_name_list, *data_default_list, *stmt_list;
3901  PT_NODE *a, *v;
3902  PT_NODE *entity_name;
3903  DB_OBJECT *class_;
3904  DB_ATTRIBUTE *attr;
3905  const char *class_name;
3906 
3907  attr_name_list = alter->info.alter.alter_clause.ch_attr_def.attr_name_list;
3908  data_default_list = alter->info.alter.alter_clause.ch_attr_def.data_default_list;
3909 
3910  entity_name = alter->info.alter.entity_name;
3911  class_name = (entity_name ? entity_name->info.name.original : NULL);
3912  if (class_name && (class_ = db_find_class (class_name)) != NULL)
3913  {
3914  stmt_list = alter->info.alter.internal_stmts;
3915  for (a = attr_name_list, v = data_default_list; a != NULL && v != NULL; a = a->next, v = v->next)
3916  {
3917  attr = db_get_attribute (class_, a->info.name.original);
3918 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
3919  if (attr && sm_has_text_domain (attr, 0))
3920  {
3921  stmt_list =
3922  pt_append_statements_on_change_default (parser, stmt_list, alter, class_name, a->info.name.original, v);
3923  if (stmt_list == NULL)
3924  {
3926  }
3927  }
3928 #endif /* ENABLE_UNUSED_FUNCTION */
3929  }
3930  alter->info.alter.internal_stmts = stmt_list;
3931  }
3932 
3933  return;
3934 }
3935 
3936 /*
3937  * pt_check_data_default () - checks data_default for semantic errors
3938  *
3939  * result : modified data_default
3940  * parser(in) : parser context
3941  * data_default_list(in) : data default node
3942  */
3943 static PT_NODE *
3944 pt_check_data_default (PARSER_CONTEXT * parser, PT_NODE * data_default_list)
3945 {
3946  PT_NODE *result;
3948  PT_NODE *save_next;
3949  PT_NODE *node_ptr;
3950  PT_NODE *data_default;
3951  PT_NODE *prev;
3952  bool has_query;
3953 
3954  if (pt_has_error (parser))
3955  {
3956  /* do nothing */
3957  return data_default_list;
3958  }
3959 
3960  if (data_default_list == NULL || data_default_list->node_type != PT_DATA_DEFAULT)
3961  {
3962  /* do nothing */
3963  return data_default_list;
3964  }
3965 
3966  prev = NULL;
3967  has_query = false;
3968  for (data_default = data_default_list; data_default; data_default = data_default->next)
3969  {
3970  save_next = data_default->next;
3971  data_default->next = NULL;
3972 
3973  default_value = data_default->info.data_default.default_value;
3974 
3975  (void) parser_walk_tree (parser, default_value, pt_find_query, &has_query, NULL, NULL);
3976  if (has_query)
3977  {
3978  PT_ERRORm (parser, default_value, MSGCAT_SET_PARSER_SEMANTIC,
3980  /* skip other checks */
3981  goto end;
3982  }
3983 
3984  result = pt_semantic_type (parser, data_default, NULL);
3985  if (result != NULL)
3986  {
3987  /* change data_default */
3988  if (prev)
3989  {
3990  prev->next = result;
3991  }
3992  else
3993  {
3994  data_default_list = result;
3995  }
3996  data_default = result;
3997  }
3998  else
3999  {
4000  /* an error has occurred, skip other checks */
4001  goto end;
4002  }
4003 
4004  node_ptr = NULL;
4005  (void) parser_walk_tree (parser, default_value, pt_find_default_expression, &node_ptr, NULL, NULL);
4006  if (node_ptr != NULL && node_ptr != default_value)
4007  {
4008  /* nested default expressions are not supported */
4010  pt_show_binopcode (node_ptr->info.expr.op));
4011  goto end;
4012  }
4013 
4014  if (PT_IS_EXPR_NODE (default_value) && default_value->info.expr.op == PT_TO_CHAR
4015  && PT_IS_EXPR_NODE (default_value->info.expr.arg1))
4016  {
4017  int op_type = -1;
4018 
4019  if (PT_IS_EXPR_NODE (default_value->info.expr.arg2))
4020  {
4021  /* nested expressions in arg2 are not supported */
4022  op_type = default_value->info.expr.arg2->info.expr.op;
4023  }
4024  else if (node_ptr == NULL)
4025  {
4026  /* nested expressions in arg1 are not supported except sys date, time and user. */
4027  op_type = default_value->info.expr.arg1->info.expr.op;
4028  }
4029 
4030  if (op_type != -1)
4031  {
4033  pt_show_binopcode ((PT_OP_TYPE) op_type));
4034  goto end;
4035  }
4036  }
4037 
4038  node_ptr = NULL;
4039  parser_walk_tree (parser, default_value, pt_find_aggregate_function, &node_ptr, NULL, NULL);
4040  if (node_ptr != NULL)
4041  {
4042  PT_ERRORmf (parser,
4043  node_ptr,
4047  goto end;
4048  }
4049 
4050  end:
4051  data_default->next = save_next;
4052  prev = data_default;
4053  }
4054 
4055  return data_default_list;
4056 }
4057 
4058 /*
4059  * pt_attr_check_default_cs_coll () - checks attribute's collation and
4060  * codeset. If necessary, they are replaced with the
4061  * ones passed as arguments.
4062  *
4063  * parser(in): parser context
4064  * attr(in/out) : data default node
4065  * default_cs(in): codeset of the attribute's class, or override value
4066  * if special value = -1 is given, then charset implied by
4067  * default_coll argument is used
4068  * default_coll(in): collation of the attribute's class, or override value
4069  */
4070 int
4071 pt_attr_check_default_cs_coll (PARSER_CONTEXT * parser, PT_NODE * attr, int default_cs, int default_coll)
4072 {
4073  int attr_cs = attr->data_type->info.data_type.units;
4074  int attr_coll = attr->data_type->info.data_type.collation_id;
4075  LANG_COLLATION *lc;
4076  int err = NO_ERROR;
4077 
4078  assert (default_coll >= 0);
4079 
4080  if (attr->data_type->info.data_type.has_cs_spec)
4081  {
4082  if (attr->data_type->info.data_type.has_coll_spec == false)
4083  {
4084  /* use binary collation of attribute's charset specifier */
4085  attr_coll = LANG_GET_BINARY_COLLATION (attr_cs);
4086  }
4087  }
4088  else if (attr->data_type->info.data_type.has_coll_spec)
4089  {
4090  lc = lang_get_collation (attr_coll);
4091  assert (lc != NULL);
4092  attr_cs = lc->codeset;
4093  }
4094  else
4095  {
4096  /* attribute does not have a codeset or collation spec; use defaults */
4097  attr_coll = default_coll;
4098  if (default_cs == -1)
4099  {
4100  lc = lang_get_collation (default_coll);
4101  assert (lc != NULL);
4102  attr_cs = lc->codeset;
4103  }
4104  else
4105  {
4106  attr_cs = default_cs;
4107  }
4108  }
4109 
4110  if (attr->type_enum == PT_TYPE_ENUMERATION && attr->data_type != NULL)
4111  {
4112  /* coerce each element of enum to actual attribute codeset */
4113  PT_NODE *elem = NULL;
4114 
4115  elem = attr->data_type->info.data_type.enumeration;
4116  while (elem != NULL)
4117  {
4118  assert (elem->node_type == PT_VALUE);
4119  assert (PT_HAS_COLLATION (elem->type_enum));
4120 
4121  if ((elem->data_type != NULL && elem->data_type->info.data_type.units != attr_cs)
4122  || (elem->data_type == NULL && attr_cs != LANG_SYS_CODESET))
4123  {
4124  PT_NODE *dt;
4125 
4126  if (elem->data_type != NULL)
4127  {
4128  dt = parser_copy_tree (parser, elem->data_type);
4129  }
4130  else
4131  {
4132  dt = parser_new_node (parser, PT_DATA_TYPE);
4133  dt->type_enum = elem->type_enum;
4135  }
4136  dt->info.data_type.collation_id = attr_coll;
4137  dt->info.data_type.units = attr_cs;
4138 
4139  if (attr_cs == INTL_CODESET_RAW_BYTES)
4140  {
4141  /* conversion from multi-byte to binary must keep text */
4142  if (elem->info.value.data_value.str != NULL)
4143  {
4145  }
4146  else if (elem->info.value.db_value_is_initialized)
4147  {
4149  }
4150  }
4151 
4152  err = pt_coerce_value (parser, elem, elem, elem->type_enum, dt);
4153  if (err != NO_ERROR)
4154  {
4155  return err;
4156  }
4157 
4158  parser_free_tree (parser, dt);
4159  }
4160  elem = elem->next;
4161  }
4162  }
4163 
4164  attr->data_type->info.data_type.units = attr_cs;
4165  attr->data_type->info.data_type.collation_id = attr_coll;
4166 
4167  return err;
4168 }
4169 
4170 /*
4171  * pt_find_query () - search for a query
4172  *
4173  * result : parser tree node
4174  * parser(in) : parser
4175  * tree(in) : parser tree node
4176  * arg(in/out) : true, if the query is found
4177  * continue_walk : Continue walk.
4178  */
4179 static PT_NODE *
4180 pt_find_query (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
4181 {
4182  bool *has_query = (bool *) arg;
4183  assert (has_query != NULL);
4184 
4185  if (PT_IS_QUERY (tree))
4186  {
4187  *has_query = true;
4188  *continue_walk = PT_STOP_WALK;
4189  }
4190 
4191  return tree;
4192 }
4193 
4194 
4195 /*
4196  * pt_find_default_expression () - find a default expression
4197  *
4198  * result :
4199  * parser(in) :
4200  * tree(in) :
4201  * arg(in) : will point to default expression if any is found
4202  * continue_walk :
4203  */
4204 static PT_NODE *
4205 pt_find_default_expression (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
4206 {
4207  PT_NODE **default_expr = (PT_NODE **) arg, *node = NULL;
4208 
4209  if (tree == NULL || !PT_IS_EXPR_NODE (tree))
4210  {
4211  *continue_walk = PT_STOP_WALK;
4212  return tree;
4213  }
4214 
4215  if (tree->info.expr.op == PT_TO_CHAR && tree->info.expr.arg1 != NULL && PT_IS_EXPR_NODE (tree->info.expr.arg1))
4216  {
4217  /* The correctness of TO_CHAR expression is done a little bit later after obtaining system time. */
4218  assert (tree->info.expr.arg2 != NULL);
4219  node = tree->info.expr.arg1;
4220  }
4221  else
4222  {
4223  node = tree;
4224  }
4225 
4226  switch (node->info.expr.op)
4227  {
4228  case PT_SYS_TIME:
4229  case PT_SYS_DATE:
4230  case PT_SYS_DATETIME:
4231  case PT_SYS_TIMESTAMP:
4232  case PT_CURRENT_TIME:
4233  case PT_CURRENT_DATE:
4234  case PT_CURRENT_TIMESTAMP:
4235  case PT_CURRENT_DATETIME:
4236  case PT_USER:
4237  case PT_CURRENT_USER:
4238  case PT_UNIX_TIMESTAMP:
4239  *default_expr = tree;
4240  *continue_walk = PT_STOP_WALK;
4241  break;
4242 
4243  default:
4244  break;
4245  }
4246 
4247  return tree;
4248 }
4249 
4250 /*
4251  * pt_find_aggregate_function () - check if current expression contains an
4252  * aggregate function
4253  *
4254  * result :
4255  * parser(in) :
4256  * tree(in) :
4257  * arg(in) : will point to an aggregate function if any is found
4258  * continue_walk :
4259  */
4260 static PT_NODE *
4261 pt_find_aggregate_function (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
4262 {
4263  PT_NODE **agg_function = (PT_NODE **) arg;
4264 
4265  if (tree == NULL || (!PT_IS_EXPR_NODE (tree) && !PT_IS_FUNCTION (tree)))
4266  {
4267  *continue_walk = PT_STOP_WALK;
4268  }
4269 
4270  if (pt_is_aggregate_function (parser, tree))
4271  {
4272  *agg_function = tree;
4273  *continue_walk = PT_STOP_WALK;
4274  }
4275 
4276  return tree;
4277 }
4278 
4279 /*
4280  * pt_find_aggregate_analytic_pre ()
4281  * - check if current expression contains an aggregate or
4282  * analytic function
4283  *
4284  * result :
4285  * parser(in) :
4286  * tree(in) :
4287  * arg(in) : will point to the function if any is found
4288  * continue_walk :
4289  */
4290 static PT_NODE *
4291 pt_find_aggregate_analytic_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
4292 {
4293  PT_NODE **function = (PT_NODE **) arg;
4294 
4295  if (*continue_walk == PT_STOP_WALK)
4296  {
4297  return tree;
4298  }
4299 
4300  assert (*function == NULL);
4301 
4302  if (tree && PT_IS_QUERY_NODE_TYPE (tree->node_type))
4303  {
4304  PT_NODE *find = NULL;
4305 
4306  /* For sub-queries, searching is limited to range of WHERE clause */
4307  find = pt_find_aggregate_analytic_in_where (parser, tree);
4308  if (find)
4309  {
4310  *function = find;
4311  }
4312 
4313  /*
4314  * Don't search children nodes of this query node, since
4315  * pt_find_aggregate_analytic_in_where already did it.
4316  * We may continue walking to search in the rest parts,
4317  * See pt_find_aggregate_analytic_post.
4318  */
4319  *continue_walk = PT_STOP_WALK;
4320  }
4321  else if (PT_IS_FUNCTION (tree))
4322  {
4323  if (pt_is_aggregate_function (parser, tree) || pt_is_analytic_function (parser, tree))
4324  {
4325  *function = tree;
4326  *continue_walk = PT_STOP_WALK;
4327  }
4328  }
4329 
4330  return tree;
4331 }
4332 
4333 /*
4334  * pt_find_aggregate_analytic_post ()
4335  *
4336  * result :
4337  * parser(in) :
4338  * tree(in) :
4339  * arg(in) :
4340  * continue_walk :
4341  */
4342 static PT_NODE *
4343 pt_find_aggregate_analytic_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
4344 {
4345  PT_NODE **function = (PT_NODE **) arg;
4346 
4347  if (tree && PT_IS_QUERY_NODE_TYPE (tree->node_type) && *function == NULL)
4348  {
4349  /* Need to search the rest part of tree */
4350  *continue_walk = PT_CONTINUE_WALK;
4351  }
4352  return tree;
4353 }
4354 
4355 /*
4356  * pt_find_aggregate_analytic_in_where ()
4357  * - find an aggregate or analytic function in where clause
4358  *
4359  * result : point to the found function if any; NULL otherwise
4360  * parser(in) :
4361  * node(in) :
4362  * continue_walk :
4363  *
4364  * [Note]
4365  * This function will search whether an aggregate or analytic function exists
4366  * in WHERE clause of below statements:
4367  * INSERT, DO, SET, DELETE, SELECT, UNION, DIFFERENCE, INTERSECTION, and
4368  * MERGE.
4369  * It stops searching when meets the first aggregate or analytic function.
4370  *
4371  * 1) For below node types, searching is limited to child node who containing
4372  * WHERE clause:
4373  * PT_DO, PT_DELETE, PT_SET_SESSION_VARIABLES, PT_SELECT
4374  *
4375  * 2) For below node types, searching is executed on its args:
4376  * PT_UNION, PT_DIFFERENCE, PT_INTERSECTION
4377  *
4378  * 3) For below node types, searching is executed on its all nested nodes:
4379  * PT_FUNCTION, PT_EXPR, PT_MERGE, PT_INSERT
4380  */
4381 static PT_NODE *
4383 {
4384  PT_NODE *find = NULL;
4385 
4386  if (node == NULL)
4387  {
4388  return NULL;
4389  }
4390 
4391  switch (node->node_type)
4392  {
4393  case PT_DO:
4394  find = pt_find_aggregate_analytic_in_where (parser, node->info.do_.expr);
4395  break;
4396 
4399  break;
4400 
4401  case PT_DELETE:
4403  break;
4404 
4405  case PT_SELECT:
4407  break;
4408 
4409  case PT_UNION:
4410  case PT_DIFFERENCE:
4411  case PT_INTERSECTION:
4412  /* search in args recursively */
4413  find = pt_find_aggregate_analytic_in_where (parser, node->info.query.q.union_.arg1);
4414  if (find)
4415  {
4416  break;
4417  }
4418 
4419  find = pt_find_aggregate_analytic_in_where (parser, node->info.query.q.union_.arg2);
4420  break;
4421 
4422  case PT_FUNCTION:
4423  if (pt_is_aggregate_function (parser, node) || pt_is_analytic_function (parser, node))
4424  {
4425  find = node;
4426  break;
4427  }
4428 
4429  /* FALLTHRU */
4430 
4431  case PT_EXPR:
4432  case PT_MERGE:
4433  case PT_INSERT:
4434  /* walk tree to search */
4436  &find);
4437  break;
4438 
4439  default:
4440  /* for the rest node types, no need to search */
4441  break;
4442  }
4443 
4444  return find;
4445 }
4446 
4447 /*
4448  * pt_check_attribute_domain () - enforce composition hierarchy restrictions
4449  * on a given list of attribute type definitions
4450  * return: none
4451  * parser(in): the parser context
4452  * attr_defs(in): a list of PT_ATTR_DEF nodes
4453  * class_type(in): class, vclass, or proxy
4454  * self(in): name of new class (for create case) or NULL (for alter case)
4455  * reuse_oid(in): whether the class being created or altered is marked as
4456  * reusable OID (non-referable)
4457  * stmt(in): current statement
4458  *
4459  * Note :
4460  * - enforce the composition hierarchy rules:
4461  * 1. enforce the (temporary?) restriction that no proxy may have an
4462  * attribute whose type is heterogeneous set/multiset/sequence of
4463  * some object and something else (homogeneous sets/sequences are OK)
4464  * 2. no attribute may have a domain of set(vclass), multiset(vclass)
4465  * or sequence(vclass).
4466  * 3. an attribute of a class may NOT have a domain of a vclass or a proxy
4467  * but may still have a domain of another class
4468  * 4. an attribute of a vclass may have a domain of a vclass or class
4469  * 5. an attribute of a proxy may have a domain of another proxy but not
4470  * a class or vclass.
4471  * 6. an attribute cannot have a reusable OID class (a non-referable
4472  * class) as a domain, neither directly nor as the domain of a set
4473  * - 'create class c (a c)' is not an error but a feature.
4474  */
4475 
4476 static void
4477 pt_check_attribute_domain (PARSER_CONTEXT * parser, PT_NODE * attr_defs, PT_MISC_TYPE class_type, const char *self,
4478  const bool reuse_oid, PT_NODE * stmt)
4479 {
4480  PT_NODE *def, *att, *dtyp, *sdtyp;
4481  DB_OBJECT *cls;
4482  const char *att_nam, *typ_nam, *styp_nam;
4483 
4484  for (def = attr_defs; def != NULL && def->node_type == PT_ATTR_DEF; def = def->next)
4485  {
4486  att = def->info.attr_def.attr_name;
4487  att_nam = att->info.name.original;
4488 
4489  /* if it is an auto_increment column, check its domain */
4490  if (def->info.attr_def.auto_increment != NULL)
4491  {
4492  dtyp = def->data_type;
4493  switch (def->type_enum)
4494  {
4495  case PT_TYPE_INTEGER:
4496  case PT_TYPE_BIGINT:
4497  case PT_TYPE_SMALLINT:
4498  break;
4499 
4500  case PT_TYPE_NUMERIC:
4501  if (dtyp->info.data_type.dec_precision != 0)
4502  {
4504  att_nam);
4505  }
4506  break;
4507 
4508  default:
4510  att_nam);
4511  }
4512  }
4513 
4514  /* we don't allow sets/multisets/sequences of vclasses or reusable OID classes */
4515  if (pt_is_set_type (def))
4516  {
4517  for (dtyp = def->data_type; dtyp != NULL; dtyp = dtyp->next)
4518  {
4519  if ((dtyp->type_enum == PT_TYPE_OBJECT) && (sdtyp = dtyp->info.data_type.entity)
4520  && (sdtyp->node_type == PT_NAME) && (styp_nam = sdtyp->info.name.original))
4521  {
4522  cls = db_find_class (styp_nam);
4523  if (cls != NULL)
4524  {
4525  if (db_is_vclass (cls) > 0)
4526  {
4528  break;
4529  }
4530  if (sm_is_reuse_oid_class (cls))
4531  {
4533  styp_nam);
4534  break;
4535  }
4536  }
4537  else if (self != NULL && intl_identifier_casecmp (self, styp_nam) == 0)
4538  {
4539  if (reuse_oid)
4540  {
4542  styp_nam);
4543  break;
4544  }
4545  }
4546  }
4547  }
4548  }
4549 
4550  if (def->type_enum == PT_TYPE_OBJECT && def->data_type && def->data_type->node_type == PT_DATA_TYPE
4551  && (dtyp = def->data_type->info.data_type.entity) != NULL && dtyp->node_type == PT_NAME
4552  && (typ_nam = dtyp->info.name.original) != NULL)
4553  {
4554  /* typ_nam must be a class in the database */
4555  cls = db_find_class (typ_nam);
4556  if (!cls)
4557  {
4558  if (self != NULL && intl_identifier_casecmp (self, typ_nam) == 0)
4559  {
4560  if (reuse_oid)
4561  {
4563  typ_nam);
4564  }
4565  }
4566  else
4567  {
4569  }
4570  }
4571  else
4572  {
4573  /* if dtyp is 'user.class' then check that 'user' owns 'class' */
4574  dtyp->info.name.db_object = cls;
4575  pt_check_user_owns_class (parser, dtyp);
4576  if (sm_is_reuse_oid_class (cls))
4577  {
4579  typ_nam);
4580  }
4581 
4582  switch (class_type)
4583  {
4584  case PT_CLASS:
4585  /* an attribute of a class must be of type class */
4586  if (db_is_vclass (cls) > 0)
4587  {
4589  }
4590  break;
4591  case PT_VCLASS:
4592  /* an attribute of a vclass must be of type vclass or class */
4593  break;
4594  default:
4595  break;
4596  }
4597  }
4598  }
4599 
4600  if (def->type_enum == PT_TYPE_ENUMERATION)
4601  {
4602  (void) pt_check_enum_data_type (parser, def->data_type);
4603  }
4604 
4605 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
4606  /* if a defined attr is TEXT, rewrite the definition */
4608  {
4609  if ((class_type != PT_CLASS) || (def->info.attr_def.data_default != NULL)
4610  || (def->info.attr_def.constrain_not_null == 1))
4611  {
4612  /* prevent vclass definition or set default */
4614  PT_ERROR (parser, stmt, er_msg ());
4615  return;
4616  }
4617  if (stmt->node_type == PT_CREATE_ENTITY)
4618  {
4621  att_nam, def);
4622  if (stmt->info.create_entity.internal_stmts == NULL)
4623  {
4624  return;
4625  }
4626  }
4627  else if (stmt->node_type == PT_ALTER)
4628  {
4629  PT_NODE *entity_nam;
4630  const char *cls_nam;
4631 
4632  entity_nam = stmt->info.alter.entity_name;
4633  cls_nam = entity_nam->info.name.original;
4634  stmt->info.alter.internal_stmts =
4635  pt_append_statements_on_add_attribute (parser, stmt->info.alter.internal_stmts, stmt, cls_nam, att_nam,
4636  def);
4637  if (stmt->info.alter.internal_stmts == NULL)
4638  {
4639  return;
4640  }
4641  }
4642  }
4643 #endif /* ENABLE_UNUSED_FUNCTION */
4644  }
4645 }
4646 
4647 /*
4648  * pt_check_mutable_attributes () - assert that a given list of attributes are
4649  * indigenous to a given class
4650  * return: none
4651  * parser(in): the parser context
4652  * cls(in): a class object
4653  * attr_defs(in): a list of attribute type definitions
4654  */
4655 
4656 static void
4658 {
4659  PT_NODE *def, *att;
4660  const char *att_nam, *cls_nam;
4661  DB_ATTRIBUTE *db_att;
4662  DB_OBJECT *super;
4663 
4664  assert (parser != NULL);
4665 
4666  if (!cls || (cls_nam = db_get_class_name (cls)) == NULL)
4667  {
4668  return;
4669  }
4670 
4671  for (def = attr_defs; def != NULL && def->node_type == PT_ATTR_DEF; def = def->next)
4672  {
4673  att = def->info.attr_def.attr_name;
4674  att_nam = att->info.name.original;
4675  db_att = db_get_attribute_force (cls, att_nam);
4676  if (!db_att)
4677  {
4679  }
4680  else
4681  {
4682  super = db_attribute_class (db_att);
4683  if (super != cls)
4685  db_get_class_name (super));
4686  }
4687  }
4688 }
4689 
4690 /*
4691  * pt_check_alter () - semantic check an alter statement
4692  * return: none
4693  * parser(in): the parser context used to derive the statement
4694  * alter(in): an alter statement
4695  */
4696 static void
4698 {
4699  DB_OBJECT *db, *super;
4700  PT_ALTER_CODE code;
4701  PT_MISC_TYPE type;
4702  PT_NODE *name, *sup, *att, *qry, *attr;
4703  const char *cls_nam, *sup_nam, *att_nam;
4704  DB_ATTRIBUTE *db_att;
4705  DB_METHOD *db_mthd;
4706  int is_meta;
4707  int is_partitioned = 0, ss_partition, trigger_involved = 0;
4708  char keyattr[DB_MAX_IDENTIFIER_LENGTH + 1];
4709 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
4710  DB_OBJECT *dom_cls;
4711  char *drop_name_list = NULL;
4712 #endif /* ENABLE_UNUSED_FUNCTION */
4713  bool reuse_oid = false;
4714  int collation_id = -1;
4715  bool for_update;
4716 
4717  /* look up the class */
4718  name = alter->info.alter.entity_name;
4719  cls_nam = name->info.name.original;
4720 
4721  if (alter->info.alter.code == PT_CHANGE_ATTR || alter->info.alter.code == PT_ADD_INDEX_CLAUSE)
4722  {
4723  for_update = false;
4724  }
4725  else
4726  {
4727  for_update = true;
4728  }
4729 
4730  db = pt_find_class (parser, name, for_update);
4731  if (!db)
4732  {
4735  return;
4736  }
4737 
4738  if (sm_get_class_collation (db, &collation_id) != NO_ERROR)
4739  {
4740  PT_ERROR (parser, alter, er_msg ());
4741  return;
4742  }
4743 
4744  reuse_oid = sm_is_reuse_oid_class (db);
4745 
4746  /* attach object */
4747  name->info.name.db_object = db;
4748  pt_check_user_owns_class (parser, name);
4749 
4750  /* check that class type is what it's supposed to be */
4751  if (alter->info.alter.entity_type == PT_MISC_DUMMY)
4752  {
4753  alter->info.alter.entity_type = pt_get_class_type (parser, db);
4754  }
4755  else
4756  {
4757  type = alter->info.alter.entity_type;
4758  if ((type == PT_CLASS && db_is_class (db) <= 0) || (type == PT_VCLASS && db_is_vclass (db) <= 0))
4759  {
4761  pt_show_misc_type (type));
4762  return;
4763  }
4764  }
4765 
4766  type = alter->info.alter.entity_type;
4767  if (do_is_partitioned_subclass (&is_partitioned, cls_nam, keyattr))
4768  {
4771  return;
4772  }
4773 
4774  code = alter->info.alter.code;
4775  switch (code)
4776  {
4777  case PT_ADD_ATTR_MTHD:
4778  if (type == PT_VCLASS)
4779  {
4780  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4781  {
4782  if (attr->info.attr_def.auto_increment != NULL)
4783  {
4785  }
4786  }
4787  }
4788 
4789  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4790  {
4791  if (PT_HAS_COLLATION (attr->type_enum) && attr->node_type == PT_ATTR_DEF)
4792  {
4793  if (pt_attr_check_default_cs_coll (parser, attr, -1, collation_id) != NO_ERROR)
4794  {
4795  return;
4796  }
4797  }
4798  }
4799 
4800  pt_check_attribute_domain (parser, alter->info.alter.alter_clause.attr_mthd.attr_def_list, type, NULL, reuse_oid,
4801  alter);
4802  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4803  {
4805  }
4806  break;
4807 
4808  case PT_ALTER_DEFAULT:
4809  for (attr = alter->info.alter.alter_clause.ch_attr_def.attr_name_list; attr; attr = attr->next)
4810  {
4811  att_nam = attr->info.name.original;
4812  is_meta = (attr->info.name.meta_class == PT_META_ATTR);
4813  db_att =
4814  (DB_ATTRIBUTE *) (is_meta ? db_get_class_attribute (db, att_nam) : db_get_attribute_force (db, att_nam));
4815  if (db_att != NULL && (db_att->auto_increment != NULL || db_att->header.name_space == ID_SHARED_ATTRIBUTE))
4816  {
4817  PT_ERRORm (parser, alter, MSGCAT_SET_PARSER_SEMANTIC,
4819  return;
4820  }
4821  }
4822  alter->info.alter.alter_clause.ch_attr_def.data_default_list =
4823  pt_check_data_default (parser, alter->info.alter.alter_clause.ch_attr_def.data_default_list);
4824 
4825  /* FALL THRU */
4826 
4827  case PT_MODIFY_DEFAULT:
4828  pt_resolve_default_external (parser, alter);
4829  break;
4830 
4831  case PT_CHANGE_ATTR:
4832  {
4833  PT_NODE *const att_def = alter->info.alter.alter_clause.attr_mthd.attr_def_list;
4834 
4835  if (att_def->next != NULL || att_def->node_type != PT_ATTR_DEF)
4836  {
4837  assert (false);
4838  break;
4839  }
4840 
4841  if (alter->info.alter.entity_type != PT_CLASS)
4842  {
4844  break;
4845  }
4846 
4847  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4848  {
4849  if (PT_HAS_COLLATION (attr->type_enum) && attr->node_type == PT_ATTR_DEF)
4850  {
4851  if (pt_attr_check_default_cs_coll (parser, attr, -1, collation_id) != NO_ERROR)
4852  {
4853  return;
4854  }
4855  }
4856  }
4857 
4858  pt_check_attribute_domain (parser, att_def, type, NULL, reuse_oid, alter);
4859  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4860  {
4862  }
4863  }
4864  break;
4865 
4866  case PT_MODIFY_ATTR_MTHD:
4867  pt_check_attribute_domain (parser, alter->info.alter.alter_clause.attr_mthd.attr_def_list, type, NULL, reuse_oid,
4868  alter);
4869  pt_check_mutable_attributes (parser, db, alter->info.alter.alter_clause.attr_mthd.attr_def_list);
4870  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
4871  {
4873  }
4874  break;
4875 
4876  case PT_RENAME_ATTR_MTHD:
4877  if (is_partitioned && keyattr[0] && (alter->info.alter.alter_clause.rename.element_type == PT_ATTRIBUTE))
4878  {
4879  if (!strncmp (alter->info.alter.alter_clause.rename.old_name->info.name.original, keyattr,
4881  {
4884  }
4885  }
4886  break;
4887 
4888  case PT_DROP_ATTR_MTHD:
4889  for (att = alter->info.alter.alter_clause.attr_mthd.attr_mthd_name_list; att != NULL && att->node_type == PT_NAME;
4890  att = att->next)
4891  {
4892  att_nam = att->info.name.original;
4893  is_meta = (att->info.name.meta_class == PT_META_ATTR);
4894  db_att =
4895  (DB_ATTRIBUTE *) (is_meta ? db_get_class_attribute (db, att_nam) : db_get_attribute_force (db, att_nam));
4896  if (db_att)
4897  {
4898  /* an inherited attribute can not be dropped by the heir */
4899  super = (DB_OBJECT *) db_attribute_class (db_att);
4900  if (super != db)
4901  {
4903  db_get_class_name (super));
4904  }
4905  if (is_partitioned && keyattr[0])
4906  {
4907  if (!strncmp (att_nam, keyattr, DB_MAX_IDENTIFIER_LENGTH))
4908  {
4910  att_nam);
4911  }
4912  }
4913 
4914 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
4915  /* if it is TEXT typed attr, collect name of the domain class */
4916  if (sm_has_text_domain (db_att, 0))
4917  {
4918  dom_cls = (DB_OBJECT *) db_domain_class (db_attribute_domain (db_att));
4919  if (drop_name_list != NULL)
4920  {
4921  drop_name_list = pt_append_string (parser, drop_name_list, ",");
4922  }
4923  drop_name_list = pt_append_string (parser, drop_name_list, db_get_class_name (dom_cls));
4924  }
4925 #endif /* ENABLE_UNUSED_FUNCTION */
4926 
4927  }
4928  else
4929  {
4930  /* perhaps it's a method */
4931  db_mthd = (DB_METHOD *) (is_meta ? db_get_class_method (db, att_nam) : db_get_method (db, att_nam));
4932  if (!db_mthd)
4933  {
4934  if (!is_meta)
4935  {
4937  cls_nam);
4938  }
4939  else
4940  {
4942  att_nam, cls_nam);
4943  }
4944  }
4945  }
4946  }
4947 
4948 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
4949  /* create internal statements to drop the TEXT saving classes */
4950  if (drop_name_list)
4951  {
4952  if ((alter->info.alter.internal_stmts =
4953  pt_append_statements_on_drop_attributes (parser, alter->info.alter.internal_stmts,
4954  drop_name_list)) == NULL)
4955  {
4957  return;
4958  }
4959  }
4960 #endif /* ENABLE_UNUSED_FUNCTION */
4961  break;
4962 
4963  case PT_APPLY_PARTITION:
4964  case PT_REMOVE_PARTITION:
4965  case PT_ANALYZE_PARTITION:
4966  case PT_DROP_PARTITION:
4967  case PT_ADD_PARTITION:
4968  case PT_ADD_HASHPARTITION:
4969  case PT_REORG_PARTITION:
4970  case PT_COALESCE_PARTITION:
4971  case PT_PROMOTE_PARTITION:
4972  if (sm_class_has_triggers (db, &trigger_involved, TR_EVENT_ALL) == NO_ERROR)
4973  {
4974  if (trigger_involved)
4975  {
4978  break;
4979  }
4980  }
4981 
4982  if (code == PT_APPLY_PARTITION)
4983  {
4984  if (is_partitioned)
4985  {
4988  break;
4989  }
4990  if (alter->info.alter.alter_clause.partition.info)
4991  {
4992  pt_check_partitions (parser, alter, db);
4993  }
4994  }
4995  else
4996  {
4997  if (!is_partitioned)
4998  {
5001  break;
5002  }
5003  if (code != PT_REMOVE_PARTITION)
5004  {
5005  pt_check_alter_partition (parser, alter, db);
5006  }
5007  }
5008  break;
5009 
5010  case PT_ADD_QUERY:
5011  case PT_MODIFY_QUERY:
5012  if (type != PT_CLASS && (qry = alter->info.alter.alter_clause.query.query) != NULL)
5013  {
5014  pt_validate_query_spec (parser, qry, db);
5015  }
5016  /* FALLTHRU */
5017  case PT_DROP_QUERY:
5018  if (type == PT_CLASS)
5019  {
5021  }
5022  break;
5023 
5024  case PT_RESET_QUERY:
5025  if (type == PT_CLASS)
5026  {
5027  /* only allow views, not classes here */
5029  }
5030  else if (db_get_subclasses (db) != NULL || db_get_superclasses (db) != NULL)
5031  {
5032  /* disallow resetting query for views that have children or parents */
5034  }
5035  else if ((qry = alter->info.alter.alter_clause.query.query) == NULL)
5036  {
5037  break;
5038  }
5039  else
5040  {
5041  pt_check_create_view (parser, alter);
5042  }
5043  break;
5044 
5045  case PT_ADD_SUPCLASS:
5046  case PT_DROP_SUPCLASS:
5047  for (sup = alter->info.alter.super.sup_class_list; sup != NULL; sup = sup->next)
5048  {
5049  sup_nam = sup->info.name.original;
5050  super = pt_find_class (parser, sup, true);
5051  if (super == NULL)
5052  {
5054  break;
5055  }
5056  if (sm_partitioned_class_type (super, &ss_partition, NULL, NULL) != NO_ERROR)
5057  {
5058  PT_ERROR (parser, alter, er_msg ());
5059  break;
5060  }
5061  if (ss_partition == DB_PARTITION_CLASS)
5062  {
5064  break;
5065  }
5066  if (code == PT_ADD_SUPCLASS)
5067  {
5068 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
5069  if (sm_has_text_domain (db_get_attributes (super), 1))
5070  {
5071  /* prevent to define it as a superclass */
5073  PT_ERROR (parser, alter, er_msg ());
5074  break;
5075  }
5076 #endif /* ENABLE_UNUSED_FUNCTION */
5077  }
5078  sup->info.name.db_object = super;
5079  pt_check_user_owns_class (parser, sup);
5080  if (code == PT_DROP_SUPCLASS)
5081  {
5082  if (db_is_superclass (super, db) <= 0)
5083  {
5085  cls_nam);
5086  }
5087  }
5088  else /* PT_ADD_SUPCLASS */
5089  {
5090  switch (type)
5091  {
5092  case PT_CLASS:
5093  if (db_is_class (super) <= 0)
5094  {
5096  sup_nam);
5097  }
5098  break;
5099  case PT_VCLASS:
5100  if (db_is_vclass (super) <= 0)
5101  {
5103  sup_nam);
5104  }
5105  break;
5106  default:
5107  break;
5108  }
5109 
5110  if (db_is_superclass (super, db))
5111  {
5113  cls_nam);
5114  }
5115  if (db == super)
5116  {
5118  }
5119  if (db_is_subclass (super, db))
5120  {
5122  cls_nam);
5123  }
5124  }
5125  }
5126  break;
5127  default:
5128  break;
5129  }
5130 }
5131 
5132 /*
5133  * attribute_name () - return the name of this attribute
5134  * return: printable name of att
5135  * parser(in): the parser context
5136  * att(in): an attribute
5137  */
5138 static const char *
5140 {
5141  if (!att)
5142  {
5143  return NULL;
5144  }
5145 
5146  if (att->node_type == PT_ATTR_DEF)
5147  {
5148  att = att->info.attr_def.attr_name;
5149  }
5150 
5151  if (att->node_type != PT_NAME)
5152  {
5153  return NULL;
5154  }
5155 
5156  return att->info.name.original;
5157 }
5158 
5159 /*
5160  * is_shared_attribute () - is this a shared attribute?
5161  * return: nonzero if att is a shared attribute
5162  * parser(in): the parser context
5163  * att(in): an attribute
5164  */
5165 static int
5167 {
5168  if (!att)
5169  {
5170  return 0;
5171  }
5172 
5173  if (att->node_type == PT_ATTR_DEF)
5174  {
5175  if (att->info.attr_def.attr_type == PT_SHARED)
5176  {
5177  return 1;
5178  }
5179 
5180  if (!(att = att->info.attr_def.attr_name))
5181  {
5182  return 0;
5183  }
5184  }
5185 
5186  if (att->node_type != PT_NAME)
5187  {
5188  return 0;
5189  }
5190 
5191  return (att->info.name.meta_class == PT_SHARED);
5192 }
5193 
5194 /*
5195  * pt_find_partition_column_count_func () - find the number of the name node
5196  * which can be used as the partition
5197  * column
5198  * return:
5199  * func(in):
5200  * name_node(in/out):
5201  */
5202 static int
5204 {
5205  int cnt = 0, ret;
5206  PT_NODE *f_arg;
5207 
5208  if (func == NULL)
5209  {
5210  return 0;
5211  }
5212 
5213  if (func->node_type != PT_FUNCTION)
5214  {
5215  return 0;
5216  }
5217 
5218  switch (func->info.function.function_type)
5219  {
5220  case F_INSERT_SUBSTRING:
5221  case F_ELT:
5222  case F_JSON_ARRAY:
5223  case F_JSON_ARRAY_APPEND:
5224  case F_JSON_ARRAY_INSERT:
5225  case F_JSON_CONTAINS:
5226  case F_JSON_CONTAINS_PATH:
5227  case F_JSON_DEPTH:
5228  case F_JSON_EXTRACT:
5229  case F_JSON_GET_ALL_PATHS:
5230  case F_JSON_KEYS:
5231  case F_JSON_INSERT:
5232  case F_JSON_LENGTH:
5233  case F_JSON_MERGE:
5234  case F_JSON_MERGE_PATCH:
5235  case F_JSON_OBJECT:
5236  case F_JSON_PRETTY:
5237  case F_JSON_QUOTE:
5238  case F_JSON_REMOVE:
5239  case F_JSON_REPLACE:
5240  case F_JSON_SEARCH:
5241  case F_JSON_SET:
5242  case F_JSON_TYPE:
5243  case F_JSON_UNQUOTE:
5244  case F_JSON_VALID:
5245  break;
5246  default:
5247  return 0; /* unsupported function */
5248  }
5249 
5250  f_arg = func->info.function.arg_list;
5251  while (f_arg != NULL)
5252  {
5253  if (f_arg->node_type == PT_NAME)
5254  {
5255  cnt++;
5256  *name_node = f_arg;
5257  }
5258  else if (f_arg->node_type == PT_EXPR)
5259  {
5260  ret = pt_find_partition_column_count (f_arg, name_node);
5261  if (ret > 0)
5262  {
5263  cnt += ret;
5264  }
5265  }
5266  f_arg = f_arg->next;
5267  }
5268 
5269  return cnt;
5270 }
5271 
5272 /*
5273  * pt_find_partition_column_count () - find the number of the name node which
5274  * can be used as the partition column
5275  * return:
5276  * expr(in):
5277  * name_node(in/out):
5278  */
5279 static int
5281 {
5282  int cnt = 0, ret;
5283 
5284  if (expr == NULL)
5285  {
5286  return 0;
5287  }
5288 
5289  if (expr->node_type != PT_EXPR)
5290  {
5291  return 0;
5292  }
5293 
5294  switch (expr->info.expr.op)
5295  {
5296  case PT_FUNCTION_HOLDER:
5297  assert (expr->info.expr.arg1 != NULL);
5298  return pt_find_partition_column_count_func (expr->info.expr.arg1, name_node);
5299  case PT_PLUS:
5300  case PT_MINUS:
5301  case PT_TIMES:
5302  case PT_DIVIDE:
5303  case PT_UNARY_MINUS:
5304  case PT_BIT_NOT:
5305  case PT_BIT_AND:
5306  case PT_BIT_OR:
5307  case PT_BIT_XOR:
5308  case PT_BITSHIFT_LEFT:
5309  case PT_BITSHIFT_RIGHT:
5310  case PT_DIV:
5311  case PT_MOD:
5312  case PT_ACOS:
5313  case PT_ASIN:
5314  case PT_ATAN:
5315  case PT_ATAN2:
5316  case PT_COS:
5317  case PT_SIN:
5318  case PT_TAN:
5319  case PT_COT:
5320  case PT_DEGREES:
5321  case PT_RADIANS:
5322  case PT_PI:
5323  case PT_LN:
5324  case PT_LOG2:
5325  case PT_LOG10:
5326  case PT_FORMAT:
5327  case PT_DATE_FORMAT:
5328  case PT_STR_TO_DATE:
5329  case PT_CONCAT:
5330  case PT_CONCAT_WS:
5331  case PT_FIELD:
5332  case PT_LEFT:
5333  case PT_RIGHT:
5334  case PT_LOCATE:
5335  case PT_MID:
5336  case PT_STRCMP:
5337  case PT_REVERSE:
5338  case PT_BIT_COUNT:
5339  case PT_ADDDATE:
5340  case PT_DATE_ADD:
5341  case PT_SUBDATE:
5342  case PT_DATE_SUB:
5343  case PT_DATEF:
5344  case PT_TIMEF:
5345  case PT_DATEDIFF:
5346  case PT_TIMEDIFF:
5347  case PT_MODULUS:
5348  case PT_POSITION:
5349  case PT_FINDINSET:
5350  case PT_SUBSTRING:
5351  case PT_SUBSTRING_INDEX:
5352  case PT_OCTET_LENGTH:
5353  case PT_BIT_LENGTH:
5354  case PT_CHAR_LENGTH:
5355  case PT_LOWER:
5356  case PT_UPPER:
5357  case PT_HEX:
5358  case PT_ASCII:
5359  case PT_CONV:
5360  case PT_BIN:
5361  case PT_MD5:
5362  case PT_TO_BASE64:
5363  case PT_FROM_BASE64:
5364  case PT_TRIM:
5365  case PT_LTRIM:
5366  case PT_RTRIM:
5367  case PT_LIKE_LOWER_BOUND:
5368  case PT_LIKE_UPPER_BOUND:
5369  case PT_LPAD:
5370  case PT_RPAD:
5371  case PT_REPEAT:
5372  case PT_SPACE:
5373  case PT_REPLACE:
5374  case PT_TRANSLATE:
5375  case PT_ADD_MONTHS:
5376  case PT_LAST_DAY:
5377  case PT_MONTHS_BETWEEN:
5378  case PT_SYS_DATE:
5379  case PT_TO_DATE:
5380  case PT_TO_NUMBER:
5381  case PT_SYS_TIME:
5382  case PT_CURRENT_DATE:
5383  case PT_CURRENT_TIME:
5384  case PT_SYS_TIMESTAMP:
5385  case PT_CURRENT_TIMESTAMP:
5386  case PT_SYS_DATETIME:
5387  case PT_CURRENT_DATETIME:
5388  case PT_UTC_TIME:
5389  case PT_UTC_DATE:
5390  case PT_TO_TIME:
5391  case PT_TO_TIMESTAMP:
5392  case PT_TO_DATETIME:
5393  case PT_SCHEMA:
5394  case PT_DATABASE:
5395  case PT_VERSION:
5396  case PT_TIME_FORMAT:
5397  case PT_TIMESTAMP:
5398  case PT_YEARF:
5399  case PT_MONTHF:
5400  case PT_DAYF:
5401  case PT_DAYOFMONTH:
5402  case PT_HOURF:
5403  case PT_MINUTEF:
5404  case PT_SECONDF:
5405  case PT_QUARTERF:
5406  case PT_WEEKDAY:
5407  case PT_DAYOFWEEK:
5408  case PT_DAYOFYEAR:
5409  case PT_TODAYS:
5410  case PT_FROMDAYS:
5411  case PT_TIMETOSEC:
5412  case PT_SECTOTIME:
5413  case PT_WEEKF:
5414  case PT_MAKEDATE:
5415  case PT_MAKETIME:
5416  case PT_ADDTIME:
5417  case PT_UNIX_TIMESTAMP:
5418  case PT_FROM_UNIXTIME:
5419  case PT_EXTRACT:
5420  case PT_TO_CHAR:
5421  case PT_CAST:
5422  case PT_STRCAT:
5423  case PT_FLOOR:
5424  case PT_CEIL:
5425  case PT_POWER:
5426  case PT_ROUND:
5427  case PT_ABS:
5428  case PT_LOG:
5429  case PT_EXP:
5430  case PT_SQRT:
5431  case PT_TRUNC:
5432  case PT_BIT_TO_BLOB:
5433  case PT_BLOB_FROM_FILE:
5434  case PT_BLOB_LENGTH:
5435  case PT_BLOB_TO_BIT:
5436  case PT_CHAR_TO_BLOB:
5437  case PT_CHAR_TO_CLOB:
5438  case PT_CLOB_FROM_FILE:
5439  case PT_CLOB_LENGTH:
5440  case PT_CLOB_TO_CHAR:
5441  case PT_TYPEOF:
5442  case PT_INET_ATON:
5443  case PT_INET_NTOA:
5444  case PT_DBTIMEZONE:
5445  case PT_SESSIONTIMEZONE:
5446  case PT_TZ_OFFSET:
5447  case PT_FROM_TZ:
5448  case PT_NEW_TIME:
5449  case PT_TO_DATETIME_TZ:
5450  case PT_TO_TIMESTAMP_TZ:
5451  case PT_UTC_TIMESTAMP:
5452  case PT_CONV_TZ:
5453  break;
5454 
5455  /* PT_DRAND and PT_DRANDOM are not supported regardless of whether a seed is given or not. because they produce
5456  * random numbers of DOUBLE type. DOUBLE type is not allowed on partition expression. */
5457  case PT_RAND:
5458  case PT_RANDOM:
5459  if (expr->info.expr.arg1 == NULL)
5460  {
5461  return -1;
5462  }
5463  break;
5464 
5465  default:
5466  return -1; /* unsupported expression */
5467  }
5468 
5469  if (expr->info.expr.arg1 != NULL)
5470  {
5471  if (expr->info.expr.arg1->node_type == PT_NAME)
5472  {
5473  *name_node = expr->info.expr.arg1;
5474  cnt++;
5475  }
5476  else if (expr->info.expr.arg1->node_type == PT_VALUE)
5477  {
5478  if (expr->info.expr.arg1->type_enum == PT_TYPE_NULL)
5479  {
5480  return -1;
5481  }
5482  }
5483  else if (expr->info.expr.arg1->node_type == PT_EXPR)
5484  {
5485  ret = pt_find_partition_column_count (expr->info.expr.arg1, name_node);
5486  if (ret < 0)
5487  {
5488  return -1;
5489  }
5490  cnt += ret;
5491  }
5492  }
5493 
5494  if (expr->info.expr.arg2 != NULL)
5495  {
5496  if (expr->info.expr.arg2->node_type == PT_NAME)
5497  {
5498  *name_node = expr->info.expr.arg2;
5499  cnt++;
5500  }
5501  else if (expr->info.expr.arg2->node_type == PT_VALUE)
5502  { /* except default NULL parameter */
5503  if (expr->info.expr.arg2->type_enum == PT_TYPE_NULL
5504  && ((expr->info.expr.arg2->line_number != expr->info.expr.arg3->line_number)
5505  || (expr->info.expr.arg2->column_number != expr->info.expr.arg3->column_number)))
5506  {
5507  return -1;
5508  }
5509  }
5510  else if (expr->info.expr.arg2->node_type == PT_EXPR)
5511  {
5512  ret = pt_find_partition_column_count (expr->info.expr.arg2, name_node);
5513  if (ret < 0)
5514  {
5515  return -1;
5516  }
5517  cnt += ret;
5518  }
5519  }
5520 
5521  if (expr->info.expr.arg3 != NULL)
5522  {
5523  if (expr->info.expr.arg3->node_type == PT_NAME)
5524  {
5525  *name_node = expr->info.expr.arg3;
5526  cnt++;
5527  }
5528  else if (expr->info.expr.arg3->node_type == PT_VALUE)
5529  {
5530  if (expr->info.expr.arg3->type_enum == PT_TYPE_NULL)
5531  {
5532  return -1;
5533  }
5534  }
5535  else if (expr->info.expr.arg3->node_type == PT_EXPR)
5536  {
5537  ret = pt_find_partition_column_count (expr->info.expr.arg3, name_node);
5538  if (ret < 0)
5539  {
5540  return -1;
5541  }
5542  cnt += ret;
5543  }
5544  }
5545  return cnt;
5546 }
5547 
5548 /*
5549  * pt_value_links_add () -
5550  * return:
5551  * parser(in):
5552  * parts(in):
5553  * val(in):
5554  * ptl(in):
5555  */
5556 static int
5558 {
5559  PT_VALUE_LINKS *vblk, *blks;
5560 
5561  vblk = (PT_VALUE_LINKS *) malloc (sizeof (PT_VALUE_LINKS));
5562  if (vblk == NULL)
5563  {
5565  return ER_FAILED;
5566  }
5567 
5568  vblk->vallink = val;
5569  vblk->next = ptl->next;
5570  if (ptl->next == NULL)
5571  { /* first item */
5572  ptl->next = vblk;
5573  return 0;
5574  }
5575 
5576  for (blks = ptl->next; blks; blks = blks->next)
5577  {
5578  if (val == NULL)
5579  {
5580  if (blks->vallink == NULL)
5581  {
5582  /* MAXVALUE or NULL duplicate */
5583  goto duplicate_error;
5584  }
5585  }
5586  else if (blks->vallink != NULL)
5587  {
5588  if (db_value_compare (pt_value_to_db (parser, val), pt_value_to_db (parser, blks->vallink)) == DB_EQ)
5589  {
5590  goto duplicate_error;
5591  }
5592  }
5593  }
5594 
5595  ptl->next = vblk;
5596 
5597  return NO_ERROR;
5598 
5599 duplicate_error:
5600  if (vblk != NULL)
5601  {
5602  free_and_init (vblk);
5603  }
5605  parts->info.parts.name->info.name.original);
5606  return ER_FAILED;
5607 }
5608 
5609 /*
5610  * pt_check_partition_values () - perform semantic check on partition
5611  * range/list specification
5612  * return: error code or NO_ERROR
5613  * parser(in) : parser context
5614  * desired_type(in) : desired type for partition values
5615  * data_type(in) : data type for desired_type
5616  * ptl(in) : values context
5617  * parts (in) : node specifying one partition
5618  */
5619 static int
5621  PT_VALUE_LINKS * ptl, PT_NODE * parts)
5622 {
5623  int error = NO_ERROR;
5624  PT_NODE *val = NULL;
5625  const char *value_text = NULL;
5626 
5627  if (parts->info.parts.values == NULL)
5628  {
5629  /* MAXVALUE specification */
5630  return pt_value_links_add (parser, parts, NULL, ptl);
5631  }
5632 
5633  for (val = parts->info.parts.values; val != NULL; val = val->next)
5634  {
5635  bool has_different_collation = false;
5636  bool has_different_codeset = false;
5637 
5638  if (val->node_type != PT_VALUE)
5639  {
5640  /* Only values are allowed in partition LIST or RANGE specification. */
5641  assert_release (val->node_type != PT_VALUE);
5642  PT_ERROR (parser, val, er_msg ());
5643  error = ER_FAILED;
5644  break;
5645  }
5646 
5647  if (PT_HAS_COLLATION (val->type_enum) && data_type != NULL && PT_HAS_COLLATION (data_type->type_enum))
5648  {
5649  if ((val->data_type != NULL && data_type->info.data_type.units != val->data_type->info.data_type.units)
5650  || (val->data_type == NULL && data_type->info.data_type.units != LANG_SYS_CODESET))
5651  {
5652  has_different_codeset = true;
5653  }
5654 
5655  if ((val->data_type != NULL
5657  || (val->data_type == NULL && data_type->info.data_type.collation_id != LANG_SYS_COLLATION))
5658  {
5659  has_different_collation = true;
5660  }
5661  }
5662 
5663  if (has_different_codeset == true)
5664  {
5665  int val_codeset;
5666 
5667  val_codeset = (val->data_type != NULL) ? val->data_type->info.data_type.units : LANG_SYS_CODESET;
5668 
5669  error = ER_FAILED;
5671  lang_charset_introducer ((INTL_CODESET) val_codeset),
5673  break;
5674  }
5675 
5676  if (val->type_enum != PT_TYPE_NULL && (val->type_enum != desired_type || has_different_collation == true))
5677  {
5678  /* Coerce this value to the desired type. We have to preserve the original text of the value for replication
5679  * reasons. The coercion below will either be successful or fail, but it should not alter the way in which
5680  * the original statement is printed */
5681  value_text = val->info.value.text;
5682  val->info.value.text = NULL;
5683  error = pt_coerce_value (parser, val, val, desired_type, data_type);
5684  val->info.value.text = value_text;
5685  if (error != NO_ERROR)
5686  {
5687  break;
5688  }
5689  }
5690 
5691  /* add this value to the values list */
5692  if (val->type_enum == PT_TYPE_NULL)
5693  {
5694  error = pt_value_links_add (parser, parts, NULL, ptl);
5695  }
5696  else
5697  {
5698  error = pt_value_links_add (parser, parts, val, ptl);
5699  }
5700 
5701  if (error != NO_ERROR)
5702  {
5703  break;
5704  }
5705  }
5706 
5707  return error;
5708 }
5709 
5710 
5711 /*
5712  * pt_check_partitions () - do semantic checks on a partition clause
5713  * return: none
5714  * parser(in): the parser context used to derive the statement
5715  * stmt(in): a create class or alter class statement
5716  * dbobj(in):
5717  *
5718  * Note :
5719  * check that
5720  * - stmt's expression have an attribute
5721  * - expression's attribute is not set nor object type
5722  * - partition type is equals to partition definitions
5723  * - partition max
5724  * - valid hash size
5725  */
5726 
5727 static void
5729 {
5730  PT_NODE *pinfo, *pcol, *attr, *pattr, *parts;
5731  int name_count, valchk, parts_cnt;
5732  PT_VALUE_LINKS vlinks = { NULL, NULL };
5733  PT_VALUE_LINKS *pvl, *delpvl;
5734  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
5735  PT_NODE *expr_type;
5736  SM_CLASS *smclass;
5737  SM_ATTRIBUTE *smatt;
5738  bool chkflag = false;
5739  DB_QUERY_TYPE *query_columns = NULL, *column = NULL;
5740  int error = NO_ERROR;
5741 
5742  assert (parser != NULL);
5743 
5744  if (!stmt || (stmt->node_type != PT_CREATE_ENTITY && stmt->node_type != PT_ALTER))
5745  {
5746  return;
5747  }
5748 
5749  if (stmt->node_type == PT_CREATE_ENTITY)
5750  {
5751  pinfo = stmt->info.create_entity.partition_info;
5752  }
5753  else
5754  {
5755  pinfo = stmt->info.alter.alter_clause.partition.info;
5756  }
5757 
5758  if (pinfo == NULL || pinfo->node_type != PT_PARTITION || pinfo->info.partition.type > PT_PARTITION_LIST)
5759  {
5761  return;
5762  }
5763 
5764  if (0 < parser->host_var_count)
5765  {
5767  return;
5768  }
5769 
5770  pcol = pinfo->info.partition.expr;
5771  if (pcol->node_type != PT_NAME && pcol->node_type != PT_EXPR)
5772  {
5774  return;
5775  }
5776 
5777  if (pcol->node_type == PT_EXPR)
5778  {
5779  name_count = pt_find_partition_column_count (pcol, &pcol);
5780  if (name_count < 0)
5781  { /* NULL constant exist */
5783  return;
5784  }
5785  else if (name_count == 0)
5786  {
5788  return;
5789  }
5790  else if (name_count > 1)
5791  {
5793  return;
5794  }
5795  }
5796 
5797  assert (pcol->node_type == PT_NAME);
5798 
5799  if (stmt->node_type == PT_CREATE_ENTITY)
5800  {
5801  for (attr = stmt->info.create_entity.attr_def_list, chkflag = false; attr && attr->node_type == PT_ATTR_DEF;
5802  attr = attr->next)
5803  {
5804  pattr = attr->info.attr_def.attr_name;
5805  if (pattr == NULL)
5806  {
5807  continue;
5808  }
5809 
5811  {
5812  if (attr->info.attr_def.attr_type != PT_NORMAL)
5813  {
5815  return;
5816  }
5817  pcol->type_enum = attr->type_enum;
5818  if (attr->data_type != NULL)
5819  {
5820  assert (pcol->data_type == NULL);
5821  pcol->data_type = parser_copy_tree (parser, attr->data_type);
5822  }
5823  else
5824  {
5825  TP_DOMAIN *d;
5826 
5828  d = tp_domain_cache (d);
5829  pcol->data_type = pt_domain_to_data_type (parser, d);
5830  }
5831  pinfo->info.partition.keycol = parser_copy_tree (parser, pcol);
5832  chkflag = true;
5833  break;
5834  }
5835  }
5836 
5837  /* check if partitioning is requested by a column in SELECT query */
5838  if (!chkflag && stmt->info.create_entity.create_select != NULL)
5839  {
5840  int error = NO_ERROR;
5841  PT_NODE *qry_select = stmt->info.create_entity.create_select;
5842  /* get columns from SELECT result */
5843 
5844  error = pt_get_select_query_columns (parser, qry_select, &query_columns);
5845  if (error != NO_ERROR)
5846  {
5847  /* error message already set at the above compilation step */
5848  return;
5849  }
5850 
5851  for (column = query_columns; column != NULL; column = db_query_format_next (column))
5852  {
5853  if (!intl_identifier_casecmp (column->original_name, pcol->info.name.original))
5854  {
5855  pcol->type_enum = pt_db_to_type_enum (column->db_type);
5856 
5857  assert (column->domain != NULL);
5858  pcol->data_type = pt_domain_to_data_type (parser, column->domain);
5859  pinfo->info.partition.keycol = parser_copy_tree (parser, pcol);
5860  chkflag = true;
5861  break;
5862  }
5863  }
5864  if (query_columns != NULL)
5865  {
5866  db_free_query_format (query_columns);
5867  query_columns = NULL;
5868  }
5869  assert (NULL == query_columns);
5870  }
5871 
5872  }
5873  else
5874  {
5875  if (au_fetch_class (dbobj, &smclass, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
5876  {
5877  for (smatt = smclass->attributes; smatt != NULL; smatt = (SM_ATTRIBUTE *) smatt->header.next)
5878  {
5879  if (SM_COMPARE_NAMES (smatt->header.name, pcol->info.name.original) == 0)
5880  {
5881  if (smatt->class_mop != stmt->info.alter.entity_name->info.name.db_object)
5882  {
5883  PT_ERRORm (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC,
5885  }
5886  pcol->type_enum = pt_db_to_type_enum (smatt->type->id);
5887  assert (smatt->domain != NULL);
5888  pcol->data_type = pt_domain_to_data_type (parser, smatt->domain);
5889  pinfo->info.partition.keycol = parser_copy_tree (parser, pcol);
5890  chkflag = true;
5891  break;
5892  }
5893  }
5894  }
5895  }
5896 
5897  if (chkflag)
5898  {
5899  switch (pcol->type_enum)
5900  {
5901  case PT_TYPE_INTEGER:
5902  case PT_TYPE_BIGINT:
5903  case PT_TYPE_SMALLINT:
5904  case PT_TYPE_DATE:
5905  case PT_TYPE_TIME:
5906  case PT_TYPE_TIMESTAMP:
5907  case PT_TYPE_TIMESTAMPTZ:
5908  case PT_TYPE_TIMESTAMPLTZ:
5909  case PT_TYPE_DATETIME:
5910  case PT_TYPE_DATETIMETZ:
5911  case PT_TYPE_DATETIMELTZ:
5912  case PT_TYPE_CHAR:
5913  case PT_TYPE_VARCHAR:
5914  case PT_TYPE_NCHAR:
5915  case PT_TYPE_VARNCHAR:
5916  break;
5917  default:
5919  return;
5920  }
5921  }
5922  else
5923  {
5924  bool found = false;
5925 
5927  {
5929 
5930  if (au_fetch_class (sup_dbobj, &smclass, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
5931  {
5932  for (smatt = smclass->attributes; smatt != NULL; smatt = (SM_ATTRIBUTE *) smatt->header.next)
5933  {
5934  if (SM_COMPARE_NAMES (smatt->header.name, pcol->info.name.original) == 0)
5935  {
5936  PT_ERRORm (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC,
5938  found = true;
5939  }
5940  }
5941  }
5942  }
5943 
5944  if (!found)
5945  {
5947  }
5948  }
5949 
5950  pcol = pinfo->info.partition.expr;
5951  sc_info.top_node = pcol;
5952  sc_info.donot_fold = false;
5953  expr_type = pt_semantic_type (parser, pcol, &sc_info);
5954  if (expr_type)
5955  {
5956  switch (expr_type->type_enum)
5957  {
5958  case PT_TYPE_INTEGER:
5959  case PT_TYPE_BIGINT:
5960  case PT_TYPE_SMALLINT:
5961  case PT_TYPE_DATE:
5962  case PT_TYPE_TIME:
5963  case PT_TYPE_TIMESTAMP:
5964  case PT_TYPE_TIMESTAMPTZ:
5965  case PT_TYPE_TIMESTAMPLTZ:
5966  case PT_TYPE_DATETIME:
5967  case PT_TYPE_DATETIMETZ:
5968  case PT_TYPE_DATETIMELTZ:
5969  case PT_TYPE_CHAR:
5970  case PT_TYPE_VARCHAR:
5971  case PT_TYPE_NCHAR:
5972  case PT_TYPE_VARNCHAR:
5973  break;
5974  default:
5976  return;
5977  }
5978  }
5979  else
5980  {
5982  return;
5983  }
5984 
5985  if (pinfo->info.partition.type == PT_PARTITION_HASH)
5986  {
5987  PT_NODE *hashsize_nodep;
5988 
5989  hashsize_nodep = pinfo->info.partition.hashsize;
5990  if (hashsize_nodep == NULL || hashsize_nodep->type_enum != PT_TYPE_INTEGER
5991  || hashsize_nodep->info.value.data_value.i < 1 || hashsize_nodep->info.value.data_value.i > MAX_PARTITIONS)
5992  {
5994  }
5995  }
5996  else
5997  { /* RANGE or LIST */
5998  parts = pinfo->info.partition.parts;
5999  if (parts == NULL)
6000  {
6002  return;
6003  }
6004 
6005  parts_cnt = 0;
6006  for (chkflag = false; parts && parts->node_type == PT_PARTS; parts = parts->next)
6007  {
6008  PT_NODE *fpart;
6009 
6010  if (parts->info.parts.type != pinfo->info.partition.type)
6011  {
6012  chkflag = true;
6013  break;
6014  }
6015  if (parts->info.parts.values != NULL)
6016  {
6017  parts->info.parts.values =
6018  parser_walk_tree (parser, parts->info.parts.values, pt_check_and_replace_hostvar, &valchk, NULL, NULL);
6019  if ((pinfo->info.partition.type == PT_PARTITION_RANGE)
6020  && parts->info.parts.values->type_enum == PT_TYPE_NULL)
6021  {
6023  parts->info.parts.name->info.name.original);
6024 
6025  goto pvl_free_end;
6026  }
6027  }
6028 
6029  valchk = pt_check_partition_values (parser, expr_type->type_enum, expr_type->data_type, &vlinks, parts);
6030  if (valchk != NO_ERROR)
6031  {
6032  goto pvl_free_end;
6033  }
6034 
6035  for (fpart = parts->next; fpart && fpart->node_type == PT_PARTS; fpart = fpart->next)
6036  {
6038  fpart->info.parts.name->info.name.original))
6039  {
6041  fpart->info.parts.name->info.name.original);
6042 
6043  goto pvl_free_end;
6044  }
6045  }
6046 
6047  /* check value increasing for range partition */
6048  if (pinfo->info.partition.type == PT_PARTITION_RANGE)
6049  {
6050  error = pt_check_range_partition_strict_increasing (parser, stmt, parts, parts->next, NULL);
6051  if (error != NO_ERROR)
6052  {
6053  assert (pt_has_error (parser));
6054 
6055  goto pvl_free_end;
6056  }
6057  }
6058 
6059  parts_cnt++;
6060  }
6061 
6062  if (parts_cnt > MAX_PARTITIONS)
6063  {
6065  }
6066  else if (chkflag)
6067  {
6069  }
6070  }
6071 
6072 pvl_free_end:
6073 
6074  pvl = vlinks.next;
6075  while (pvl)
6076  {
6077  delpvl = pvl;
6078  pvl = pvl->next;
6079  free_and_init (delpvl);
6080  }
6081 }
6082 
6083 /*
6084  * partition_range_min_max () - find min/max value
6085  * return: 0-process, 1-duplicate
6086  * dest(in/out): min or max value
6087  * inval(in): input value
6088  * min_max(in): RANGE_MIN, RANGE_MAX
6089  *
6090  * Note :
6091  * check that
6092  * - stmt's expression have an attribute
6093  * - expression's attribute is not set nor object type
6094  * - partition type is equals to partition definitions
6095  * - partition max
6096  * - valid hash size
6097  */
6098 static int
6099 partition_range_min_max (DB_VALUE ** dest, DB_VALUE * inval, int min_max)
6100 {
6101  int op, rst;
6102  DB_VALUE nullval;
6103 
6104  if (dest == NULL)
6105  {
6106  return 0;
6107  }
6108 
6109  if (inval == NULL)
6110  {
6111  db_make_null (&nullval);
6112  inval = &nullval;
6113  }
6114 
6115  if (DB_IS_NULL (inval))
6116  { /* low or high infinite */
6117  if (*dest != NULL)
6118  {
6119  if (DB_IS_NULL (*dest))
6120  {
6121  return 1;
6122  }
6123  pr_free_ext_value (*dest);
6124  }
6125  *dest = db_value_copy (inval);
6126  return 0;
6127  }
6128 
6129  if (*dest == NULL)
6130  {
6131  *dest = db_value_copy (inval);
6132  }
6133  else
6134  {
6135  if (DB_IS_NULL (*dest))
6136  { /* low or high infinite */
6137  if (DB_IS_NULL (inval))
6138  {
6139  return 1;
6140  }
6141  else
6142  {
6143  return 0;
6144  }
6145  }
6146  op = (min_max == RANGE_MIN) ? DB_GT : DB_LT;
6147  rst = db_value_compare (*dest, inval);
6148  if (rst == op)
6149  {
6150  pr_free_ext_value (*dest);
6151  *dest = db_value_copy (inval);
6152  }
6153  else if (rst == DB_EQ)
6154  {
6155  return 1;
6156  }
6157  }
6158 
6159  return 0;
6160 }
6161 
6162 /*
6163  * db_value_list_add () -
6164  * return:
6165  * ptail(out):
6166  * val(in):
6167  */
6168 static int
6170 {
6171  DB_VALUE_PLIST *tmp_vallist;
6172  DB_VALUE nullval, *chkval;
6173 
6174  if (ptail == NULL)
6175  {
6176  return -1;
6177  }
6178 
6179  if (val == NULL)
6180  {
6181  db_make_null (&nullval);
6182  chkval = &nullval;
6183  }
6184  else
6185  {
6186  chkval = val;
6187  }
6188 
6189  tmp_vallist = (DB_VALUE_PLIST *) malloc (sizeof (DB_VALUE_PLIST));
6190  if (tmp_vallist == NULL)
6191  {
6192  return -1;
6193  }
6194 
6195  if (*ptail == NULL)
6196  {
6197  *ptail = tmp_vallist;
6198  }
6199  else
6200  {
6201  (*ptail)->next = tmp_vallist;
6202  *ptail = tmp_vallist;
6203  }
6204 
6205  (*ptail)->next = NULL;
6206  (*ptail)->val = db_value_copy (chkval);
6207 
6208  return 0;
6209 }
6210 
6211 /*
6212  * db_value_list_find () -
6213  * return:
6214  * phead(in):
6215  * val(in):
6216  */
6217 static int
6219 {
6220  DB_VALUE_PLIST *tmp;
6221  DB_VALUE nullval, *chkval;
6222 
6223  if (phead == NULL)
6224  {
6225  return 0;
6226  }
6227 
6228  if (val == NULL)
6229  {
6230  db_make_null (&nullval);
6231  chkval = &nullval;
6232  }
6233  else
6234  {
6235  chkval = (DB_VALUE *) val;
6236  }
6237 
6238  for (tmp = (DB_VALUE_PLIST *) phead; tmp; tmp = tmp->next)
6239  {
6240  if ((DB_IS_NULL (tmp->val) && DB_IS_NULL (chkval)) || db_value_compare (tmp->val, chkval) == DB_EQ)
6241  {
6242  return 1;
6243  }
6244  }
6245 
6246  return 0;
6247 }
6248 
6249 /*
6250  * db_value_list_finddel () -
6251  * return:
6252  * phead(in/out):
6253  * val(in):
6254  */
6255 static int
6257 {
6258  DB_VALUE_PLIST *tmp, *pre = NULL;
6259  DB_VALUE nullval, *chkval;
6260 
6261  if (phead == NULL)
6262  {
6263  return 0;
6264  }
6265 
6266  if (val == NULL)
6267  {
6268  db_make_null (&nullval);
6269  chkval = &nullval;
6270  }
6271  else
6272  {
6273  chkval = val;
6274  }
6275 
6276  for (tmp = *phead; tmp; tmp = tmp->next)
6277  {
6278  if ((DB_IS_NULL (tmp->val) && DB_IS_NULL (chkval)) || db_value_compare (tmp->val, chkval) == DB_EQ)
6279  {
6280  if (pre == NULL)
6281  {
6282  *phead = tmp->next;
6283  }
6284  else
6285  {
6286  pre->next = tmp->next;
6287  }
6288 
6289  pr_free_ext_value (tmp->val);
6290  free_and_init (tmp);
6291 
6292  return 1;
6293  }
6294  pre = tmp;
6295  }
6296 
6297  return 0;
6298 }
6299 
6300 /*
6301  * pt_check_alter_partition () - do semantic checks on a alter partition clause
6302  * return: none
6303  * parser(in): the parser context used to derive the statement
6304  * stmt(in): a alter class statement
6305  * dbobj(in):
6306  *
6307  * Note :
6308  * check that
6309  * - partition type is equals to original partition definitions
6310  * - partition min/max
6311  */
6312 
6313 static void
6315 {
6316  PT_NODE *name_list, *part_list;
6317  PT_NODE *names, *parts, *val, *next_parts;
6318  PT_ALTER_CODE cmd;
6319  SM_CLASS *smclass, *subcls;
6320  DB_OBJLIST *objs;
6321  int i, setsize;
6322  int orig_cnt = 0, name_cnt = 0, parts_cnt = 0, chkflag = 0;
6323  DB_VALUE *psize;
6324  char *class_name, *part_name;
6325  DB_VALUE minele, maxele, *minval = NULL, *maxval = NULL;
6326  DB_VALUE *parts_val, *partmin = NULL, *partmax = NULL;
6327  DB_VALUE null_val;
6328  DB_VALUE_PLIST *minmax_head = NULL, *minmax_tail = NULL;
6329  DB_VALUE_PLIST *outlist_head = NULL, *outlist_tail = NULL;
6330  DB_VALUE_PLIST *inlist_head = NULL, *inlist_tail = NULL;
6331  DB_VALUE_PLIST *min_list, *max_list;
6332  DB_VALUE_PLIST *p, *next;
6333  PT_NODE *column_dt = NULL;
6334  PARSER_CONTEXT *tmp_parser = NULL;
6335  PT_NODE **statements = NULL;
6336  const char *expr_sql = NULL;
6337  int error = NO_ERROR;
6338 
6339  assert (parser != NULL);
6340 
6341  if (stmt == NULL)
6342  {
6343  return;
6344  }
6345 
6346  db_make_null (&minele);
6347  db_make_null (&maxele);
6348  db_make_null (&null_val);
6349 
6350  class_name = (char *) stmt->info.alter.entity_name->info.name.original;
6351  cmd = stmt->info.alter.code;
6352  if (cmd == PT_DROP_PARTITION || cmd == PT_ANALYZE_PARTITION || cmd == PT_REORG_PARTITION
6353  || cmd == PT_PROMOTE_PARTITION)
6354  {
6355  name_list = stmt->info.alter.alter_clause.partition.name_list;
6356  }
6357  else
6358  {
6359  name_list = NULL;
6360  }
6361 
6362  if (0 < parser->host_var_count)
6363  {
6365  return;
6366  }
6367 
6368  if (cmd == PT_ADD_HASHPARTITION || cmd == PT_COALESCE_PARTITION)
6369  {
6370  psize = pt_value_to_db (parser, stmt->info.alter.alter_clause.partition.size);
6371  }
6372  else
6373  {
6374  psize = NULL;
6375  }
6376 
6377  if (cmd == PT_ADD_PARTITION || cmd == PT_REORG_PARTITION)
6378  {
6379  part_list = stmt->info.alter.alter_clause.partition.parts;
6380  }
6381  else
6382  {
6383  part_list = NULL;
6384  }
6385 
6386  switch (cmd)
6387  { /* parameter check */
6388  case PT_DROP_PARTITION: /* name_list */
6389  case PT_PROMOTE_PARTITION:
6390  if (name_list == NULL)
6391  {
6392  chkflag = 1;
6393  }
6394  break;
6395  case PT_ANALYZE_PARTITION: /* NULL = ALL */
6396  break;
6397  case PT_ADD_PARTITION: /* parts */
6398  if (part_list == NULL)
6399  {
6400  chkflag = 1;
6401  }
6402  break;
6403  case PT_ADD_HASHPARTITION: /* psize */
6404  case PT_COALESCE_PARTITION: /* psize */
6405  if (psize == NULL)
6406  {
6407  chkflag = 1;
6408  }
6409  break;
6410  case PT_REORG_PARTITION: /* name_list, parts */
6411  if (name_list == NULL || part_list == NULL)
6412  {
6413  chkflag = 1;
6414  }
6415  break;
6416  default:
6417  chkflag = 1;
6418  break;
6419  }
6420 
6421  if (chkflag)
6422  {
6425  return;
6426  }
6427 
6428  /* get partition information : count, name, type */
6429  if (au_fetch_class (dbobj, &smclass, AU_FETCH_READ, AU_SELECT) != NO_ERROR || smclass->partition == NULL)
6430  {
6432  class_name);
6433  return;
6434  }
6435 
6436  if (smclass->partition->partition_type != PT_PARTITION_HASH)
6437  {
6438  PT_NODE *select_list;
6439 
6440  tmp_parser = parser_create_parser ();
6441  if (tmp_parser == NULL)
6442  {
6443  assert (er_errid () != NO_ERROR);
6444 
6445  goto check_end;
6446  }
6447 
6448  /* get partition expr */
6449  expr_sql = smclass->partition->expr;
6450 
6451  /* compile the select statement and get the correct data_type */
6452  statements = parser_parse_string (tmp_parser, expr_sql);
6453  if (statements == NULL)
6454  {
6455  if (er_errid () == NO_ERROR)
6456  {
6458  }
6459 
6460  goto check_end;
6461  }
6462 
6463  statements[0] = pt_compile (tmp_parser, statements[0]);
6464  if (statements[0] == NULL)
6465  {
6466  if (er_errid () == NO_ERROR)
6467  {
6469  }
6470 
6471  goto check_end;
6472  }
6473 
6474  assert (statements[0]->node_type == PT_SELECT && statements[0]->info.query.q.select.list != NULL);
6475 
6476  select_list = statements[0]->info.query.q.select.list;
6477  if (select_list->data_type != NULL)
6478  {
6479  column_dt = parser_copy_tree (parser, select_list->data_type);
6480  }
6481  else
6482  {
6483  column_dt = pt_domain_to_data_type (parser,
6485  }
6486 
6487  parser_free_parser (tmp_parser);
6488  tmp_parser = NULL;
6489  }
6490 
6491  chkflag = 0;
6492  switch (cmd)
6493  { /* possible action check */
6494  case PT_DROP_PARTITION: /* RANGE/LIST */
6495  case PT_ADD_PARTITION:
6496  case PT_REORG_PARTITION:
6497  case PT_PROMOTE_PARTITION:
6498  if (smclass->partition->partition_type == PT_PARTITION_HASH)
6499  {
6500  chkflag = 1;
6501  }
6502  break;
6503 
6504  case PT_ANALYZE_PARTITION: /* ALL */
6505  break;
6506 
6507  case PT_ADD_HASHPARTITION: /* HASH */
6508  case PT_COALESCE_PARTITION:
6509  if (smclass->partition->partition_type != PT_PARTITION_HASH)
6510  {
6511  chkflag = 1;
6512  }
6513  break;
6514 
6515  default:
6516  break;
6517  }
6518 
6519  if (chkflag)
6520  {
6523  goto check_end;
6524  }
6525 
6526  db_make_null (&null_val);
6527  for (objs = smclass->users; objs; objs = objs->next)
6528  {
6529  if (au_fetch_class (objs->op, &subcls, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
6530  {
6531  PT_ERRORc (parser, stmt, er_msg ());
6532  goto check_end;
6533  }
6534 
6535  if (!subcls->partition)
6536  {
6537  continue; /* not partitioned */
6538  }
6539 
6540  orig_cnt++;
6541 
6542  db_make_null (&minele);
6543  db_make_null (&maxele);
6544 
6545  if (psize == NULL)
6546  { /* RANGE or LIST */
6547  if (subcls->partition == NULL || subcls->partition->pname == NULL)
6548  {
6549  /* get partition type */
6550  goto invalid_partition_info_fail;
6551  }
6552 
6554  && cmd != PT_PROMOTE_PARTITION)
6555  {
6556  if (set_get_element_nocopy (subcls->partition->values, 0, &minele) != NO_ERROR)
6557  {
6558  goto invalid_partition_info_fail; /* RANGE MIN */
6559  }
6560  if (set_get_element_nocopy (subcls->partition->values, 1, &maxele) != NO_ERROR)
6561  {
6562  goto invalid_partition_info_fail; /* RANGE MAX */
6563  }
6564 
6565  /* MAX VALUE find for ADD PARTITION */
6566  if (cmd == PT_ADD_PARTITION)
6567  {
6568  partition_range_min_max (&maxval, &maxele, RANGE_MAX);
6569  }
6570  }
6571 
6572  for (names = name_list, chkflag = 0; names; names = names->next)
6573  {
6574  if (!names->flag.partition_pruned
6575  && !intl_identifier_casecmp (names->info.name.original, subcls->partition->pname))
6576  {
6577  chkflag = 1;
6578  names->flag.partition_pruned = 1; /* existence marking */
6579  names->info.name.db_object = objs->op;
6580 
6582  {
6583  partition_range_min_max (&maxval, &maxele, RANGE_MAX);
6584  partition_range_min_max (&minval, &minele, RANGE_MIN);
6585  }
6586 
6587  if (smclass->partition->partition_type == DB_PARTITION_LIST && cmd == PT_REORG_PARTITION)
6588  {
6589  setsize = set_size (subcls->partition->values);
6590  for (i = 0; i < setsize; i++)
6591  { /* in-list old value */
6592  if (set_get_element_nocopy (subcls->partition->values, i, &minele) != NO_ERROR)
6593  {
6594  goto invalid_partition_info_fail;
6595  }
6596 
6597  if (db_value_list_add (&inlist_tail, &minele))
6598  {
6599  goto out_of_mem_fail;
6600  }
6601 
6602  if (inlist_head == NULL)
6603  {
6604  inlist_head = inlist_tail;
6605  }
6606  }
6607  }
6608  }
6609  }
6610 
6611  if (chkflag == 0)
6612  {
6613  if (smclass->partition->partition_type == DB_PARTITION_LIST)
6614  {
6615  setsize = set_size (subcls->partition->values);
6616  for (i = 0; i < setsize; i++)
6617  { /* out-list value */
6618  if (set_get_element_nocopy (subcls->partition->values, i, &minele) != NO_ERROR)
6619  {
6620  goto invalid_partition_info_fail;
6621  }
6622 
6623  if (db_value_list_add (&outlist_tail, &minele))
6624  {
6625  goto out_of_mem_fail;
6626  }
6627 
6628  if (outlist_head == NULL)
6629  {
6630  outlist_head = outlist_tail;
6631  }
6632  }
6633  }
6634  else if (smclass->partition->partition_type == DB_PARTITION_RANGE && cmd == PT_REORG_PARTITION)
6635  {
6636  /* for non-continuous or overlap ranges check */
6637  if (db_value_list_add (&minmax_tail, &minele))
6638  {
6639  goto out_of_mem_fail;
6640  }
6641 
6642  if (minmax_head == NULL)
6643  {
6644  minmax_head = minmax_tail;
6645  }
6646 
6647  if (db_value_list_add (&minmax_tail, &maxele))
6648  {
6649  goto out_of_mem_fail;
6650  }
6651  }
6652  }
6653 
6654 
6655  for (parts = part_list; parts; parts = parts->next)
6656  {
6657  if (!parts->flag.partition_pruned
6659  {
6660  parts->flag.partition_pruned = 1; /* existence marking */
6661  }
6662  }
6663  }
6664  }
6665 
6666  if (name_list)
6667  { /* checks unknown partition */
6668  for (names = name_list; names; names = names->next)
6669  {
6670  if (!names->flag.partition_pruned)
6671  {
6673  names->info.name.original);
6674  goto check_end;
6675  }
6676  name_cnt++;
6677  }
6678  }
6679 
6680  if (part_list)
6681  { /* checks duplicated definition */
6682  for (parts = part_list; parts; parts = parts->next)
6683  {
6684  if (smclass->partition->partition_type != (int) parts->info.parts.type)
6685  {
6687  parts->info.parts.name->info.name.original);
6688  goto check_end;
6689  }
6690 
6691  /* next part */
6692  next_parts = parts->next;
6693  if (next_parts != NULL && smclass->partition->partition_type != (int) next_parts->info.parts.type)
6694  {
6696  next_parts->info.parts.name->info.name.original);
6697  goto check_end;
6698  }
6699 
6700  part_name = (char *) parts->info.parts.name->info.name.original;
6701  if (parts->info.parts.values)
6702  {
6703  parts->info.parts.values =
6704  parser_walk_tree (parser, parts->info.parts.values, pt_check_and_replace_hostvar, &chkflag, NULL, NULL);
6705  if (parts->info.parts.type == PT_PARTITION_RANGE && parts->info.parts.values->type_enum == PT_TYPE_NULL)
6706  {
6708  part_name);
6709  goto check_end;
6710  }
6711  }
6712 
6713  if (smclass->partition->partition_type == PT_PARTITION_RANGE)
6714  {
6715  /* corece the partition value */
6716  val = parts->info.parts.values;
6717 
6718  if (val != NULL)
6719  {
6720  error = pt_coerce_partition_value_with_data_type (parser, val, column_dt);
6721  if (error != NO_ERROR)
6722  {
6724 
6725  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error, part_name);
6726 
6727  goto check_end;
6728  }
6729  }
6730 
6731  /* check strict increasing rule */
6732  error = pt_check_range_partition_strict_increasing (parser, stmt, parts, next_parts, column_dt);
6733  if (error != NO_ERROR)
6734  {
6735  assert (pt_has_error (parser));
6736 
6737  goto check_end;
6738  }
6739 
6740  parts_val = pt_value_to_db (parser, parts->info.parts.values);
6741  if (parts_val == NULL)
6742  {
6743  parts_val = &null_val;
6744  }
6745 
6746  if (db_value_list_find (inlist_head, parts_val))
6747  {
6749  part_name);
6750  goto check_end;
6751  }
6752 
6753  if (db_value_list_add (&inlist_tail, parts_val))
6754  {
6756  goto check_end;
6757  }
6758  if (inlist_head == NULL)
6759  {
6760  inlist_head = inlist_tail;
6761  }
6762 
6763  partition_range_min_max (&partmax, parts_val, RANGE_MAX);
6764  if (!DB_IS_NULL (parts_val))
6765  { /* MAXVALUE */
6766  partition_range_min_max (&partmin, parts_val, RANGE_MIN);
6767  }
6768  }
6769  else
6770  { /* LIST */
6771  for (val = parts->info.parts.values; val && val->node_type == PT_VALUE; val = val->next)
6772  {
6773  error = pt_coerce_partition_value_with_data_type (parser, val, column_dt);
6774  if (error != NO_ERROR)
6775  {
6777  part_name);
6778 
6779  goto check_end;
6780  }
6781 
6782  parts_val = pt_value_to_db (parser, val);
6783  if (parts_val == NULL)
6784  {
6785  parts_val = &null_val;
6786  }
6787 
6788  /* new-list duplicate check */
6789  if (db_value_list_find (minmax_head, parts_val))
6790  {
6792  part_name);
6793  goto check_end;
6794  }
6795 
6796  if (db_value_list_add (&minmax_tail, parts_val))
6797  {
6799  goto check_end;
6800  }
6801  if (minmax_head == NULL)
6802  {
6803  minmax_head = minmax_tail;
6804  }
6805 
6806  /* out-list duplicate check */
6807  if (db_value_list_find (outlist_head, parts_val))
6808  {
6810  part_name);
6811  goto check_end;
6812  }
6813 
6814  /* in-list delete - lost check */
6815  db_value_list_finddel (&inlist_head, parts_val);
6816  }
6817  }
6818 
6819  /* check if has duplicated name in parts_list of itself */
6820  for (next_parts = parts->next; next_parts; next_parts = next_parts->next)
6821  {
6822  if (!intl_identifier_casecmp (next_parts->info.parts.name->info.name.original, part_name))
6823  {
6825  part_name);
6826  goto check_end;
6827  }
6828  }
6829 
6830  parts_cnt++;
6831  if (parts->flag.partition_pruned)
6832  {
6833  if (name_list)
6834  {
6835  for (names = name_list; names; names = names->next)
6836  {
6837  if (!intl_identifier_casecmp (part_name, names->info.name.original))
6838  {
6839  names->flag.partition_pruned = 0;
6840  break; /* REORG partition name reuse */
6841  }
6842  }
6843  if (names != NULL)
6844  {
6845  continue;
6846  }
6847  }
6848 
6850  goto check_end;
6851  }
6852  }
6853  }
6854 
6855  if (psize == NULL)
6856  { /* RANGE or LIST */
6857  orig_cnt = orig_cnt - name_cnt + parts_cnt;
6858  if (cmd != PT_PROMOTE_PARTITION)
6859  {
6860  if (orig_cnt < 1 && cmd == PT_DROP_PARTITION)
6861  {
6863  goto check_end;
6864  }
6865 
6866  if (orig_cnt < 1 || orig_cnt > MAX_PARTITIONS)
6867  {
6869  goto check_end;
6870  }
6871  }
6872 
6873  if (smclass->partition->partition_type == PT_PARTITION_RANGE)
6874  {
6875  if (cmd == PT_ADD_PARTITION)
6876  {
6877  if (DB_IS_NULL (maxval) || (partmin != NULL && db_value_compare (maxval, partmin) != DB_LT))
6878  {
6880  goto check_end;
6881  }
6882 
6883  /* maxval save for do_create_partition */
6884  stmt->info.alter.alter_clause.partition.info = pt_dbval_to_value (parser, maxval);
6885  }
6886  else if (cmd == PT_REORG_PARTITION)
6887  {
6888  if (partmin == NULL)
6889  {
6890  /* reorganizing into one partition with MAXVALUE */
6891  if (parts_cnt != 1)
6892  {
6894  class_name);
6895  goto check_end;
6896  }
6897  }
6898  else if (!DB_IS_NULL (minval) && db_value_compare (partmin, minval) != DB_GT)
6899  {
6900  range_invalid_error:
6902  class_name);
6903  goto check_end;
6904  }
6905  if ((DB_IS_NULL (maxval) && !DB_IS_NULL (partmax))
6906  || (!DB_IS_NULL (maxval) && !DB_IS_NULL (partmax) && db_value_compare (maxval, partmax) == DB_GT))
6907  {
6909  goto check_end;
6910  }
6911 
6912  /* checks non-continuous or overlap ranges */
6913  for (min_list = minmax_head, max_list = (min_list) ? min_list->next : NULL; (min_list && max_list);
6914  min_list = max_list->next, max_list = (min_list) ? min_list->next : NULL)
6915  {
6916  if (DB_IS_NULL (partmax))
6917  { /* new-high infinite */
6918  if (DB_IS_NULL (max_list->val))
6919  {
6920  goto range_invalid_error;
6921  }
6922  continue;
6923  }
6924 
6925  if (DB_IS_NULL (min_list->val))
6926  { /* orig-low infinite */
6927  if (db_value_compare (partmin, max_list->val) != DB_GT)
6928  {
6929  goto range_invalid_error;
6930  }
6931  continue;
6932  }
6933 
6934  if (DB_IS_NULL (max_list->val))
6935  { /* orig-high infinite */
6936  if (db_value_compare (min_list->val, partmax) == DB_LT)
6937  {
6938  goto range_invalid_error;
6939  }
6940  continue;
6941  }
6942 
6943  if ((db_value_compare (minval, min_list->val) != DB_GT
6944  && db_value_compare (min_list->val, partmax) == DB_LT)
6945  || (db_value_compare (minval, max_list->val) == DB_LT
6946  && db_value_compare (max_list->val, partmax) != DB_GT)
6947  || (db_value_compare (min_list->val, minval) != DB_GT
6948  && db_value_compare (minval, max_list->val) == DB_LT)
6949  || (db_value_compare (min_list->val, partmax) == DB_LT
6950  && db_value_compare (partmax, max_list->val) != DB_GT))
6951  {
6952  goto range_invalid_error;
6953  }
6954  }
6955  }
6956  } /* end RANGE */
6957  else
6958  { /* LIST */
6959  if (cmd == PT_REORG_PARTITION && inlist_head != NULL)
6960  {
6962  goto check_end;
6963  }
6964  }
6965  }
6966  else
6967  { /* HASH */
6968  if (cmd == PT_ADD_HASHPARTITION)
6969  {
6970  orig_cnt += psize->data.i;
6971  }
6972  else
6973  {
6974  orig_cnt -= psize->data.i;
6975  }
6976 
6977  if (orig_cnt < 1 || psize->data.i < 1 || orig_cnt > MAX_PARTITIONS)
6978  {
6980  goto check_end;
6981  }
6982  }
6983 
6984 check_end:
6985  if (tmp_parser != NULL)
6986  {
6987  parser_free_parser (tmp_parser);
6988  tmp_parser = NULL;
6989  }
6990 
6991  if (column_dt != NULL)
6992  {
6993  parser_free_tree (parser, column_dt);
6994  column_dt = NULL;
6995  }
6996 
6997  if (maxval)
6998  {
6999  pr_free_ext_value (maxval);
7000  }
7001  if (minval)
7002  {
7003  pr_free_ext_value (minval);
7004  }
7005  if (partmax)
7006  {
7007  pr_free_ext_value (partmax);
7008  }
7009  if (partmin)
7010  {
7011  pr_free_ext_value (partmin);
7012  }
7013 
7014  for (p = minmax_head; p; p = next)
7015  {
7016  next = p->next;
7017  pr_free_ext_value (p->val);
7018  free_and_init (p);
7019  }
7020  for (p = inlist_head; p; p = next)
7021  {
7022  next = p->next;
7023  pr_free_ext_value (p->val);
7024  free_and_init (p);
7025  }
7026  for (p = outlist_head; p; p = next)
7027  {
7028  next = p->next;
7029  pr_free_ext_value (p->val);
7030  free_and_init (p);
7031  }
7032 
7033  return;
7034 
7035 out_of_mem_fail:
7037  goto out_of_mem;
7038 
7039 invalid_partition_info_fail:
7041 
7042 out_of_mem:
7043  pr_clear_value (&minele);
7044  pr_clear_value (&maxele);
7045  goto check_end;
7046 }
7047 
7048 /*
7049  * pt_attr_refers_to_self () - is this a self referencing attribute?
7050  * return: 1 if attr refers to self
7051  * parser(in): the parser context
7052  * attr(in): an attribute
7053  * self(in): name of vclass being created/altered
7054  */
7055 static bool
7056 pt_attr_refers_to_self (PARSER_CONTEXT * parser, PT_NODE * attr, const char *self)
7057 {
7058  PT_NODE *type;
7059  DB_OBJECT *self_obj, *attr_obj;
7060 
7061  if (!attr || attr->type_enum != PT_TYPE_OBJECT || !attr->data_type || attr->data_type->node_type != PT_DATA_TYPE
7062  || !self)
7063  {
7064  return false;
7065  }
7066 
7067  for (type = attr->data_type->info.data_type.entity; type && type->node_type == PT_NAME; type = type->next)
7068  {
7069  /* self is a string because in the create case, self does not exist yet */
7070  if (!intl_identifier_casecmp (self, type->info.name.original))
7071  {
7072  return true;
7073  }
7074 
7075  /* an attribute whose type is a subclass of self is also considered a self-referencing attribute */
7076  self_obj = db_find_class (self);
7077  attr_obj = type->info.name.db_object;
7078  if (self_obj && attr_obj && db_is_subclass (attr_obj, self_obj) > 0)
7079  {
7080  return true;
7081  }
7082  }
7083 
7084  return false;
7085 }
7086 
7087 /*
7088  * pt_is_compatible_type () -
7089  * return: true on compatible type
7090  * arg1_type(in):
7091  * arg2_type(in):
7092  */
7093 static bool
7094 pt_is_compatible_type (const PT_TYPE_ENUM arg1_type, const PT_TYPE_ENUM arg2_type)
7095 {
7096  bool is_compatible = false;
7097  if (arg1_type == arg2_type)
7098  {
7099  is_compatible = true;
7100  }
7101  else
7102  switch (arg1_type)
7103  {
7104  case PT_TYPE_SMALLINT:
7105  case PT_TYPE_INTEGER:
7106  case PT_TYPE_BIGINT:
7107  case PT_TYPE_FLOAT:
7108  case PT_TYPE_DOUBLE:
7109  case PT_TYPE_NUMERIC:
7110  case PT_TYPE_MONETARY:
7111  switch (arg2_type)
7112  {
7113  case PT_TYPE_SMALLINT:
7114  case PT_TYPE_INTEGER:
7115  case PT_TYPE_BIGINT:
7116  case PT_TYPE_FLOAT:
7117  case PT_TYPE_DOUBLE:
7118  case PT_TYPE_NUMERIC:
7119  case PT_TYPE_MONETARY:
7120  case PT_TYPE_LOGICAL: /* logical is compatible with these types */
7121  is_compatible = true;
7122  break;
7123  default:
7124  break;
7125  }
7126  break;
7127  case PT_TYPE_CHAR:
7128  case PT_TYPE_VARCHAR:
7129  switch (arg2_type)
7130  {
7131  case PT_TYPE_CHAR:
7132  case PT_TYPE_VARCHAR:
7133  is_compatible = true;
7134  break;
7135  default:
7136  break;
7137  }
7138  break;
7139  case PT_TYPE_NCHAR:
7140  case PT_TYPE_VARNCHAR:
7141  switch (arg2_type)
7142  {
7143  case PT_TYPE_NCHAR:
7144  case PT_TYPE_VARNCHAR:
7145  is_compatible = true;
7146  break;
7147  default:
7148  break;
7149  }
7150  break;
7151  case PT_TYPE_BIT:
7152  case PT_TYPE_VARBIT:
7153  switch (arg2_type)
7154  {
7155  case PT_TYPE_BIT:
7156  case PT_TYPE_VARBIT:
7157  is_compatible = true;
7158  break;
7159  default:
7160  break;
7161  }
7162  break;
7163  default:
7164  break;
7165  }
7166 
7167  return is_compatible;
7168 }
7169 
7170 /*
7171  * pt_check_vclass_attr_qspec_compatible () -
7172  * return:
7173  * parser(in):
7174  * attr(in):
7175  * col(in):
7176  */
7177 static PT_UNION_COMPATIBLE
7179 {
7180  bool is_object_type;
7181  PT_UNION_COMPATIBLE c = pt_union_compatible (parser, attr, col, true, &is_object_type);
7182 
7183  if (c == PT_UNION_INCOMP && pt_is_compatible_type (attr->type_enum, col->type_enum))
7184  {
7185  c = PT_UNION_COMP;
7186  }
7187 
7188  return c;
7189 }
7190 
7191 /*
7192  * pt_check_vclass_union_spec () -
7193  * return:
7194  * parser(in):
7195  * qry(in):
7196  * attrs(in):
7197  */
7198 static PT_NODE *
7200 {
7201  PT_NODE *attrd = NULL;
7202  PT_NODE *attrs1 = NULL;
7203  PT_NODE *attrs2 = NULL;
7204  PT_NODE *att1 = NULL;
7205  PT_NODE *att2 = NULL;
7206  PT_NODE *result_stmt = NULL;
7207 
7208  /* parser assures us that it's a query but better make sure */
7209  if (!pt_is_query (qry))
7210  {
7211  return NULL;
7212  }
7213 
7214  if (!(qry->node_type == PT_UNION || qry->node_type == PT_DIFFERENCE || qry->node_type == PT_INTERSECTION))
7215  {
7216  assert (qry->node_type == PT_SELECT);
7217  return qry;
7218  }
7219 
7220  result_stmt = pt_check_vclass_union_spec (parser, qry->info.query.q.union_.arg1, attrds);
7221  if (pt_has_error (parser) || result_stmt == NULL)
7222  {
7223  return NULL;
7224  }
7225  result_stmt = pt_check_vclass_union_spec (parser, qry->info.query.q.union_.arg2, attrds);
7226  if (pt_has_error (parser) || result_stmt == NULL)
7227  {
7228  return NULL;
7229  }
7230 
7231  attrs1 = pt_get_select_list (parser, qry->info.query.q.union_.arg1);
7232  if (attrs1 == NULL)
7233  {
7234  return NULL;
7235  }
7236  attrs2 = pt_get_select_list (parser, qry->info.query.q.union_.arg2);
7237  if (attrs2 == NULL)
7238  {
7239  return NULL;
7240  }
7241 
7242  for (attrd = attrds, att1 = attrs1, att2 = attrs2;
7243  attrd != NULL && att1 != NULL && att2 != NULL; attrd = attrd->next, att1 = att1->next, att2 = att2->next)
7244  {
7245  /* bypass any class_attribute in the vclass attribute defs */
7246  if (attrd->info.attr_def.attr_type == PT_META_ATTR)
7247  {
7248  continue;
7249  }
7250 
7251  /* we have a vclass attribute def context, so do union vclass compatibility checks where applicable */
7252  if (attrd->type_enum != PT_TYPE_OBJECT)
7253  {
7254  continue;
7255  }
7256 
7257  if (pt_vclass_compatible (parser, attrd->data_type, att1)
7258  && pt_vclass_compatible (parser, attrd->data_type, att2))
7259  {
7260  continue;
7261  }
7262 
7263  if (!pt_class_assignable (parser, attrd->data_type, att1))
7264  {
7266  attribute_name (parser, attrd), pt_short_print (parser, att1));
7267  return NULL;
7268  }
7269  if (!pt_class_assignable (parser, attrd->data_type, att2))
7270  {
7272  attribute_name (parser, attrd), pt_short_print (parser, att2));
7273  return NULL;
7274  }
7275  }
7276 
7277  assert (attrd == NULL && att1 == NULL && att2 == NULL);
7278 
7279  return qry;
7280 }
7281 
7282 /*
7283  * pt_check_cyclic_reference_in_view_spec () -
7284  * return:
7285  * parser(in):
7286  * node(in):
7287  * arg(in):
7288  * continue_walk(in):
7289  */
7290 PT_NODE *
7291 pt_check_cyclic_reference_in_view_spec (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
7292 {
7293  const char *spec_name = NULL;
7294  PT_NODE *entity_name = NULL;
7295  DB_OBJECT *class_object;
7296  DB_QUERY_SPEC *db_query_spec;
7297  PT_NODE **result;
7298  PT_NODE *query_spec;
7299  const char *query_spec_string;
7300  const char *self = (const char *) arg;
7301  PARSER_CONTEXT *query_cache;
7302 
7303  if (node == NULL)
7304  {
7305  return node;
7306  }
7307 
7308  switch (node->node_type)
7309  {
7310  case PT_SPEC:
7311 
7312  entity_name = node->info.spec.entity_name;
7313  if (entity_name == NULL)
7314  {
7315  return node;
7316  }
7317  if (entity_name->node_type != PT_NAME)
7318  {
7319  return node;
7320  }
7321 
7322  spec_name = pt_get_name (entity_name);
7323  if (pt_str_compare (spec_name, self, CASE_INSENSITIVE) == 0)
7324  {
7326  *continue_walk = PT_STOP_WALK;
7327  return node;
7328  }
7329 
7330  class_object = entity_name->info.name.db_object;
7331  if (db_is_vclass (class_object) <= 0)
7332  {
7333  return node;
7334  }
7335 
7336  query_cache = parser_create_parser ();
7337  if (query_cache == NULL)
7338  {
7339  return node;
7340  }
7341 
7342  db_query_spec = db_get_query_specs (class_object);
7343  while (db_query_spec)
7344  {
7345  query_spec_string = db_query_spec_string (db_query_spec);
7346  result = parser_parse_string_use_sys_charset (query_cache, query_spec_string);
7347 
7348  if (result != NULL)
7349  {
7350  query_spec = *result;
7351  parser_walk_tree (query_cache, query_spec, pt_check_cyclic_reference_in_view_spec, arg, NULL, NULL);
7352  }
7353 
7354  if (pt_has_error (query_cache))
7355  {
7356  PT_ERROR (parser, node, query_cache->error_msgs->info.error_msg.error_message);
7357 
7358  *continue_walk = PT_STOP_WALK;
7359  break;
7360  }
7361 
7362  db_query_spec = db_query_spec_next (db_query_spec);
7363  }
7364  parser_free_parser (query_cache);
7365  break;
7366 
7367  default:
7368  break;
7369  }
7370 
7371  return node;
7372 }
7373 
7374 /*
7375  * pt_check_vclass_query_spec () - do semantic checks on a vclass query spec
7376  * return:
7377  * parser(in): the parser context used to derive the qry
7378  * qry(in): a vclass query specification
7379  * attrs(in): the attributes of the vclass
7380  * self(in): name of vclass being created/altered
7381  *
7382  * Note :
7383  * check that query_spec:
7384  * - count(attrs) == count(columns)
7385  * - corresponding attribute and query_spec column match type-wise
7386  * - query_spec column that corresponds to a shared attribute must be NA
7387  */
7388 
7389 static PT_NODE *
7390 pt_check_vclass_query_spec (PARSER_CONTEXT * parser, PT_NODE * qry, PT_NODE * attrs, const char *self,
7391  const bool do_semantic_check)
7392 {
7393  PT_NODE *columns, *col, *attr;
7394  int col_count, attr_count;
7395 
7396  if (!pt_is_query (qry))
7397  {
7398  return NULL;
7399  }
7400 
7401  if (qry->info.query.into_list != NULL)
7402  {
7404  return NULL;
7405  }
7406 
7407  if (do_semantic_check)
7408  {
7409  qry->flag.do_not_replace_orderby = 1;
7410  qry = pt_semantic_check (parser, qry);
7411  if (pt_has_error (parser) || qry == NULL)
7412  {
7413  return NULL;
7414  }
7415  }
7416 
7417  (void) parser_walk_tree (parser, qry, pt_check_cyclic_reference_in_view_spec, (void *) self, NULL, NULL);
7418  if (pt_has_error (parser))
7419  {
7420  return NULL;
7421  }
7422 
7423  /* count(attrs) == count(query spec columns) */
7424  columns = pt_get_select_list (parser, qry);
7425  col_count = pt_length_of_select_list (columns, EXCLUDE_HIDDEN_COLUMNS);
7426  attr_count = pt_length_of_list (attrs);
7427  if (attr_count != col_count)
7428  {
7429  PT_ERRORmf2 (parser, qry, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_ATT_CNT_NE_COL_CNT, attr_count, col_count);
7430  return NULL;
7431  }
7432 
7433  qry = pt_check_vclass_union_spec (parser, qry, attrs);
7434  if (pt_has_error (parser) || qry == NULL)
7435  {
7436  return NULL;
7437  }
7438 
7439  /* foreach normal/shared attribute and query_spec column do */
7440  for (attr = attrs, col = columns; attr != NULL && col != NULL; attr = attr->next, col = col->next)
7441  {
7442  /* bypass any class_attribute */
7443  if (attr->info.attr_def.attr_type == PT_META_ATTR)
7444  {
7445  attr = attr->next;
7446  continue;
7447  }
7448 
7449  if (col->node_type == PT_HOST_VAR)
7450  {
7452  }
7453  else if (attr->type_enum == PT_TYPE_NONE)
7454  {
7455  if (col->node_type == PT_VALUE && col->type_enum == PT_TYPE_NULL)
7456  {
7458  attribute_name (parser, attr), pt_short_print (parser, col));
7459  }
7460  else
7461  {
7462  pt_fixup_column_type (col);
7463 
7464  attr->type_enum = col->type_enum;
7465  if (col->data_type)
7466  {
7467  attr->data_type = parser_copy_tree_list (parser, col->data_type);
7468  }
7469  }
7470  }
7471  /* attribute and query_spec column must match type-wise */
7472  else if (attr->type_enum == PT_TYPE_OBJECT)
7473  {
7474  if (!pt_attr_refers_to_self (parser, attr, self) && !pt_vclass_compatible (parser, attr->data_type, col)
7475  && !pt_class_assignable (parser, attr->data_type, col))
7476  {
7478  attribute_name (parser, attr), pt_short_print (parser, col));
7479  }
7480  }
7481  else if (PT_IS_COLLECTION_TYPE (attr->type_enum))
7482  {
7483  if (!pt_collection_assignable (parser, attr, col))
7484  {
7486  attribute_name (parser, attr), pt_short_print (parser, col));
7487  }
7488  }
7489  else if (pt_check_vclass_attr_qspec_compatible (parser, attr, col) != PT_UNION_COMP)
7490  {
7492  attribute_name (parser, attr), pt_short_print (parser, col));
7493  }
7494 
7495  /* any shared attribute must correspond to NA in the query_spec */
7496  if (is_shared_attribute (parser, attr) && col->type_enum != PT_TYPE_NA && col->type_enum != PT_TYPE_NULL)
7497  {
7499  attribute_name (parser, attr));
7500  }
7501  }
7502 
7503  return qry;
7504 }
7505 
7506 /*
7507  * pt_type_cast_vclass_query_spec_column () -
7508  * return: current or new column
7509  * parser(in): the parser context used to derive the qry
7510  * attr(in): the attributes of the vclass
7511  * col(in): the query_spec column of the vclass
7512  */
7513 
7514 PT_NODE *
7516 {
7517  bool is_object_type;
7519  PT_NODE *new_col, *new_dt, *next_col;
7520 
7521  /* guarantees PT_TYPE_OBJECT and SET types are fully compatible. */
7522  if (attr->type_enum == PT_TYPE_OBJECT || PT_IS_COLLECTION_TYPE (attr->type_enum))
7523  {
7524  return col;
7525  }
7526 
7527  c = pt_union_compatible (parser, attr, col, true, &is_object_type);
7528  if (((c == PT_UNION_COMP)
7529  && (attr->type_enum == col->type_enum && PT_IS_PARAMETERIZED_TYPE (attr->type_enum) && attr->data_type
7530  && col->data_type)
7533  || (c == PT_UNION_INCOMP))
7534  {
7535  /* rewrite */
7536  next_col = col->next;
7537  col->next = NULL;
7538  new_col = new_dt = NULL;
7539 
7540  new_col = parser_new_node (parser, PT_EXPR);
7541  if (new_col == NULL)
7542  {
7544  return col; /* give up */
7545  }
7546 
7547  new_dt = parser_new_node (parser, PT_DATA_TYPE);
7548  if (new_dt == NULL)
7549  {
7551  parser_free_tree (parser, new_col);
7552  return col; /* give up */
7553  }
7554 
7555  /* move alias */
7556  new_col->line_number = col->line_number;
7557  new_col->column_number = col->column_number;
7558  new_col->alias_print = col->alias_print;
7559  col->alias_print = NULL;
7560  new_dt->type_enum = attr->type_enum;
7561  if (attr->data_type)
7562  {
7565  new_dt->info.data_type.units = attr->data_type->info.data_type.units;
7567  assert (new_dt->info.data_type.collation_id >= 0);
7568  new_dt->info.data_type.enumeration =
7570  }
7571  new_col->type_enum = new_dt->type_enum;
7572  new_col->info.expr.op = PT_CAST;
7573  new_col->info.expr.cast_type = new_dt;
7574  new_col->info.expr.arg1 = col;
7575  new_col->next = next_col;
7576  new_col->data_type = parser_copy_tree_list (parser, new_dt);
7578  col = new_col;
7579  }
7580 
7581  return col;
7582 }
7583 
7584 /*
7585  * pt_type_cast_vclass_query_spec () -
7586  * return:
7587  * parser(in):
7588  * qry(in):
7589  * attrs(in):
7590  */
7591 static PT_NODE *
7593 {
7594  PT_NODE *columns, *col, *attr;
7595  PT_NODE *new_col, *prev_col;
7596  PT_NODE *node_list;
7597 
7598  /* parser assures us that it's a query but better make sure */
7599  if (!pt_is_query (qry))
7600  {
7601  return NULL;
7602  }
7603 
7604  if (qry->node_type != PT_SELECT)
7605  {
7606  if (!pt_type_cast_vclass_query_spec (parser, qry->info.query.q.union_.arg1, attrs) || pt_has_error (parser)
7607  || (!pt_type_cast_vclass_query_spec (parser, qry->info.query.q.union_.arg2, attrs)) || pt_has_error (parser))
7608  {
7609  return NULL;
7610  }
7611  }
7612 
7613  if (qry->node_type != PT_SELECT)
7614  {
7615  return qry; /* already done */
7616  }
7617 
7618  if (PT_IS_VALUE_QUERY (qry))
7619  {
7620  for (node_list = qry->info.query.q.select.list; node_list != NULL; node_list = node_list->next)
7621  {
7622  assert (node_list->node_type == PT_NODE_LIST);
7623 
7624  columns = node_list->info.node_list.list;
7625 
7626  col = columns;
7627  attr = attrs;
7628  prev_col = NULL;
7629 
7630  while (attr != NULL && col != NULL)
7631  {
7632  /* skip class attribute */
7633  if (attr->info.attr_def.attr_type == PT_META_ATTR)
7634  {
7635  attr = attr->next;
7636  continue;
7637  }
7638 
7639  new_col = pt_type_cast_vclass_query_spec_column (parser, attr, col);
7640  if (new_col != col)
7641  {
7642  if (prev_col == NULL)
7643  {
7644  node_list->info.node_list.list = new_col;
7645  qry->type_enum = new_col->type_enum;
7646  if (qry->data_type)
7647  {
7648  parser_free_tree (parser, qry->data_type);
7649  }
7650  qry->data_type = parser_copy_tree_list (parser, new_col->data_type);
7651  }
7652  else
7653  {
7654  prev_col->next = new_col;
7655  }
7656 
7657  col = new_col;
7658  }
7659 
7660  prev_col = col;
7661  col = col->next;
7662  attr = attr->next;
7663  }
7664  }
7665  }
7666  else
7667  {
7668 
7669  columns = pt_get_select_list (parser, qry);
7670 
7671  /* foreach normal/shared attribute and query_spec column do */
7672  attr = attrs;
7673  col = columns;
7674  prev_col = NULL;
7675 
7676  while (attr && col)
7677  {
7678  /* bypass any class_attribute */
7679  if (attr->info.attr_def.attr_type == PT_META_ATTR)
7680  {
7681  attr = attr->next;
7682  continue;
7683  }
7684 
7685  new_col = pt_type_cast_vclass_query_spec_column (parser, attr, col);
7686  if (new_col != col)
7687  {
7688  if (prev_col == NULL)
7689  {
7690  qry->info.query.q.select.list = new_col;
7691  qry->type_enum = new_col->type_enum;
7692  if (qry->data_type)
7693  {
7694  parser_free_tree (parser, qry->data_type);
7695  }
7696  qry->data_type = parser_copy_tree_list (parser, new_col->data_type);
7697  }
7698  else
7699  {
7700  prev_col->next = new_col;
7701  }
7702 
7703  col = new_col;
7704  }
7705 
7706  /* save previous link */
7707  prev_col = col;
7708  /* advance to next attribute and column */
7709  attr = attr->next;
7710  col = col->next;
7711  }
7712  }
7713 
7714  return qry;
7715 }
7716 
7717 /*
7718  * pt_check_default_vclass_query_spec () -
7719  * return: new attrs node including default values
7720  * parser(in):
7721  * qry(in):
7722  * attrs(in):
7723  *
7724  * For all those view attributes that don't have implicit default values,
7725  * copy the default values from the original table
7726  *
7727  * NOTE: there are two ways attrs is constructed at this point:
7728  * - stmt: create view (attr_list) as select... and the attrs will be created directly from the statement
7729  * - stmt: create view as select... and the attrs will be created from the query's select list
7730  * In both cases, each attribute in attrs will correspond to the column in the select list at the same index
7731  */
7732 static PT_NODE *
7734 {
7735  PT_NODE *attr, *col;
7736  PT_NODE *columns = pt_get_select_list (parser, qry);
7737  PT_NODE *default_data = NULL;
7738  PT_NODE *default_value = NULL, *default_op_value = NULL;
7739  PT_NODE *spec, *entity_name;
7740  DB_OBJECT *obj;
7741  DB_ATTRIBUTE *col_attr;
7742  const char *lang_str;
7743  int flag = 0;
7744  bool has_user_format;
7745 
7746  /* Import default value and on update default expr from referenced table
7747  * for those attributes in the the view that don't have them. */
7748  for (attr = attrs, col = columns; attr && col; attr = attr->next, col = col->next)
7749  {
7751  {
7752  /* default values are overwritten */
7753  continue;
7754  }
7755  if (col->node_type != PT_NAME)
7756  {
7757  continue;
7758  }
7759  if (col->info.name.spec_id == 0)
7760  {
7761  continue;
7762  }
7763 
7764  spec = (PT_NODE *) col->info.name.spec_id;
7765  entity_name = spec->info.spec.entity_name;
7766  if (entity_name == NULL || !PT_IS_NAME_NODE (entity_name))
7767  {
7768  continue;
7769  }
7770 
7771  obj = entity_name->info.name.db_object;
7772  if (obj == NULL)
7773  {
7774  continue;
7775  }
7776 
7777  col_attr = db_get_attribute_force (obj, col->info.name.original);
7778  if (col_attr == NULL)
7779  {
7780  continue;
7781  }
7782 
7783  if (attr->info.attr_def.on_update == DB_DEFAULT_NONE)
7784  {
7785  attr->info.attr_def.on_update = col_attr->on_update_default_expr;
7786  }
7787 
7788  if (attr->info.attr_def.data_default == NULL)
7789  {
7790  if (DB_IS_NULL (&col_attr->default_value.value)
7792  {
7793  /* don't create any default node if default value is null unless default expression type is not
7794  * DB_DEFAULT_NONE */
7795  continue;
7796  }
7797 
7799  {
7800  default_value = pt_dbval_to_value (parser, &col_attr->default_value.value);
7801  if (default_value == NULL)
7802  {
7804  goto error;
7805  }
7806 
7807  default_data = parser_new_node (parser, PT_DATA_DEFAULT);
7808  if (default_data == NULL)
7809  {
7810  parser_free_tree (parser, default_value);
7812  goto error;
7813  }
7814  default_data->info.data_default.default_value = default_value;
7815  default_data->info.data_default.shared = PT_DEFAULT;
7817  }
7818  else
7819  {
7820  default_op_value = parser_new_node (parser, PT_EXPR);
7821  if (default_op_value == NULL)
7822  {
7824  goto error;
7825  }
7826 
7827  default_op_value->info.expr.op =
7829 
7831  {
7832  default_value = default_op_value;
7833  }
7834  else
7835  {
7836  PT_NODE *arg1, *arg2, *arg3;
7837 
7838  arg1 = default_op_value;
7839  has_user_format = col_attr->default_value.default_expr.default_expr_format ? 1 : 0;
7841  if (arg2 == NULL)
7842  {
7843  parser_free_tree (parser, default_op_value);
7845  goto error;
7846  }
7847 
7848  arg3 = parser_new_node (parser, PT_VALUE);
7849  if (arg3 == NULL)
7850  {
7851  parser_free_tree (parser, default_op_value);
7852  parser_free_tree (parser, arg2);
7853  }
7854  arg3->type_enum = PT_TYPE_INTEGER;
7856  lang_set_flag_from_lang (lang_str, has_user_format, 0, &flag);
7857  arg3->info.value.data_value.i = (long) flag;
7858 
7859  default_value = parser_make_expression (parser, PT_TO_CHAR, arg1, arg2, arg3);
7860  if (default_value == NULL)
7861  {
7862  parser_free_tree (parser, default_op_value);
7863  parser_free_tree (parser, arg2);
7864  parser_free_tree (parser, arg3);
7866  goto error;
7867  }
7868  }
7869 
7870  default_data = parser_new_node (parser, PT_DATA_DEFAULT);
7871  if (default_data == NULL)
7872  {
7873  parser_free_tree (parser, default_value);
7875  goto error;
7876  }
7877 
7878  default_data->info.data_default.default_value = default_value;
7879  default_data->info.data_default.shared = PT_DEFAULT;
7880  default_data->info.data_default.default_expr_type =
7882  }
7883 
7884  attr->info.attr_def.data_default = default_data;
7885  }
7886  }
7887 
7888  return attrs;
7889 
7890 error:
7891  parser_free_tree (parser, attrs);
7892  return NULL;
7893 }
7894 
7895 /*
7896  * pt_check_create_view () - do semantic checks on a create vclass statement
7897  * or an "ALTER VIEW AS SELECT" statement
7898  *
7899  * return: none
7900  * parser(in): the parser context used to derive the statement
7901  * stmt(in): a create vclass statement
7902  *
7903  * Note :
7904  * This function is also called when doing "ALTER VIEW xxx AS SELECT ...",
7905  * which is a simplified case, since it does not support class inheritance.
7906  *
7907  * check that
7908  * - stmt's query_specs are union compatible with each other
7909  * - if no attributes are given, derive them from the query_spec columns
7910  * - if an attribute has no data type then derive it from its
7911  * matching query_spec column
7912  * - corresponding attribute and query_spec column must match type-wise
7913  * - count(attributes) == count(query_spec columns)
7914  * - query_spec column that corresponds to a shared attribute must be NA
7915  * - we allow order by clauses in the queries
7916  */
7917 
7918 static void
7920 {
7921  PT_NODE *all_attrs = NULL;
7922  PT_NODE *derived_attr = NULL;
7923  PT_NODE *result_stmt = NULL;
7924  PT_NODE **qry_specs_ptr = NULL;
7925  PT_NODE *crt_qry = NULL;
7926  PT_NODE **prev_qry_link_ptr = NULL;
7927  PT_NODE **attr_def_list_ptr = NULL;
7928  PT_NODE *prev_qry;
7929  const char *name = NULL;
7930  int attr_count = 0;
7931 
7932  assert (parser != NULL);
7933 
7934  if (stmt == NULL)
7935  {
7936  return;
7937  }
7938  if (stmt->node_type == PT_CREATE_ENTITY)
7939  {
7941  {
7942  return;
7943  }
7944  }
7945  else if ((stmt->node_type == PT_ALTER) && (stmt->info.alter.code == PT_RESET_QUERY))
7946  {
7947  if (stmt->info.alter.entity_type != PT_VCLASS || stmt->info.alter.entity_name == NULL)
7948  {
7949  return;
7950  }
7951  }
7952  else
7953  {
7954  return;
7955  }
7956 
7957 
7958  if (stmt->node_type == PT_CREATE_ENTITY)
7959  {
7961  qry_specs_ptr = &stmt->info.create_entity.as_query_list;
7962  attr_def_list_ptr = &stmt->info.create_entity.attr_def_list;
7963  }
7964  else
7965  {
7966  assert ((stmt->node_type == PT_ALTER) && (stmt->info.alter.code == PT_RESET_QUERY));
7967  name = stmt->info.alter.entity_name->info.name.original;
7968  qry_specs_ptr = &stmt->info.alter.alter_clause.query.query;
7969  attr_def_list_ptr = &stmt->info.alter.alter_clause.query.attr_def_list;
7970  }
7971 
7972  if (*qry_specs_ptr == NULL || pt_has_error (parser))
7973  {
7974  return;
7975  }
7976 
7977  prev_qry = NULL;
7978  for (crt_qry = *qry_specs_ptr, prev_qry_link_ptr = qry_specs_ptr; crt_qry != NULL;
7979  prev_qry_link_ptr = &crt_qry->next, crt_qry = crt_qry->next)
7980  {
7981  PT_NODE *const save_next = crt_qry->next;
7982 
7983  crt_qry->next = NULL;
7984 
7985  /* TODO This seems to flag too many queries as view specs because it also traverses the tree to subqueries. It
7986  * might need a pre_function that returns PT_STOP_WALK for subqueries. */
7987  result_stmt = parser_walk_tree (parser, crt_qry, pt_set_is_view_spec, NULL, NULL, NULL);
7988  if (result_stmt == NULL)
7989  {
7990  assert (false);
7991  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
7992  return;
7993  }
7994  crt_qry = result_stmt;
7995 
7996  crt_qry->flag.do_not_replace_orderby = 1;
7997  result_stmt = pt_semantic_check (parser, crt_qry);
7998  if (pt_has_error (parser))
7999  {
8000  if (prev_qry)
8001  {
8002  prev_qry->next = save_next;
8003  }
8004  crt_qry = NULL;
8005  (*prev_qry_link_ptr) = crt_qry;
8006  return;
8007  }
8008 
8009  if (result_stmt == NULL)
8010  {
8011  assert (false);
8012  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
8013  return;
8014  }
8015 
8016  if (pt_has_parameters (parser, result_stmt))
8017  {
8019  return;
8020  }
8021 
8022  crt_qry = result_stmt;
8023 
8024  crt_qry->next = save_next;
8025  (*prev_qry_link_ptr) = crt_qry;
8026  prev_qry = crt_qry;
8027  }
8028 
8029  attr_count = pt_number_of_attributes (parser, stmt, &all_attrs);
8030 
8031  /* if no attributes are given, try to derive them from the query_spec columns. */
8032  if (attr_count <= 0)
8033  {
8034  PT_NODE *crt_attr = NULL;
8035  PT_NODE *const qspec_attr = pt_get_select_list (parser, *qry_specs_ptr);
8036 
8037  assert (attr_count == 0);
8038  assert (*attr_def_list_ptr == NULL);
8039 
8040  for (crt_attr = qspec_attr; crt_attr != NULL; crt_attr = crt_attr->next)
8041  {
8042  PT_NODE *s_attr = NULL;
8043 
8044  if (crt_attr->alias_print)
8045  {
8046  s_attr = crt_attr;
8047  }
8048  else
8049  {
8050  /* allow attributes to be derived only from path expressions. */
8051  s_attr = pt_get_end_path_node (crt_attr);
8052  if (s_attr->node_type != PT_NAME)
8053  {
8054  s_attr = NULL;
8055  }
8056  }
8057 
8058  if (s_attr == NULL)
8059  {
8061  pt_short_print (parser, crt_attr));
8062  return;
8063  }
8064  else if (s_attr->node_type == PT_HOST_VAR)
8065  {
8067  return;
8068  }
8069  else if (s_attr->node_type == PT_VALUE && s_attr->type_enum == PT_TYPE_NULL)
8070  {
8072  return;
8073  }
8074 
8075  derived_attr = pt_derive_attribute (parser, s_attr);
8076  if (derived_attr == NULL)
8077  {
8078  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
8079  return;
8080  }
8081 
8082  *attr_def_list_ptr = parser_append_node (derived_attr, *attr_def_list_ptr);
8083  }
8084 
8085  attr_count = pt_number_of_attributes (parser, stmt, &all_attrs);
8086  }
8087 
8088  assert (attr_count >= 0);
8089 
8090  /* do other checks on query specs */
8091  for (crt_qry = *qry_specs_ptr, prev_qry_link_ptr = qry_specs_ptr; crt_qry != NULL;
8092  prev_qry_link_ptr = &crt_qry->next, crt_qry = crt_qry->next)
8093  {
8094  PT_NODE *const save_next = crt_qry->next;
8095 
8096  crt_qry->next = NULL;
8097 
8098  result_stmt = pt_check_vclass_query_spec (parser, crt_qry, all_attrs, name, false);
8099  if (pt_has_error (parser))
8100  {
8101  return;
8102  }
8103  if (result_stmt == NULL)
8104  {
8105  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
8106  return;
8107  }
8108  crt_qry = result_stmt;
8109 
8110  all_attrs = pt_check_default_vclass_query_spec (parser, crt_qry, all_attrs);
8111  if (pt_has_error (parser))
8112  {
8113  return;
8114  }
8115  if (all_attrs == NULL)
8116  {
8117  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
8118  return;
8119  }
8120 
8121  result_stmt = pt_type_cast_vclass_query_spec (parser, crt_qry, all_attrs);
8122  if (pt_has_error (parser))
8123  {
8124  return;
8125  }
8126  if (result_stmt == NULL)
8127  {
8128  assert (false);
8129  PT_ERRORm (parser, stmt, MSGCAT_SET_ERROR, -(ER_GENERIC_ERROR));
8130  return;
8131  }
8132  crt_qry = result_stmt;
8133 
8134  crt_qry->next = save_next;
8135  (*prev_qry_link_ptr) = crt_qry;
8136  }
8137 }
8138 
8139 /*
8140  * pt_check_create_user () - semantic check a create user statement
8141  * return : none
8142  * parser(in) : the parser context
8143  * node(in) : create user node
8144  */
8145 static void
8147 {
8148  PT_NODE *user_name;
8149  const char *name;
8150  int name_upper_size;
8151 
8152  if (!node)
8153  {
8154  return;
8155  }
8156  if (node->node_type != PT_CREATE_USER)
8157  {
8158  return;
8159  }
8160 
8161  user_name = node->info.create_user.user_name;
8162  if (user_name->node_type != PT_NAME)
8163  {
8164  return;
8165  }
8166 
8167  name = user_name->info.name.original;
8168  if (name == NULL)
8169  {
8170  return;
8171  }
8172  name_upper_size = intl_identifier_upper_string_size (name);
8173  if (name_upper_size >= DB_MAX_USER_LENGTH)
8174  {
8176  }
8177 }
8178 
8179 /*
8180  * pt_check_create_entity () - semantic check a create class/vclass
8181  * return: none
8182  * parser(in): the parser context used to derive the statement
8183  * node(in): a create statement
8184  */
8185 
8186 static void
8188 {
8189  PT_NODE *parent, *qry_specs, *name, *create_like;
8190  PT_NODE *all_attrs, *r, *resolv_class, *attr;
8191  PT_NODE *tbl_opt_charset, *cs_node, *tbl_opt_coll, *coll_node;
8192  PT_NODE *tbl_opt = NULL;
8193  PT_MISC_TYPE entity_type;
8194  DB_OBJECT *db_obj, *existing_entity;
8195  int found, partition_status = DB_NOT_PARTITIONED_CLASS;
8196  int collation_id, charset;
8197  bool found_reuse_oid_option = false, reuse_oid = false;
8198  bool found_auto_increment = false;
8199  bool found_tbl_comment = false;
8200  bool found_tbl_encrypt = false;
8201  int error = NO_ERROR;
8202 
8203  entity_type = node->info.create_entity.entity_type;
8204 
8205  if (entity_type != PT_CLASS && entity_type != PT_VCLASS)
8206  {
8207  /* control should never reach here if tree is well-formed */
8208  assert (false);
8209  return;
8210  }
8211 
8212  tbl_opt_charset = tbl_opt_coll = NULL;
8213  for (tbl_opt = node->info.create_entity.table_option_list; tbl_opt != NULL; tbl_opt = tbl_opt->next)
8214  {
8215  assert (tbl_opt->node_type == PT_TABLE_OPTION);
8216 
8217  switch (tbl_opt->info.table_option.option)
8218  {
8220  {
8221  if (found_reuse_oid_option)
8222  {
8224  parser_print_tree (parser, tbl_opt));
8225  return;
8226  }
8227  else
8228  {
8229  found_reuse_oid_option = true;
8230  reuse_oid = true;
8231  }
8232  }
8233  break;
8234 
8236  {
8237  if (found_reuse_oid_option)
8238  {
8240  parser_print_tree (parser, tbl_opt));
8241  return;
8242  }
8243  else
8244  {
8245  found_reuse_oid_option = true;
8246  reuse_oid = false;
8247  }
8248  }
8249  break;
8250 
8252  {
8253  if (found_auto_increment)
8254  {
8256  parser_print_tree (parser, tbl_opt));
8257  return;
8258  }
8259  else
8260  {
8261  if (tbl_opt->info.table_option.val != NULL)
8262  {
8263  found_auto_increment = true;
8264  assert (tbl_opt->info.table_option.val->node_type == PT_VALUE);
8266  }
8267  }
8268  }
8269  break;
8270 
8272  {
8273  if (tbl_opt_charset != NULL)
8274  {
8276  parser_print_tree (parser, tbl_opt));
8277  return;
8278  }
8279  else
8280  {
8281  tbl_opt_charset = tbl_opt;
8282  }
8283  }
8284  break;
8285 
8287  {
8288  if (tbl_opt_coll != NULL)
8289  {
8291  parser_print_tree (parser, tbl_opt));
8292  return;
8293  }
8294  else
8295  {
8296  tbl_opt_coll = tbl_opt;
8297  }
8298  }
8299  break;
8301  {
8302  if (found_tbl_comment)
8303  {
8305  parser_print_tree (parser, tbl_opt));
8306  return;
8307  }
8308  else
8309  {
8310  found_tbl_comment = true;
8311  }
8312  }
8313  break;
8315  {
8316  if (found_tbl_encrypt)
8317  {
8319  parser_print_tree (parser, tbl_opt));
8320  return;
8321  }
8322  else
8323  {
8324  found_tbl_encrypt = true;
8325  }
8326  }
8327  break;
8328  default:
8329  /* should never arrive here */
8330  assert (false);
8331  break;
8332  }
8333  }
8334 
8335  /* get default value of reuse_oid from system parameter and create pt_node and add it into table_option_list, if don't use table option related reuse_oid */
8336  if (!found_reuse_oid_option && entity_type == PT_CLASS)
8337  {
8338  PT_NODE *tmp;
8339 
8342 
8343  if (tmp)
8344  {
8346  node->info.create_entity.table_option_list = tmp;
8347  }
8348  }
8349 
8350  /* validate charset and collation options, if any */
8351  cs_node = (tbl_opt_charset) ? tbl_opt_charset->info.table_option.val : NULL;
8352  coll_node = (tbl_opt_coll) ? tbl_opt_coll->info.table_option.val : NULL;
8353  charset = LANG_SYS_CODESET;
8354  collation_id = LANG_SYS_COLLATION;
8355  if ((cs_node != NULL || coll_node != NULL)
8356  && pt_check_grammar_charset_collation (parser, cs_node, coll_node, &charset, &collation_id) != NO_ERROR)
8357  {
8358  return;
8359  }
8360 
8361  /* check name doesn't already exist as a class */
8362  name = node->info.create_entity.entity_name;
8363  existing_entity = pt_find_class (parser, name, false);
8364  if (existing_entity != NULL)
8365  {
8366  if (!(entity_type == PT_VCLASS && node->info.create_entity.or_replace == 1 && db_is_vclass (existing_entity) > 0)
8367  /* If user sets "IF NOT EXISTS", do not throw ERROR if TABLE or VIEW with the same name exists, to stay
8368  * compatible with MySQL. */
8369  && !(entity_type == PT_CLASS && node->info.create_entity.if_not_exists == 1))
8370  {
8372  return;
8373  }
8374  }
8375  else
8376  {
8378  {
8379  /* Because the class is still inexistent, normally, here we will have to encounter some errors/warnings like
8380  * ER_LC_UNKNOWN_CLASSNAME which is unuseful for current context indeed and may disturb other subsequent
8381  * routines. Thus, we can/should clear the errors safely. */
8382  er_clear ();
8383  }
8384  }
8385 
8386  pt_check_user_exists (parser, name);
8387 
8388  /* check uniqueness of non-inherited attribute names */
8389  all_attrs = node->info.create_entity.attr_def_list;
8390  pt_check_unique_attr (parser, name->info.name.original, all_attrs, PT_ATTR_DEF);
8391 
8392  if (entity_type == PT_CLASS)
8393  {
8394  /* for regular classes (no views) set default collation if needed */
8395  for (attr = node->info.create_entity.attr_def_list; attr; attr = attr->next)
8396  {
8397  if (attr->node_type == PT_ATTR_DEF && PT_HAS_COLLATION (attr->type_enum))
8398  {
8399  if (pt_attr_check_default_cs_coll (parser, attr, charset, collation_id) != NO_ERROR)
8400  {
8401  return;
8402  }
8403  }
8404  }
8405  }
8406 
8407  /* enforce composition hierarchy restrictions on attr type defs */
8408  pt_check_attribute_domain (parser, all_attrs, entity_type, name->info.name.original, reuse_oid, node);
8409 
8410  /* check that any and all super classes do exist */
8411  for (parent = node->info.create_entity.supclass_list; parent != NULL; parent = parent->next)
8412  {
8413  db_obj = pt_find_class (parser, parent, false);
8414  if (db_obj != NULL)
8415  {
8416  parent->info.name.db_object = db_obj;
8417  error = sm_partitioned_class_type (db_obj, &partition_status, NULL, NULL);
8418  if (error != NO_ERROR)
8419  {
8420  PT_ERROR (parser, node, er_msg ());
8421  break;
8422  }
8423  if (partition_status == DB_PARTITION_CLASS)
8424  {
8426  parent->info.name.original);
8427  break;
8428  }
8429  pt_check_user_owns_class (parser, parent);
8430 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
8431  if (sm_has_text_domain (db_get_attributes (db_obj), 1))
8432  {
8433  /* prevent to define it as a superclass */
8435  PT_ERROR (parser, node, er_msg ());
8436  break;
8437  }
8438 #endif /* ENABLE_UNUSED_FUNCTION */
8439  }
8440  else
8441  {
8443  parent->info.name.original, pt_short_print (parser, node));
8444  return;
8445  }
8446  }
8447 
8448  if (error != NO_ERROR)
8449  {
8450  return;
8451  }
8452 
8453  /* an INHERIT_clause in a create_vclass_stmt without a SUBCLASS_clause is not meaningful. */
8455  {
8458  return;
8459  }
8460  else
8461  {
8462  /* the INHERIT_clause can only reference classes that are in the SUBCLASS_clause. */
8463  for (r = node->info.create_entity.resolution_list; r; r = r->next)
8464  {
8465  resolv_class = r->info.resolution.of_sup_class_name;
8466  found = 0;
8467 
8468  for (parent = node->info.create_entity.supclass_list; parent && !found; parent = parent->next)
8469  {
8470  found = !pt_str_compare (resolv_class->info.name.original, parent->info.name.original, CASE_INSENSITIVE);
8471  }
8472 
8473  if (!found)
8474  {
8476  parser_print_tree (parser, r), pt_short_print_l (parser,
8478  return;
8479  }
8480  }
8481  }
8482 
8483  if (entity_type == PT_VCLASS)
8484  {
8485  /* The grammar restricts table options to CREATE CLASS / TABLE */
8487 
8488  for (attr = all_attrs; attr; attr = attr->next)
8489  {
8490  if (attr->info.attr_def.auto_increment != NULL)
8491  {
8493  return;
8494  }
8495  }
8496  }
8497 
8498  qry_specs = node->info.create_entity.as_query_list;
8499  if (node->info.create_entity.entity_type == PT_CLASS)
8500  {
8501  PT_NODE *select = node->info.create_entity.create_select;
8502  PT_NODE *crt_attr = NULL;
8503  PT_NODE *const qspec_attr = pt_get_select_list (parser, select);
8504 
8505  /* simple CLASSes must not have any query specs */
8506  if (qry_specs)
8507  {
8509  return;
8510  }
8511  /* user variables are not allowed in select list for CREATE ... AS SELECT ... */
8512  if (select != NULL)
8513  {
8514  for (crt_attr = qspec_attr; crt_attr != NULL; crt_attr = crt_attr->next)
8515  {
8516  if (crt_attr->alias_print == NULL && crt_attr->node_type != PT_NAME && crt_attr->node_type != PT_DOT_)
8517  {
8519  pt_short_print (parser, crt_attr));
8520  return;
8521  }
8522  }
8523 
8524  if (select->info.query.with != NULL)
8525  {
8526  // run semantic check only for CREATE ... AS WITH ...
8527  if ((crt_attr = pt_check_with_clause (parser, select)) != NULL)
8528  {
8529  /* no alias for CTE select list */
8531  pt_short_print (parser, crt_attr));
8532  return;
8533  }
8534 
8535  select = pt_semantic_check (parser, select);
8536  }
8537 
8538  if (pt_has_parameters (parser, select))
8539  {
8541  return;
8542  }
8543  }
8544  if (!pt_has_error (parser) && node->info.create_entity.partition_info)
8545  {
8546  pt_check_partitions (parser, node, NULL);
8547  }
8548  }
8549  else /* must be a CREATE VCLASS statement */
8550  {
8551  pt_check_create_view (parser, node);
8552  }
8553 
8554  /* check that all constraints look valid */
8555  if (!pt_has_error (parser))
8556  {
8557  (void) pt_check_constraints (parser, node);
8558  }
8559 
8560  /*
8561  * check the auto_increment table option, AND REWRITE IT as
8562  * a constraint for the (single) AUTO_INCREMENT column.
8563  */
8564  if (found_auto_increment)
8565  {
8566  (void) pt_check_auto_increment_table_option (parser, node);
8567  }
8568 
8569  create_like = node->info.create_entity.create_like;
8570  if (create_like != NULL)
8571  {
8572  assert (entity_type == PT_CLASS);
8573 
8574  db_obj = pt_find_class (parser, create_like, false);
8575  if (db_obj == NULL)
8576  {
8578  create_like->info.name.original);
8579  return;
8580  }
8581  else
8582  {
8583  create_like->info.name.db_object = db_obj;
8584  pt_check_user_owns_class (parser, create_like);
8585  if (db_is_class (db_obj) <= 0)
8586  {
8588  create_like->info.name.original, pt_show_misc_type (PT_CLASS));
8589  return;
8590  }
8591  }
8592  }
8593 
8594  for (attr = node->info.create_entity.attr_def_list; attr; attr = attr->next)
8595  {
8597  }
8598 }
8599 
8600 /*
8601  * pt_check_create_index () - semantic check a create index
8602  * return: none
8603  * parser(in): the parser context used to derive the statement
8604  * node(in): a create index statement
8605  */
8606 
8607 static void
8609 {
8610  PT_NODE *name, *prefix_length, *col, *col_expr;
8611  DB_OBJECT *db_obj;
8612  int is_partition = DB_NOT_PARTITIONED_CLASS;
8613 
8614  /* check that there trying to create an index on a class */
8615  name = node->info.index.indexed_class->info.spec.entity_name;
8616  db_obj = db_find_class (name->info.name.original);
8617 
8618  if (db_obj == NULL)
8619  {
8621  return;
8622  }
8623  else
8624  {
8625  /* make sure it's not a virtual class */
8626  if (db_is_class (db_obj) <= 0)
8627  {
8629  return;
8630  }
8631  /* check if this is a partition class */
8632  if (sm_partitioned_class_type (db_obj, &is_partition, NULL, NULL) != NO_ERROR)
8633  {
8634  PT_ERROR (parser, node, er_msg ());
8635  return;
8636  }
8637 
8638  if (is_partition == DB_PARTITION_CLASS)
8639  {
8641  return;
8642  }
8643 
8644  /* Check if the columns are valid. We only allow expressions and attribute names. The actual expressions will be
8645  * validated later, we're only interested in the node type */
8646  for (col = node->info.index.column_names; col != NULL; col = col->next)
8647  {
8648  if (col->node_type != PT_SORT_SPEC)
8649  {
8651  return;
8652  }
8653  col_expr = col->info.sort_spec.expr;
8654  if (col_expr == NULL)
8655  {
8656  continue;
8657  }
8658  if (col_expr->node_type == PT_NAME)
8659  {
8660  /* make sure this is not a parameter */
8661  if (col_expr->info.name.meta_class != PT_NORMAL)
8662  {
8664  pt_short_print (parser, col_expr));
8665  return;
8666  }
8667  }
8668  else if (col_expr->node_type != PT_EXPR)
8669  {
8671  pt_short_print (parser, col_expr));
8672  return;
8673  }
8674  }
8675  /* make sure we don't mix up index types */
8676 
8677  pt_check_function_index_expr (parser, node);
8678  if (pt_has_error (parser))
8679  {
8680  return;
8681  }
8682 
8683  if (node->info.index.function_expr)
8684  {
8685  if (node->info.index.prefix_length || node->info.index.where)
8686  {
8688  }
8689  return;
8690  }
8691 
8692  name->info.name.db_object = db_obj;
8693 
8694  /* check that there is only one column to index on */
8696  if (pt_has_error (parser))
8697  {
8698  return;
8699  }
8700  pt_check_user_owns_class (parser, name);
8701  if (pt_has_error (parser))
8702  {
8703  return;
8704  }
8705 
8706  prefix_length = node->info.index.prefix_length;
8707  if (prefix_length)
8708  {
8709  PT_NODE *index_column;
8710 
8711  if (prefix_length->type_enum != PT_TYPE_INTEGER || prefix_length->info.value.data_value.i == 0)
8712  {
8713  /*
8714  * Parser can read PT_TYPE_BIGINT or PT_TYPE_NUMERIC values
8715  * but domain precision is defined as integer.
8716  * So, we accept only non-zero values of PT_TYPE_INTEGER.
8717  */
8719  prefix_length->info.value.text);
8720  return;
8721  }
8722 
8723  assert (node->info.index.column_names != NULL);
8724 
8725  /* check if prefix index is allowed for this type of column */
8726  for (index_column = node->info.index.column_names; index_column != NULL; index_column = index_column->next)
8727  {
8728  PT_NODE *col_dt;
8729 
8730  if (index_column->node_type != PT_SORT_SPEC || index_column->info.sort_spec.expr == NULL
8731  || index_column->info.sort_spec.expr->node_type != PT_NAME)
8732  {
8733  continue;
8734  }
8735 
8736  col_dt = index_column->info.sort_spec.expr->data_type;
8737 
8738  if (col_dt != NULL && PT_HAS_COLLATION (col_dt->type_enum))
8739  {
8740  LANG_COLLATION *lc;
8741 
8743 
8744  assert (lc != NULL);
8745 
8746  if (!(lc->options.allow_prefix_index))
8747  {
8749  index_column->info.sort_spec.expr->info.name.original);
8750  return;
8751  }
8752  }
8753  }
8754  }
8755  }
8756 
8757  /* if this is a filter index, check that the filter is a valid filter expression. */
8758  pt_check_filter_index_expr (parser, node->info.index.column_names, node->info.index.where, db_obj);
8759 }
8760 
8761 /*
8762  * pt_check_drop () - do semantic checks on the drop statement
8763  * return: none
8764  * parser(in): the parser context used to derive the statement
8765  * node(in): a statement
8766  */
8767 static void
8769 {
8770  PT_NODE *temp;
8771  PT_NODE *name;
8772  DB_OBJECT *db_obj;
8773  DB_ATTRIBUTE *attributes;
8774  PT_FLAT_SPEC_INFO info;
8775 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
8776  DB_OBJECT *domain_class;
8777  char *drop_name_list = NULL;
8778 #endif /* ENABLE_UNUSED_FUNCTION */
8779 
8780  if (node->info.drop.if_exists)
8781  {
8782  PT_NODE *prev_node, *free_node, *tmp1, *tmp2;
8783  prev_node = free_node = node->info.drop.spec_list;
8784 
8785  while ((free_node != NULL) && (free_node->node_type == PT_SPEC))
8786  {
8787  const char *cls_name;
8788  /* check if class name exists. if not, we remove the corresponding node from spec_list. */
8789  if ((name = free_node->info.spec.entity_name) != NULL && name->node_type == PT_NAME
8790  && (cls_name = name->info.name.original) != NULL
8791  && (db_obj = db_find_class_with_purpose (cls_name, true)) == NULL)
8792  {
8793  if (free_node == node->info.drop.spec_list)
8794  {
8795  node->info.drop.spec_list = node->info.drop.spec_list->next;
8796  prev_node = free_node->next;
8797  parser_free_node (parser, free_node);
8798  free_node = node->info.drop.spec_list;
8799  }
8800  else
8801  {
8802  prev_node->next = free_node->next;
8803  parser_free_node (parser, free_node);
8804  free_node = prev_node->next;
8805  }
8806  }
8807  else
8808  {
8809  prev_node = free_node;
8810  free_node = free_node->next;
8811  }
8812  }
8813  /* For each class, we check if it has previously been placed in spec_list. We also check if every class has a
8814  * superclass marked with PT_ALL previously placed in spec_list. If any of the two cases above occurs, we mark
8815  * for deletion the corresponding node in spec_list. Marking is done by setting the entity_name as NULL. */
8816 
8817  if (node->info.drop.spec_list && (node->info.drop.spec_list)->next)
8818  {
8819  tmp1 = (node->info.drop.spec_list)->next;
8820  while ((tmp1 != NULL) && (tmp1->node_type == PT_SPEC))
8821  {
8822  tmp2 = node->info.drop.spec_list;
8823  while ((tmp2 != NULL) && (tmp2 != tmp1) && (tmp2->node_type == PT_SPEC))
8824  {
8825  DB_OBJECT *db_obj1, *db_obj2;
8826  PT_NODE *name1, *name2;
8827  const char *cls_name1, *cls_name2;
8828 
8829  name1 = tmp1->info.spec.entity_name;
8830  name2 = tmp2->info.spec.entity_name;
8831  if (name1 && name2)
8832  {
8833  cls_name1 = name1->info.name.original;
8834  cls_name2 = name2->info.name.original;
8835 
8836  db_obj1 = db_find_class_with_purpose (cls_name1, true);
8837  db_obj2 = db_find_class_with_purpose (cls_name2, true);
8838 
8839  if ((db_obj1 == db_obj2)
8840  || ((tmp2->info.spec.only_all == PT_ALL) && db_is_subclass (db_obj1, db_obj2)))
8841  {
8842  parser_free_node (parser, name1);
8843  tmp1->info.spec.entity_name = NULL;
8844  break;
8845  }
8846  }
8847 
8848  tmp2 = tmp2->next;
8849  }
8850 
8851  tmp1 = tmp1->next;
8852  }
8853  }
8854 
8855  /* now we remove the nodes with entity_name NULL */
8856 
8857  prev_node = free_node = node->info.drop.spec_list;
8858 
8859  while ((free_node != NULL) && (free_node->node_type == PT_SPEC))
8860  {
8861 
8862  if ((name = free_node->info.spec.entity_name) == NULL)
8863  {
8864  if (free_node == node->info.drop.spec_list)
8865  {
8866  node->info.drop.spec_list = node->info.drop.spec_list->next;
8867  prev_node = free_node->next;
8868  parser_free_node (parser, free_node);
8869  free_node = node->info.drop.spec_list;
8870  }
8871  else
8872  {
8873  prev_node->next = free_node->next;
8874  parser_free_node (parser, free_node);
8875  free_node = prev_node->next;
8876  }
8877  }
8878  else
8879  {
8880  prev_node = free_node;
8881  free_node = free_node->next;
8882  }
8883  }
8884 
8885  }
8886 
8887  info.spec_parent = NULL;
8888  info.for_update = true;
8889  /* Replace each Entity Spec with an Equivalent flat list */
8890  parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
8891 
8893  {
8894  const char *cls_nam;
8895  PT_MISC_TYPE typ = node->info.drop.entity_type;
8896 
8897  /* verify declared class type is correct */
8898  for (temp = node->info.drop.spec_list; temp && temp->node_type == PT_SPEC; temp = temp->next)
8899  {
8900  if ((name = temp->info.spec.entity_name) != NULL && name->node_type == PT_NAME
8901  && (cls_nam = name->info.name.original) != NULL && (db_obj = db_find_class (cls_nam)) != NULL)
8902  {
8903  if (typ != PT_MISC_DUMMY)
8904  {
8905  name->info.name.db_object = db_obj;
8906  pt_check_user_owns_class (parser, name);
8907  if ((typ == PT_CLASS && db_is_class (db_obj) <= 0)
8908  || (typ == PT_VCLASS && db_is_vclass (db_obj) <= 0))
8909  {
8911  pt_show_misc_type (typ));
8912  }
8913  }
8914 
8915  if (node->info.drop.is_cascade_constraints && db_is_vclass (db_obj) > 0)
8916  {
8917  PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
8919  }
8920  }
8921  }
8922  }
8923 
8924  /* for the classes to drop, check if a TEXT attr is defined on the class, and if defined, drop the reference class
8925  * for the attr */
8926  for (temp = node->info.drop.spec_list; temp && temp->node_type == PT_SPEC; temp = temp->next)
8927  {
8928  const char *cls_nam;
8929 
8930  if ((name = temp->info.spec.entity_name) != NULL && name->node_type == PT_NAME
8931  && (cls_nam = name->info.name.original) != NULL && (db_obj = db_find_class (cls_nam)) != NULL)
8932  {
8933  attributes = db_get_attributes_force (db_obj);
8934  while (attributes)
8935  {
8936  if (db_attribute_type (attributes) == DB_TYPE_OBJECT)
8937  {
8938 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
8939  if (sm_has_text_domain (attributes, 0))
8940  {
8941  domain_class = db_domain_class (db_attribute_domain (attributes));
8942  if (drop_name_list != NULL)
8943  {
8944  drop_name_list = pt_append_string (parser, drop_name_list, ",");
8945  }
8946 
8947  drop_name_list = pt_append_string (parser, drop_name_list, db_get_class_name (domain_class));
8948  }
8949 #endif /* ENABLE_UNUSED_FUNCTION */
8950  }
8951  attributes = db_attribute_next (attributes);
8952  }
8953  }
8954  }
8955 
8956 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
8957  if (drop_name_list)
8958  {
8959  node->info.drop.internal_stmts =
8960  pt_append_statements_on_drop_attributes (parser, node->info.drop.internal_stmts, drop_name_list);
8961  if (node->info.drop.internal_stmts == NULL)
8962  {
8964  return;
8965  }
8966  }
8967 #endif /* ENABLE_UNUSED_FUNCTION */
8968 }
8969 
8970 /*
8971  * pt_check_grant_revoke () - do semantic checks on the grant statement
8972  * return: none
8973  * parser(in): the parser context used to derive the statement
8974  * node(in): a statement
8975  */
8976 
8977 static void
8979 {
8980  PT_NODE *user;
8981  const char *username;
8982  PT_FLAT_SPEC_INFO info;
8983 
8984  /* Replace each Entity Spec with an Equivalent flat list */
8985  info.spec_parent = NULL;
8986  info.for_update = false;
8987  parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
8988 
8989  /* make sure the grantees/revokees exist */
8990  for ((user = (node->node_type == PT_GRANT ? node->info.grant.user_list : node->info.revoke.user_list)); user;
8991  user = user->next)
8992  {
8993  if (user->node_type == PT_NAME && (username = user->info.name.original) && !db_find_user (username))
8994  {
8996  }
8997  }
8998 }
8999 
9000 /*
9001  * pt_check_method () - semantic checking for method calls in expressions.
9002  * return: none
9003  * parser(in): the parser context used to derive the statement
9004  * node(in): a statement
9005  */
9006 
9007 static void
9009 {
9010  PT_NODE *target;
9011  DB_VALUE val;
9012  const char *method_name;
9013  DB_OBJECT *class_op;
9014  DB_METHOD *method = NULL;
9015 
9016  /* Note: it is possible that an error has been raised eariler. An example is that, method_name is NULL due to a
9017  * connection lost, i.e. db_Connect_status is 0, 'MSGCAT_SEMANTIC_METH_NO_TARGET' is set. So we must check error
9018  * first. */
9019 
9020  assert (parser != NULL);
9021 
9022  if (pt_has_error (parser))
9023  {
9024  return;
9025  }
9026 
9027  assert (node != NULL && node->info.method_call.method_name != NULL);
9028 
9029  db_make_null (&val);
9030 
9031  /* check if call has a target */
9032  target = node->info.method_call.on_call_target;
9033  if (target == NULL)
9034  {
9036  {
9037  return;
9038  }
9039  else
9040  {
9042  return;
9043  }
9044  }
9045 
9046  /* if we have a null target, constant folding has determined we have no target, there is nothing to check. */
9047  if ((target->node_type == PT_VALUE) && (target->type_enum == PT_TYPE_NULL))
9048  {
9049  return;
9050  }
9051 
9052  if ((!target->data_type) || (!target->data_type->info.data_type.entity))
9053  {
9055  return;
9056  }
9057 
9058  if (!(class_op = target->data_type->info.data_type.entity->info.name.db_object))
9059  {
9060  PT_INTERNAL_ERROR (parser, "semantic");
9061  return;
9062  }
9063 
9064  method_name = node->info.method_call.method_name->info.name.original;
9065  method = (DB_METHOD *) db_get_method (class_op, method_name);
9066  if (method == NULL)
9067  {
9068  if (er_errid () == ER_OBJ_INVALID_METHOD)
9069  {
9070  er_clear ();
9071  }
9072 
9073  method = (DB_METHOD *) db_get_class_method (class_op, method_name);
9074  if (method == NULL)
9075  {
9077  return;
9078  }
9079  else
9080  {
9081  /* Check to see that they are calling the class method on a class object. We check the initial value if it
9082  * is a parameter knowing that the user could change it at run time. We probably need to add runtime checks
9083  * if we are not already doing this. Also we probably shouldn't get PT_VALUES here now that parameters are
9084  * not bound until runtime (but we'll guard against them anyway). */
9085  if (((target->node_type != PT_NAME) || (target->info.name.meta_class != PT_PARAMETER)
9086  || !pt_eval_path_expr (parser, target, &val) || db_is_instance (db_get_object (&val)) <= 0)
9087  && target->node_type != PT_VALUE
9089  {
9091  return;
9092  }
9093  }
9094  }
9095  else
9096  {
9097  /* Check to see that they are calling the instance method on an instance object. We check the initial value if
9098  * it is a parameter knowing that the user could change it at run time. We probably need to add runtime checks
9099  * if we are not already doing this. Also we probably shouldn't get PT_VALUES here now that parameters are not
9100  * bound until runtime (but we'll guard against them anyway). */
9101  if (((target->node_type != PT_NAME) || (target->info.name.meta_class != PT_PARAMETER)
9102  || !pt_eval_path_expr (parser, target, &val) || db_is_instance (db_get_object (&val)) <= 0)
9103  && target->node_type != PT_VALUE
9105  {
9107  return;
9108  }
9109  }
9110 
9111  /* check if number of parameters match */
9113  {
9115  return;
9116  }
9117 
9118 }
9119 
9120 /*
9121  * pt_check_truncate () - do semantic checks on the truncate statement
9122  * return: none
9123  * parser(in): the parser context used to derive the statement
9124  * node(in): a statement
9125  */
9126 static void
9128 {
9129  PT_NODE *temp;
9130  PT_NODE *name;
9131  PT_FLAT_SPEC_INFO info;
9132  DB_OBJECT *db_obj;
9133 
9134  /* replace entity spec with an equivalent flat list */
9135  info.spec_parent = NULL;
9136  info.for_update = false;
9137  parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
9138 
9139  temp = node->info.truncate.spec;
9140  if (temp && temp->node_type == PT_SPEC)
9141  {
9142  const char *cls_nam;
9143 
9144  if ((name = temp->info.spec.entity_name) != NULL && name->node_type == PT_NAME
9145  && (cls_nam = name->info.name.original) != NULL && (db_obj = db_find_class (cls_nam)) != NULL)
9146  {
9147  name->info.name.db_object = db_obj;
9148  pt_check_user_owns_class (parser, name);
9149  if (db_is_class (db_obj) <= 0)
9150  {
9153  }
9154  }
9155  }
9156 }
9157 
9158 /*
9159  * pt_check_kill () - do semantic checks on the kill statement
9160  * return: none
9161  * parser(in): the parser context used to derive the statement
9162  * node(in): a statement
9163  */
9164 static void
9166 {
9167  PT_NODE *tran_id;
9168 
9169  for (tran_id = node->info.killstmt.tran_id_list; tran_id != NULL; tran_id = tran_id->next)
9170  {
9171  if (tran_id->type_enum != PT_TYPE_INTEGER)
9172  {
9174  break;
9175  }
9176  }
9177 }
9178 
9179 /*
9180  * pt_check_single_valued_node () - looks for names outside an aggregate
9181  * which are not in group by list. If it finds one, raises an error
9182  * return:
9183  * parser(in):
9184  * node(in):
9185  * arg(in/out):
9186  * continue_walk(in/out):
9187  */
9188 static PT_NODE *
9189 pt_check_single_valued_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9190 {
9191  PT_AGG_CHECK_INFO *info = (PT_AGG_CHECK_INFO *) arg;
9192  PT_NODE *spec, *arg2, *group, *expr;
9193  char *node_str;
9194 
9195  *continue_walk = PT_CONTINUE_WALK;
9196 
9197  if (pt_is_aggregate_function (parser, node))
9198  {
9199  *continue_walk = PT_LIST_WALK;
9200  }
9201  else if (node->node_type == PT_SELECT)
9202  {
9203  /* Can not increment level for list portion of walk. Since those queries are not sub-queries of this query.
9204  * Consequently, we recurse separately for the list leading from a query. Can't just call
9205  * pt_to_uncorr_subquery_list() directly since it needs to do a leaf walk and we want to do a full walk on the
9206  * next list. */
9207  if (node->next)
9208  {
9209  (void) parser_walk_tree (parser, node->next, pt_check_single_valued_node, info,
9211  }
9212 
9213  /* don't get confused by uncorrelated, set-derived subqueries. */
9214  if (node->info.query.correlation_level == 0 && (spec = node->info.query.q.select.from)
9216  {
9217  /* no need to dive into the uncorrelated subquery */
9218  *continue_walk = PT_STOP_WALK;
9219  }
9220  else
9221  {
9222  *continue_walk = PT_LEAF_WALK;
9223  }
9224 
9225  /* increase query depth as we dive into subqueries */
9226  info->depth++;
9227  }
9228  else
9229  {
9230  switch (node->node_type)
9231  {
9232  case PT_NAME:
9233  *continue_walk = PT_LIST_WALK;
9234 
9235  if (pt_find_spec (parser, info->from, node) && pt_find_attribute (parser, node, info->group_by) < 0)
9236  {
9237  if ((!PT_IS_OID_NAME (node) || parser->oid_included != PT_INCLUDE_OID_TRUSTME)
9238  && !PT_IS_CLASSOID_NAME (node) && node->info.name.meta_class != PT_METHOD
9240  && node->info.name.meta_class != PT_PARAMETER)
9241  {
9243  pt_short_print (parser, node));
9244  }
9245  }
9246  break;
9247 
9248  case PT_DOT_:
9249  *continue_walk = PT_LIST_WALK;
9250 
9251  if ((arg2 = node->info.dot.arg2) && pt_find_spec (parser, info->from, arg2)
9252  && (pt_find_attribute (parser, arg2, info->group_by) < 0))
9253  {
9254  if (!PT_IS_OID_NAME (node->info.dot.arg2) || parser->oid_included != PT_INCLUDE_OID_TRUSTME)
9255  {
9257  pt_short_print (parser, node));
9258  }
9259  }
9260  break;
9261 
9262  case PT_VALUE:
9263  /* watch out for parameters of type object--don't walk their data_type list */
9264  *continue_walk = PT_LIST_WALK;
9265  break;
9266 
9267  case PT_EXPR:
9268  if (node->info.expr.op == PT_INST_NUM || node->info.expr.op == PT_ROWNUM || node->info.expr.op == PT_PRIOR
9269  || node->info.expr.op == PT_CONNECT_BY_ROOT || node->info.expr.op == PT_SYS_CONNECT_BY_PATH)
9270  {
9271  if (info->depth == 0)
9272  { /* not in subqueries */
9274  pt_short_print (parser, node));
9275  }
9276  }
9277  else if (node->info.expr.op == PT_LEVEL || node->info.expr.op == PT_CONNECT_BY_ISCYCLE
9278  || node->info.expr.op == PT_CONNECT_BY_ISLEAF)
9279  {
9280  if (info->depth == 0)
9281  { /* not in subqueries */
9282  for (group = info->group_by; group; group = group->next)
9283  {
9284  expr = group->info.sort_spec.expr;
9285  if (expr->node_type == PT_EXPR && expr->info.expr.op == node->info.expr.op)
9286  {
9287  break;
9288  }
9289  }
9290  if (group == NULL)
9291  {
9293  pt_short_print (parser, node));
9294  }
9295  }
9296  }
9297  else
9298  {
9299  unsigned int save_custom;
9300 
9301  save_custom = parser->custom_print; /* save */
9302 
9303  parser->custom_print |= PT_CONVERT_RANGE;
9304  node_str = parser_print_tree (parser, node);
9305 
9306  for (group = info->group_by; group; group = group->next)
9307  {
9308  expr = group->info.sort_spec.expr;
9309  if (expr->node_type == PT_EXPR && pt_str_compare (node_str, expr->alias_print, CASE_INSENSITIVE) == 0)
9310  {
9311  /* find matched expression */
9312  *continue_walk = PT_LIST_WALK;
9313  break;
9314  }
9315  }
9316 
9317  parser->custom_print = save_custom; /* restore */
9318  }
9319  break;
9320 
9321  default:
9322  break;
9323  }
9324  }
9325 
9326  return node;
9327 }
9328 
9329 /*
9330  * pt_check_single_valued_node_post () -
9331  * return:
9332  * parser(in):
9333  * node(in):
9334  * arg(in/out):
9335  * continue_walk(in/out):
9336  */
9337 static PT_NODE *
9338 pt_check_single_valued_node_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9339 {
9340  PT_AGG_CHECK_INFO *info = (PT_AGG_CHECK_INFO *) arg;
9341 
9342  *continue_walk = PT_CONTINUE_WALK;
9343 
9344  if (node->node_type == PT_SELECT)
9345  {
9346  info->depth--; /* decrease query depth */
9347  }
9348 
9349  return node;
9350 }
9351 
9352 /*
9353  * pt_check_into_clause () - check arity of any into_clause
9354  * equals arity of query
9355  * return: none
9356  * parser(in): the parser context used to derive the statement
9357  * qry(in): a SELECT/UNION/INTERSECTION/DIFFERENCE statement
9358  */
9359 static void
9361 {
9362  PT_NODE *into;
9363  int tgt_cnt, col_cnt;
9364 
9365  assert (parser != NULL);
9366 
9367  if (!qry)
9368  return;
9369 
9370  if (!(into = qry->info.query.into_list))
9371  return;
9372 
9373  if (qry->info.query.is_subquery != 0)
9374  {
9375  /* current query execution mechanism can not handle select_into inside subqueries, since only the results of
9376  * the main query are available on the client, where the select_into assignment is done
9377  */
9379  }
9380 
9381  tgt_cnt = pt_length_of_list (into);
9383  if (tgt_cnt != col_cnt)
9384  {
9386  }
9387 }
9388 
9389 static int
9391 {
9392  std::string normalized_path;
9393 
9394  int error_code = db_json_normalize_path_string (c, normalized_path);
9395  if (error_code != NO_ERROR)
9396  {
9397  return error_code;
9398  }
9399  char *normalized = (char *) parser_alloc (parser, (int) (normalized_path.length () + 1) * sizeof (char));
9400  strcpy (normalized, normalized_path.c_str ());
9401  c = normalized;
9402  return NO_ERROR;
9403 }
9404 
9405 static int
9407 {
9408  DB_VALUE res_str, temp;
9409  db_make_string (&temp, c);
9410 
9411  int error_code = db_string_convert_to (&temp, &res_str, INTL_CODESET_UTF8, LANG_COLL_UTF8_BINARY);
9412  if (error_code != NO_ERROR)
9413  {
9414  pr_clear_value (&res_str);
9415  ASSERT_ERROR ();
9416  return error_code;
9417  }
9418 
9419  c = (char *) parser_alloc (parser, db_get_string_size (&res_str));
9420  strcpy (c, db_get_string (&res_str));
9421 
9422  pr_clear_value (&res_str);
9423  return NO_ERROR;
9424 }
9425 
9426 /*
9427  * pt_check_json_table_node () - check json_table's paths and type check ON_ERROR & ON_EMPTY
9428  *
9429  * return: NO_ERROR or ER_JSON_INVALID_PATH
9430  * node(in): json_table node
9431  */
9432 static int
9434 {
9435  assert (node != NULL && node->node_type == PT_JSON_TABLE_NODE);
9436 
9437  int error_code = pt_json_str_codeset_normalization (parser, node->info.json_table_node_info.path);
9438  if (error_code != NO_ERROR)
9439  {
9440  return error_code;
9441  }
9442 
9443  error_code = pt_normalize_path (parser, node->info.json_table_node_info.path);
9444  if (error_code != NO_ERROR)
9445  {
9446  return error_code;
9447  }
9448 
9449  for (PT_NODE * col = node->info.json_table_node_info.columns; col; col = col->next)
9450  {
9451  PT_JSON_TABLE_COLUMN_INFO & col_info = col->info.json_table_column_info;
9453  {
9454  assert (col_info.on_empty.m_default_value != NULL);
9455 
9456  if (DB_IS_STRING (col_info.on_empty.m_default_value))
9457  {
9458  error_code = db_json_convert_to_utf8 (col_info.on_empty.m_default_value);
9459  if (error_code != NO_ERROR)
9460  {
9461  return NO_ERROR;
9462  }
9463  }
9464 
9465  TP_DOMAIN *domain = pt_xasl_node_to_domain (parser, col);
9466  TP_DOMAIN_STATUS status_cast =
9467  tp_value_cast (col_info.on_empty.m_default_value, col_info.on_empty.m_default_value, domain, false);
9468  if (status_cast != DOMAIN_COMPATIBLE)
9469  {
9470  return tp_domain_status_er_set (status_cast, ARG_FILE_LINE, col_info.on_empty.m_default_value, domain);
9471  }
9472  }
9473 
9475  {
9476  assert (col_info.on_error.m_default_value != NULL);
9477 
9478  if (DB_IS_STRING (col_info.on_error.m_default_value))
9479  {
9480  error_code = db_json_convert_to_utf8 (col_info.on_error.m_default_value);
9481  if (error_code != NO_ERROR)
9482  {
9483  return NO_ERROR;
9484  }
9485  }
9486 
9487  TP_DOMAIN *domain = pt_xasl_node_to_domain (parser, col);
9488  TP_DOMAIN_STATUS status_cast =
9489  tp_value_cast (col_info.on_error.m_default_value, col_info.on_error.m_default_value, domain, false);
9490  if (status_cast != DOMAIN_COMPATIBLE)
9491  {
9492  return tp_domain_status_er_set (status_cast, ARG_FILE_LINE, col_info.on_error.m_default_value, domain);
9493  }
9494  }
9495 
9496  if (col_info.func == JSON_TABLE_ORDINALITY)
9497  {
9498  // ORDINALITY columns do not have a path
9499  assert (col_info.path == NULL);
9500  continue;
9501  }
9502  error_code = pt_normalize_path (parser, col_info.path);
9503  if (error_code)
9504  {
9505  return error_code;
9506  }
9507  }
9508 
9509  for (PT_NODE * nested_col = node->info.json_table_node_info.nested_paths; nested_col; nested_col = nested_col->next)
9510  {
9511  error_code = pt_check_json_table_node (parser, nested_col);
9512  if (error_code)
9513  {
9514  return error_code;
9515  }
9516  }
9517  return NO_ERROR;
9518 }
9519 
9520 /*
9521  * pt_semantic_check_local () - checks semantics on a particular statement
9522  * return:
9523  * parser(in):
9524  * node(in):
9525  * arg(in):
9526  * continue_walk(in):
9527  */
9528 static PT_NODE *
9529 pt_semantic_check_local (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
9530 {
9531  SEMANTIC_CHK_INFO *info = (SEMANTIC_CHK_INFO *) arg;
9532  PT_NODE *next, *top_node = info->top_node;
9533  PT_NODE *orig = node;
9534  PT_NODE *t_node;
9535  PT_NODE *entity, *derived_table;
9537  STATEMENT_SET_FOLD fold_as;
9538  PT_FUNCTION_INFO *func_info_p = NULL;
9539 
9540  assert (parser != NULL);
9541 
9542  if (!node)
9543  return NULL;
9544 
9545  next = node->next;
9546  node->next = NULL;
9547 
9548  switch (node->node_type)
9549  {
9550  /* Every type of node that can appear at the highest level should be listed here, unless no semantic check is
9551  * required. */
9552  case PT_DELETE:
9553  if (top_node->flag.cannot_prepare == 1)
9554  {
9555  node->flag.cannot_prepare = 1;
9556  }
9557 
9558  entity = NULL;
9559 
9560  /* Make sure that none of the classes that are subject for delete is a derived table */
9561  t_node = node->info.delete_.target_classes;
9562 
9563  if (t_node == NULL)
9564  {
9565  /* this is not a multi-table delete; check all specs for derived tables */
9566  entity = node->info.delete_.spec;
9567 
9568  while (entity)
9569  {
9570  assert (entity->node_type == PT_SPEC);
9571 
9572  if (entity->info.spec.derived_table != NULL)
9573  {
9575  break;
9576  }
9577  }
9578  }
9579  else
9580  {
9581  /* multi-table delete */
9582  while (t_node)
9583  {
9584  entity = pt_find_spec_in_statement (parser, node, t_node);
9585 
9586  if (entity == NULL)
9587  {
9589  t_node->info.name.original);
9590  break;
9591  }
9592 
9593  if (entity->info.spec.derived_table != NULL)
9594  {
9596  break;
9597  }
9598 
9599  t_node = t_node->next;
9600  }
9601  }
9602 
9603  node = pt_semantic_type (parser, node, info);
9604  break;
9605 
9606  case PT_INSERT:
9607  if (top_node && top_node->flag.cannot_prepare == 1)
9608  {
9609  node->flag.cannot_prepare = 1;
9610  }
9611 
9612  if (node->info.insert.into_var != NULL && node->info.insert.value_clauses->next != NULL)
9613  {
9615  if (!pt_has_error (parser))
9616  {
9617  PT_ERRORc (parser, node, db_error_string (3));
9618  }
9619  break;
9620  }
9621 
9622  if (node->info.insert.odku_assignments != NULL)
9623  {
9624  node = pt_check_odku_assignments (parser, node);
9625  if (node == NULL || pt_has_error (parser))
9626  {
9627  break;
9628  }
9629  }
9630  /* semantic check value clause for SELECT and INSERT subclauses */
9631  if (node)
9632  {
9633  node = pt_semantic_type (parser, node, info);
9634  }
9635 
9636  /* try to coerce insert_values into types indicated by insert_attributes */
9637  if (node)
9638  {
9639  pt_coerce_insert_values (parser, node);
9640  }
9641  if (pt_has_error (parser))
9642  {
9643  break;
9644  }
9645 
9647  {
9648  /* Search and check sub-inserts in value list */
9650  }
9651  if (pt_has_error (parser))
9652  {
9653  break;
9654  }
9655 
9656  if (top_node && top_node->node_type != PT_INSERT && top_node->node_type != PT_SCOPE)
9657  {
9659  }
9660  break;
9661 
9662  case PT_EVALUATE:
9663  if (node)
9664  {
9665  node = pt_semantic_type (parser, node, info);
9666  }
9667  break;
9668 
9669  case PT_METHOD_CALL:
9671  {
9672  pt_check_method (parser, node);
9673  }
9674  else if (node->info.method_call.call_or_expr == PT_IS_CALL_STMT)
9675  {
9676  /* Expressions in method calls from a CALL statement need to be typed explicitly since they are not wrapped
9677  * in a query and are not explicitly type-checked via pt_check_method(). This is due to a bad decision which
9678  * allowed users to refrain from fully typing methods before the advent of methods in queries. */
9679  node->info.method_call.arg_list = pt_semantic_type (parser, node->info.method_call.arg_list, info);
9681  pt_semantic_type (parser, node->info.method_call.on_call_target, info);
9682  }
9683  break;
9684 
9685  case PT_FUNCTION:
9686  func_info_p = &node->info.function;
9687 
9688  if (func_info_p->function_type == PT_GENERIC && (pt_length_of_list (func_info_p->arg_list) > NUM_F_GENERIC_ARGS))
9689  {
9691  func_info_p->generic_name, NUM_F_GENERIC_ARGS);
9692  }
9693 
9694  /* check order by for aggregate function */
9695  if (func_info_p->function_type == PT_GROUP_CONCAT)
9696  {
9697  if (pt_check_group_concat_order_by (parser, node) != NO_ERROR)
9698  {
9699  break;
9700  }
9701  }
9702  else if (func_info_p->function_type == PT_CUME_DIST || func_info_p->function_type == PT_PERCENT_RANK)
9703  {
9704  /* for CUME_DIST and PERCENT_RANK aggregate function */
9705  if (pt_check_cume_dist_percent_rank_order_by (parser, node) != NO_ERROR)
9706  {
9707  break;
9708  }
9709  }
9710 
9711  break;
9712 
9713  case PT_UNION:
9714  case PT_INTERSECTION:
9715  case PT_DIFFERENCE:
9716  if (top_node->flag.cannot_prepare == 1)
9717  {
9718  node->flag.cannot_prepare = 1;
9719  }
9720 
9721  /* semantic check {union|intersection|difference} operands */
9722  if (pt_has_error (parser))
9723  {
9724  break;
9725  }
9726 
9727  fold_as = pt_check_union_is_foldable (parser, node);
9728  if (fold_as != STATEMENT_SET_FOLD_NOTHING)
9729  {
9730  node = pt_fold_union (parser, node, fold_as);
9731 
9732  /* don't need do the following steps */
9733  break;
9734  }
9735 
9736  pt_check_into_clause (parser, node);
9737 
9738  /* check the orderby clause if present (all 3 nodes have SAME structure) */
9739  if (pt_check_order_by (parser, node) != NO_ERROR)
9740  {
9741  break; /* error */
9742  }
9743 
9744  node = pt_semantic_type (parser, node, info);
9745  if (node == NULL)
9746  {
9747  break;
9748  }
9749 
9750  /* only root UNION nodes */
9751  if (node->info.query.q.union_.is_leaf_node == false)
9752  {
9753  PT_NODE *attrs = NULL;
9754  int cnt, k;
9755  SEMAN_COMPATIBLE_INFO *cinfo = NULL;
9756  PT_UNION_COMPATIBLE status;
9757 
9758  /* do collation inference necessary */
9759  attrs = pt_get_select_list (parser, node->info.query.q.union_.arg1);
9761 
9762  cinfo = (SEMAN_COMPATIBLE_INFO *) malloc (cnt * sizeof (SEMAN_COMPATIBLE_INFO));
9763  if (cinfo == NULL)
9764  {
9766  break;
9767  }
9768 
9769  for (k = 0; k < cnt; ++k)
9770  {
9771  cinfo[k].idx = -1;
9772  cinfo[k].type_enum = PT_TYPE_NONE;
9773  cinfo[k].prec = DB_DEFAULT_PRECISION;
9774  cinfo[k].scale = DB_DEFAULT_SCALE;
9776  cinfo[k].coll_infer.codeset = LANG_SYS_CODESET;
9778  cinfo[k].coll_infer.can_force_cs = false;
9779  cinfo[k].ref_att = NULL;
9780  }
9781 
9782  status = pt_get_select_list_coll_compat (parser, node, cinfo, cnt);
9783  if (status == PT_UNION_INCOMP)
9784  {
9785  (void) pt_apply_union_select_list_collation (parser, node, cinfo, cnt);
9786  free (cinfo);
9787  break;
9788  }
9789 
9790  free (cinfo);
9791  }
9792  break;
9793 
9794  case PT_SELECT:
9795  if (top_node->flag.cannot_prepare == 1)
9796  {
9797  node->flag.cannot_prepare = 1;
9798  }
9799 
9800  if (node->info.query.flag.single_tuple == 1)
9801  {
9803  {
9804  /* illegal multi-column subquery */
9806  }
9807  }
9808 
9809  pt_check_into_clause (parser, node);
9810 
9811  if (node->info.query.q.select.with_increment)
9812  {
9813  PT_NODE *select_list = node->info.query.q.select.list;
9814  PT_NODE *hidden_list = node->info.query.q.select.with_increment;
9815 
9816  (void) parser_append_node (hidden_list, select_list);
9818  }
9819 
9820  if (pt_has_aggregate (parser, node))
9821  {
9822  PT_AGG_CHECK_INFO info;
9823  PT_NODE *r;
9825  PT_NODE *referred_node;
9826  int max_position;
9827 
9828  /* STEP 1: init agg info */
9829  info.from = node->info.query.q.select.from;
9830  info.depth = 0;
9831  info.group_by = node->info.query.q.select.group_by;
9832 
9834 
9835  for (t_node = info.group_by; t_node; t_node = t_node->next)
9836  {
9837  r = t_node->info.sort_spec.expr;
9838  if (r == NULL)
9839  {
9840  continue;
9841  }
9842  /*
9843  * If a position is specified on group by clause,
9844  * we should check its range.
9845  */
9846  if (r->node_type == PT_VALUE && r->alias_print == NULL)
9847  {
9848  if (r->type_enum != PT_TYPE_INTEGER)
9849  {
9851  continue;
9852  }
9853  else if (r->info.value.data_value.i == 0 || r->info.value.data_value.i > max_position)
9854  {
9856  r->info.value.data_value.i);
9857  continue;
9858  }
9859  }
9860  else if (r->node_type == PT_HOST_VAR)
9861  {
9863  pt_short_print (parser, r));
9864  continue;
9865  }
9866 
9867  /* check for after group by position */
9868  pt_to_pos_descr (parser, &pos, r, node, &referred_node);
9869  if (pos.pos_no > 0)
9870  {
9871  /* set after group by position num, domain info */
9872  t_node->info.sort_spec.pos_descr = pos;
9873  }
9874  /*
9875  * If there is a node referred by the position,
9876  * we should rewrite the position to real name or expression
9877  * regardless of pos.pos_no.
9878  */
9879  if (referred_node != NULL)
9880  {
9881  t_node->info.sort_spec.expr = parser_copy_tree (parser, referred_node);
9882  parser_free_node (parser, r);
9883  }
9884  }
9885 
9886  /* STEP 2: check that grouped things are single valued */
9888  {
9889  (void) parser_walk_tree (parser, node->info.query.q.select.list, pt_check_single_valued_node, &info,
9891  (void) parser_walk_tree (parser, node->info.query.q.select.having, pt_check_single_valued_node, &info,
9893  }
9894  }
9895 
9896  if (pt_has_analytic (parser, node))
9897  {
9898  (void) parser_walk_tree (parser, node->info.query.q.select.list, pt_check_analytic_function, (void *) node,
9899  NULL, NULL);
9900  }
9901 
9902  /* check the order by */
9903  if (pt_check_order_by (parser, node) != NO_ERROR)
9904  {
9905  break; /* error */
9906  }
9907 
9909  {
9910  bool has_gbynum = false;
9911 
9912  /* we do not allow GROUP BY ... WITH ROLLUP and GROUPBY_NUM () */
9914  pt_check_groupbynum_post, (void *) &has_gbynum);
9915 
9916  if (has_gbynum)
9917  {
9919  }
9920  }
9921 
9922  if (node->info.query.q.select.connect_by)
9923  {
9924  bool has_level_greater, has_level_lesser;
9925  int disallow_ops[] = {
9926  2, /* number of operators */
9929  };
9930  (void) parser_walk_tree (parser, node->info.query.q.select.connect_by, pt_expr_disallow_op_pre, disallow_ops,
9931  NULL, NULL);
9932 
9933  /* check if the LEVEL of connect by is limited */
9934  pt_check_level_expr (parser, node->info.query.q.select.connect_by, &has_level_greater, &has_level_lesser);
9935  if (has_level_lesser)
9936  {
9937  /* override checking cycles to be ignored */
9939  {
9941  }
9942  else
9943  {
9945  }
9946  }
9947  }
9948 
9949  entity = node->info.query.q.select.from;
9950  if (entity != NULL && entity->info.spec.derived_table_type == PT_IS_SHOWSTMT
9951  && (derived_table = entity->info.spec.derived_table) != NULL && derived_table->node_type == PT_SHOWSTMT)
9952  {
9953  SHOWSTMT_TYPE show_type;
9954  SHOW_SEMANTIC_CHECK_FUNC check_func = NULL;
9955 
9956  show_type = derived_table->info.showstmt.show_type;
9957  check_func = showstmt_get_metadata (show_type)->semantic_check_func;
9958  if (check_func != NULL)
9959  {
9960  node = (*check_func) (parser, node);
9961  }
9962  }
9963 
9964  /* check for session variable assignments */
9965  {
9966  int arg[2];
9967 
9968  arg[0] = PT_DEFINE_VARIABLE; /* type */
9969  arg[1] = 0; /* found */
9970 
9971  (void) parser_walk_tree (parser, node->info.query.q.select.list, pt_find_op_type_pre, arg, NULL, NULL);
9972 
9973  if (arg[1]) /* an assignment was found */
9974  {
9976  }
9977  }
9978 
9979  node = pt_semantic_type (parser, node, info);
9980  break;
9981 
9982  case PT_DO:
9983  node = pt_semantic_type (parser, node, info);
9984  break;
9985 
9986  case PT_SET_XACTION:
9987  /* Check for multiple isolation settings and multiple timeout settings */
9988  (void) pt_check_xaction_list (parser, node->info.set_xaction.xaction_modes);
9989 
9990  /* Check for mismatch of schema and instance isolation levels */
9992  break;
9993 
9994  case PT_UPDATE:
9995  if (top_node->flag.cannot_prepare == 1)
9996  {
9997  node->flag.cannot_prepare = 1;
9998  }
9999 
10000  if (pt_has_aggregate (parser, node))
10001  {
10003  }
10004 
10005  pt_check_assignments (parser, node);
10006  pt_no_double_updates (parser, node);
10007 
10008  /* cannot update derived tables */
10009  pt_init_assignments_helper (parser, &ea, node->info.update.assignment);
10010  while ((t_node = pt_get_next_assignment (&ea)) != NULL)
10011  {
10012  entity = pt_find_spec_in_statement (parser, node, t_node);
10013 
10014  if (entity == NULL)
10015  {
10017  t_node->info.name.original);
10018  break;
10019  }
10020 
10021  if (entity->info.spec.derived_table != NULL || PT_SPEC_IS_CTE (entity))
10022  {
10024  break;
10025  }
10026 
10027  /* Update of views hierarchies not allowed */
10029  && entity->info.spec.only_all == PT_ALL)
10030  {
10032  t_node->info.name.original);
10033  break;
10034  }
10035  }
10036 
10037  /* Replace left to right attribute references in assignments before doing semantic check. The type checking phase
10038  * might have to perform some coercions on the replaced names. */
10039  node = pt_replace_names_in_update_values (parser, node);
10040 
10041  node = pt_semantic_type (parser, node, info);
10042 
10043  if (node != NULL && node->info.update.order_by != NULL)
10044  {
10045  PT_NODE *order;
10046  for (order = node->info.update.order_by; order != NULL; order = order->next)
10047  {
10048  PT_NODE *r = order->info.sort_spec.expr;
10049  if (r != NULL && r->node_type == PT_VALUE)
10050  {
10052  pt_short_print (parser, r));
10053  break;
10054  }
10055  }
10056  }
10057  break;
10058 
10060  node = pt_semantic_type (parser, node, info);
10061  break;
10062 
10063  case PT_EXPR:
10064  if (node->info.expr.op == PT_CAST)
10065  {
10066  node = pt_semantic_type (parser, node, info);
10067  if (node == NULL)
10068  {
10069  break;
10070  }
10071 
10072  if (node->node_type == PT_EXPR && node->info.expr.op == PT_CAST)
10073  {
10074  (void) pt_check_cast_op (parser, node);
10075  }
10076  }
10077 
10078  /* check instnum compatibility */
10080  {
10082  "INST_NUM() or ROWNUM", "INST_NUM() or ROWNUM");
10083  }
10084 
10085  /* check default function */
10086  if (node->info.expr.op == PT_DEFAULTF)
10087  {
10088  pt_check_defaultf (parser, node);
10089  }
10090 
10091  break;
10092 
10093  case PT_SPEC:
10094  {
10095  PT_NODE *derived_table, *a, *b, *select_list;
10096  int attr_cnt, col_cnt, i, j;
10097 
10098  /* check ambiguity in as_attr_list of derived-query */
10099  for (a = node->info.spec.as_attr_list; a && !pt_has_error (parser); a = a->next)
10100  {
10101  for (b = a->next; b && !pt_has_error (parser); b = b->next)
10102  {
10103  if (a->node_type == PT_NAME && b->node_type == PT_NAME
10105  {
10107  b->info.name.original);
10108  }
10109  }
10110  }
10111 
10112  /* check hidden column of subquery-derived table */
10113  if (!pt_has_error (parser) && node->info.spec.derived_table_type == PT_IS_SUBQUERY
10114  && (derived_table = node->info.spec.derived_table) && derived_table->node_type == PT_SELECT
10115  && derived_table->info.query.order_by && (select_list = pt_get_select_list (parser, derived_table)))
10116  {
10117  attr_cnt = pt_length_of_list (node->info.spec.as_attr_list);
10118  col_cnt = pt_length_of_select_list (select_list, INCLUDE_HIDDEN_COLUMNS);
10119  if (col_cnt - attr_cnt > 0)
10120  {
10121  /* make hidden column attrs */
10122  for (i = attr_cnt, j = attr_cnt; i < col_cnt; i++)
10123  {
10124  t_node = pt_name (parser, mq_generate_name (parser, "ha", &j));
10125  node->info.spec.as_attr_list = parser_append_node (t_node, node->info.spec.as_attr_list);
10126  }
10127  }
10128  }
10129  }
10130  break;
10131 
10132  case PT_NAME:
10135  {
10136  PT_NODE *data_type = node->data_type;
10137 
10138  if (data_type != NULL && data_type->type_enum == PT_TYPE_OBJECT)
10139  {
10140  const char *name = data_type->info.data_type.entity->info.name.original;
10141  DB_OBJECT *class_obj = db_find_class (name);
10142 
10143  if (class_obj != NULL && sm_is_reuse_oid_class (class_obj))
10144  {
10146  }
10147  }
10148  }
10149  break;
10150 
10151  case PT_MERGE:
10152  if (pt_has_error (parser))
10153  {
10154  break;
10155  }
10156 
10157  if (top_node->flag.cannot_prepare == 1)
10158  {
10159  node->flag.cannot_prepare = 1;
10160  }
10161 
10162  if (pt_has_aggregate (parser, node))
10163  {
10165  break;
10166  }
10167 
10168  pt_check_assignments (parser, node);
10169  pt_no_double_updates (parser, node);
10170 
10171  /* check destination derived table */
10172  entity = node->info.merge.into;
10173  if (entity->info.spec.derived_table != NULL)
10174  {
10176  break;
10177  }
10178 
10179  /* check update spec */
10180  pt_init_assignments_helper (parser, &ea, node->info.merge.update.assignment);
10181  while ((t_node = pt_get_next_assignment (&ea)) != NULL)
10182  {
10183  entity = pt_find_spec_in_statement (parser, node, t_node);
10184 
10185  if (entity == NULL)
10186  {
10188  t_node->info.name.original);
10189  break;
10190  }
10191  /* update assign spec should be merge target */
10192  if (entity->info.spec.id != node->info.merge.into->info.spec.id)
10193  {
10195  break;
10196  }
10197  }
10198  if (pt_has_error (parser))
10199  {
10200  break;
10201  }
10202 
10203  if (node->info.merge.insert.value_clauses)
10204  {
10205  if (node->info.merge.insert.value_clauses->next)
10206  {
10208  if (!pt_has_error (parser))
10209  {
10210  PT_ERRORc (parser, node, db_error_string (3));
10211  }
10212  break;
10213  }
10214  /* check insert attributes list */
10215  for (entity = node->info.merge.insert.attr_list; entity; entity = entity->next)
10216  {
10217  if (entity->info.name.spec_id != node->info.merge.into->info.spec.id)
10218  {
10219  PT_ERRORm (parser, entity, MSGCAT_SET_PARSER_SEMANTIC,
10221  break;
10222  }
10223  }
10224  if (pt_has_error (parser))
10225  {
10226  break;
10227  }
10228  }
10229 
10230  node = pt_semantic_type (parser, node, info);
10231 
10232  /* try to coerce insert_values into types indicated by insert_attributes */
10233  if (node)
10234  {
10235  pt_coerce_insert_values (parser, node);
10236  }
10237  break;
10238 
10239  case PT_JSON_TABLE:
10240  if (pt_has_error (parser))
10241  {
10242  break;
10243  }
10244 
10246  {
10249  }
10250 
10251  if (pt_check_json_table_node (parser, node->info.json_table_info.tree))
10252  {
10253  ASSERT_ERROR ();
10254  PT_ERRORc (parser, node, er_msg ());
10255  }
10256 
10257  break;
10258 
10259  default: /* other node types */
10260  break;
10261  }
10262 
10263  /* Select Aliasing semantic checking of select aliasing, check if it is zero-length string, i.e. "" Only appropriate
10264  * PT_NODE to be check will have 'alias' field as not NULL pointer because the initialized value of 'alias' is NULL
10265  * pointer. So it is safe to do semantic checking of aliasing out of the scope of above 'switch' statement and
10266  * without considering type of the PT_NODE. */
10267  if (node && node->alias_print && *(node->alias_print) == '\0')
10268  {
10270  }
10271 
10272  /* restore list link, if any */
10273  if (node)
10274  {
10275  node->next = next;
10276  }
10277 
10278  if (pt_has_error (parser))
10279  {
10280  if (node)
10281  {
10282  pt_register_orphan (parser, node);
10283  }
10284  else
10285  {
10286  pt_register_orphan (parser, orig);
10287  }
10288  return NULL;
10289  }
10290  else
10291  {
10292  return node;
10293  }
10294 }
10295 
10296 /*
10297  * pt_gen_isnull_preds () - Construct the IS NULL disjuncts for the expanded
10298  * list of path segments
10299  * return:
10300  * parser(in):
10301  * pred(in):
10302  * chain(in):
10303  */
10304 static PT_NODE *
10306 {
10307  PT_NODE *disj, *arg1, *next_spec, *conj, *new_path, *new_expr;
10308  PT_NODE *new_pred = NULL;
10309  UINTPTR next_spec_id;
10310  int i;
10311 
10312  /* The algorithm here is that we will incrementally build each new "IS NULL" disjunct. Each successive disjunct will
10313  * contain the previous path expression extended with the next path segment. We will use arg1 to build each
10314  * successive path expression. new_pred will collect the new disjuncts as we build them. */
10315 
10316  arg1 = NULL;
10317  for (i = 0; i < chain->chain_length - 1; i++)
10318  {
10319  /* Remember that the chain was constructed from the end of the path expression to the beginning. Thus, in path
10320  * expr a.b.c.d is null, segment d is in chain[0], c is in chain[1], b is in chain[2], and a is in chain[3].
10321  * Also, by convention, the path conjuncts implied by a path expression segment are hung off the path entity that
10322  * is generated by the path expression segment. In our case, this is the next spec in the chain. */
10323 
10324  next_spec = chain->chain_ptr[chain->chain_length - i - 2];
10325  next_spec_id = next_spec->info.spec.id;
10326  conj = next_spec->info.spec.path_conjuncts;
10327 
10328  /* check for structural errors */
10329  if ((conj->node_type != PT_EXPR) || (!conj->info.expr.arg1) || (!conj->info.expr.arg2)
10330  || (conj->info.expr.arg1->node_type != PT_NAME) || (conj->info.expr.arg2->node_type != PT_NAME)
10331  || (conj->info.expr.arg2->info.name.spec_id != next_spec_id))
10332  {
10333  goto error;
10334  }
10335 
10336  if (arg1 == NULL)
10337  {
10338  /* This is the first segment in the path expression. In this case we want to use the exposed name of the
10339  * spec found in the last chain slot. (i should be 0 here) */
10340  arg1 = parser_copy_tree (parser, conj->info.expr.arg1);
10341  if (arg1 == NULL)
10342  {
10343  goto out_of_mem;
10344  }
10345  }
10346  else
10347  {
10348  PT_NODE *arg2;
10349 
10350  /* we are building a new segment on the previous path expr */
10351  if (((new_path = parser_new_node (parser, PT_DOT_)) == NULL)
10352  || ((arg2 = parser_copy_tree (parser, conj->info.expr.arg1)) == NULL))
10353  {
10354  goto out_of_mem;
10355  }
10356 
10357  /* We need to null the resolved field of arg2 according to path expression conventions. This is necessary
10358  * since we copied part of the conjunct which is fully resolved. */
10359  arg2->info.name.resolved = NULL;
10360 
10361  /* attach both arguments to the new path segment */
10362  new_path->info.expr.arg1 = parser_copy_tree (parser, arg1);
10363  if (new_path->info.expr.arg1 == NULL)
10364  {
10365  goto out_of_mem;
10366  }
10367 
10368  new_path->info.expr.arg2 = arg2;
10369 
10370  /* attach the data type */
10371  new_path->line_number = pred->line_number;
10372  new_path->column_number = pred->column_number;
10373  new_path->type_enum = arg2->type_enum;
10374  if (arg2->data_type && ((new_path->data_type = parser_copy_tree_list (parser, arg2->data_type)) == NULL))
10375  {
10376  goto out_of_mem;
10377  }
10378 
10379  /* Maintain the loop invariant that arg1 always is the path expression that we build on. */
10380  arg1 = new_path;
10381  }
10382 
10383  /* Link it in with a disjunct. */
10384  disj = parser_new_node (parser, PT_EXPR);
10385  if (disj == NULL)
10386  {
10387  goto out_of_mem;
10388  }
10389 
10390  disj->line_number = pred->line_number;
10391  disj->column_number = pred->column_number;
10392  disj->type_enum = PT_TYPE_LOGICAL;
10393  disj->info.expr.op = PT_IS_NULL;
10394  disj->info.expr.arg1 = arg1;
10395 
10396  if (new_pred == NULL)
10397  {
10398  /* Maintain the loop invariant that new_pred contains the predicate built so far. */
10399  new_pred = disj;
10400  }
10401  else
10402  {
10403  new_expr = parser_new_node (parser, PT_EXPR);
10404  if (new_expr == NULL)
10405  {
10406  goto out_of_mem;
10407  }
10408 
10409  new_expr->line_number = pred->line_number;
10410  new_expr->column_number = pred->column_number;
10411  new_expr->type_enum = PT_TYPE_LOGICAL;
10412  new_expr->info.expr.op = PT_OR;
10413  new_expr->info.expr.arg1 = new_pred;
10414  new_expr->info.expr.arg2 = disj;
10415 
10416  /* Maintain the loop invariant that new_pred contains the predicate built so far. */
10417  new_pred = new_expr;
10418  }
10419  }
10420 
10421  new_expr = parser_new_node (parser, PT_EXPR);
10422  if (new_expr == NULL)
10423  {
10424  goto out_of_mem;
10425  }
10426 
10427  new_expr->line_number = pred->line_number;
10428  new_expr->column_number = pred->column_number;
10429  new_expr->type_enum = PT_TYPE_LOGICAL;
10430  new_expr->info.expr.op = PT_OR;
10431  new_expr->info.expr.arg1 = pred;
10432  new_expr->info.expr.arg2 = new_pred;
10433  new_expr->info.expr.paren_type = 1;
10434 
10435  return new_expr;
10436 
10437 out_of_mem:
10439  return NULL;
10440 
10441 error:
10442  PT_INTERNAL_ERROR (parser, "resolution");
10443  return NULL;
10444 }
10445 
10446 /*
10447  * pt_path_chain () - Construct the list of path entities that are used
10448  * in a path expression
10449  * return:
10450  * parser(in):
10451  * node(in):
10452  * arg(in):
10453  * continue_walk(in):
10454  */
10455 static PT_NODE *
10456 pt_path_chain (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10457 {
10458  PT_CHAIN_INFO *chain = (PT_CHAIN_INFO *) arg;
10459  PT_NODE *tmp;
10460 
10461  switch (node->node_type)
10462  {
10463  case PT_SPEC:
10464  if (node->info.spec.id == (UINTPTR) chain->spec_id)
10465  {
10466  /* This is the spec to which the final path segment resolves. Start gathering the spec chain. */
10467  chain->chain_ptr[0] = node;
10468  chain->chain_length = 1;
10469  }
10470  else if (chain->chain_length > 0)
10471  {
10472  /* This indicates that we are currently walking up the chain. Need to check if this spec is the parent of the
10473  * last spec. */
10474  for (tmp = node->info.spec.path_entities; tmp != NULL; tmp = tmp->next)
10475  {
10476  if (tmp == chain->chain_ptr[chain->chain_length - 1])
10477  {
10478  /* This is the parent, add it to the list. First check if we have space. */
10479  if (chain->chain_length == chain->chain_size)
10480  {
10481  /* Need to expand, just double the size. */
10482 
10483  chain->chain_size *= 2;
10484  if (chain->chain_ptr == chain->chain)
10485  {
10486  /* This will be the first time we need to alloc. */
10487  chain->chain_ptr = (PT_NODE **) malloc (chain->chain_size * sizeof (PT_NODE *));
10488  if (chain->chain_ptr == NULL)
10489  {
10490  goto out_of_mem;
10491  }
10492  memcpy (chain->chain_ptr, &chain->chain, (chain->chain_length * sizeof (PT_NODE *)));
10493  }
10494  else
10495  {
10496  PT_NODE **tmp;
10497 
10498  tmp = (PT_NODE **) realloc (chain->chain_ptr, (chain->chain_size * sizeof (PT_NODE *)));
10499  if (tmp == NULL)
10500  {
10501  goto out_of_mem;
10502  }
10503  chain->chain_ptr = tmp;
10504  }
10505  }
10506 
10507  /* Add in the parent. */
10508  chain->chain_ptr[chain->chain_length] = node;
10509  chain->chain_length++;
10510  }
10511  }
10512  }
10513  break;
10514 
10515  case PT_SELECT:
10516  case PT_DELETE:
10517  case PT_UPDATE:
10518  case PT_MERGE:
10519  if (chain->chain_length > 0)
10520  {
10521  /* We are about to leave the scope where the chain was found, we can safely stop the walk since we must have
10522  * found the whole chain. */
10523  *continue_walk = PT_STOP_WALK;
10524  }
10525  break;
10526 
10527  default:
10528  break;
10529  }
10530 
10531  return node;
10532 
10533 out_of_mem:
10535 
10536  *continue_walk = PT_STOP_WALK;
10537  return node;
10538 }
10539 
10540 /*
10541  * pt_expand_isnull_preds_helper () - expand path_expr "IS NULL" predicates to
10542  * include any path segment being NULL
10543  * return:
10544  * parser(in):
10545  * node(in):
10546  * arg(in):
10547  * continue_walk(in):
10548  */
10549 static PT_NODE *
10550 pt_expand_isnull_preds_helper (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10551 {
10552  PT_NODE *statement = (PT_NODE *) arg;
10553  PT_CHAIN_INFO chain_info;
10554 
10555  if (node->node_type == PT_EXPR && node->info.expr.op == PT_IS_NULL && node->info.expr.arg1->node_type == PT_DOT_)
10556  {
10557  chain_info.chain_ptr = chain_info.chain;
10558  chain_info.chain_size = PT_CHAIN_LENGTH;
10559  chain_info.chain_length = 0;
10560  chain_info.spec_id = node->info.expr.arg1->info.dot.arg2->info.name.spec_id;
10561 
10562  (void) parser_walk_tree (parser, statement, NULL, NULL, pt_path_chain, &chain_info);
10563 
10564  /* now that we have the chain, we need to construct the new "IS NULL" disjuncts. */
10565  if (!pt_has_error (parser) && chain_info.chain_length > 1)
10566  {
10567  node = pt_gen_isnull_preds (parser, node, &chain_info);
10568  }
10569 
10570  /* Free any allocated memory for the spec chain. */
10571  if (chain_info.chain_ptr != chain_info.chain)
10572  {
10573  free_and_init (chain_info.chain_ptr);
10574  }
10575  }
10576 
10577  return node;
10578 }
10579 
10580 /*
10581  * pt_expand_isnull_preds () - expand path_expr "IS NULL" predicates to
10582  * include any path segment being NULL
10583  * return:
10584  * parser(in):
10585  * node(in):
10586  * arg(in):
10587  * continue_walk(in):
10588  */
10589 static PT_NODE *
10590 pt_expand_isnull_preds (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10591 {
10592  PT_NODE *statement = (PT_NODE *) arg;
10593  PT_NODE **pred = NULL;
10594 
10595  switch (node->node_type)
10596  {
10597  case PT_UPDATE:
10598  pred = &node->info.update.search_cond;
10599  break;
10600 
10601  case PT_DELETE:
10602  pred = &node->info.delete_.search_cond;
10603  break;
10604 
10605  case PT_SELECT:
10606  pred = &node->info.query.q.select.where;
10607  break;
10608 
10609  case PT_MERGE:
10610  pred = &node->info.merge.insert.search_cond;
10611  if (pred)
10612  {
10613  *pred = parser_walk_tree (parser, *pred, NULL, NULL, pt_expand_isnull_preds_helper, statement);
10614  }
10615  pred = &node->info.merge.update.search_cond;
10616  if (pred)
10617  {
10618  *pred = parser_walk_tree (parser, *pred, NULL, NULL, pt_expand_isnull_preds_helper, statement);
10619  }
10620  pred = &node->info.merge.update.del_search_cond;
10621  if (pred)
10622  {
10623  *pred = parser_walk_tree (parser, *pred, NULL, NULL, pt_expand_isnull_preds_helper, statement);
10624  }
10625  pred = &node->info.merge.search_cond;
10626  break;
10627 
10628  default:
10629  break;
10630  }
10631 
10632  if (pred)
10633  {
10634  *pred = parser_walk_tree (parser, *pred, NULL, NULL, pt_expand_isnull_preds_helper, statement);
10635  }
10636 
10637  return node;
10638 }
10639 
10640 /*
10641  * pt_check_and_replace_hostvar () -
10642  * return:
10643  * parser(in):
10644  * node(in):
10645  * arg(in):
10646  * continue_walk(in/out):
10647  */
10648 static PT_NODE *
10649 pt_check_and_replace_hostvar (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
10650 {
10651  PT_NODE *value;
10652  DB_VALUE *dbval;
10653  DB_TYPE type;
10654  int *check = (int *) arg;
10655 
10656  /* do not replace path expression */
10657  if (pt_is_dot_node (node))
10658  {
10660  {
10661  *check = 1; /* this statement cannot be prepared */
10662  }
10663  *continue_walk = PT_LIST_WALK;
10664  return node;
10665  }
10666 
10667  /* method check */
10668  if (pt_is_method_call (node))
10669  {
10670  *check = 1; /* this statement cannot be prepared */
10671  return node;
10672  }
10673 
10674  /* replace input host var/parameter with its value if given */
10675  if ((pt_is_input_hostvar (node) && parser->host_var_count > node->info.host_var.index
10676  && parser->flag.set_host_var == 1) || pt_is_input_parameter (node))
10677  {
10678  type = pt_node_to_db_type (node);
10679  if (type == DB_TYPE_OBJECT || type == DB_TYPE_VOBJ || TP_IS_SET_TYPE (type))
10680  {
10681  if (pt_is_input_parameter (node))
10682  {
10683  *check = 1; /* this statement cannot be prepared */
10684  }
10685  return node;
10686  }
10687 
10688  dbval = pt_value_to_db (parser, node);
10689  if (dbval && !pr_is_set_type (db_value_type (dbval)))
10690  {
10691  value = pt_dbval_to_value (parser, dbval);
10692  if (value)
10693  {
10694  if (PT_HAS_COLLATION (value->type_enum))
10695  {
10696  value->info.value.print_charset = true;
10697  value->info.value.print_collation = true;
10698  value->info.value.is_collate_allowed = true;
10699  }
10700  if (pt_is_input_hostvar (node))
10701  {
10702  /* save host_var index */
10703  value->info.value.host_var_index = node->info.host_var.index;
10704  }
10705  PT_NODE_MOVE_NUMBER_OUTERLINK (value, node);
10706  parser_free_tree (parser, node);
10707  node = value;
10708  }
10709  }
10710  }
10711 
10712  return node;
10713 }
10714 
10715 /*
10716  * pt_check_with_clause () -
10717  * do semantic checks on "create entity" has "with clause"
10718  * this function is called from pt_check_create_entity only
10719  * so, not needed to check NULL for node
10720  *
10721  * return: NULL if no errors, attribute of CTE otherwise
10722  * node(in): a "with" statement that needs to be checked.
10723  */
10724 
10725 static PT_NODE *
10727 {
10729 
10730  if (cte)
10731  {
10732  PT_NODE *cte_part;
10733  PT_NODE *cte_attr;
10734 
10735  if (cte->info.cte.as_attr_list == NULL)
10736  {
10737  cte_part = cte->info.cte.non_recursive_part;
10738  if (cte_part)
10739  {
10740  for (cte_attr = pt_get_select_list (parser, cte_part); cte_attr != NULL; cte_attr = cte_attr->next)
10741  {
10742  if (cte_attr->alias_print == NULL && cte_attr->node_type != PT_NAME && cte_attr->node_type != PT_DOT_)
10743  {
10744  return cte_attr;
10745  }
10746  }
10747  }
10748 
10749  cte_part = cte->info.cte.recursive_part;
10750  if (cte_part)
10751  {
10752  for (cte_attr = pt_get_select_list (parser, cte_part); cte_attr != NULL; cte_attr = cte_attr->next)
10753  {
10754  if (cte_attr->alias_print == NULL && cte_attr->node_type != PT_NAME && cte_attr->node_type != PT_DOT_)
10755  {
10756  return cte_attr;
10757  }
10758  }
10759  }
10760  }
10761  }
10762 
10763  return NULL;
10764 }
10765 
10766 /*
10767  * pt_check_with_info () - do name resolution & semantic checks on this tree
10768  * return: statement if no errors, NULL otherwise
10769  * parser(in): the parser context
10770  * node(in): a parsed sql statement that needs to be checked.
10771  * info(in): NULL or info->attrdefs is a vclass' attribute defs list
10772  */
10773 
10774 static PT_NODE *
10776 {
10777  PT_NODE *next;
10778  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
10779  SEMANTIC_CHK_INFO *sc_info_ptr = info;
10780  bool save_donot_fold = false;
10781 
10782  assert (parser != NULL);
10783 
10784  if (!node)
10785  {
10786  return NULL;
10787  }
10788 
10789  /* If it is an internally created statement, set its host variable info again to search host variables at parent
10790  * parser */
10792 
10793  if (sc_info_ptr == NULL)
10794  {
10795  sc_info_ptr = &sc_info;
10796  }
10797  if (info)
10798  {
10799  save_donot_fold = sc_info_ptr->donot_fold; /* save */
10800  }
10801 
10802  sc_info_ptr->top_node = node;
10803  sc_info_ptr->donot_fold = false;
10804  next = node->next;
10805  node->next = NULL;
10806 
10807  switch (node->node_type)
10808  {
10809  case PT_UPDATE:
10810  /*
10811  * If it is an update object, get the object to update, and create an
10812  * entity so that pt_resolve_names will work.
10813  * THIS NEEDS TO BE MOVED INTO RESOLVE NAMES.
10814  */
10815  if (node->info.update.object_parameter != NULL)
10816  {
10817  pt_resolve_object (parser, node);
10818  }
10819  /* FALLTHRU */
10820 
10821  case PT_HOST_VAR:
10822  case PT_EXPR:
10823  case PT_NAME:
10824  case PT_VALUE:
10825  case PT_FUNCTION:
10826 
10827  case PT_DELETE:
10828  case PT_INSERT:
10829  case PT_METHOD_CALL:
10830  case PT_UNION:
10831  case PT_INTERSECTION:
10832  case PT_DIFFERENCE:
10833  case PT_SELECT:
10834  case PT_EVALUATE:
10835  case PT_SET_XACTION:
10836  case PT_SCOPE:
10837  case PT_DO:
10839  case PT_MERGE:
10840 #if 0 /* to disable TEXT */
10841  /* we postpone TEXT resolution of a insert statement at '*' resolution if (node->node_type == PT_INSERT) {
10842  * pt_resolve_insert_external(parser, node); } else */
10843  if (node->node_type == PT_DELETE)
10844  {
10845  pt_resolve_delete_external (parser, node);
10846  }
10847  else if (node->node_type == PT_UPDATE)
10848  {
10849  pt_resolve_update_external (parser, node);
10850  }
10851 #endif /* 0 */
10852 
10853  sc_info_ptr->system_class = false;
10854  node = pt_resolve_names (parser, node, sc_info_ptr);
10855 
10856  if (!pt_has_error (parser))
10857  {
10858  node = pt_check_where (parser, node);
10859  }
10860 
10861  if (!pt_has_error (parser))
10862  {
10863  if (sc_info_ptr->system_class && PT_IS_QUERY (node))
10864  {
10865  /* do not cache the result if a system class is involved in the query */
10866  node->info.query.flag.reexecute = 1;
10867  node->info.query.flag.do_cache = 0;
10868  node->info.query.flag.do_not_cache = 1;
10869  node->info.query.flag.has_system_class = 1;
10870  }
10871 
10872  if (node->node_type == PT_UPDATE || node->node_type == PT_DELETE || node->node_type == PT_INSERT
10873  || node->node_type == PT_UNION || node->node_type == PT_INTERSECTION || node->node_type == PT_DIFFERENCE
10874  || node->node_type == PT_SELECT || node->node_type == PT_DO || node->node_type == PT_SET_SESSION_VARIABLES
10875  || node->node_type == PT_MERGE)
10876  {
10877  /* may have WHERE clause */
10878  int check = 0;
10879 
10880  node = parser_walk_tree (parser, node, pt_check_and_replace_hostvar, &check, pt_continue_walk, NULL);
10881  if (check)
10882  {
10883  node->flag.cannot_prepare = 1;
10884  }
10885 
10886  /* because the statement has some object type PT_PARAMETER, it cannot be prepared */
10887  if (parent_parser != NULL)
10888  {
10889  node->flag.cannot_prepare = 1;
10890  }
10891  }
10892 
10894 
10895  if (!pt_has_error (parser))
10896  {
10897  /* remove unnecessary variable */
10898  node = parser_walk_tree (parser, node, NULL, NULL, pt_semantic_check_local, sc_info_ptr);
10899 
10900  if (!pt_has_error (parser))
10901  {
10902  /* This must be done before CNF since we are adding disjuncts to the "IS NULL" expression. */
10903  node = parser_walk_tree (parser, node, pt_expand_isnull_preds, node, NULL, NULL);
10904  }
10905  }
10906  }
10907 
10908  break;
10909 
10910  case PT_CREATE_INDEX:
10911  case PT_ALTER_INDEX:
10912  case PT_DROP_INDEX:
10913  if (parser->host_var_count)
10914  {
10916  }
10917  else
10918  {
10919  sc_info_ptr->system_class = false;
10920  node = pt_resolve_names (parser, node, sc_info_ptr);
10921  if (!pt_has_error (parser) && node->node_type == PT_CREATE_INDEX)
10922  {
10923  pt_check_create_index (parser, node);
10924  }
10925 
10926  if (!pt_has_error (parser) && (node->node_type == PT_DROP_INDEX || node->node_type == PT_ALTER_INDEX))
10927  {
10928  pt_check_function_index_expr (parser, node);
10929  }
10930 
10931  if (!pt_has_error (parser) && node->node_type == PT_ALTER_INDEX)
10932  {
10933  DB_OBJECT *db_obj = NULL;
10934  PT_NODE *name = NULL;
10935 
10936  if (node->info.index.indexed_class)
10937  {
10938  name = node->info.index.indexed_class->info.spec.entity_name;
10939  db_obj = db_find_class (name->info.name.original);
10940 
10941  if (db_obj == NULL)
10942  {
10944  name->info.name.original);
10945  }
10946  }
10947 
10948  if (!pt_has_error (parser))
10949  {
10950  pt_check_filter_index_expr (parser, node->info.index.column_names, node->info.index.where, db_obj);
10951  }
10952  }
10953 
10954  if (!pt_has_error (parser))
10955  {
10956  node = pt_semantic_type (parser, node, info);
10957  }
10958 
10959  if (node && !pt_has_error (parser))
10960  {
10961  if (node->info.index.where && pt_false_search_condition (parser, node->info.index.where))
10962  {
10964  pt_short_print (parser, node->info.index.where));
10965  }
10966  }
10967 
10968  if (node && !pt_has_error (parser))
10969  {
10970  if (node->info.index.function_expr
10972  {
10973  break;
10974  }
10975  }
10976 
10977  if (node && !pt_has_error (parser))
10978  {
10979  node = parser_walk_tree (parser, node, NULL, NULL, pt_semantic_check_local, sc_info_ptr);
10980 
10981  if (!pt_has_error (parser))
10982  {
10983  /* This must be done before CNF since we are adding disjuncts to the "IS NULL" expression. */
10984  node = parser_walk_tree (parser, node, pt_expand_isnull_preds, node, NULL, NULL);
10985  }
10986  }
10987  }
10988  break;
10989 
10990  case PT_SAVEPOINT:
10992  {
10993  node = pt_resolve_names (parser, node, sc_info_ptr);
10994  }
10995  break;
10996 
10997  case PT_ROLLBACK_WORK:
10998  if ((node->info.rollback_work.save_name)
11000  {
11001  node = pt_resolve_names (parser, node, sc_info_ptr);
11002  }
11003  break;
11004 
11005  case PT_AUTH_CMD:
11006  break; /* see GRANT/REVOKE */
11007 
11008  case PT_DROP:
11009  pt_check_drop (parser, node);
11010  break;
11011 
11012  case PT_VACUUM:
11013  pt_check_vacuum (parser, node);
11014  break;
11015 
11016  case PT_GRANT:
11017  case PT_REVOKE:
11018  pt_check_grant_revoke (parser, node);
11019  break;
11020 
11021  case PT_TRUNCATE:
11022  pt_check_truncate (parser, node);
11023  break;
11024 
11025  case PT_KILL_STMT:
11026  pt_check_kill (parser, node);
11027  break;
11028 
11029  case PT_ALTER_SERIAL:
11030  case PT_ALTER_TRIGGER:
11031  case PT_ALTER_USER:
11032  case PT_CREATE_SERIAL:
11033  case PT_CREATE_TRIGGER:
11034  case PT_DROP_SERIAL:
11035  case PT_DROP_TRIGGER:
11036  case PT_DROP_USER:
11037  case PT_RENAME:
11038  case PT_RENAME_TRIGGER:
11039  case PT_UPDATE_STATS:
11040  break;
11041 
11042  case PT_ALTER:
11043  pt_check_alter (parser, node);
11044 
11045  if (node->info.alter.code == PT_ADD_ATTR_MTHD || node->info.alter.code == PT_ADD_INDEX_CLAUSE)
11046  {
11047  if (parser->host_var_count)
11048  {
11050  break;
11051  }
11052  }
11053 
11054  if (node->info.alter.code == PT_ADD_INDEX_CLAUSE)
11055  {
11056  /* apply typechecking on ALTER TABLE ADD INDEX statements, to check the expression in the WHERE clause of
11057  * a partial index */
11058  PT_NODE *p = node->info.alter.create_index;
11059  assert (p != NULL);
11060 
11061  while (p)
11062  {
11063  sc_info_ptr->system_class = false;
11064  p = pt_resolve_names (parser, p, sc_info_ptr);
11065  if (p && !pt_has_error (parser))
11066  {
11067  pt_check_create_index (parser, p);
11068  }
11069 
11070  if (!pt_has_error (parser))
11071  {
11072  p = pt_semantic_type (parser, p, info);
11073  }
11074 
11075  if (p && !pt_has_error (parser))
11076  {
11077  p = parser_walk_tree (parser, p, NULL, NULL, pt_semantic_check_local, sc_info_ptr);
11078 
11079  if (p && !pt_has_error (parser))
11080  {
11081  /* This must be done before CNF since we are adding disjuncts to the "IS NULL" expression. */
11082  p = parser_walk_tree (parser, p, pt_expand_isnull_preds, p, NULL, NULL);
11083  }
11084  }
11085 
11086  if (p != NULL && !pt_has_error (parser) && p->info.index.function_expr != NULL
11088  {
11089  break;
11090  }
11091  if (p && !pt_has_error (parser))
11092  {
11093  p = p->next;
11094  }
11095  else
11096  {
11097  break;
11098  }
11099  }
11100  }
11101  break;
11102 
11103  case PT_CREATE_ENTITY:
11104  pt_check_create_entity (parser, node);
11105  break;
11106 
11107  case PT_CREATE_USER:
11108  pt_check_create_user (parser, node);
11109  break;
11110 
11111  default:
11112  break;
11113  }
11114 
11115  /* restore list link, if any */
11116  if (node)
11117  {
11118  node->next = next;
11119  }
11120 
11121  if (info)
11122  {
11123  sc_info_ptr->donot_fold = save_donot_fold; /* restore */
11124  }
11125 
11127 
11129  {
11130  PT_ERRORc (parser, node, db_error_string (3));
11131  }
11132 
11133  if (pt_has_error (parser))
11134  {
11135  pt_register_orphan (parser, node);
11136  return NULL;
11137  }
11138  else
11139  {
11140  return node;
11141  }
11142 }
11143 
11144 /*
11145  * pt_semantic_quick_check_node () - perform semantic validation on a
11146  * node that is not necessarily part of a
11147  * statement
11148  * return : modified node or NULL on error
11149  * parser (in) : parser context
11150  * entity_name (in) : PT_NAME of the class containing attributes from node
11151  * node (in) : node to check
11152  *
11153  * Note: Callers of this function need both the spec and the node after
11154  * the call. This is why we have to pass pointers to PT_NODE*
11155  */
11156 PT_NODE *
11158 {
11159  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
11160  int error = NO_ERROR;
11161  PT_NODE *node = NULL;
11162 
11163  /* resolve names */
11164  error = pt_quick_resolve_names (parser, spec_p, node_p, &sc_info);
11165  if (error != NO_ERROR || pt_has_error (parser))
11166  {
11167  return NULL;
11168  }
11169 
11170  node = *node_p;
11171 
11172  /* perform semantic check */
11173  node = pt_semantic_type (parser, node, &sc_info);
11174  if (node == NULL)
11175  {
11176  return NULL;
11177  }
11178  node_p = &node;
11179  return node;
11180 }
11181 
11182 /*
11183  * pt_semantic_check () -
11184  * return: PT_NODE *(modified) if no errors, else NULL if errors
11185  * parser(in):
11186  * node(in): statement a parsed sql statement that needs to be checked
11187  */
11188 
11189 PT_NODE *
11191 {
11192  return pt_check_with_info (parser, node, NULL);
11193 }
11194 
11195 /*
11196  * pt_find_class () -
11197  * return: DB_OBJECT * for the class whose name is in p,
11198  * NULL if not a class name
11199  * parser(in):
11200  * p(in): a PT_NAME node
11201  *
11202  * Note :
11203  * Finds CLASS VCLASS VIEW only
11204  */
11205 static DB_OBJECT *
11206 pt_find_class (PARSER_CONTEXT * parser, PT_NODE * p, bool for_update)
11207 {
11208  if (!p)
11209  return 0;
11210 
11211  if (p->node_type != PT_NAME)
11212  return 0;
11213 
11214  return db_find_class_with_purpose (p->info.name.original, for_update);
11215 }
11216 
11217 
11218 /*
11219  * pt_check_unique_attr () - check that there are no duplicate attr
11220  * in given list
11221  * return: none
11222  * parser(in): the parser context
11223  * entity_name(in): class name or index name
11224  * att(in): an attribute definition list
11225  * att_type(in): an attribute definition type list
11226  */
11227 static void
11228 pt_check_unique_attr (PARSER_CONTEXT * parser, const char *entity_name, PT_NODE * att, PT_NODE_TYPE att_type)
11229 {
11230  PT_NODE *p, *q, *p_nam, *q_nam;
11231 
11232  assert (parser != NULL);
11233  if (!att)
11234  {
11235  return;
11236  }
11237 
11238  for (p = att; p; p = p->next)
11239  {
11240  if (p->node_type != att_type)
11241  {
11242  continue; /* give up */
11243  }
11244 
11245  p_nam = NULL; /* init */
11246  if (att_type == PT_ATTR_DEF)
11247  {
11248  p_nam = p->info.attr_def.attr_name;
11249  }
11250  else if (att_type == PT_SORT_SPEC)
11251  {
11252  p_nam = p->info.sort_spec.expr;
11253  }
11254 
11255  if (p_nam == NULL || p_nam->node_type != PT_NAME)
11256  {
11257  continue; /* give up */
11258  }
11259 
11260  for (q = p->next; q; q = q->next)
11261  {
11262  if (q->node_type != att_type)
11263  {
11264  continue; /* give up */
11265  }
11266 
11267  q_nam = NULL; /* init */
11268  if (att_type == PT_ATTR_DEF)
11269  {
11270  q_nam = q->info.attr_def.attr_name;
11271  }
11272  else if (att_type == PT_SORT_SPEC)
11273  {
11274  q_nam = q->info.sort_spec.expr;
11275  }
11276 
11277  if (q_nam == NULL || q_nam->node_type != PT_NAME)
11278  {
11279  continue; /* give up */
11280  }
11281 
11282  /* a class attribute and a normal attribute can have identical names */
11283  if (att_type == PT_ATTR_DEF)
11284  {
11286  {
11287  continue; /* OK */
11288  }
11289  }
11290 
11292  {
11293  if (att_type == PT_ATTR_DEF) /* is class entity */
11294  {
11296  q_nam->info.name.original, entity_name);
11297  }
11298  else /* is index entity */
11299  {
11301  q_nam->info.name.original);
11302  }
11303  }
11304  }
11305  }
11306 }
11307 
11308 /*
11309  * pt_assignment_class_compatible () - Make sure that the rhs is a valid
11310  * candidate for assignment into the lhs
11311  * return: error_code
11312  * parser(in): handle to context used to parse the insert statement
11313  * lhs(in): the AST form of an attribute from the namelist part of an insert
11314  * rhs(in): the AST form of an expression from the values part of an insert
11315  */
11316 static int
11318 {
11319  assert (parser != NULL);
11320  assert (lhs != NULL);
11321  assert (lhs->node_type == PT_NAME);
11322  assert (lhs->type_enum != PT_TYPE_NONE);
11323  assert (rhs != NULL);
11324 
11325  if (lhs->node_type == PT_NAME)
11326  {
11327  if (lhs->type_enum == PT_TYPE_OBJECT)
11328  {
11329  if (!pt_class_assignable (parser, lhs->data_type, rhs))
11330  {
11331  /* incompatible object domains */
11333  lhs->info.name.original);
11334  return ER_FAILED;
11335  }
11336  }
11337  }
11338 
11339  return NO_ERROR;
11340 }
11341 
11342 /*
11343  * pt_assignment_compatible () - Make sure that the rhs is a valid candidate
11344  * for assignment into the lhs
11345  * return: the rhs node if compatible, NULL for errors
11346  * parser(in): handle to context used to parse the insert statement
11347  * lhs(in): the AST form of an attribute from the namelist part of an insert
11348  * rhs(in): the AST form of an expression from the values part of an insert
11349  */
11350 static PT_NODE *
11352 {
11353  assert (parser != NULL);
11354  assert (lhs != NULL);
11355  assert (lhs->node_type == PT_NAME);
11356  assert (rhs != NULL);
11357 
11358  if (lhs->type_enum == PT_TYPE_OBJECT)
11359  {
11360  if (rhs->node_type == PT_HOST_VAR && (rhs->type_enum == PT_TYPE_NONE || rhs->type_enum == PT_TYPE_MAYBE))
11361  {
11362  rhs->type_enum = lhs->type_enum;
11363  rhs->data_type = parser_copy_tree_list (parser, lhs->data_type);
11364  return rhs;
11365  }
11366 
11367  if (pt_assignment_class_compatible (parser, lhs, rhs) != NO_ERROR)
11368  {
11369  return NULL;
11370  }
11371  }
11372  else
11373  {
11374  SEMAN_COMPATIBLE_INFO sci = {
11375  0, PT_TYPE_NONE, 0, 0, false, pt_coll_infer (), NULL
11376  };
11377  bool is_cast_allowed = true;
11378 
11379  sci.type_enum = lhs->type_enum;
11380  if (lhs->data_type)
11381  {
11382  sci.prec = lhs->data_type->info.data_type.precision;
11384  if (lhs->type_enum == PT_TYPE_JSON && lhs->data_type->info.data_type.json_schema != NULL)
11385  {
11386  sci.force_cast = true;
11387  }
11388  }
11389 
11390  if (PT_HAS_COLLATION (lhs->type_enum))
11391  {
11392  (void) pt_get_collation_info (lhs, &(sci.coll_infer));
11393  }
11394 
11395  if (pt_is_compatible_without_cast (parser, &sci, rhs, &is_cast_allowed))
11396  {
11397  return rhs;
11398  }
11399 
11400  if (!is_cast_allowed)
11401  {
11402  return NULL;
11403  }
11404 
11405  if (rhs->type_enum != PT_TYPE_NULL)
11406  {
11407  if (rhs->type_enum == PT_TYPE_MAYBE)
11408  {
11409  TP_DOMAIN *d;
11410 
11411  if (lhs->type_enum == PT_TYPE_ENUMERATION)
11412  {
11413  d = pt_data_type_to_db_domain (parser, lhs->data_type, NULL);
11414  d = tp_domain_cache (d);
11415  }
11416  else
11417  {
11418  DB_TYPE lhs_dbtype;
11419 
11421  || lhs->data_type != NULL);
11422  lhs_dbtype = pt_type_enum_to_db (lhs->type_enum);
11423 
11424  if (rhs->node_type != PT_HOST_VAR)
11425  {
11426  // TODO: It should be considered for parameterized types, refer to PT_IS_PARAMETERIZED_TYPE()
11427  if (lhs->type_enum == PT_TYPE_NUMERIC && lhs->data_type != NULL)
11428  {
11429  d = tp_domain_resolve (lhs_dbtype, NULL, sci.prec, sci.scale, NULL, 0);
11430  }
11431  else
11432  {
11433  d = tp_domain_resolve_default (lhs_dbtype);
11434  }
11435  }
11436  else
11437  {
11438  TP_DOMAIN *hv_domain = NULL;
11439 
11440  /* node_type is PT_HOST_VAR set host var's expected domain with next order of priority. 1.
11441  * host_var->host_var_expected_domains[index] 2. lhs's expected domain 3. default domain of lhs
11442  * type */
11443  if (rhs->info.host_var.index < parser->host_var_count && parser->host_var_expected_domains)
11444  {
11445  hv_domain = parser->host_var_expected_domains[rhs->info.host_var.index];
11446  }
11447 
11448  if (hv_domain && hv_domain->type->id != DB_TYPE_UNKNOWN)
11449  {
11450  /* host var's expected domain is already set */
11451  d = hv_domain;
11453  {
11454  d->codeset = sci.coll_infer.codeset;
11455  d->collation_id = sci.coll_infer.coll_id;
11456  }
11457  }
11458  else
11459  {
11460  /* use lhs's expected_domain */
11461  if (lhs->expected_domain != NULL)
11462  {
11463  d = lhs->expected_domain;
11464  }
11465  else
11466  {
11467  // TODO: It should be considered for parameterized types, refer to PT_IS_PARAMETERIZED_TYPE()
11468  if (lhs->type_enum == PT_TYPE_NUMERIC && lhs->data_type != NULL)
11469  {
11470  d = tp_domain_resolve (lhs_dbtype, NULL, sci.prec, sci.scale, NULL, 0);
11471  }
11472  else
11473  {
11474  d = tp_domain_resolve_default (lhs_dbtype);
11475  }
11476  }
11477 
11478  if (PT_HAS_COLLATION (lhs->type_enum))
11479  {
11480  d = tp_domain_copy (d, false);
11481  d->codeset = sci.coll_infer.codeset;
11482  d->collation_id = sci.coll_infer.coll_id;
11483  d = tp_domain_cache (d);
11484  }
11485  }
11486  }
11487  }
11488 
11489  pt_set_expected_domain (rhs, d);
11490  if (rhs->node_type == PT_HOST_VAR)
11491  {
11492  pt_preset_hostvar (parser, rhs);
11493  }
11494  }
11495  else
11496  {
11497  bool rhs_is_collection_with_str = false;
11498  PT_NODE *cast_dt = NULL;
11499 
11501  || lhs->data_type != NULL);
11502 
11503  if (PT_IS_COLLECTION_TYPE (rhs->type_enum) && lhs->data_type == NULL && rhs->data_type != NULL)
11504  {
11505  PT_NODE *dt_element;
11506 
11507  dt_element = rhs->data_type;
11508 
11509  while (dt_element != NULL)
11510  {
11511  if (PT_IS_CHAR_STRING_TYPE (dt_element->type_enum))
11512  {
11513  rhs_is_collection_with_str = true;
11514  break;
11515  }
11516  dt_element = dt_element->next;
11517  }
11518  }
11519 
11521  && lhs->data_type == NULL && rhs_is_collection_with_str == true)
11522  {
11523  PT_NODE *dt_element;
11524 
11525  /* create a data type for lhs with with string having DB charset */
11526  cast_dt = parser_copy_tree_list (parser, rhs->data_type);
11527 
11528  dt_element = cast_dt;
11529 
11530  while (dt_element != NULL)
11531  {
11532  if (PT_IS_CHAR_STRING_TYPE (dt_element->type_enum))
11533  {
11535  dt_element->info.data_type.units = lang_charset ();
11537  }
11538  dt_element = dt_element->next;
11539  }
11540  }
11541  else
11542  {
11543  cast_dt = lhs->data_type;
11544  }
11545 
11546  rhs = pt_wrap_with_cast_op (parser, rhs, lhs->type_enum, 0, 0, cast_dt);
11547  if (cast_dt != NULL && cast_dt != lhs->data_type)
11548  {
11549  parser_free_tree (parser, cast_dt);
11550  cast_dt = NULL;
11551  }
11552  /* the call to pt_wrap_with_cast_op might fail because a call to allocate memory failed. In this case,
11553  * the error message is set by the calls inside pt_wrap_with_cast_op and we just return NULL */
11554  }
11555  }
11556  }
11557 
11558  return rhs;
11559 }
11560 
11561 /*
11562  * pt_check_assignments () - assert that the lhs of the set clause are
11563  * all pt_name nodes.
11564  * This will guarantee that there are no complex path expressions.
11565  * Also asserts that the right hand side is assignment compatible.
11566  * return: none
11567  * parser(in): the parser context
11568  * stmt(in): an update or merge statement
11569  */
11570 
11571 static void
11573 {
11574  PT_NODE *a, *next, *lhs, *rhs, *list, *rhs_list;
11575  PT_NODE *assignment_list;
11576 
11577  assert (parser != NULL);
11578 
11579  assignment_list = pt_get_assignments (stmt);
11580  if (assignment_list == NULL)
11581  {
11582  return;
11583  }
11584 
11585  for (a = assignment_list; a; a = next)
11586  {
11587  next = a->next; /* save next link */
11588  if (a->node_type == PT_EXPR && a->info.expr.op == PT_ASSIGN && (lhs = a->info.expr.arg1) != NULL
11589  && (rhs = a->info.expr.arg2) != NULL)
11590  {
11591  if (lhs->node_type == PT_NAME)
11592  {
11593  if (pt_is_query (rhs))
11594  {
11595  /* check select list length */
11596  rhs_list = pt_get_select_list (parser, rhs);
11597  assert (rhs_list != NULL);
11598  if (pt_length_of_select_list (rhs_list, EXCLUDE_HIDDEN_COLUMNS) != 1)
11599  {
11600  /* e.g., a = (select 1, 2 from ...) */
11602  }
11603  else
11604  {
11605  (void) pt_assignment_class_compatible (parser, lhs, rhs_list);
11606  }
11607  }
11608  else
11609  {
11610  /* Not a query, just check if assignment is possible. The call below will wrap the rhs node with a
11611  * cast to the type of the lhs_node */
11612  (void) pt_assignment_class_compatible (parser, lhs, rhs);
11613  }
11614  }
11615  else if (lhs->node_type == PT_EXPR && PT_IS_N_COLUMN_UPDATE_EXPR (lhs) && (list = lhs->info.expr.arg1))
11616  {
11617  /* multi-column update with subquery CASE1: always-false subquery is already converted NULL. so, change
11618  * NULL into NULL paren-expr (a) = NULL -> a = NULL (a, b) = NULL -> a = NULL, b = NULL CASE2: (a, b) =
11619  * subquery */
11620 
11621  if (rhs->type_enum == PT_TYPE_NA || rhs->type_enum == PT_TYPE_NULL)
11622  {
11623  /* CASE 1: flatten multi-column assignment expr */
11624  PT_NODE *e1, *e1_next, *e2, *tmp;
11625 
11626  a->next = NULL; /* cut-off expr link */
11627  lhs->info.expr.arg1 = NULL; /* cut-off lhs link */
11628 
11629  parser_free_tree (parser, lhs); /* free exp, arg1 */
11630  parser_free_tree (parser, rhs); /* free exp, arg1 */
11631 
11632  e2 = parser_new_node (parser, PT_VALUE);
11633  if (e2 == NULL)
11634  {
11636  return;
11637  }
11638 
11639  e2->type_enum = PT_TYPE_NULL;
11640  a->info.expr.arg1 = list;
11641  a->info.expr.arg2 = e2;
11642  e1 = list->next;
11643  list->next = NULL;
11644  tmp = NULL; /* init */
11645 
11646  for (; e1; e1 = e1_next)
11647  {
11648  e1_next = e1->next;
11649  e1->next = NULL;
11650 
11651  e2 = parser_new_node (parser, PT_VALUE);
11652  if (e2 == NULL)
11653  {
11655  return;
11656  }
11657  e2->type_enum = PT_TYPE_NULL;
11658 
11659  tmp = parser_new_node (parser, PT_EXPR);
11660  if (tmp == NULL)
11661  {
11663  return;
11664  }
11665 
11666  tmp->info.expr.op = PT_ASSIGN;
11667  tmp->info.expr.arg1 = e1;
11668  tmp->info.expr.arg2 = e2;
11669  parser_append_node (tmp, a);
11670  }
11671 
11672  if (tmp == NULL)
11673  {
11674  a->next = next; /* (a) = NULL */
11675  }
11676  else
11677  {
11678  tmp->next = next; /* (a, b) = NULL */
11679  }
11680  }
11681  else if (pt_is_query (rhs))
11682  {
11683  /* check select list length */
11684  rhs_list = pt_get_select_list (parser, rhs);
11685  assert (rhs_list != NULL);
11687  {
11689  }
11690  else
11691  {
11692  for (; list && rhs_list; rhs_list = rhs_list->next)
11693  {
11694  if (rhs_list->flag.is_hidden_column)
11695  {
11696  /* skip hidden column */
11697  continue;
11698  }
11699 
11700  (void) pt_assignment_class_compatible (parser, list, rhs_list);
11701  list = list->next;
11702  }
11703  assert (list == NULL);
11704  assert (rhs_list == NULL);
11705  }
11706  }
11707  }
11708  else
11709  {
11711  }
11712  }
11713  else
11714  {
11715  /* malformed assignment list */
11716  PT_INTERNAL_ERROR (parser, "semantic");
11717  }
11718  }
11719 }
11720 
11721 /*
11722  * pt_replace_names_in_update_values () - Walk through update assignments and
11723  * replace references to attributes
11724  * with assignments for those
11725  * attributes
11726  * return : UPDATE statement or NULL
11727  * parser (in) : parser context
11728  * update (in) : UPDATE parse tree
11729  *
11730  * Note: Update assignments are considered to be evaluate left to right.
11731  * For each attribute referenced on the right side of an assignment, if the
11732  * attribute was referenced in an assignment which appears in the UPDATE
11733  * statement before this assignment (i.e.: to the left of this assigment)
11734  * replace the value with that assignment.
11735  */
11736 static PT_NODE *
11738 {
11739  PT_NODE *attr = NULL, *val = NULL;
11740  PT_NODE *node = NULL, *prev = NULL;
11741 
11743  {
11744  /* Use SQL standard approach which always uses the existing value for an attribute rather than the updated value */
11745  return update;
11746  }
11747 
11748  if (update == NULL)
11749  {
11750  return NULL;
11751  }
11752 
11753  prev = update->info.update.assignment;
11754  if (prev == NULL)
11755  {
11756  return NULL;
11757  }
11758 
11759  if (prev->next == NULL)
11760  {
11761  /* only one assignment, nothing to be done */
11762  return update;
11763  }
11764 
11765  for (node = prev->next; node != NULL; prev = node, node = node->next)
11766  {
11767  if (!PT_IS_EXPR_NODE (node) || node->info.expr.op != PT_ASSIGN)
11768  {
11769  /* this is probably an error but it will be caught later */
11770  continue;
11771  }
11772 
11773  attr = node->info.expr.arg1;
11774  if (PT_IS_N_COLUMN_UPDATE_EXPR (attr))
11775  {
11776  /* Cannot reference other assignments in N_COLUMN_UPDATE_EXPR */
11777  continue;
11778  }
11779 
11780  val = node->info.expr.arg2;
11781  if (val == NULL || PT_IS_CONST (val))
11782  {
11783  /* nothing to be done for constants */
11784  continue;
11785  }
11786 
11787  /* This assignment is attr = expr. Walk expr and replace all occurrences of attributes with previous assignments.
11788  * Set prev->next to NULL so that we only search in assignments to the left of the current one. */
11789  prev->next = NULL;
11790 
11791  val =
11793 
11794  if (val != NULL && val != node->info.expr.arg2)
11795  {
11796  parser_free_tree (parser, node->info.expr.arg2);
11797  node->info.expr.arg2 = val;
11798  }
11799 
11800  /* repair node and list */
11801  prev->next = node;
11802  }
11803 
11804  return update;
11805 }
11806 
11807 /*
11808  * pt_replace_referenced_attributes () - replace an attributes with
11809  * expressions from previous assignments
11810  * return : node or NULL
11811  * parser (in) :
11812  * node (in) :
11813  * arg (in) :
11814  * continue_walk (in) :
11815  */
11816 static PT_NODE *
11817 pt_replace_referenced_attributes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
11818 {
11819  PT_NODE *assignment = NULL, *val = NULL;
11820  PT_NODE *assignments = (PT_NODE *) arg;
11821 
11822  *continue_walk = PT_CONTINUE_WALK;
11823 
11824  if (!pt_is_attr (node))
11825  {
11826  return node;
11827  }
11828 
11829  if (node->node_type != PT_NAME)
11830  {
11831  /* this is a PT_DOT, we don't have to go further */
11832  *continue_walk = PT_LIST_WALK;
11833  }
11834 
11835  if (assignments == NULL)
11836  {
11837  assert_release (assignments != NULL);
11838  return node;
11839  }
11840 
11841  /* search for name in assignments */
11842  for (assignment = assignments; assignment != NULL; assignment = assignment->next)
11843  {
11844  if (PT_IS_N_COLUMN_UPDATE_EXPR (assignment))
11845  {
11846  continue;
11847  }
11848 
11849  if (pt_name_equal (parser, assignment->info.expr.arg1, node))
11850  {
11851  /* Found the attribute we're looking for */
11852  break;
11853  }
11854  }
11855 
11856  if (assignment == NULL)
11857  {
11858  /* Did not find the attribute. This means that UPDATE should use the existing value */
11859  return node;
11860  }
11861 
11862  /* Replace node with rhs from the assignment. Notice that we're stopping at the first encounter of this attribute.
11863  * Normally, we should find the last assignment (from left to right), but, since CUBRID does not allow multiple
11864  * assignments to the same attribute, the first occurrence is the only one. */
11865  val = parser_copy_tree (parser, assignment->info.expr.arg2);
11866 
11867  if (val == NULL)
11868  {
11869  /* set error and return original node */
11870  PT_INTERNAL_ERROR (parser, "allocate new node");
11871  return node;
11872  }
11873 
11874  /* do not recurse into this node */
11875  *continue_walk = PT_LIST_WALK;
11876 
11877  return val;
11878 }
11879 
11880 /*
11881  * pt_no_attr_and_meta_attr_updates () - check for mixed (class, non-class)
11882  * assignments in the same update/merge statement
11883  * return: none
11884  * parser(in): the parser context
11885  * stmt(in): an update/merge statement
11886  */
11887 void
11889 {
11890  bool has_attrib = false, has_meta_attrib = false;
11892  PT_NODE *assignments;
11893 
11894  assignments = pt_get_assignments (statement);
11895  if (assignments == NULL)
11896  {
11897  return;
11898  }
11899 
11900  pt_init_assignments_helper (parser, &ea, assignments);
11901  while (pt_get_next_assignment (&ea) && (!has_attrib || !has_meta_attrib))
11902  {
11903  if (ea.lhs->info.name.meta_class == PT_META_ATTR)
11904  {
11905  has_meta_attrib = true;
11906  }
11907  else
11908  {
11909  has_attrib = true;
11910  }
11911  }
11912  if (has_attrib && has_meta_attrib)
11913  {
11915  }
11916 }
11917 
11918 /*
11919  * pt_node_double_insert_assignments () - Check if an attribute is assigned
11920  * more than once.
11921  *
11922  * return : Void.
11923  * parser (in) : Parser context.
11924  * stmt (in) : Insert statement.
11925  */
11926 void
11928 {
11929  PT_NODE *attr = NULL, *spec = NULL;
11930  PT_NODE *entity_name;
11931 
11932  if (stmt == NULL || stmt->node_type != PT_INSERT)
11933  {
11934  return;
11935  }
11936 
11937  spec = stmt->info.insert.spec;
11938  entity_name = spec->info.spec.entity_name;
11939  if (entity_name == NULL)
11940  {
11941  assert (false);
11942  PT_ERROR (parser, stmt,
11943  "The parse tree of the insert statement is incorrect." " entity_name of spec must be set.");
11944  return;
11945  }
11946 
11947  if (entity_name->info.name.original == NULL)
11948  {
11949  assert (false);
11950  PT_ERROR (parser, entity_name, er_msg ());
11951  return;
11952  }
11953 
11954  /* check for duplicate assignments */
11955  for (attr = stmt->info.insert.attr_list; attr != NULL; attr = attr->next)
11956  {
11957  PT_NODE *attr2;
11958  for (attr2 = attr->next; attr2 != NULL; attr2 = attr2->next)
11959  {
11960  if (pt_name_equal (parser, attr, attr2))
11961  {
11963  entity_name->info.name.original, attr2->info.name.original);
11964  return;
11965  }
11966  }
11967  }
11968 }
11969 
11970 /*
11971  * pt_no_double_updates () - assert that there are no multiple assignments to
11972  * the same attribute in the given update or merge statement
11973  * return: none
11974  * parser(in): the parser context
11975  * stmt(in): an update or merge statement
11976  */
11977 
11978 void
11980 {
11981  PT_NODE *a, *b, *att_a, *att_b;
11982  PT_NODE *assignment_list;
11983 
11984  assert (parser != NULL);
11985 
11986  assignment_list = pt_get_assignments (stmt);
11987  if (assignment_list == NULL)
11988  {
11989  return;
11990  }
11991 
11992  for (a = assignment_list; a; a = a->next)
11993  {
11994  if (!(a->node_type == PT_EXPR && a->info.expr.op == PT_ASSIGN && (att_a = a->info.expr.arg1)))
11995  {
11996  goto exit_on_error;
11997  }
11998 
11999  if (att_a->node_type != PT_NAME)
12000  {
12001  if (PT_IS_N_COLUMN_UPDATE_EXPR (att_a))
12002  {
12003  att_a = att_a->info.expr.arg1;
12004  }
12005  else
12006  {
12007  goto exit_on_error;
12008  }
12009  }
12010 
12011  for (; att_a; att_a = att_a->next)
12012  {
12013  /* first, check current node */
12014  for (att_b = att_a->next; att_b; att_b = att_b->next)
12015  {
12016  if (att_b->node_type != PT_NAME || att_b->info.name.original == NULL)
12017  {
12018  goto exit_on_error;
12019  }
12020  /* for multi-table we must check name and spec id */
12022  && att_a->info.name.spec_id == att_b->info.name.spec_id)
12023  {
12025  att_a->info.name.resolved, att_a->info.name.original);
12026  return;
12027  }
12028  }
12029 
12030  /* then, check the following node */
12031  for (b = a->next; b; b = b->next)
12032  {
12033  if (!(b->node_type == PT_EXPR && b->info.expr.op == PT_ASSIGN && (att_b = b->info.expr.arg1)))
12034  {
12035  goto exit_on_error;
12036  }
12037 
12038  if (att_b->node_type != PT_NAME)
12039  {
12040  if (PT_IS_N_COLUMN_UPDATE_EXPR (att_b))
12041  {
12042  att_b = att_b->info.expr.arg1;
12043  }
12044  else
12045  {
12046  goto exit_on_error;
12047  }
12048  }
12049 
12050  for (; att_b; att_b = att_b->next)
12051  {
12052  if (att_b->node_type != PT_NAME || att_b->info.name.original == NULL)
12053  {
12054  goto exit_on_error;
12055  }
12056  /* for multi-table we must check name and spec id */
12058  && att_a->info.name.spec_id == att_b->info.name.spec_id)
12059  {
12061  att_a->info.name.resolved, att_a->info.name.original);
12062  return;
12063  }
12064  }
12065  }
12066  }
12067  }
12068 
12069  return;
12070 
12071 exit_on_error:
12072  /* malformed assignment list */
12073  PT_INTERNAL_ERROR (parser, "semantic");
12074  return;
12075 }
12076 
12077 /*
12078  * pt_invert () -
12079  * return:
12080  * parser(in):
12081  * name_expr(in): an expression from a select list
12082  * result(out): written in terms of the same single variable or path-expr
12083  *
12084  * Note :
12085  * Given an expression p that involves only:
12086  * + - / * ( ) constants and a single variable (which occurs only once).
12087  *
12088  * Find the functional inverse of the expression.
12089  * [ f and g are functional inverses if f(g(x)) == x ]
12090  *
12091  * function inverse
12092  * -------- --------
12093  * -x -x
12094  * 4*x x/4
12095  * 4*x+10 (x-10)/4
12096  * 6+x x-6
12097  *
12098  * Can't invert: x+y; x+x; x*x; constants ; count(*); f(x) ;
12099  */
12100 PT_NODE *
12101 pt_invert (PARSER_CONTEXT * parser, PT_NODE * name_expr, PT_NODE * result)
12102 {
12103  int result_isnull = 0;
12104  PT_NODE *tmp;
12105  PT_NODE *msgs;
12106  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
12107 
12108  assert (parser != NULL);
12109  msgs = parser->error_msgs;
12110 
12111  /* find the variable and return if none */
12112  if (pt_find_var (name_expr, &tmp) != 1 || tmp == NULL)
12113  {
12114  return NULL;
12115  }
12116 
12117  /* walk through the expression, inverting as you go */
12118  while (name_expr)
12119  {
12120  /* Got a path expression, you're done. ( result = path expr ) */
12121  if (name_expr->node_type == PT_NAME)
12122  break;
12123 
12124  /* not an expression? then can't do it */
12125  if (name_expr->node_type != PT_EXPR)
12126  {
12127  result = 0;
12128  break;
12129  }
12130 
12131  /* the inverse of any expression involving NULL is NULL */
12132  result_isnull = result->type_enum == PT_TYPE_NULL;
12133  switch (name_expr->info.expr.op)
12134  {
12135  case PT_UNARY_MINUS:
12136  /* ( result = -expr ) <=> ( -result = expr ) */
12137  name_expr = name_expr->info.expr.arg1;
12138  if (!result_isnull)
12139  {
12140  tmp = parser_new_node (parser, PT_EXPR);
12141  if (tmp == NULL)
12142  {
12143  PT_INTERNAL_ERROR (parser, "allocate new node");
12144  return NULL;
12145  }
12146 
12147  tmp->info.expr.op = PT_UNARY_MINUS;
12148  tmp->info.expr.arg1 = result;
12149  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12150  {
12151  tmp->info.expr.arg1->info.expr.paren_type = 1;
12152  }
12153  result = tmp;
12154  }
12155  break;
12156 
12157  case PT_PLUS:
12158  /* ( result = A + B ) <=> ( result - A = B ) */
12159  if (pt_find_var (name_expr->info.expr.arg1, 0))
12160  {
12161  if (result_isnull)
12162  {
12163  /* no need to invert result because result already has a null */
12164  name_expr = name_expr->info.expr.arg1;
12165  }
12166  else
12167  {
12168  tmp = parser_new_node (parser, PT_EXPR);
12169  if (tmp == NULL)
12170  {
12171  PT_INTERNAL_ERROR (parser, "allocate new node");
12172  return NULL;
12173  }
12174 
12175  tmp->info.expr.op = PT_MINUS;
12176  tmp->info.expr.arg1 = result;
12177  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg2);
12178 
12179  if (tmp->info.expr.arg2 == NULL)
12180  {
12181  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12182  return NULL;
12183  }
12184 
12185  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12186  {
12187  tmp->info.expr.arg1->info.expr.paren_type = 1;
12188  }
12189  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12190  {
12191  tmp->info.expr.arg2->info.expr.paren_type = 1;
12192  }
12193  name_expr = name_expr->info.expr.arg1;
12194  result = tmp;
12195  }
12196  break;
12197  }
12198 
12199  if (pt_find_var (name_expr->info.expr.arg2, 0))
12200  {
12201  if (result_isnull)
12202  {
12203  /* no need to invert result because result already has a null */
12204  name_expr = name_expr->info.expr.arg2;
12205  }
12206  else
12207  {
12208  tmp = parser_new_node (parser, PT_EXPR);
12209  if (tmp == NULL)
12210  {
12211  PT_INTERNAL_ERROR (parser, "allocate new node");
12212  return NULL;
12213  }
12214 
12215  tmp->info.expr.op = PT_MINUS;
12216  tmp->info.expr.arg1 = result;
12217  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg1);
12218  if (tmp->info.expr.arg2 == NULL)
12219  {
12220  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12221  return NULL;
12222  }
12223 
12224  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12225  {
12226  tmp->info.expr.arg1->info.expr.paren_type = 1;
12227  }
12228  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12229  {
12230  tmp->info.expr.arg2->info.expr.paren_type = 1;
12231  }
12232  name_expr = name_expr->info.expr.arg2;
12233  result = tmp;
12234  }
12235  break;
12236  }
12237 
12238  return NULL;
12239 
12240  case PT_MINUS:
12241  /* ( result = A-B ) <=> ( result+B = A ) ( result = A-B ) <=> ( A-result = B ) */
12242  if (pt_find_var (name_expr->info.expr.arg1, 0))
12243  {
12244  if (result_isnull)
12245  {
12246  /* no need to invert result because result already has a null */
12247  name_expr = name_expr->info.expr.arg1;
12248  }
12249  else
12250  {
12251  tmp = parser_new_node (parser, PT_EXPR);
12252  if (tmp == NULL)
12253  {
12254  PT_INTERNAL_ERROR (parser, "allocate new node");
12255  return NULL;
12256  }
12257 
12258  tmp->info.expr.op = PT_PLUS;
12259  tmp->info.expr.arg1 = result;
12260  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg2);
12261  if (tmp->info.expr.arg2 == NULL)
12262  {
12263  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12264  return NULL;
12265  }
12266 
12267  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12268  {
12269  tmp->info.expr.arg1->info.expr.paren_type = 1;
12270  }
12271  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12272  {
12273  tmp->info.expr.arg2->info.expr.paren_type = 1;
12274  }
12275  name_expr = name_expr->info.expr.arg1;
12276  result = tmp;
12277  }
12278  break;
12279  }
12280 
12281  if (pt_find_var (name_expr->info.expr.arg2, 0))
12282  {
12283  if (result_isnull)
12284  {
12285  /* no need to invert result because result already has a null */
12286  name_expr = name_expr->info.expr.arg2;
12287  }
12288  else
12289  {
12290  tmp = parser_new_node (parser, PT_EXPR);
12291  if (tmp == NULL)
12292  {
12293  PT_INTERNAL_ERROR (parser, "allocate new node");
12294  return NULL;
12295  }
12296 
12297  tmp->info.expr.op = PT_MINUS;
12298  tmp->info.expr.arg2 = result;
12299  tmp->info.expr.arg1 = parser_copy_tree (parser, name_expr->info.expr.arg1);
12300  if (tmp->info.expr.arg1 == NULL)
12301  {
12302  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12303  return NULL;
12304  }
12305 
12306  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12307  {
12308  tmp->info.expr.arg1->info.expr.paren_type = 1;
12309  }
12310  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12311  {
12312  tmp->info.expr.arg2->info.expr.paren_type = 1;
12313  }
12314  name_expr = name_expr->info.expr.arg2;
12315  result = tmp;
12316  }
12317  break;
12318  }
12319 
12320  return NULL;
12321 
12322  case PT_DIVIDE:
12323  /* ( result = A/B ) <=> ( result*B = A ) ( result = A/B ) <=> ( A/result = B ) */
12324  if (pt_find_var (name_expr->info.expr.arg1, 0))
12325  {
12326  if (result_isnull)
12327  {
12328  /* no need to invert result because result already has a null */
12329  name_expr = name_expr->info.expr.arg1;
12330  }
12331  else
12332  {
12333  tmp = parser_new_node (parser, PT_EXPR);
12334  if (tmp == NULL)
12335  {
12336  PT_INTERNAL_ERROR (parser, "allocate new node");
12337  return NULL;
12338  }
12339 
12340  tmp->info.expr.op = PT_TIMES;
12341  tmp->info.expr.arg1 = result;
12342  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg2);
12343  if (tmp->info.expr.arg2 == NULL)
12344  {
12345  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12346  return NULL;
12347  }
12348 
12349  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12350  {
12351  tmp->info.expr.arg1->info.expr.paren_type = 1;
12352  }
12353  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12354  {
12355  tmp->info.expr.arg2->info.expr.paren_type = 1;
12356  }
12357  name_expr = name_expr->info.expr.arg1;
12358  result = tmp;
12359  }
12360  break;
12361  }
12362 
12363  if (pt_find_var (name_expr->info.expr.arg2, 0))
12364  {
12365  if (result_isnull)
12366  {
12367  /* no need to invert result because result already has a null */
12368  name_expr = name_expr->info.expr.arg2;
12369  }
12370  else
12371  {
12372  tmp = parser_new_node (parser, PT_EXPR);
12373  if (tmp == NULL)
12374  {
12375  PT_INTERNAL_ERROR (parser, "allocate new node");
12376  return NULL;
12377  }
12378 
12379  tmp->info.expr.op = PT_DIVIDE;
12380  tmp->info.expr.arg2 = result;
12381  tmp->info.expr.arg1 = parser_copy_tree (parser, name_expr->info.expr.arg1);
12382  if (tmp->info.expr.arg1 == NULL)
12383  {
12384  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12385  return NULL;
12386  }
12387 
12388  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12389  {
12390  tmp->info.expr.arg1->info.expr.paren_type = 1;
12391  }
12392  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12393  {
12394  tmp->info.expr.arg2->info.expr.paren_type = 1;
12395  }
12396  name_expr = name_expr->info.expr.arg2;
12397  result = tmp;
12398  }
12399  break;
12400  }
12401 
12402  return NULL;
12403 
12404  case PT_TIMES:
12405  /* ( result = A*B ) <=> ( result/A = B ) */
12406  if (pt_find_var (name_expr->info.expr.arg1, 0))
12407  {
12408  if (result_isnull)
12409  {
12410  /* no need to invert result because result already has a null */
12411  name_expr = name_expr->info.expr.arg1;
12412  }
12413  else
12414  {
12415  tmp = parser_new_node (parser, PT_EXPR);
12416  if (tmp == NULL)
12417  {
12418  PT_INTERNAL_ERROR (parser, "allocate new node");
12419  return NULL;
12420  }
12421 
12422  tmp->info.expr.op = PT_DIVIDE;
12423  tmp->info.expr.arg1 = result;
12424  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg2);
12425  if (tmp->info.expr.arg2 == NULL)
12426  {
12427  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12428  return NULL;
12429  }
12430 
12431  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12432  {
12433  tmp->info.expr.arg1->info.expr.paren_type = 1;
12434  }
12435  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12436  {
12437  tmp->info.expr.arg2->info.expr.paren_type = 1;
12438  }
12439  name_expr = name_expr->info.expr.arg1;
12440  result = tmp;
12441  }
12442  break;
12443  }
12444 
12445  if (pt_find_var (name_expr->info.expr.arg2, 0))
12446  {
12447  if (result_isnull)
12448  {
12449  /* no need to invert result because result already has a null */
12450  name_expr = name_expr->info.expr.arg2;
12451  }
12452  else
12453  {
12454  tmp = parser_new_node (parser, PT_EXPR);
12455  if (tmp == NULL)
12456  {
12457  PT_INTERNAL_ERROR (parser, "allocate new node");
12458  return NULL;
12459  }
12460 
12461  tmp->info.expr.op = PT_DIVIDE;
12462  tmp->info.expr.arg1 = result;
12463  tmp->info.expr.arg2 = parser_copy_tree (parser, name_expr->info.expr.arg1);
12464  if (tmp->info.expr.arg2 == NULL)
12465  {
12466  PT_INTERNAL_ERROR (parser, "parser_copy_tree");
12467  return NULL;
12468  }
12469 
12470  if (tmp->info.expr.arg1->node_type == PT_EXPR)
12471  {
12472  tmp->info.expr.arg1->info.expr.paren_type = 1;
12473  }
12474  if (tmp->info.expr.arg2->node_type == PT_EXPR)
12475  {
12476  tmp->info.expr.arg2->info.expr.paren_type = 1;
12477  }
12478  name_expr = name_expr->info.expr.arg2;
12479  result = tmp;
12480  }
12481  break;
12482  }
12483 
12484  return NULL;
12485 
12486  case PT_CAST:
12487  /* special case */
12488  name_expr = name_expr->info.expr.arg1;
12489  break;
12490 
12491  default:
12492  return NULL;
12493  }
12494  }
12495 
12496  /* set type of expression */
12497  if (!result_isnull)
12498  {
12499  sc_info.top_node = name_expr;
12500  sc_info.donot_fold = false;
12501  result = pt_semantic_type (parser, result, &sc_info);
12502  }
12503 
12504  if (result)
12505  {
12506  /* return name and resulting expression */
12507  result->next = parser_copy_tree (parser, name_expr);
12508  }
12509 
12510  if (pt_has_error (parser))
12511  {
12512  /* if we got an error just indicate not-invertible, end return with previous error state. */
12513  parser->error_msgs = msgs;
12514  return NULL;
12515  }
12516 
12517  return result;
12518 }
12519 
12520 /*
12521  * pt_find_var () - Explores an expression looking for a path expr.
12522  * Count these and return the count
12523  * return: number of path (PT_NAME node) expressions in the tree
12524  * p(in): an parse tree representing the syntactic
12525  * result(out): for returning a result expression pointer
12526  */
12527 
12528 int
12530 {
12531  if (!p)
12532  return 0;
12533 
12534  /* got a name expression */
12535  if (p->node_type == PT_NAME || (p->node_type == PT_DOT_))
12536  {
12537  if (result)
12538  *result = p;
12539  return 1;
12540  }
12541 
12542  /* if an expr (binary op) count both paths */
12543  if (p->node_type == PT_EXPR)
12544  {
12545  return (pt_find_var (p->info.expr.arg1, result) + pt_find_var (p->info.expr.arg2, result));
12546  }
12547 
12548  return 0;
12549 }
12550 
12551 /*
12552  * pt_remove_from_list () -
12553  * return: PT_NODE* to the list without "node" in it
12554  * parser(in):
12555  * node(in/out):
12556  * list(in/out):
12557  */
12558 PT_NODE *
12560 {
12561  PT_NODE *temp;
12562 
12563  if (!list)
12564  return list;
12565 
12566  if (node == list)
12567  {
12568  temp = node->next;
12569  node->next = NULL;
12570  parser_free_tree (parser, node);
12571  return temp;
12572  }
12573 
12574  temp = list;
12575  while (temp && temp->next != node)
12576  {
12577  temp = temp->next;
12578  }
12579 
12580  if (temp)
12581  {
12582  temp->next = node->next;
12583  node->next = NULL;
12584  parser_free_tree (parser, node);
12585  }
12586 
12587  return list;
12588 }
12589 
12590 /*
12591  * pt_find_order_value_in_list () - checking an ORDER_BY list for a node with
12592  * the same value as sort_spec
12593  * return: PT_NODE* the found match or NULL
12594  * parser(in):
12595  * sort_value(in):
12596  * order_list(in):
12597  */
12598 
12599 PT_NODE *
12600 pt_find_order_value_in_list (PARSER_CONTEXT * parser, const PT_NODE * sort_value, const PT_NODE * order_list)
12601 {
12602  PT_NODE *match = NULL;
12603 
12604  match = (PT_NODE *) order_list;
12605 
12606  while (match && sort_value && match->info.sort_spec.expr)
12607  {
12608  if (sort_value->node_type == PT_VALUE && match->info.sort_spec.expr->node_type == PT_VALUE
12609  && (match->info.sort_spec.expr->info.value.data_value.i == sort_value->info.value.data_value.i))
12610  {
12611  break;
12612  }
12613  else if (sort_value->node_type == PT_NAME && match->info.sort_spec.expr->node_type == PT_NAME
12614  && (pt_check_path_eq (parser, sort_value, match->info.sort_spec.expr) == 0))
12615  {
12616  /* when create/alter view, columns which are not in select list will not be replaced as value type. */
12617  break;
12618  }
12619  else
12620  {
12621  match = match->next;
12622  }
12623  }
12624 
12625  return match;
12626 }
12627 
12628 /*
12629  * pt_check_order_by () - checking an ORDER_BY clause
12630  * return:
12631  * parser(in):
12632  * query(in): query node has ORDER BY
12633  *
12634  * Note :
12635  * If it is an INTEGER, make sure it does not exceed the number of items
12636  * in the select list.
12637  * If it is a path expression, match it with an item in the select list and
12638  * replace it with the corresponding INTEGER.
12639  * IF not match, add hidden_column to select_list.
12640  * For the order-by clause of a UNION/INTERSECTION type query,
12641  * simply check that the items are ALL INTEGERS and it does not
12642  * exceed the number of items in the select list..
12643  */
12644 
12645 int
12647 {
12648  PT_NODE *select_list, *order_by, *col, *r, *temp, *order, *match;
12649  int n, i, select_list_len, select_list_full_len;
12650  bool ordbynum_flag;
12651  char *r_str = NULL;
12652  int error;
12653  bool skip_orderby_num = false;
12654 
12655  /* initinalize local variables */
12656  error = NO_ERROR;
12657  select_list = order_by = NULL;
12658 
12659  /* get select_list */
12660  switch (query->node_type)
12661  {
12662  case PT_SELECT:
12663  select_list = query->info.query.q.select.list;
12664  break;
12665 
12666  case PT_UNION:
12667  case PT_INTERSECTION:
12668  case PT_DIFFERENCE:
12669  {
12670  PT_NODE *arg1, *arg2;
12671 
12672  /* traverse through nested union */
12673  temp = query;
12674  while (1)
12675  {
12676  arg1 = temp->info.query.q.union_.arg1;
12677  arg2 = temp->info.query.q.union_.arg2;
12678 
12679  if (PT_IS_QUERY (arg1))
12680  {
12681  if (arg1->node_type == PT_SELECT)
12682  { /* found, exit loop */
12683  select_list = arg1->info.query.q.select.list;
12684  break;
12685  }
12686  else
12687  {
12688  temp = arg1; /* continue */
12689  }
12690  }
12691  else
12692  {
12693  /* should not get here, that is an error! */
12695  PT_ERRORmf2 (parser, arg1, MSGCAT_SET_PARSER_SEMANTIC, error, pt_short_print (parser, arg1),
12696  pt_short_print (parser, arg2));
12697  break;
12698  }
12699  }
12700  }
12701  break;
12702 
12703  default:
12704  break;
12705  }
12706 
12707  /* not query statement or error occurs */
12708  if (select_list == NULL)
12709  {
12710  return error;
12711  }
12712 
12713  if (query->node_type == PT_SELECT && pt_is_single_tuple (parser, query))
12714  {
12715  /*
12716  * This case means "select count(*) from athlete order by code"
12717  * we will remove order by clause to avoid error message
12718  * but, "select count(*) from athlete order by 2" should make out of range err
12719  */
12720  if (query->info.query.order_by != NULL)
12721  {
12722  PT_NODE head;
12723  PT_NODE *last = &head;
12724  PT_NODE *order_by = query->info.query.order_by;
12725 
12726  last->next = NULL;
12727  while (order_by != NULL)
12728  {
12729  PT_NODE *next = order_by->next;
12730  order_by->next = NULL;
12731 
12732  if (order_by->info.sort_spec.expr->node_type == PT_NAME
12733  || order_by->info.sort_spec.expr->node_type == PT_EXPR)
12734  {
12735  parser_free_node (parser, order_by);
12736  skip_orderby_num = true;
12737  }
12738  else
12739  {
12740  // leave PT_VALUE, PT_HOST_VAR, in fact, PT_HOST_VAR will be rejected soon.
12741  last->next = order_by;
12742  last = order_by;
12743  }
12744 
12745  order_by = next;
12746  }
12747 
12748  query->info.query.order_by = head.next;
12749  }
12750 
12751  /*
12752  * This case means "select count(*) from athlete limit ?"
12753  * This limit clause should be evaluated after "select count(*) from athlete"
12754  * So we will change it as subquery.
12755  */
12756  if (query->info.query.limit != NULL)
12757  {
12758  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
12759  PT_NODE *limit = query->info.query.limit;
12760  query->info.query.limit = NULL;
12761 
12762  /* rewrite as derived table */
12763  query = mq_rewrite_aggregate_as_derived (parser, query);
12764  if (query == NULL || pt_has_error (parser))
12765  {
12766  return ER_FAILED;
12767  }
12768 
12769  /* clear spec_ids of names referring derived table and re-run name resolving; their types are not resolved
12770  * and, since we're on the post stage of the tree walk, this will not happen naturally; */
12771  query->info.query.q.select.list =
12772  mq_clear_ids (parser, query->info.query.q.select.list, query->info.query.q.select.from);
12773 
12774  /* re-resolve names */
12775  sc_info.donot_fold = true;
12776  sc_info.top_node = query;
12777  query = pt_resolve_names (parser, query, &sc_info);
12778  if (pt_has_error (parser) || !query)
12779  {
12780  return ER_FAILED;
12781  }
12782 
12783  query->info.query.limit = limit;
12784  }
12785  }
12786 
12787  /* get ORDER BY clause */
12788  order_by = query->info.query.order_by;
12789  if (order_by == NULL)
12790  {
12791  if (query->node_type == PT_SELECT)
12792  {
12793  /* need to check select_list */
12794  goto check_select_list;
12795  }
12796 
12797  /* union has not ORDER BY */
12798  return error;
12799  }
12800 
12801  /* save original length of select_list */
12802  select_list_len = 0;
12803  select_list_full_len = pt_length_of_select_list (select_list, INCLUDE_HIDDEN_COLUMNS);
12804 #if !defined (NDEBUG)
12805  select_list_len = pt_length_of_select_list (select_list, EXCLUDE_HIDDEN_COLUMNS);
12806 #endif /* !NDEBUG */
12807 
12808  for (order = order_by; order; order = order->next)
12809  {
12810  /* get the EXPR */
12811  r = order->info.sort_spec.expr;
12812  if (r == NULL)
12813  { /* impossible case */
12814  continue;
12815  }
12816 
12817  /* if a good integer, done */
12818  if (r->node_type == PT_VALUE)
12819  {
12820  if (r->type_enum == PT_TYPE_INTEGER)
12821  {
12822  n = r->info.value.data_value.i;
12823  /* check size of the integer */
12824  if (select_list_full_len < n || n < 1)
12825  {
12827  PT_ERRORmf (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error, n);
12828  /* go ahead */
12829  }
12830  else
12831  {
12832  /* the following invalid query cause error in here SELECT orderby_num() FROM t ORDER BY 1; */
12833  for (col = select_list, i = 1; i < n; i++)
12834  {
12835  col = col->next;
12836  }
12837 
12838  /* sorting node should be either an existing select node or an hidden column added by system */
12839  assert (n <= select_list_len || col->flag.is_hidden_column);
12840 
12841  if (col->node_type == PT_EXPR && col->info.expr.op == PT_ORDERBY_NUM)
12842  {
12844  PT_ERRORmf (parser, col, MSGCAT_SET_PARSER_SEMANTIC, error, "ORDERBY_NUM()");
12845  /* go ahead */
12846  }
12847  }
12848  }
12849  else
12850  {
12852  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
12853  /* go ahead */
12854  }
12855  }
12856  else if (r->node_type == PT_HOST_VAR)
12857  {
12859  pt_short_print (parser, r));
12861  }
12862  else
12863  {
12864  /* not an integer value. Try to match with something in the select list. */
12865 
12866  n = 1; /* a counter for position in select_list */
12867  if (r->node_type != PT_NAME && r->node_type != PT_DOT_)
12868  {
12869  r_str = parser_print_tree (parser, r);
12870  }
12871 
12872  for (col = select_list; col; col = col->next)
12873  {
12874  /* if match, break; */
12875  if (r->node_type == col->node_type)
12876  {
12877  if (r->node_type == PT_NAME || r->node_type == PT_DOT_)
12878  {
12879  if (pt_check_path_eq (parser, r, col) == 0)
12880  {
12881  break; /* match */
12882  }
12883  }
12884  else
12885  {
12886  if (pt_str_compare (r_str, parser_print_tree (parser, col), CASE_INSENSITIVE) == 0)
12887  {
12888  break; /* match */
12889  }
12890  }
12891  }
12892  else if (pt_check_compatible_node_for_orderby (parser, r, col))
12893  {
12894  break;
12895  }
12896  n++;
12897  }
12898 
12899  /* if end of list, no match create a hidden column node and append to select_list */
12900  if (col == NULL)
12901  {
12902  if (query->node_type != PT_SELECT)
12903  {
12905  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
12906  }
12907  else if (query->info.query.all_distinct == PT_DISTINCT)
12908  {
12910  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
12911  }
12912  else
12913  {
12914  /* when check order by clause in create/alter view, do not change order_by and select_list. The order
12915  * by clause will be replaced in mq_translate_subqueries() again. */
12916  if (query->flag.do_not_replace_orderby)
12917  {
12918  continue;
12919  }
12920 
12921  col = parser_copy_tree (parser, r);
12922  if (col == NULL)
12923  {
12925  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
12926  return error; /* give up */
12927  }
12928  else
12929  {
12930  /* mark as a hidden column */
12931  col->flag.is_hidden_column = 1;
12932  parser_append_node (col, select_list);
12933  }
12934  }
12935  }
12936 
12937  /* we got a match=n, Create a value node and replace expr with it */
12938  temp = parser_new_node (parser, PT_VALUE);
12939  if (temp == NULL)
12940  {
12942  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
12943  }
12944  else
12945  {
12946  temp->type_enum = PT_TYPE_INTEGER;
12947  temp->info.value.data_value.i = n;
12948  pt_value_to_db (parser, temp);
12949  parser_free_tree (parser, r);
12950  order->info.sort_spec.expr = temp;
12951  }
12952  }
12953 
12954  if (error != NO_ERROR)
12955  { /* something wrong */
12956  continue; /* go ahead */
12957  }
12958 
12959  /* set order by position num */
12960  order->info.sort_spec.pos_descr.pos_no = n;
12961  if (query->node_type != PT_SELECT)
12962  {
12963  continue; /* OK */
12964  }
12965 
12966  /* at here, query->node_type == PT_SELECT set order_by domain info */
12967  if (col->type_enum != PT_TYPE_NONE && col->type_enum != PT_TYPE_MAYBE)
12968  { /* is resolved */
12969  order->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, col);
12970  }
12971  } /* for (order = order_by; ...) */
12972 
12973  /* now check for duplicate entries. - If they match on ascending/descending, remove the second. - If they do not,
12974  * generate an error. */
12975  for (order = order_by; order; order = order->next)
12976  {
12977  while ((match = pt_find_order_value_in_list (parser, order->info.sort_spec.expr, order->next)))
12978  {
12979  if ((order->info.sort_spec.asc_or_desc != match->info.sort_spec.asc_or_desc)
12980  || (pt_to_null_ordering (order) != pt_to_null_ordering (match)))
12981  {
12983  PT_ERRORmf (parser, match, MSGCAT_SET_PARSER_SEMANTIC, error, pt_short_print (parser, match));
12984  break;
12985  }
12986  else
12987  {
12988  order->next = pt_remove_from_list (parser, match, order->next);
12989  }
12990  }
12991  }
12992 
12993  if (error != NO_ERROR)
12994  { /* give up */
12995  return error;
12996  }
12997 
12998 check_select_list:
12999 
13000  /* orderby_num() in select list restriction check */
13001  for (col = select_list; col; col = col->next)
13002  {
13003  if (PT_IS_QUERY_NODE_TYPE (col->node_type))
13004  {
13005  /* skip orderby_num() expression in subqueries */
13006  continue;
13007  }
13008 
13009  if (col->node_type == PT_EXPR && col->info.expr.op == PT_ORDERBY_NUM)
13010  {
13011  if (!order_by && !skip_orderby_num)
13012  {
13013  /* the following invalid query cause error in here; SELECT orderby_num() FROM t; */
13015  PT_ERRORmf (parser, col, MSGCAT_SET_PARSER_SEMANTIC, error, "ORDERBY_NUM()");
13016  break;
13017  }
13018  }
13019  else
13020  {
13021  /* the following query cause error in here; SELECT orderby_num()+1 FROM t; SELECT orderby_num()+1, a FROM t
13022  * ORDER BY 2; SELECT {orderby_num()} FROM t; SELECT {orderby_num()+1}, a FROM t ORDER BY 2; */
13023  ordbynum_flag = false;
13025  &ordbynum_flag);
13026  if (ordbynum_flag)
13027  {
13029  PT_ERRORm (parser, col, MSGCAT_SET_PARSER_SEMANTIC, error);
13030  break;
13031  }
13032  }
13033  }
13034 
13035  return error;
13036 }
13037 
13038 /*
13039  * pt_check_path_eq () - determine if two path expressions are the same
13040  * return: 0 if two path expressions are the same, else non-zero.
13041  * parser(in):
13042  * p(in):
13043  * q(in):
13044  */
13045 int
13046 pt_check_path_eq (PARSER_CONTEXT * parser, const PT_NODE * p, const PT_NODE * q)
13047 {
13048  PT_NODE_TYPE n;
13049 
13050  if (p == NULL && q == NULL)
13051  {
13052  return 0;
13053  }
13054 
13055  if (p == NULL || q == NULL)
13056  {
13057  return 1;
13058  }
13059 
13060  /* check node types are same */
13061  if (p->node_type != q->node_type)
13062  {
13063  return 1;
13064  }
13065 
13066  n = p->node_type;
13067  switch (n)
13068  {
13069  /* if a name, the original and resolved fields must match */
13070  case PT_NAME:
13072  {
13073  return 1;
13074  }
13076  {
13077  return 1;
13078  }
13079  if (p->info.name.spec_id != q->info.name.spec_id)
13080  {
13081  return 1;
13082  }
13083  break;
13084 
13085  /* EXPR must be X.Y.Z. */
13086  case PT_DOT_:
13087  if (pt_check_path_eq (parser, p->info.dot.arg1, q->info.dot.arg1))
13088  {
13089  return 1;
13090  }
13091 
13092  /* A recursive call on arg2 should work, except that we have not yet recognised common sub-path expressions
13093  * However, it is also sufficient and true that the left path be strictly equal and arg2's names match. That even
13094  * allows us to use this very function to implement recognition of common path expressions. */
13095  if (p->info.dot.arg2 == NULL || q->info.dot.arg2 == NULL)
13096  {
13097  return 1;
13098  }
13099 
13100  if (p->info.dot.arg2->node_type != PT_NAME || q->info.dot.arg2->node_type != PT_NAME)
13101  {
13102  return 1;
13103  }
13104 
13106  {
13107  return 1;
13108  }
13109 
13110  break;
13111 
13112  default:
13114  pt_short_print (parser, p));
13115  return 1;
13116  }
13117 
13118  return 0;
13119 }
13120 
13121 /*
13122  * pt_check_class_eq () - determine if two class name expressions are the same
13123  * return: 0 if two class name expressions are the same, else non-zero
13124  * parser(in):
13125  * p(in):
13126  * q(in):
13127  */
13128 int
13130 {
13131  PT_NODE_TYPE n;
13132 
13133  if (p == NULL && q == NULL)
13134  {
13135  return 0;
13136  }
13137 
13138  if (p == NULL || q == NULL)
13139  {
13140  return 1;
13141  }
13142 
13143  /* check if node types are same */
13144  if (p->node_type != q->node_type)
13145  {
13146  return 1;
13147  }
13148 
13149  n = p->node_type;
13150  switch (n)
13151  {
13152  /* if a name, the resolved (class name) fields must match */
13153  case PT_NAME:
13155  {
13156  return 1;
13157  }
13158  if (p->info.name.spec_id != q->info.name.spec_id)
13159  {
13160  return 1;
13161  }
13162  break;
13163 
13164  default:
13166  pt_short_print (parser, p));
13167  return 1;
13168  }
13169 
13170  return 0;
13171 }
13172 
13173 /*
13174  * pt_coerce_insert_values () - try to coerce the insert values to the types
13175  * indicated by the insert attributes
13176  * return:
13177  * parser(in): handle to context used to parse the insert/merge statement
13178  * stmt(in): the AST form of an insert/merge statement
13179  */
13180 static PT_NODE *
13182 {
13183  PT_NODE *v = NULL, *a = NULL, *crt_list = NULL;
13184  int a_cnt = 0, v_cnt = 0;
13185  PT_NODE *prev = NULL;
13186  PT_NODE *attr_list = NULL;
13187  PT_NODE *value_clauses = NULL;
13188 
13189  /* preconditions are not met */
13190  if (stmt->node_type != PT_INSERT && stmt->node_type != PT_MERGE)
13191  {
13192  return NULL;
13193  }
13194 
13195 #if 0 /* to disable TEXT */
13196  pt_resolve_insert_external (parser, ins);
13197 #endif /* 0 */
13198 
13199  if (stmt->node_type == PT_INSERT)
13200  {
13201  attr_list = stmt->info.insert.attr_list;
13202  value_clauses = stmt->info.insert.value_clauses;
13203  }
13204  else
13205  {
13206  attr_list = stmt->info.merge.insert.attr_list;
13207  value_clauses = stmt->info.merge.insert.value_clauses;
13208  }
13209 
13210  a_cnt = pt_length_of_list (attr_list);
13211 
13212  for (crt_list = value_clauses; crt_list != NULL; crt_list = crt_list->next)
13213  {
13214  if (crt_list->info.node_list.list_type == PT_IS_DEFAULT_VALUE)
13215  {
13216  v = NULL;
13217  }
13218  else if (crt_list->info.node_list.list_type == PT_IS_SUBQUERY)
13219  {
13220  /* this sort of nods at union queries */
13221  v = pt_get_select_list (parser, crt_list->info.node_list.list);
13223  if (a_cnt != v_cnt)
13224  {
13226  }
13227  else
13228  {
13229  continue;
13230  }
13231  }
13232  else
13233  {
13234  v = crt_list->info.node_list.list;
13235  v_cnt = pt_length_of_list (v);
13236  if (a_cnt != v_cnt)
13237  {
13239  }
13240  }
13241  prev = NULL;
13242  for (a = attr_list; v != NULL && a != NULL; prev = v, v = v->next, a = a->next)
13243  {
13244  /* test assignment compatibility. This sets parser->error_msgs */
13245  PT_NODE *new_node;
13246 
13247  new_node = pt_assignment_compatible (parser, a, v);
13248  if (new_node == NULL)
13249  {
13250  /* this in an error and the message was set by the call to pt_assignment_compatible. Just continue */
13251  continue;
13252  }
13253 
13254  if (new_node != v)
13255  {
13256  v = new_node;
13257  if (prev == NULL)
13258  {
13259  /* first node in the list */
13260  crt_list->info.node_list.list = v;
13261  }
13262  else
13263  {
13264  /* relink list to the wrapped node */
13265  prev->next = v;
13266  }
13267  }
13268 
13269  if (v->node_type == PT_HOST_VAR && v->type_enum == PT_TYPE_MAYBE && v->expected_domain == NULL
13270  && (PT_IS_NUMERIC_TYPE (a->type_enum) || PT_IS_STRING_TYPE (a->type_enum)))
13271  {
13272  TP_DOMAIN *d;
13273 
13274  d = pt_node_to_db_domain (parser, a, NULL);
13275  d = tp_domain_cache (d);
13276  v->expected_domain = d;
13277  }
13278  }
13279  }
13280  return stmt;
13281 }
13282 
13283 /*
13284  * pt_check_sub_insert () - Checks if sub-inserts are semantically correct
13285  *
13286  * return : Unchanged node argument.
13287  * parser (in) : Parser context.
13288  * node (in) : Parse tree node.
13289  * void_arg (in) : Unused argument.
13290  * continue_walk (in) : Continue walk.
13291  */
13292 static PT_NODE *
13293 pt_check_sub_insert (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk)
13294 {
13295  PT_NODE *entity_name = NULL, *value_clauses = NULL;
13296 
13297  if (*continue_walk == PT_STOP_WALK)
13298  {
13299  return node;
13300  }
13301 
13302  switch (node->node_type)
13303  {
13304  case PT_INSERT:
13305  /* continue to checks */
13306  *continue_walk = PT_LIST_WALK;
13307  break;
13308  case PT_SELECT:
13309  case PT_INTERSECTION:
13310  case PT_DIFFERENCE:
13311  case PT_UNION:
13312  /* stop advancing into this node */
13313  *continue_walk = PT_LIST_WALK;
13314  return node;
13315  default:
13316  /* do nothing */
13317  *continue_walk = PT_CONTINUE_WALK;
13318  return node;
13319  }
13320  /* Check current insert node */
13321  value_clauses = node->info.insert.value_clauses;
13322  if (value_clauses->next)
13323  {
13324  /* Only one row is allowed for sub-inserts */
13326  if (!pt_has_error (parser))
13327  {
13328  PT_ERRORc (parser, node, db_error_string (3));
13329  }
13330  *continue_walk = PT_STOP_WALK;
13331  return node;
13332  }
13333  entity_name = node->info.insert.spec->info.spec.entity_name;
13334  if (entity_name == NULL || entity_name->info.name.db_object == NULL)
13335  {
13336  PT_INTERNAL_ERROR (parser, "Unresolved insert spec");
13337  *continue_walk = PT_STOP_WALK;
13338  return node;
13339  }
13340  if (sm_is_reuse_oid_class (entity_name->info.name.db_object))
13341  {
13342  /* Inserting Reusable OID is not allowed */
13344  entity_name->info.name.original);
13345  *continue_walk = PT_STOP_WALK;
13346  return node;
13347  }
13348 
13349  /* check sub-inserts for this sub-insert */
13350  if (value_clauses->info.node_list.list_type != PT_IS_SUBQUERY)
13351  {
13352  (void) parser_walk_tree (parser, value_clauses, pt_check_sub_insert, NULL, NULL, NULL);
13353  if (pt_has_error (parser))
13354  {
13355  *continue_walk = PT_STOP_WALK;
13356  }
13357  }
13358  return node;
13359 }
13360 
13361 /*
13362  * pt_count_input_markers () - If the node is a input host variable marker,
13363  * compare its index+1 against *num_ptr and record the bigger of
13364  * the two into *num_ptr
13365  * return:
13366  * parser(in):
13367  * node(in): the node to check
13368  * arg(in/out):
13369  * continue_walk(in):
13370  */
13371 
13372 PT_NODE *
13373 pt_count_input_markers (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13374 {
13375  int *num_markers;
13376 
13377  num_markers = (int *) arg;
13378 
13379  if (pt_is_input_hostvar (node))
13380  {
13381  if (*num_markers < node->info.host_var.index + 1)
13382  {
13383  *num_markers = node->info.host_var.index + 1;
13384  }
13385  }
13386 
13387  return node;
13388 }
13389 
13390 /*
13391  * pt_count_output_markers () - If the node is a output host variable marker,
13392  * compare its index+1 against *num_ptr and record the bigger of
13393  * the two into *num_ptr
13394  * return:
13395  * parser(in):
13396  * node(in): the node to check
13397  * arg(in/out):
13398  * continue_walk(in):
13399  */
13400 PT_NODE *
13401 pt_count_output_markers (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13402 {
13403  int *num_markers;
13404 
13405  num_markers = (int *) arg;
13406 
13407  if (pt_is_output_hostvar (node))
13408  {
13409  if (*num_markers < node->info.host_var.index + 1)
13410  {
13411  *num_markers = node->info.host_var.index + 1;
13412  }
13413  }
13414 
13415  return node;
13416 }
13417 
13418 /*
13419  * pt_has_using_index_clause () -
13420  * return:
13421  * parser(in):
13422  * node(in):
13423  * arg(in):
13424  * continue_walk(in):
13425  */
13426 PT_NODE *
13427 pt_has_using_index_clause (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13428 {
13429  bool *found = (bool *) arg;
13430  PT_NODE *ui_node;
13431 
13432  switch (node->node_type)
13433  {
13434  case PT_DELETE:
13435  ui_node = node->info.delete_.using_index;
13436  break;
13437 
13438  case PT_UPDATE:
13439  ui_node = node->info.update.using_index;
13440  break;
13441 
13442  case PT_SELECT:
13443  ui_node = node->info.query.q.select.using_index;
13444  break;
13445 
13446  default:
13447  ui_node = NULL;
13448  break;
13449  }
13450 
13451  if (ui_node)
13452  {
13453  *found = true;
13454  *continue_walk = PT_STOP_WALK;
13455  }
13456 
13457  return node;
13458 }
13459 
13460 /*
13461  * pt_validate_query_spec () - check if a query_spec is compatible with a
13462  * given {vclass} object
13463  * return: an error code if checking found an error, NO_ERROR otherwise
13464  * parser(in): handle to context used to parse the query_specs
13465  * s(in): a query_spec in parse_tree form
13466  * c(in): a vclass object
13467  */
13468 
13469 int
13471 {
13472  PT_NODE *attrs = NULL;
13473  int error_code = NO_ERROR;
13474 
13475  assert (parser != NULL && s != NULL && c != NULL);
13476 
13477  /* a syntax error for query_spec */
13478  if (pt_has_error (parser))
13479  {
13480  pt_report_to_ersys (parser, PT_SYNTAX);
13481  error_code = er_errid ();
13482  goto error_exit;
13483  }
13484 
13485  if (db_is_vclass (c) <= 0)
13486  {
13487  error_code = ER_OBJ_INVALID_ARGUMENTS;
13488  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 0);
13489  goto error_exit;
13490  }
13491 
13492  s = parser_walk_tree (parser, s, pt_set_is_view_spec, NULL, NULL, NULL);
13493  assert (s != NULL);
13494 
13495  attrs = pt_get_attributes (parser, c);
13496 
13497  /* apply semantic checks to query_spec */
13498  s = pt_check_vclass_query_spec (parser, s, attrs, db_get_class_name (c), true);
13499  if (pt_has_error (parser))
13500  {
13501  pt_report_to_ersys (parser, PT_SEMANTIC);
13502  error_code = er_errid ();
13503  goto error_exit;
13504  }
13505  if (s == NULL)
13506  {
13507  error_code = ER_GENERIC_ERROR;
13508  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 0);
13509  goto error_exit;
13510  }
13511 
13512  s = pt_type_cast_vclass_query_spec (parser, s, attrs);
13513  if (pt_has_error (parser))
13514  {
13515  pt_report_to_ersys (parser, PT_SEMANTIC);
13516  error_code = er_errid ();
13517  goto error_exit;
13518  }
13519  if (s == NULL)
13520  {
13521  error_code = ER_GENERIC_ERROR;
13522  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 0);
13523  goto error_exit;
13524  }
13525 
13526  return error_code;
13527 
13528 error_exit:
13529  return error_code;
13530 }
13531 
13532 
13533 /*
13534  * pt_check_xaction_list () - Checks to see if there is more than one
13535  * isolation level clause or more than one timeout value clause
13536  * return:
13537  * parser(in):
13538  * node(in): the node to check
13539  */
13540 
13541 static void
13543 {
13544  int num_iso_nodes = 0;
13545  int num_time_nodes = 0;
13546 
13547  (void) parser_walk_tree (parser, node, pt_count_iso_nodes, &num_iso_nodes, NULL, NULL);
13548 
13549  (void) parser_walk_tree (parser, node, pt_count_time_nodes, &num_time_nodes, NULL, NULL);
13550 
13551  if (num_iso_nodes > 1)
13552  {
13554  }
13555 
13556  if (num_time_nodes > 1)
13557  {
13559  }
13560 }
13561 
13562 /*
13563  * pt_count_iso_nodes () - returns node unchanged, count by reference
13564  * return:
13565  * parser(in):
13566  * node(in): the node to check
13567  * arg(in/out): count of isolation level nodes
13568  * continue_walk(in):
13569  */
13570 
13571 static PT_NODE *
13572 pt_count_iso_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13573 {
13574  int *cnt = (int *) arg;
13575 
13576  if (node->node_type == PT_ISOLATION_LVL)
13577  {
13578  (*cnt)++;
13579  }
13580 
13581  return node;
13582 }
13583 
13584 /*
13585  * pt_count_time_nodes () - returns node timeouted, count by reference
13586  * return:
13587  * parser(in):
13588  * node(in): the node to check
13589  * arg(in/out): count of timeout nodes
13590  * continue_walk(in):
13591  */
13592 static PT_NODE *
13593 pt_count_time_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13594 {
13595  int *cnt = (int *) arg;
13596 
13597  if (node->node_type == PT_TIMEOUT)
13598  {
13599  (*cnt)++;
13600  }
13601 
13602  return node;
13603 }
13604 
13605 /*
13606  * pt_check_isolation_lvl () - checks isolation level node
13607  * return:
13608  * parser(in):
13609  * node(in/out): the node to check
13610  * arg(in):
13611  * continue_walk(in):
13612  *
13613  * Note :
13614  * checks
13615  * 1) if isolation levels for schema & instances are compatible.
13616  * 2) if isolation number entered, check to see if it is valid.
13617  */
13618 
13619 static PT_NODE *
13620 pt_check_isolation_lvl (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13621 {
13622  DB_TRAN_ISOLATION cur_lvl;
13623  int dummy;
13624 
13625  if (node->node_type == PT_ISOLATION_LVL)
13626  {
13627  if (node->info.isolation_lvl.level != NULL)
13628  {
13629  /* assume correct type, value checking will be done at run-time */
13630  return node;
13631  }
13632 
13633  /* check to make sure an isolation level has been given */
13636  && (node->info.isolation_lvl.async_ws == false))
13637  {
13639  }
13640 
13641  /* get the current isolation level in case user is defaulting either the schema or the instances level. */
13642  (void) db_get_tran_settings (&dummy, &cur_lvl);
13643 
13645  {
13646  switch (cur_lvl)
13647  {
13649  /* in this case, the user is specifying only the instance level when there was not a previous isolation
13650  * level set. Default the schema isolation level to the instance isolation level. */
13652  break;
13653 
13654  case TRAN_READ_COMMITTED:
13655  case TRAN_REPEATABLE_READ:
13657  break;
13658 
13659  case TRAN_SERIALIZABLE:
13661  break;
13662  }
13663  }
13664 
13666  {
13667  switch (cur_lvl)
13668  {
13670  /* in this case, the user is specifying only the schema level when there was not a previous isolation
13671  * level set. Default the instances isolation level to the schema isolation level. */
13673  break;
13674 
13675  case TRAN_READ_COMMITTED:
13677  break;
13678 
13679  case TRAN_REPEATABLE_READ:
13681  break;
13682 
13683  case TRAN_SERIALIZABLE:
13685  break;
13686  }
13687  }
13688 
13689  /* coercing/correcting of incompatible level happens in do_set_xaction() */
13690  }
13691 
13692  return node;
13693 }
13694 
13695 #if defined (ENABLE_UNUSED_FUNCTION)
13696 /*
13697  * pt_find_attr_def () - Finds the PT_NODE in attr_def_list with the same
13698  * original_name as the given name
13699  * return: db_user instance if user exists, NULL otherwise.
13700  * attr_def_list(in): the list of attr_def's in a CREATE_ENTITY node
13701  * name(in): a PT_NAME node
13702  */
13703 
13704 PT_NODE *
13705 pt_find_attr_def (const PT_NODE * attr_def_list, const PT_NODE * name)
13706 {
13707  PT_NODE *p;
13708 
13709  for (p = (PT_NODE *) attr_def_list; p; p = p->next)
13710  {
13712  {
13713  break;
13714  }
13715  }
13716 
13717  return p;
13718 }
13719 
13720 /*
13721  * pt_find_cnstr_def () - Finds the PT_NODE in cnstr_def_list with the same
13722  * original_name as the given name
13723  * return: attribute instance iff attribute exists, NULL otherwise.
13724  * cnstr_def_list(in): the list of constraint elements
13725  * name(in): a PT_NAME node
13726  */
13727 PT_NODE *
13728 pt_find_cnstr_def (const PT_NODE * cnstr_def_list, const PT_NODE * name)
13729 {
13730  PT_NODE *p;
13731 
13732  for (p = (PT_NODE *) cnstr_def_list; p; p = p->next)
13733  {
13735  {
13736  break;
13737  }
13738  }
13739 
13740  return p;
13741 }
13742 #endif
13743 
13744 /*
13745  * pt_check_constraint () - Checks the given constraint appears to be valid
13746  * return: the constraint node
13747  * parser(in): the current parser context
13748  * create(in): a CREATE_ENTITY node
13749  * constraint(in): a CONSTRAINT node, assumed to have come from the
13750  * constraint_list of "create"
13751  *
13752  * Note :
13753  * Right now single-column UNIQUE and NOT NULL constraints are the only
13754  * ones that are understood. All others are ignored (with a warning).
13755  * Unfortunately, this can't do the whole job because at this point we know
13756  * nothing about inherited attributes, etc. For example, someone could be
13757  * trying to add a UNIQUE constraint to an inherited attribute, but we won't
13758  * be able to handle it because we'll be unable to resolve the name. Under
13759  * the current architecture the template stuff will need to be extended to
13760  * understand constraints.
13761  */
13762 
13763 static PT_NODE *
13764 pt_check_constraint (PARSER_CONTEXT * parser, const PT_NODE * create, const PT_NODE * constraint)
13765 {
13766  switch (constraint->info.constraint.type)
13767  {
13768  case PT_CONSTRAIN_UNKNOWN:
13769  goto warning;
13770 
13771  case PT_CONSTRAIN_NULL:
13772  case PT_CONSTRAIN_NOT_NULL:
13773  case PT_CONSTRAIN_UNIQUE:
13774  break;
13775 
13778  case PT_CONSTRAIN_CHECK:
13779  if (create->info.create_entity.entity_type != PT_CLASS)
13780  {
13781  goto error;
13782  }
13783  else
13784  {
13785  goto warning;
13786  }
13787  }
13788 
13789  return (PT_NODE *) constraint;
13790 
13791 warning:
13793  parser_print_tree (parser, constraint));
13794  return (PT_NODE *) constraint;
13795 
13796 error:
13798  return NULL;
13799 }
13800 
13801 /*
13802  * pt_check_constraints () - Checks all of the constraints given in
13803  * this CREATE_ENTITY node
13804  * return: the CREATE_ENTITY node
13805  * parser(in): the current parser context
13806  * create(in): a CREATE_ENTITY node
13807  */
13808 static PT_NODE *
13809 pt_check_constraints (PARSER_CONTEXT * parser, const PT_NODE * create)
13810 {
13811  PT_NODE *constraint;
13812 
13813  for (constraint = create->info.create_entity.constraint_list; constraint; constraint = constraint->next)
13814  {
13815  (void) pt_check_constraint (parser, create, constraint);
13816  }
13817 
13818  return (PT_NODE *) create;
13819 }
13820 
13821 /*
13822  * pt_find_class_of_index () - Find the name of the class that has a given
13823  * index (specified by its name and type)
13824  * return: a PT_NAME node with the class name or NULL on error
13825  * parser(in):
13826  * index_name(in):
13827  * index_type(in):
13828  *
13829  * Note:
13830  * Only constraint types that satisfy the DB_IS_CONSTRAINT_INDEX_FAMILY
13831  * condition will be searched for.
13832  */
13833 PT_NODE *
13834 pt_find_class_of_index (PARSER_CONTEXT * parser, const char *const index_name, const DB_CONSTRAINT_TYPE index_type)
13835 {
13836  PT_NODE *node = NULL;
13837  DB_OBJECT *const class_ = db_find_class_of_index (index_name, index_type);
13838 
13839  if (class_ == NULL)
13840  {
13841  return NULL;
13842  }
13843  node = pt_name (parser, db_get_class_name (class_));
13844  if (node == NULL)
13845  {
13846  PT_INTERNAL_ERROR (parser, "allocate new node");
13847  return NULL;
13848  }
13849  return node;
13850 }
13851 
13852 /*
13853  * pt_check_defaultf () - Checks to see if default function is well-formed
13854  * return: none
13855  * parser(in):
13856  * node(in): the node to check
13857  */
13858 static int
13860 {
13861  PT_NODE *arg;
13862 
13863  assert (node != NULL && node->node_type == PT_EXPR && node->info.expr.op == PT_DEFAULTF);
13864  if (node == NULL || node->node_type != PT_EXPR || node->info.expr.op != PT_DEFAULTF)
13865  {
13866  PT_INTERNAL_ERROR (parser, "bad node type");
13867  return ER_FAILED;
13868  }
13869 
13870  arg = node->info.expr.arg1;
13871 
13872  /* OIDs don't have default value */
13873  if (arg == NULL || arg->node_type != PT_NAME || arg->info.name.meta_class == PT_OID_ATTR
13875  {
13877  return ER_FAILED;
13878  }
13879 
13880  /* Argument of DEFAULT function should be given. So, PT_NAME_INFO_FILL_DEFAULT bit might be always set when
13881  * expression node was created. The following assertion and defensive code will be used to handle unexpected
13882  * situation. */
13885  {
13886  PT_INTERNAL_ERROR (parser, "bad DEFAULTF node");
13887  return ER_FAILED;
13888  }
13889 
13890  /* In case of no default value defined on an attribute: DEFAULT function returns NULL when the attribute given as
13891  * argument has UNIQUE or no constraint, but it returns a semantic error for PRIMARY KEY or NOT NULL constraint. This
13892  * function does not return a semantic error for attributes with auto_increment because, regardless of the default
13893  * value, NULL will not be inserted there. */
13894  if (arg->info.name.resolved && arg->info.name.original)
13895  {
13896  DB_ATTRIBUTE *db_att = NULL;
13898 
13899  if (db_att && !db_attribute_is_auto_increment (db_att))
13900  {
13901  if ((db_attribute_is_primary_key (db_att) || db_attribute_is_non_null (db_att))
13904  {
13906  PT_ERRORc (parser, arg, er_msg ());
13907  return ER_FAILED;
13908  }
13909  }
13910  }
13911  return NO_ERROR;
13912 }
13913 
13914 
13915 /*
13916  * pt_check_auto_increment_table_option () - Checks that the AUTO_INCREMENT
13917  * table option has a non-ambiguous field to apply to and that
13918  * the respective field does not have an explicit auto_increment start
13919  * value.
13920  *
13921  * NOTE: the function also modifies the parse tree by rewriting the
13922  * table option as an AUTO_INCREMENT constraint for the respective field.
13923  *
13924  * return: error code
13925  * parser(in): the current parser context
13926  * create(in): a CREATE_ENTITY node
13927  */
13928 static int
13930 {
13931  PT_NODE *attr = NULL;
13932  PT_NODE *auto_inc_attr = NULL;
13933  PT_NODE *start_val = NULL;
13934  PT_NODE *increment_val = NULL;
13935  PT_NODE *tbl_opt = NULL;
13936  PT_NODE *prev_tbl_opt = NULL;
13937 
13938  /* do we have EXACTLY ONE auto_increment node in our attr list? */
13939  for (attr = create->info.create_entity.attr_def_list; attr != NULL; attr = attr->next)
13940  {
13941  if (attr->info.attr_def.auto_increment != NULL)
13942  {
13943  if (auto_inc_attr != NULL)
13944  {
13945  /* we already found an auto increment attr! */
13947  return ER_FAILED;
13948  }
13949  auto_inc_attr = attr;
13950  }
13951  }
13952 
13953  if (auto_inc_attr == NULL)
13954  {
13956  return ER_FAILED;
13957  }
13958 
13959  /* here we have exactly ONE attribute with auto_increment */
13960 
13961  if (auto_inc_attr->info.attr_def.auto_increment->info.auto_increment.start_val != NULL)
13962  {
13963  /* does it already have a start value? this is not good */
13965  return ER_FAILED;
13966  }
13967 
13968  /* alter the tree */
13969 
13970  /* locate the tbl opt, save its numeric value and destroy it */
13971 
13972  prev_tbl_opt = NULL;
13973  tbl_opt = create->info.create_entity.table_option_list;
13974  while (tbl_opt != NULL)
13975  {
13977  {
13978  start_val = parser_copy_tree (parser, tbl_opt->info.table_option.val);
13979  if (prev_tbl_opt != NULL)
13980  {
13981  prev_tbl_opt->next = tbl_opt->next;
13982  }
13983  else
13984  {
13985  create->info.create_entity.table_option_list = tbl_opt->next;
13986  }
13987 
13988  tbl_opt->next = NULL;
13989  parser_free_tree (parser, tbl_opt);
13990  break;
13991 
13992  }
13993 
13994  prev_tbl_opt = tbl_opt;
13995  tbl_opt = tbl_opt->next;
13996  }
13997 
13998  /* add the two nodes to the attribute definition */
13999  increment_val = pt_make_integer_value (parser, 1);
14000 
14001  if (start_val == NULL || increment_val == NULL)
14002  {
14003  PT_INTERNAL_ERROR (parser, "allocate new node");
14004  return NO_ERROR;
14005  }
14006 
14007  auto_inc_attr->info.attr_def.auto_increment->info.auto_increment.start_val = start_val;
14008  auto_inc_attr->info.attr_def.auto_increment->info.auto_increment.increment_val = increment_val;
14009 
14010  return NO_ERROR;
14011 }
14012 
14013 /*
14014  * pt_check_group_concat_order_by () - checks an ORDER_BY clause of a
14015  * GROUP_CONCAT aggregate function;
14016  * if the expression or identifier from
14017  * ORDER BY clause matches an argument of function,
14018  * the ORDER BY item is converted into associated
14019  * number.
14020  * return:
14021  * parser(in):
14022  * query(in): query node has ORDER BY
14023  *
14024  *
14025  * Note :
14026  *
14027  * Only one order by item is supported :
14028  * - if it is an INTEGER, make sure it does not exceed the number of items
14029  * in the argument list.
14030  * - if it is a path expression, match it with an argument in the
14031  * function's argument list and replace the node with a PT_VALUE
14032  * with corresponding number.
14033  * - if it doesn't match, an error is issued.
14034  */
14035 static int
14037 {
14038  PT_NODE *arg_list = NULL;
14039  PT_NODE *order_by = NULL;
14040  PT_NODE *arg = NULL;
14041  PT_NODE *temp, *order;
14042  int n, i, arg_list_len;
14043  int error = NO_ERROR;
14044  PT_NODE *group_concat_sep_node_save = NULL;
14045 
14047 
14048  /* get ORDER BY clause */
14049  order_by = func->info.function.order_by;
14050  if (order_by == NULL)
14051  {
14052  goto error_exit;
14053  }
14054 
14055  arg_list = func->info.function.arg_list;
14056  if (arg_list == NULL)
14057  {
14059  goto error_exit;
14060  }
14061 
14062  /* remove separator from list of arguments */
14063  group_concat_sep_node_save = func->info.function.arg_list->next;
14064  func->info.function.arg_list->next = NULL;
14065 
14066  /* save original length of select_list */
14067  arg_list_len = pt_length_of_list (arg_list);
14068  for (order = order_by; order != NULL; order = order->next)
14069  {
14070  /* get the EXPR */
14071  PT_NODE *r = order->info.sort_spec.expr;
14072  if (r == NULL)
14073  { /* impossible case */
14074  continue;
14075  }
14076 
14077  if (PT_IS_LOB_TYPE (r->type_enum))
14078  {
14080  pt_short_print (parser, r));
14081  goto error_exit;
14082  }
14083 
14084  /* if a good integer, done */
14085  if (r->node_type == PT_VALUE)
14086  {
14087  if (r->type_enum == PT_TYPE_INTEGER)
14088  {
14089  n = r->info.value.data_value.i;
14090  /* check size of the integer */
14091  if (n > arg_list_len || n < 1)
14092  {
14094  PT_ERRORmf (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error, n);
14095  /* go ahead */
14096  }
14097  else
14098  {
14099  /* goto associated argument: */
14100  for (arg = arg_list, i = 1; i < n; i++)
14101  {
14102  arg = arg->next;
14103  }
14104  }
14105  }
14106  else
14107  {
14109  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
14110  /* go ahead */
14111  }
14112  }
14113  else
14114  {
14115  char *r_str = NULL;
14116  /* not an integer value. Try to match with something in the select list. */
14117 
14118  n = 1; /* a counter for position in select_list */
14119  if (r->node_type != PT_NAME && r->node_type != PT_DOT_)
14120  {
14121  r_str = parser_print_tree (parser, r);
14122  }
14123 
14124  for (arg = arg_list; arg != NULL; arg = arg->next)
14125  {
14126  /* if match, break; */
14127  if (r->node_type == arg->node_type)
14128  {
14129  if (r->node_type == PT_NAME || r->node_type == PT_DOT_)
14130  {
14131  if (pt_check_path_eq (parser, r, arg) == 0)
14132  {
14133  break; /* match */
14134  }
14135  }
14136  else
14137  {
14138  if (pt_str_compare (r_str, parser_print_tree (parser, arg), CASE_INSENSITIVE) == 0)
14139  {
14140  break; /* match */
14141  }
14142  }
14143  }
14144  n++;
14145  }
14146 
14147  /* if end of list -> error : currently aggregate functions don't support other order by expression than
14148  * arguments */
14149  if (arg == NULL)
14150  {
14152  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
14153  /* go ahead */
14154  }
14155  else
14156  {
14157  /* we got a match=n, Create a value node and replace expr with it */
14158  temp = parser_new_node (parser, PT_VALUE);
14159  if (temp == NULL)
14160  {
14162  PT_ERRORm (parser, r, MSGCAT_SET_PARSER_SEMANTIC, error);
14163  }
14164  else
14165  {
14166  temp->type_enum = PT_TYPE_INTEGER;
14167  temp->info.value.data_value.i = n;
14168  pt_value_to_db (parser, temp);
14169  parser_free_tree (parser, r);
14170  order->info.sort_spec.expr = temp;
14171  }
14172  }
14173  }
14174 
14175  if (error != NO_ERROR)
14176  { /* something wrong, exit */
14177  goto error_exit;
14178  }
14179 
14180  /* at this point <n> contains the sorting position : either specified in statement or computed, and <arg> is the
14181  * corresponding function argument */
14182  assert (arg != NULL);
14183  assert (n > 0 && n <= arg_list_len);
14184 
14185  /* set order by position num */
14186  order->info.sort_spec.pos_descr.pos_no = n;
14187 
14188  /* set order_by domain info */
14189  if (arg->type_enum != PT_TYPE_NONE && arg->type_enum != PT_TYPE_MAYBE)
14190  { /* is resolved */
14191  order->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, arg);
14192  }
14193  }
14194 
14195  assert (func->info.function.order_by->next == NULL);
14196 
14197 error_exit:
14198  if (group_concat_sep_node_save != NULL)
14199  {
14200  func->info.function.arg_list->next = group_concat_sep_node_save;
14201  }
14202 
14203  return error;
14204 }
14205 
14206 /*
14207  * pt_check_cume_dist_percent_rank_order_by () - checks an ORDER_BY clause of a
14208  * CUME_DIST aggregate function;
14209  * if the expression or identifier from
14210  * ORDER BY clause matches an argument of function,
14211  * the ORDER BY item is converted into associated
14212  * number.
14213  * return: NO_ERROR or error_code
14214  * parser(in):
14215  * func(in):
14216  *
14217  *
14218  * Note :
14219  * We need to check arguments and order by,
14220  * because the arguments must be constant expression and
14221  * match the ORDER BY clause by position.
14222  */
14223 
14224 static int
14226 {
14227  PT_NODE *arg_list = NULL;
14228  PT_NODE *order_by = NULL;
14229  PT_NODE *arg = NULL;
14230  PT_NODE *order = NULL;
14231  PT_NODE *order_expr = NULL;
14232  DB_OBJECT *obj = NULL;
14233  DB_ATTRIBUTE *att = NULL;
14234  TP_DOMAIN *dom = NULL;
14235  DB_VALUE *value = NULL;
14236  int i, arg_list_len, order_by_list_len;
14237  int error = NO_ERROR;
14238  const char *func_name;
14239 
14240  /* get function name for ERROR message */
14241  if (func->info.function.function_type == PT_CUME_DIST)
14242  {
14243  func_name = "CUME_DIST";
14244  }
14245  else if (func->info.function.function_type == PT_PERCENT_RANK)
14246  {
14247  func_name = "PERCENT_RANK";
14248  }
14249  else
14250  {
14251  assert (false);
14252  return ER_FAILED;
14253  }
14254 
14255  /* first check if the arguments are constant */
14256  arg_list = func->info.function.arg_list;
14257  order_by = func->info.function.order_by;
14258 
14259  /* for analytic function */
14260  if (func->info.function.analytic.is_analytic)
14261  {
14262  if (arg_list != NULL || order_by != NULL)
14263  {
14264  error = ER_FAILED;
14266  }
14267  goto error_exit;
14268  }
14269 
14270  /* aggregate function */
14271  if (arg_list == NULL || order_by == NULL)
14272  {
14273  error = ER_FAILED;
14275  goto error_exit;
14276  }
14277 
14278  /* save original length of select_list */
14279  arg_list_len = pt_length_of_list (arg_list);
14280  order_by_list_len = pt_length_of_list (order_by);
14281  if (arg_list_len != order_by_list_len)
14282  {
14284  goto error_exit;
14285  }
14286 
14287  arg = arg_list;
14288  order = order_by;
14289  for (i = 0; i < arg_list_len; i++)
14290  {
14291  /* check argument type: arguments must be constant */
14292  if (!pt_is_const_expr_node (arg))
14293  {
14295  goto error_exit;
14296  }
14297 
14298  /* check order by */
14299  order_expr = order->info.sort_spec.expr;
14300  if (order->node_type != PT_SORT_SPEC || (order_expr->node_type != PT_NAME && order_expr->node_type != PT_VALUE)
14301  || PT_IS_LOB_TYPE (order_expr->type_enum))
14302  {
14304  goto error_exit;
14305  }
14306 
14307  if (order_expr->node_type == PT_NAME)
14308  {
14309  /* check if the arg matches order by clause by position */
14310  dom = NULL;
14311  obj = db_find_class (order_expr->info.name.resolved);
14312  if (obj != NULL)
14313  {
14314  att = db_get_attribute (obj, order_expr->info.name.original);
14315  if (att != NULL)
14316  {
14317  dom = att->domain;
14318  }
14319  }
14320 
14321  /* Note: it is possible that class is not found. i.e. 'select PERCENT_RANK(null,3) within group (order by
14322  * score,score1) from (select NULL score,'00001' score1 from db_root) S;' We just let it go if an attribute
14323  * could not be found. */
14324 
14325  /* for common values */
14326  if (arg->node_type == PT_VALUE && dom != NULL)
14327  {
14328  value = &arg->info.value.db_value;
14329  error = db_value_coerce (value, value, dom);
14330  if (error != NO_ERROR)
14331  {
14333  pt_short_print (parser, arg), pt_show_type_enum (order_expr->type_enum));
14334  goto error_exit;
14335  }
14336  }
14337  }
14338 
14339  /* to next */
14340  order->info.sort_spec.pos_descr.pos_no = i + 1;
14341  arg = arg->next;
14342  order = order->next;
14343  }
14344 
14345 error_exit:
14346 
14347  return error;
14348 }
14349 
14350 
14351 /*
14352  * pt_has_parameters () - check if a statement uses session variables
14353  * return : true if the statement uses session variables
14354  * parser (in) : parser context
14355  * stmt (in) : statement
14356  */
14357 static bool
14359 {
14360  bool has_paramenters = false;
14361 
14362  parser_walk_tree (parser, stmt, pt_is_parameter_node, &has_paramenters, NULL, NULL);
14363 
14364  return has_paramenters;
14365 }
14366 
14367 /*
14368  * pt_is_parameter_node () - check if a node is a session variable
14369  * return : node
14370  * parser (in) : parser context
14371  * node (in) : node
14372  * arg (in) :
14373  * continue_walk (in) :
14374  */
14375 static PT_NODE *
14376 pt_is_parameter_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
14377 {
14378  bool *is_parameter = (bool *) arg;
14379  *continue_walk = PT_CONTINUE_WALK;
14380 
14381  if (*is_parameter)
14382  {
14383  /* stop checking, there already is a parameter in the statement */
14384  return node;
14385  }
14386 
14387  if (node->node_type == PT_EXPR)
14388  {
14389  if (node->info.expr.op == PT_EVALUATE_VARIABLE || node->info.expr.op == PT_DEFINE_VARIABLE)
14390  {
14391  *is_parameter = true;
14392  *continue_walk = PT_STOP_WALK;
14393  }
14394  }
14395 
14396  return node;
14397 }
14398 
14399 /*
14400  * pt_resolve_sort_spec_expr - resolves a sort spec expression
14401  * returns: parser node or NULL on error
14402  * sort_spec(in): PT_SORT_SPEC node whose expression must be resolved
14403  * select_list(in): statement's select list for PT_VALUE lookup
14404  */
14405 static PT_NODE *
14406 pt_resolve_sort_spec_expr (PARSER_CONTEXT * parser, PT_NODE * sort_spec, PT_NODE * select_list)
14407 {
14408  PT_NODE *expr, *resolved;
14409 
14410  if (parser == NULL || sort_spec == NULL)
14411  {
14412  /* nothing to do */
14413  return NULL;
14414  }
14415 
14416  if (sort_spec->node_type != PT_SORT_SPEC)
14417  {
14418  PT_INTERNAL_ERROR (parser, "expecting a sort spec");
14419  return NULL;
14420  }
14421 
14422  expr = sort_spec->info.sort_spec.expr;
14423  if (expr == NULL)
14424  {
14425  PT_INTERNAL_ERROR (parser, "null sort expression");
14426  return NULL;
14427  }
14428 
14429  if (expr->node_type == PT_EXPR && expr->info.expr.op == PT_UNARY_MINUS)
14430  {
14432  return NULL;
14433  }
14434  else if (expr->node_type != PT_VALUE)
14435  {
14436  return expr;
14437  }
14438 
14439  /* we have a PT_VALUE sort expression; look it up in select list */
14440  if (expr->type_enum == PT_TYPE_INTEGER)
14441  {
14442  int index = expr->info.value.data_value.i;
14443  resolved = pt_get_node_from_list (select_list, index - 1);
14444 
14445  if (resolved != NULL)
14446  {
14447  return resolved;
14448  }
14449  else
14450  {
14452  return NULL;
14453  }
14454  }
14455  else
14456  {
14458  return NULL;
14459  }
14460 }
14461 
14462 /*
14463  * pt_compare_sort_spec_expr - compare two sort expressions
14464  * returns: true if expressions are the same, false otherwise
14465  * expr1(in): first expression
14466  * expr2(in): second expression
14467  */
14468 static bool
14470 {
14471  if (parser == NULL || expr1 == NULL || expr2 == NULL)
14472  {
14473  return false;
14474  }
14475 
14476  if ((expr1->node_type == PT_NAME || expr1->node_type == PT_DOT_)
14477  && (expr2->node_type == PT_NAME || expr2->node_type == PT_DOT_))
14478  {
14479  /* we have comparable names */
14480  if (pt_check_path_eq (parser, expr1, expr2) == 0)
14481  {
14482  /* name match */
14483  return true;
14484  }
14485  }
14486  else
14487  {
14488  /* brute method, compare printed trees */
14489  char *str_expr = parser_print_tree (parser, expr1);
14490  char *str_spec_expr = parser_print_tree (parser, expr2);
14491 
14492  if (pt_str_compare (str_expr, str_spec_expr, CASE_INSENSITIVE) == 0)
14493  {
14494  /* match */
14495  return true;
14496  }
14497  }
14498 
14499  /* no match */
14500  return false;
14501 }
14502 
14503 /*
14504  * pt_find_matching_sort_spec - find a matching sort spec in a spec list
14505  * return: match or NULL
14506  * parser(in): parser context
14507  * spec(in): sort spec to look for
14508  * spec_list(in): sort spec list to look into
14509  * select_list(in): statement's select list, for PT_VALUE lookup
14510  */
14511 static PT_NODE *
14512 pt_find_matching_sort_spec (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * spec_list, PT_NODE * select_list)
14513 {
14514  PT_NODE *spec_expr, *expr;
14515 
14516  if (parser == NULL || spec == NULL || spec_list == NULL)
14517  {
14518  /* nothing to do here */
14519  return NULL;
14520  }
14521 
14522  /* fetch sort expression */
14523  spec_expr = pt_resolve_sort_spec_expr (parser, spec, select_list);
14524  if (spec_expr == NULL)
14525  {
14526  return NULL;
14527  }
14528 
14529  /* iterate list and check for match */
14530  while (spec_list)
14531  {
14532  /* fetch sort expression */
14533  expr = pt_resolve_sort_spec_expr (parser, spec_list, select_list);
14534  if (expr == NULL)
14535  {
14536  return NULL;
14537  }
14538 
14539  /* compare */
14540  if (pt_compare_sort_spec_expr (parser, expr, spec_expr))
14541  {
14542  /* found match */
14543  return spec_list;
14544  }
14545 
14546  /* advance */
14547  spec_list = spec_list->next;
14548  }
14549 
14550  /* nothing was found */
14551  return NULL;
14552 }
14553 
14554 /*
14555  * pt_remove_unusable_sort_specs () - remove unusable sort specs
14556  * return: new list, after filtering sort specs
14557  * parser(in): parser context
14558  * list(in): spec list
14559  * Note:
14560  * This call remove useless sort specs like NULL and constant expressions
14561  * (e.g.: order by null, order by 1 + 5, etc)
14562  */
14563 static PT_NODE *
14565 {
14566  PT_NODE *item, *expr, *save_next;
14567 
14568  /* check nulls */
14569  if (parser == NULL)
14570  {
14571  assert (false);
14572  return NULL;
14573  }
14574 
14575  if (list == NULL)
14576  {
14577  return NULL;
14578  }
14579 
14580  /* remove nulls */
14581  item = list;
14582  list = NULL;
14583  while (item)
14584  {
14585  /* unlink */
14586  save_next = item->next;
14587  item->next = NULL;
14588 
14589  if (item->node_type != PT_SORT_SPEC || item->info.sort_spec.expr == NULL)
14590  {
14591  assert (false);
14592  PT_INTERNAL_ERROR (parser, "invalid sort spec");
14593  }
14594 
14595  expr = item->info.sort_spec.expr;
14596  if (expr->node_type == PT_VALUE && expr->type_enum == PT_TYPE_NULL)
14597  {
14598  /* NULL spec, get rid of it */
14599  parser_free_tree (parser, item);
14600  }
14601  else if (expr->node_type == PT_EXPR && pt_is_const_expr_node (expr))
14602  {
14603  /* order by constant which is not place holder, get rid of it */
14604  parser_free_tree (parser, item);
14605  }
14606  else
14607  {
14608  /* normal spec, keep it */
14609  list = parser_append_node (item, list);
14610  }
14611 
14612  /* continue */
14613  item = save_next;
14614  }
14615 
14616  /* list contains only normal specs */
14617  return list;
14618 }
14619 
14620 /*
14621  * pt_check_analytic_function () -
14622  * return:
14623  * parser(in):
14624  * func(in): Function node
14625  * arg(in): SELECT node
14626  * continue_walk(in):
14627  *
14628  */
14629 static PT_NODE *
14630 pt_check_analytic_function (PARSER_CONTEXT * parser, PT_NODE * func, void *arg, int *continue_walk)
14631 {
14632  PT_NODE *arg_list, *partition_by, *order_by, *select_list;
14633  PT_NODE *order, *query;
14634  PT_NODE *link = NULL, *order_list = NULL, *match = NULL;
14635  PT_NODE *new_order = NULL;
14636 
14637  if (func->node_type != PT_FUNCTION || !func->info.function.analytic.is_analytic)
14638  {
14639  return func;
14640  }
14641 
14642  query = (PT_NODE *) arg;
14643  if (query->node_type != PT_SELECT)
14644  {
14646  pt_short_print (parser, func));
14647  return func;
14648  }
14649 
14650  arg_list = func->info.function.arg_list;
14651  if (arg_list == NULL && func->info.function.function_type != PT_COUNT_STAR
14655  {
14657  pt_short_print (parser, func));
14658  return func;
14659  }
14660 
14661  /* median doesn't support over(order by ...) */
14662  if (func->info.function.function_type == PT_MEDIAN)
14663  {
14664  if (func->info.function.analytic.order_by != NULL)
14665  {
14667  return func;
14668  }
14669  else if (!PT_IS_CONST (arg_list))
14670  {
14671  /* only sort data when arg is not constant */
14672  new_order = parser_new_node (parser, PT_SORT_SPEC);
14673  if (new_order == NULL)
14674  {
14676  return func;
14677  }
14678 
14679  new_order->info.sort_spec.asc_or_desc = PT_ASC;
14681  new_order->info.sort_spec.expr = parser_copy_tree (parser, arg_list);
14682  if (new_order->info.sort_spec.expr == NULL)
14683  {
14685  return func;
14686  }
14687 
14688  func->info.function.analytic.order_by = new_order;
14689  }
14690  }
14691 
14692  /* remove NULL specs */
14696 
14697  partition_by = func->info.function.analytic.partition_by;
14698  order_by = func->info.function.analytic.order_by;
14699  select_list = query->info.query.q.select.list;
14700 
14701  /* order_by sort direction has priority over partition_by direction */
14702  if (order_by != NULL && partition_by != NULL)
14703  {
14704  PT_NODE *part, *match;
14705 
14706  /* iterate partition_by nodes */
14707  for (part = partition_by; part; part = part->next)
14708  {
14709  /* find matching sort spec in order_by list and copy direction */
14710  match = pt_find_matching_sort_spec (parser, part, order_by, select_list);
14711 
14712  if (match != NULL)
14713  {
14716  }
14717  }
14718  }
14719 
14720  /* link partition and order lists together */
14721  for (link = partition_by; link && link->next; link = link->next)
14722  {
14723  ;
14724  }
14725  if (link)
14726  {
14727  order_list = partition_by;
14728  link->next = order_by;
14729  }
14730  else
14731  {
14732  order_list = order_by;
14733  }
14734 
14735  /* check for nested analytic functions */
14736  if (pt_has_analytic (parser, order_list))
14737  {
14739  goto error_exit;
14740  }
14741 
14742  /* replace names/exprs with positions in select list where possible; this also re-processes PT_VALUE sort expressions
14743  * so we can identify and reduce cases like: SELECT a, b, a, AVG(b) OVER (PARTITION BY A ORDER BY 1 asc, 3 asc) */
14744  for (order = order_list; order; order = order->next)
14745  {
14746  PT_NODE *expr, *col, *temp;
14747  int index;
14748 
14749  /* resolve sort spec */
14750  expr = pt_resolve_sort_spec_expr (parser, order, select_list);
14751  if (expr == NULL)
14752  {
14753  goto error_exit;
14754  }
14755 
14756  /* try to match with something in the select list */
14757  for (col = select_list, index = 1; col; col = col->next, index++)
14758  {
14759  if (col->flag.is_hidden_column)
14760  {
14761  /* skip hidden columns; they might disappear later on */
14762  continue;
14763  }
14764 
14765  if (pt_compare_sort_spec_expr (parser, expr, col))
14766  {
14767  /* found a match in select list */
14768  break;
14769  }
14770  }
14771 
14772  /* if we have a match in the select list, we can replace it on the spot; otherwise, wait for XASL generation */
14773  if (col != NULL)
14774  {
14775  PT_NODE *save_next = col->next;
14776 
14777  col->next = NULL;
14778  if (pt_has_analytic (parser, col))
14779  {
14780  col->next = save_next;
14781 
14782  /* sort expression contains analytic function */
14784  goto error_exit;
14785  }
14786  else
14787  {
14788  col->next = save_next;
14789  }
14790 
14791  /* create a value node and replace expr with it */
14792  temp = parser_new_node (parser, PT_VALUE);
14793  if (temp == NULL)
14794  {
14796  goto error_exit;
14797  }
14798  else
14799  {
14800  temp->type_enum = PT_TYPE_INTEGER;
14801  temp->info.value.data_value.i = index;
14802  (void) pt_value_to_db (parser, temp);
14803  parser_free_tree (parser, order->info.sort_spec.expr);
14804  order->info.sort_spec.expr = temp;
14805  }
14806 
14807  /* set position descriptor and resolve domain */
14808  order->info.sort_spec.pos_descr.pos_no = index;
14809  if (col->type_enum != PT_TYPE_NONE && col->type_enum != PT_TYPE_MAYBE)
14810  { /* is resolved */
14811  order->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, col);
14812  }
14813  }
14814  }
14815 
14816  /* check for duplicate entries */
14817  for (order = order_list; order; order = order->next)
14818  {
14819  PT_NODE *temp;
14820 
14821  while ((match = pt_find_matching_sort_spec (parser, order, order->next, select_list)))
14822  {
14823  if ((order->info.sort_spec.asc_or_desc != match->info.sort_spec.asc_or_desc)
14824  || (pt_to_null_ordering (order) != pt_to_null_ordering (match)))
14825  {
14827  pt_short_print (parser, match));
14828  goto error_exit;
14829  }
14830  else
14831  {
14832  /* check if we are going to remove the link */
14833  if (link && match == link)
14834  {
14835  temp = order_list;
14836  while (temp->next != match)
14837  {
14838  temp = temp->next;
14839  }
14840  link = temp;
14841  }
14842 
14843  /* check if we are going to remove the first ORDER BY node */
14844  if (link && match == link->next)
14845  {
14846  /* func may be printed again by pt_find_matching_sort_spec, make sure we don't reference garbage in
14847  * order_by */
14848  func->info.function.analytic.order_by = match->next;
14849  }
14850 
14851  /* remove match */
14852  order->next = pt_remove_from_list (parser, match, order->next);
14853  }
14854  }
14855  }
14856 
14857 error_exit:
14858  /* un-link partition and order lists */
14859  if (link)
14860  {
14861  func->info.function.analytic.order_by = link->next;
14862  link->next = NULL;
14863  }
14864 
14865  return func;
14866 }
14867 
14868 /* pt_check_function_index_expr () - check if there is at most one expression
14869  * in the index definition and , if one
14870  * expression does exist, it is checked to
14871  * see if it meets the constraints of being
14872  * part of an index
14873  * return :
14874  * parser(in) : parser context
14875  * node (in) : node - PT_CREATE_INDEX
14876  */
14877 static void
14879 {
14880  PT_NODE *col, *rem = NULL;
14881  int fnc_cnt = 0;
14882  int i = 0;
14883 
14884  for (col = node->info.index.column_names, i = 0; col != NULL; col = col->next, i++)
14885  {
14886  if (col->info.sort_spec.expr->node_type != PT_NAME)
14887  {
14888  if (pt_is_function_index_expr (parser, col->info.sort_spec.expr, true))
14889  {
14891  NULL);
14892  if (pt_has_error (parser))
14893  {
14894  /* Stop. */
14895  return;
14896  }
14897  node->info.index.function_expr = parser_copy_tree (parser, col);
14898  node->info.index.func_pos = i;
14899  rem = col;
14900  }
14901  else
14902  {
14903  return;
14904  }
14905  fnc_cnt++;
14906  }
14907  }
14908  if (fnc_cnt > 1)
14909  {
14911  }
14912  else if (fnc_cnt > 0 && rem)
14913  {
14914  PT_NODE *list, *arg, *n;
14915  node->info.index.column_names = pt_remove_from_list (parser, rem, node->info.index.column_names);
14917 
14918  for (arg = list; arg != NULL; arg = arg->next)
14919  {
14920  for (n = node->info.index.column_names; n != NULL; n = n->next)
14921  {
14924  {
14925  break;
14926  }
14927  }
14928  if (n == NULL)
14929  {
14930  PT_NODE *new_node = parser_copy_tree (parser, arg);
14931  new_node->next = NULL;
14932  node->info.index.column_names = parser_append_node (new_node, node->info.index.column_names);
14933  node->info.index.func_no_args++;
14934  }
14935  }
14936  }
14937 }
14938 
14939 /*
14940  * pt_check_function_index_expr_pre () - Helper function to check function
14941  * index semantic correctness.
14942  *
14943  * return : Current node.
14944  * parser (in) : Parser context.
14945  * node (in) : Current node.
14946  * arg (in/out) : Not used.
14947  * continue_walk (in/out) : Walker argument to know when to stop advancing.
14948  */
14949 static PT_NODE *
14950 pt_check_function_index_expr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
14951 {
14952  assert (continue_walk != NULL);
14953 
14954  if (*continue_walk == PT_STOP_WALK || node == NULL)
14955  {
14956  return node;
14957  }
14958  if (node->node_type == PT_NAME && PT_IS_LTZ_TYPE (node->type_enum))
14959  {
14961  *continue_walk = PT_STOP_WALK;
14962  }
14963  return node;
14964 }
14965 
14966 /*
14967  * pt_check_filter_index_expr () - verify if an expression tree is allowed
14968  * to be used in the filter expression of an
14969  * index
14970  * return : true if expression tree is valid, false otherwise
14971  * parser (in) : parser context
14972  * atts (in): an attribute definition list
14973  * node (in) : root node of expression tree
14974  * db_obj (in) : class mop
14975  */
14976 static void
14978 {
14979  PT_FILTER_INDEX_INFO info;
14980  int atts_count = 0, i = 0;
14981 
14982  if (node == NULL)
14983  {
14984  /* null node; nothing to check */
14985  return;
14986  }
14987 
14988  info.atts = atts;
14989  while (atts)
14990  {
14991  atts_count++;
14992  atts = atts->next;
14993  }
14994 
14995  info.atts_count = atts_count;
14996  info.is_null_atts = (bool *) malloc (atts_count * sizeof (bool));
14997  if (info.is_null_atts == NULL)
14998  {
15000  return;
15001  }
15002  for (i = 0; i < atts_count; i++)
15003  {
15004  info.is_null_atts[i] = false;
15005  }
15006  info.is_valid_expr = true;
15007  info.is_constant_expression = true;
15008  info.has_keys_in_expression = false;
15009  info.depth = 0;
15010  info.has_not = false;
15011 
15013 
15014  /* at least one key must be contained in filter expression (without IS_NULL operator, or variations like "not a is
15015  * not null") or at least one key must be not null constrained */
15016  if (info.is_valid_expr == true && info.is_constant_expression == false && info.has_keys_in_expression == false)
15017  {
15018  PT_NODE *attr = NULL, *p_nam = NULL;
15019  SM_CLASS *smclass = NULL;
15020  SM_ATTRIBUTE *smatt = NULL;
15021  int i;
15022  bool has_not_null_constraint;
15023 
15024  /* search for null constraints */
15025  i = 0;
15026  has_not_null_constraint = false;
15027  for (attr = info.atts; attr != NULL && has_not_null_constraint == false; attr = attr->next, i++)
15028  {
15029  if (attr->node_type == PT_SORT_SPEC)
15030  {
15031  p_nam = attr->info.sort_spec.expr;
15032  }
15033  else if (attr->node_type == PT_ATTR_DEF)
15034  {
15035  p_nam = attr->info.attr_def.attr_name;
15036  }
15037 
15038  if (p_nam == NULL || p_nam->node_type != PT_NAME)
15039  {
15040  continue; /* give up */
15041  }
15042 
15043  if (smclass == NULL)
15044  {
15045  assert (db_obj != NULL);
15046  if (au_fetch_class (db_obj, &smclass, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
15047  {
15048  info.is_valid_expr = false;
15049  break;
15050  }
15051  }
15052 
15053  for (smatt = smclass->attributes; smatt != NULL; smatt = (SM_ATTRIBUTE *) smatt->header.next)
15054  {
15055  if (SM_COMPARE_NAMES (smatt->header.name, p_nam->info.name.original) == 0)
15056  {
15057  if (db_attribute_is_non_null (smatt))
15058  {
15059  has_not_null_constraint = true;
15060  }
15061  break;
15062  }
15063  }
15064  }
15065 
15066  if (has_not_null_constraint == false)
15067  {
15068  info.is_valid_expr = false;
15069  }
15070  }
15071  if (info.is_valid_expr == false)
15072  {
15074  pt_short_print (parser, node));
15075  }
15076 
15077  if (info.is_null_atts)
15078  {
15079  free_and_init (info.is_null_atts);
15080  }
15081 }
15082 
15083 /*
15084  * pt_check_filter_index_expr_post ()
15085  *
15086  * return : current node
15087  * parser (in) : parser context
15088  * node (in) : node
15089  * arg (in/out) : (is_valid_expr, expression depth)
15090  * continue_walk (in) : continue walk
15091  */
15092 static PT_NODE *
15093 pt_check_filter_index_expr_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
15094 {
15096  assert (info != NULL);
15097 
15098  switch (node->node_type)
15099  {
15100  case PT_EXPR:
15101  info->depth--;
15102  switch (node->info.expr.op)
15103  {
15104  case PT_NOT:
15105  info->has_not = !(info->has_not);
15106  break;
15107 
15108  default:
15109  break;
15110  }
15111  break;
15112 
15113  case PT_FUNCTION:
15114  info->depth--;
15115  break;
15116 
15117  default:
15118  break;
15119  }
15120 
15121  return node;
15122 }
15123 
15124 /*
15125  * pt_check_filter_index_expr () - verify if a node is allowed to be used
15126  * in the filter expression of an index
15127  * return : current node
15128  * parser (in) : parser context
15129  * node (in) : node
15130  * arg (in/out) : PT_FILTER_INDEX_INFO *
15131  * continue_walk (in) : continue walk
15132  */
15133 static PT_NODE *
15134 pt_check_filter_index_expr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
15135 {
15137  assert (info != NULL);
15138 
15139  if (node == NULL || info->is_valid_expr == false)
15140  {
15141  return node;
15142  }
15143  *continue_walk = PT_CONTINUE_WALK;
15144 
15145  switch (node->node_type)
15146  {
15147  case PT_EXPR:
15148  info->depth++;
15149  /* only allow expressions that have a deterministic result */
15150  switch (node->info.expr.op)
15151  {
15152  case PT_AND:
15153  case PT_BETWEEN:
15154  case PT_NOT_BETWEEN:
15155  case PT_LIKE:
15156  case PT_NOT_LIKE:
15157  case PT_IS_IN:
15158  case PT_IS_NOT_IN:
15159  case PT_IS:
15160  case PT_IS_NOT:
15161  case PT_EQ_SOME:
15162  case PT_NE_SOME:
15163  case PT_GE_SOME:
15164  case PT_GT_SOME:
15165  case PT_LT_SOME:
15166  case PT_LE_SOME:
15167  case PT_EQ_ALL:
15168  case PT_NE_ALL:
15169  case PT_GE_ALL:
15170  case PT_GT_ALL:
15171  case PT_LT_ALL:
15172  case PT_LE_ALL:
15173  case PT_EQ:
15174  case PT_NE:
15175  case PT_GE:
15176  case PT_GT:
15177  case PT_LT:
15178  case PT_LE:
15179  case PT_NULLSAFE_EQ:
15180  case PT_PLUS:
15181  case PT_MINUS:
15182  case PT_TIMES:
15183  case PT_DIVIDE:
15184  case PT_UNARY_MINUS:
15185  case PT_BIT_NOT:
15186  case PT_BIT_XOR:
15187  case PT_BIT_AND:
15188  case PT_BIT_OR:
15189  case PT_BIT_COUNT:
15190  case PT_BITSHIFT_LEFT:
15191  case PT_BITSHIFT_RIGHT:
15192  case PT_DIV:
15193  case PT_MOD:
15194  case PT_XOR:
15195  case PT_BETWEEN_AND:
15196  case PT_BETWEEN_GE_LE:
15197  case PT_BETWEEN_GE_LT:
15198  case PT_BETWEEN_GT_LE:
15199  case PT_BETWEEN_GT_LT:
15200  case PT_BETWEEN_EQ_NA:
15201  case PT_BETWEEN_INF_LE:
15202  case PT_BETWEEN_INF_LT:
15203  case PT_BETWEEN_GE_INF:
15204  case PT_BETWEEN_GT_INF:
15205  case PT_RANGE:
15206  case PT_MODULUS:
15207  case PT_POSITION:
15208  case PT_SUBSTRING:
15209  case PT_OCTET_LENGTH:
15210  case PT_BIT_LENGTH:
15211  case PT_SUBSTRING_INDEX:
15212  case PT_SPACE:
15213  case PT_CHAR_LENGTH:
15214  case PT_LOWER:
15215  case PT_UPPER:
15216  case PT_TRIM:
15217  case PT_LTRIM:
15218  case PT_RTRIM:
15219  case PT_LPAD:
15220  case PT_RPAD:
15221  case PT_REPLACE:
15222  case PT_TRANSLATE:
15223  case PT_REPEAT:
15224  case PT_ADD_MONTHS:
15225  case PT_LAST_DAY:
15226  case PT_MONTHS_BETWEEN:
15227  case PT_TO_CHAR:
15228  case PT_TO_DATE:
15229  case PT_TO_NUMBER:
15230  case PT_TO_TIME:
15231  case PT_TO_TIMESTAMP:
15232  case PT_TO_DATETIME:
15233  case PT_EXTRACT:
15234  case PT_LIKE_ESCAPE:
15235  case PT_CAST:
15236  case PT_FLOOR:
15237  case PT_CEIL:
15238  case PT_SIGN:
15239  case PT_POWER:
15240  case PT_ROUND:
15241  case PT_ABS:
15242  case PT_TRUNC:
15243  case PT_CHR:
15244  case PT_INSTR:
15245  case PT_LEAST:
15246  case PT_GREATEST:
15247  case PT_STRCAT:
15248  case PT_DECODE:
15249  case PT_LOG:
15250  case PT_EXP:
15251  case PT_SQRT:
15252  case PT_CONCAT:
15253  case PT_CONCAT_WS:
15254  case PT_FIELD:
15255  case PT_LEFT:
15256  case PT_RIGHT:
15257  case PT_LOCATE:
15258  case PT_MID:
15259  case PT_STRCMP:
15260  case PT_REVERSE:
15261  case PT_ACOS:
15262  case PT_ASIN:
15263  case PT_ATAN:
15264  case PT_ATAN2:
15265  case PT_COS:
15266  case PT_SIN:
15267  case PT_COT:
15268  case PT_TAN:
15269  case PT_DEGREES:
15270  case PT_RADIANS:
15271  case PT_PI:
15272  case PT_FORMAT:
15273  case PT_LN:
15274  case PT_LOG2:
15275  case PT_LOG10:
15276  case PT_TIME_FORMAT:
15277  case PT_TIMESTAMP:
15278  case PT_FROM_UNIXTIME:
15279  case PT_ADDDATE:
15280  case PT_DATE_ADD:
15281  case PT_SUBDATE:
15282  case PT_DATE_SUB:
15283  case PT_DATE_FORMAT:
15284  case PT_DATEF:
15285  case PT_TIMEF:
15286  case PT_YEARF:
15287  case PT_MONTHF:
15288  case PT_DAYF:
15289  case PT_HOURF:
15290  case PT_MINUTEF:
15291  case PT_SECONDF:
15292  case PT_DAYOFMONTH:
15293  case PT_WEEKDAY:
15294  case PT_DAYOFWEEK:
15295  case PT_DAYOFYEAR:
15296  case PT_QUARTERF:
15297  case PT_TODAYS:
15298  case PT_FROMDAYS:
15299  case PT_TIMETOSEC:
15300  case PT_SECTOTIME:
15301  case PT_MAKEDATE:
15302  case PT_MAKETIME:
15303  case PT_WEEKF:
15304  case PT_USER:
15305  case PT_DATEDIFF:
15306  case PT_TIMEDIFF:
15307  case PT_STR_TO_DATE:
15308  case PT_DEFAULTF:
15309  case PT_LIKE_LOWER_BOUND:
15310  case PT_LIKE_UPPER_BOUND:
15311  case PT_BLOB_LENGTH:
15312  case PT_BLOB_TO_BIT:
15313  case PT_CLOB_LENGTH:
15314  case PT_CLOB_TO_CHAR:
15315  case PT_RLIKE:
15316  case PT_RLIKE_BINARY:
15317  case PT_NOT_RLIKE:
15318  case PT_NOT_RLIKE_BINARY:
15319  case PT_HEX:
15320  case PT_ADDTIME:
15321  case PT_ASCII:
15322  case PT_CONV:
15323  case PT_BIN:
15324  case PT_FINDINSET:
15325  case PT_INET_ATON:
15326  case PT_INET_NTOA:
15327  case PT_TZ_OFFSET:
15328  case PT_NEW_TIME:
15329  case PT_FROM_TZ:
15330  case PT_TO_DATETIME_TZ:
15331  case PT_TO_TIMESTAMP_TZ:
15332  case PT_CONV_TZ:
15333  /* valid expression, nothing to do */
15334  break;
15335  case PT_NOT:
15336  info->has_not = !(info->has_not);
15337  break;
15338  case PT_IS_NULL:
15339  case PT_IS_NOT_NULL:
15340  {
15341  PT_NODE *attr = NULL, *p_nam = NULL;
15342  PT_NODE *arg1 = NULL;
15343  int i = 0, j = 0;
15344 
15345  if (node->info.expr.op == PT_IS_NULL)
15346  {
15347  if (info->has_not == true)
15348  {
15349  /* not expression is null case */
15350  break;
15351  }
15352  }
15353  else if (info->has_not == false)
15354  {
15355  /* expression is not null case */
15356  break;
15357  }
15358 
15359  arg1 = node->info.expr.arg1;
15360  if (arg1 == NULL || info->atts == NULL)
15361  {
15362  break;
15363  }
15364 
15365  if (arg1->node_type != PT_NAME)
15366  {
15367  /* do not allow expression is null do not allow not expression is not null */
15368  info->is_valid_expr = false;
15369 
15370  break;
15371  }
15372 
15373  /* arg1 is PT_NAME node */
15374  if (arg1->info.name.original == NULL)
15375  {
15376  break;
15377  }
15378 
15379  i = 0;
15380  for (attr = info->atts; attr != NULL; attr = attr->next, i++)
15381  {
15382  if (attr->node_type == PT_SORT_SPEC)
15383  {
15384  p_nam = attr->info.sort_spec.expr;
15385  }
15386  else if (attr->node_type == PT_ATTR_DEF)
15387  {
15388  p_nam = attr->info.attr_def.attr_name;
15389  }
15390 
15391  if (p_nam == NULL || p_nam->node_type != PT_NAME)
15392  {
15393  continue; /* give up */
15394  }
15395 
15396  if (!pt_str_compare (p_nam->info.name.original, arg1->info.name.original, CASE_INSENSITIVE))
15397  {
15398  info->is_null_atts[i] = true;
15399  for (j = 0; j < info->atts_count; j++)
15400  {
15401  if (info->is_null_atts[j] == false)
15402  {
15403  break;
15404  }
15405  }
15406  if (j == info->atts_count)
15407  {
15408  info->is_valid_expr = false;
15409  }
15410 
15411  break;
15412  }
15413  }
15414  }
15415  break;
15416 
15417  case PT_FUNCTION_HOLDER:
15418  PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
15421  info->is_valid_expr = false;
15422  break;
15423 
15424  default:
15425  PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
15427  info->is_valid_expr = false;
15428  break;
15429  }
15430  break;
15431 
15432  case PT_FUNCTION:
15433  info->depth++;
15434  /* do not allow aggregates and analytic functions */
15435  switch (node->info.function.function_type)
15436  {
15437  case F_SET:
15438  case F_MULTISET:
15439  case F_SEQUENCE:
15440  /* the functions above are used in the argument IN (values list) expression */
15441  case F_ELT:
15442  case F_INSERT_SUBSTRING:
15443  case F_JSON_ARRAY:
15444  case F_JSON_ARRAY_APPEND:
15445  case F_JSON_ARRAY_INSERT:
15446  case F_JSON_CONTAINS:
15447  case F_JSON_CONTAINS_PATH:
15448  case F_JSON_DEPTH:
15449  case F_JSON_EXTRACT:
15450  case F_JSON_GET_ALL_PATHS:
15451  case F_JSON_KEYS:
15452  case F_JSON_INSERT:
15453  case F_JSON_LENGTH:
15454  case F_JSON_MERGE:
15455  case F_JSON_MERGE_PATCH:
15456  case F_JSON_OBJECT:
15457  case F_JSON_PRETTY:
15458  case F_JSON_QUOTE:
15459  case F_JSON_REMOVE:
15460  case F_JSON_REPLACE:
15461  case F_JSON_SEARCH:
15462  case F_JSON_SET:
15463  case F_JSON_TYPE:
15464  case F_JSON_UNQUOTE:
15465  case F_JSON_VALID:
15466  /* valid expression, nothing to do */
15467  break;
15468  default:
15469  PT_ERRORmf (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
15472  info->is_valid_expr = false;
15473  break;
15474  }
15475  break;
15476 
15477  case PT_NAME:
15478  /* only allow attribute names */
15479  info->is_constant_expression = false;
15480  if (node->info.name.meta_class != PT_META_ATTR && node->info.name.meta_class != PT_NORMAL)
15481  {
15482  /* valid expression, nothing to do */
15483  info->is_valid_expr = false;
15484  }
15485  else if (PT_IS_LTZ_TYPE (node->type_enum))
15486  {
15488  info->is_valid_expr = false;
15489  }
15490  else if (info->has_keys_in_expression == false)
15491  {
15492  PT_NODE *attr = NULL, *p_nam = NULL;
15493  int i;
15494  i = 0;
15495  for (attr = info->atts; attr != NULL; attr = attr->next, i++)
15496  {
15497  if (attr->node_type == PT_SORT_SPEC)
15498  {
15499  p_nam = attr->info.sort_spec.expr;
15500  }
15501  else if (attr->node_type == PT_ATTR_DEF)
15502  {
15503  p_nam = attr->info.attr_def.attr_name;
15504  }
15505 
15506  if (p_nam == NULL || p_nam->node_type != PT_NAME)
15507  {
15508  continue; /* give up */
15509  }
15510 
15511  if ((pt_str_compare (p_nam->info.name.original, node->info.name.original, CASE_INSENSITIVE) == 0)
15512  && (info->is_null_atts[i] == 0))
15513  {
15514  info->has_keys_in_expression = true;
15515  break;
15516  }
15517  }
15518  }
15519  break;
15520 
15521  case PT_VALUE:
15522  if (info->depth == 0)
15523  {
15525  {
15526  if (db_get_int (&node->info.value.db_value) == 0)
15527  {
15528  info->is_valid_expr = false;
15529  }
15530  }
15531  }
15532  break;
15533  case PT_DATA_TYPE:
15534  /* valid expression, nothing to do */
15535  break;
15536 
15537  default:
15538  info->is_valid_expr = false;
15539  break;
15540  }
15541 
15542  if (info->is_valid_expr == false)
15543  {
15544  *continue_walk = PT_STOP_WALK;
15545  }
15546 
15547  return node;
15548 }
15549 
15550 /*
15551  * pt_get_assignments () - get assignment list for INSERT/UPDATE/MERGE
15552  * statements
15553  * return : assignment list or NULL
15554  * node (in): statement node
15555  */
15556 static PT_NODE *
15558 {
15559  if (node == NULL)
15560  {
15561  return NULL;
15562  }
15563 
15564  switch (node->node_type)
15565  {
15566  case PT_UPDATE:
15567  return node->info.update.assignment;
15568  case PT_MERGE:
15569  return node->info.merge.update.assignment;
15570  case PT_INSERT:
15571  return node->info.insert.odku_assignments;
15572  default:
15573  return NULL;
15574  }
15575 }
15576 
15577 /*
15578  * pt_check_odku_assignments () - check ON DUPLICATE KEY assignments of an
15579  * INSERT statement
15580  * return : node
15581  * parser (in) : parser context
15582  * insert (in) : insert statement
15583  *
15584  * Note: this function performs the following validations:
15585  * - there are no double assignments
15586  * - assignments are only performed to columns belonging to the insert spec
15587  * - only instance attributes are updated
15588  */
15589 PT_NODE *
15591 {
15592  PT_NODE *assignment, *spec, *lhs;
15593  if (insert == NULL || insert->node_type != PT_INSERT)
15594  {
15595  return insert;
15596  }
15597 
15598  if (insert->info.insert.odku_assignments == NULL)
15599  {
15600  return insert;
15601  }
15602 
15603  pt_no_double_updates (parser, insert);
15604  if (pt_has_error (parser))
15605  {
15606  return NULL;
15607  }
15608  pt_check_assignments (parser, insert);
15609  if (pt_has_error (parser))
15610  {
15611  return NULL;
15612  }
15613 
15614  spec = insert->info.insert.spec;
15615  for (assignment = insert->info.insert.odku_assignments; assignment != NULL; assignment = assignment->next)
15616  {
15617  if (assignment->node_type != PT_EXPR || assignment->info.expr.op != PT_ASSIGN)
15618  {
15619  assert (false);
15620  PT_INTERNAL_ERROR (parser, "semantic");
15621  return NULL;
15622  }
15623  lhs = assignment->info.expr.arg1;
15624  if (lhs == NULL || lhs->node_type != PT_NAME)
15625  {
15626  assert (false);
15627  PT_INTERNAL_ERROR (parser, "semantic");
15628  return NULL;
15629  }
15630  if (lhs->info.name.spec_id != spec->info.spec.id)
15631  {
15633  return NULL;
15634  }
15635  }
15636  return insert;
15637 }
15638 
15639 /*
15640  * pt_check_vacuum () - Check VACUUM statement.
15641  *
15642  * return : Void.
15643  * parser (in) : Parser context.
15644  * node (in) : VACUUM parse tree node.
15645  */
15646 static void
15648 {
15649  PT_FLAT_SPEC_INFO info;
15650 
15651  assert (parser != NULL);
15652  if (!PT_IS_VACUUM_NODE (node))
15653  {
15654  /* Not the scope of this function */
15655  return;
15656  }
15657 
15658  info.spec_parent = NULL;
15659  info.for_update = false;
15660  /* Replace each Entity Spec with an Equivalent flat list */
15661  parser_walk_tree (parser, node, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
15662 }
15663 
15664 /*
15665  * pt_get_select_list_coll_compat () - scans a UNION parse tree and retains
15666  * for each column with collation the node
15667  * (and its compatibility info) having the
15668  * least (collation) coercible level
15669  *
15670  * return: compatibility status
15671  * parser(in): the parser context
15672  * query(in): query node
15673  * cinfo(in/out): compatibility info array structure
15674  * num_cinfo(in): number of elements in cinfo
15675  */
15676 static PT_UNION_COMPATIBLE
15678 {
15679  PT_NODE *attrs, *att;
15680  int i;
15681  PT_UNION_COMPATIBLE status = PT_UNION_COMP, status2;
15682 
15683  assert (query != NULL);
15684 
15685  switch (query->node_type)
15686  {
15687  case PT_SELECT:
15688 
15689  attrs = pt_get_select_list (parser, query);
15690 
15691  for (att = attrs, i = 0; i < num_cinfo && att != NULL; ++i, att = att->next)
15692  {
15693  SEMAN_COMPATIBLE_INFO cinfo_att;
15694 
15695  if (!PT_HAS_COLLATION (att->type_enum))
15696  {
15697  continue;
15698  }
15699 
15700  pt_get_compatible_info_from_node (att, &cinfo_att);
15701 
15702  if (cinfo[i].type_enum == PT_TYPE_NONE)
15703  {
15704  /* first query, init this column */
15705  memcpy (&(cinfo[i]), &cinfo_att, sizeof (cinfo_att));
15706  }
15707  else if (cinfo_att.coll_infer.coerc_level < cinfo[i].coll_infer.coerc_level)
15708  {
15709  assert (PT_HAS_COLLATION (cinfo[i].type_enum));
15710 
15711  memcpy (&(cinfo[i].coll_infer), &(cinfo_att.coll_infer), sizeof (cinfo_att.coll_infer));
15712  cinfo[i].ref_att = att;
15713  status = PT_UNION_INCOMP;
15714  }
15715  else if (cinfo_att.coll_infer.coll_id != cinfo[i].coll_infer.coll_id)
15716  {
15717  status = PT_UNION_INCOMP;
15718  }
15719  }
15720  break;
15721  case PT_UNION:
15722  case PT_INTERSECTION:
15723  case PT_DIFFERENCE:
15724  status = pt_get_select_list_coll_compat (parser, query->info.query.q.union_.arg1, cinfo, num_cinfo);
15725 
15726  if (status != PT_UNION_COMP && status != PT_UNION_INCOMP)
15727  {
15728  break;
15729  }
15730 
15731  status2 = pt_get_select_list_coll_compat (parser, query->info.query.q.union_.arg2, cinfo, num_cinfo);
15732  if (status2 != PT_UNION_COMP)
15733  {
15734  status = status2;
15735  }
15736  break;
15737  default:
15738  break;
15739  }
15740 
15741  return status;
15742 }
15743 
15744 /*
15745  * pt_apply_union_select_list_collation () - scans a UNION parse tree and
15746  * sets for each node with collation the collation corresponding
15747  * of the column in 'cinfo' array
15748  *
15749  * return: union compatibility status
15750  * parser(in): the parser context
15751  * query(in): query node
15752  * cinfo(in): compatibility info array structure
15753  * num_cinfo(in): number of elements in cinfo
15754  */
15755 static PT_UNION_COMPATIBLE
15757  int num_cinfo)
15758 {
15759  PT_NODE *attrs, *att, *prev_att, *next_att, *new_att;
15760  int i;
15761  PT_UNION_COMPATIBLE status = PT_UNION_COMP, status2;
15762 
15763  assert (query != NULL);
15764 
15765  switch (query->node_type)
15766  {
15767  case PT_SELECT:
15768 
15769  attrs = pt_get_select_list (parser, query);
15770 
15771  prev_att = NULL;
15772  next_att = NULL;
15773 
15774  for (att = attrs, i = 0; i < num_cinfo && att != NULL; ++i, prev_att = att, att = next_att)
15775  {
15776  SEMAN_COMPATIBLE_INFO cinfo_att;
15777 
15778  next_att = att->next;
15779 
15780  if (!PT_HAS_COLLATION (att->type_enum))
15781  {
15782  continue;
15783  }
15784 
15785  assert (PT_HAS_COLLATION (cinfo[i].type_enum));
15786 
15787  pt_get_compatible_info_from_node (att, &cinfo_att);
15788 
15789  if (cinfo_att.coll_infer.coll_id != cinfo[i].coll_infer.coll_id)
15790  {
15791  bool new_cast_added = false;
15792 
15793  if (pt_common_collation (&cinfo_att.coll_infer, &(cinfo[i].coll_infer), NULL, 2, false,
15794  &cinfo_att.coll_infer.coll_id, &cinfo_att.coll_infer.codeset) != 0)
15795  {
15797  pt_short_print (parser, att), pt_short_print (parser, cinfo[i].ref_att));
15799  }
15800 
15801  new_att = pt_make_cast_with_compatible_info (parser, att, next_att, &cinfo_att, &new_cast_added);
15802  if (new_att == NULL)
15803  {
15805  pt_short_print (parser, att), pt_short_print (parser, cinfo[i].ref_att));
15807  }
15808 
15809  att = new_att;
15810 
15811  if (new_cast_added)
15812  {
15813  if (prev_att == NULL)
15814  {
15815  query->info.query.q.select.list = att;
15816  query->type_enum = att->type_enum;
15817  if (query->data_type)
15818  {
15819  parser_free_tree (parser, query->data_type);
15820  }
15821 
15822  query->data_type = parser_copy_tree_list (parser, att->data_type);
15823  }
15824  else
15825  {
15826  prev_att->next = att;
15827  }
15828  }
15829 
15830  status = PT_UNION_INCOMP;
15831  }
15832  }
15833  break;
15834  case PT_UNION:
15835  case PT_INTERSECTION:
15836  case PT_DIFFERENCE:
15837  status = pt_apply_union_select_list_collation (parser, query->info.query.q.union_.arg1, cinfo, num_cinfo);
15838  if (status != PT_UNION_COMP && status != PT_UNION_INCOMP)
15839  {
15840  return status;
15841  }
15842 
15843  status2 = pt_apply_union_select_list_collation (parser, query->info.query.q.union_.arg2, cinfo, num_cinfo);
15844 
15845  if (status2 != PT_UNION_COMP && status2 != PT_UNION_INCOMP)
15846  {
15847  return status;
15848  }
15849 
15850  if (status2 != PT_UNION_COMP)
15851  {
15852  status = status2;
15853  }
15854 
15855  if (status == PT_UNION_INCOMP)
15856  {
15857  if (query->data_type != NULL)
15858  {
15859  parser_free_tree (parser, query->data_type);
15860  }
15861 
15862  query->data_type = parser_copy_tree (parser, query->info.query.q.union_.arg1->data_type);
15863  }
15864  break;
15865  default:
15866  break;
15867  }
15868 
15869  return status;
15870 }
15871 
15872 /*
15873  * pt_mark_union_leaf_nodes () - walking function for setting for each UNION
15874  * DIFFERENCE/INTERSECTION query if it is a root
15875  * of a leaf node.
15876  * return:
15877  * parser(in):
15878  * node(in):
15879  * arg(in):
15880  * continue_walk(in/out):
15881  */
15882 static PT_NODE *
15883 pt_mark_union_leaf_nodes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
15884 {
15885  if (PT_IS_UNION (node) || PT_IS_INTERSECTION (node) || PT_IS_DIFFERENCE (node))
15886  {
15887  PT_NODE *arg;
15888 
15889  arg = node->info.query.q.union_.arg1;
15890  if (PT_IS_UNION (arg) || PT_IS_INTERSECTION (arg) || PT_IS_DIFFERENCE (arg))
15891  {
15892  arg->info.query.q.union_.is_leaf_node = 1;
15893  }
15894 
15895  arg = node->info.query.q.union_.arg2;
15896  if (PT_IS_UNION (arg) || PT_IS_INTERSECTION (arg) || PT_IS_DIFFERENCE (arg))
15897  {
15898  arg->info.query.q.union_.is_leaf_node = 1;
15899  }
15900  }
15901 
15902  return node;
15903 }
15904 
15905 /*
15906  * pt_check_where () - do semantic checks on a node's where clause
15907  * return:
15908  * parser(in): the parser context
15909  * node(in): the node to check
15910  */
15911 static PT_NODE *
15913 {
15914  PT_NODE *function = NULL;
15915 
15916  /* check if exists aggregate/analytic functions in where clause */
15917  function = pt_find_aggregate_analytic_in_where (parser, node);
15918  if (function != NULL)
15919  {
15920  if (pt_is_aggregate_function (parser, function))
15921  {
15923  }
15924  else
15925  {
15927  }
15928  }
15929 
15930  return node;
15931 }
15932 
15933 /*
15934  * pt_check_range_partition_strict_increasing () -
15935  * return: NO_ERROR or error code
15936  * parser(in): the parser context
15937  * stmt(in): the top statement
15938  * part(in): current partition
15939  * part_next(in): the next partition
15940  * column_dt(in): data type
15941  *
15942  */
15943 static int
15945  PT_NODE * part_next, PT_NODE * column_dt)
15946 {
15947  int error = NO_ERROR;
15948  PT_NODE *pt_val1 = NULL, *pt_val2 = NULL;
15949  DB_VALUE *db_val1 = NULL, *db_val2 = NULL;
15950  DB_VALUE null_val;
15951  DB_VALUE_COMPARE_RESULT compare_result;
15952 
15953  assert (parser != NULL && stmt != NULL && part != NULL && part->node_type == PT_PARTS);
15954  assert (part_next == NULL || part_next->node_type == PT_PARTS);
15955  assert (column_dt == NULL || column_dt->node_type == PT_DATA_TYPE);
15956 
15957  /* make sure value1 is the same type described by column_dt */
15958  pt_val1 = part->info.parts.values;
15959  assert (pt_val1 == NULL || column_dt == NULL
15960  || (pt_val1->type_enum == column_dt->type_enum
15961  && (!PT_IS_STRING_TYPE (pt_val1->type_enum)
15962  || (pt_val1->data_type == NULL
15963  || (pt_val1->data_type->info.data_type.collation_id ==
15964  column_dt->info.data_type.collation_id)))));
15965 
15966  db_make_null (&null_val);
15967 
15968  /* next value */
15969  if (part_next != NULL)
15970  {
15971  /* the first value */
15972  db_val1 = pt_value_to_db (parser, pt_val1);
15973  if (db_val1 == NULL)
15974  {
15975  if (pt_has_error (parser))
15976  {
15978 
15979  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error, part->info.parts.name->info.name.original);
15980 
15981  goto end;
15982  }
15983 
15984  db_val1 = &null_val;
15985  }
15986 
15987  pt_val2 = part_next->info.parts.values;
15988 
15989  /* if column_dt is not null, do the cast if needed */
15990  if (pt_val2 != NULL && column_dt != NULL)
15991  {
15992  error = pt_coerce_partition_value_with_data_type (parser, pt_val2, column_dt);
15993 
15994  if (error != NO_ERROR)
15995  {
15997 
15998  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error,
15999  part_next->info.parts.name->info.name.original);
16000 
16001  goto end;
16002  }
16003  }
16004 
16005  db_val2 = pt_value_to_db (parser, pt_val2);
16006  if (db_val2 == NULL)
16007  {
16008  if (pt_has_error (parser))
16009  {
16011 
16012  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error,
16013  part_next->info.parts.name->info.name.original);
16014 
16015  goto end;
16016  }
16017 
16018  db_val2 = &null_val;
16019  }
16020 
16021  /* check the strict increasing */
16022  if (DB_IS_NULL (db_val1))
16023  {
16024  /* this is an error */
16026 
16027  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error, part);
16028 
16029  goto end;
16030  }
16031  else if (!DB_IS_NULL (db_val2))
16032  {
16033  compare_result = (DB_VALUE_COMPARE_RESULT) db_value_compare (db_val1, db_val2);
16034  if (compare_result != DB_LT)
16035  {
16036  /* this is an error */
16038 
16039  PT_ERRORmf (parser, stmt, MSGCAT_SET_PARSER_SEMANTIC, error, part_next);
16040 
16041  goto end;
16042  }
16043  }
16044  }
16045 
16046 end:
16047 
16048  return error;
16049 }
16050 
16051 /*
16052  * pt_coerce_partition_value_with_data_type () - do the cast
16053  * return: NO_ERROR or error code
16054  * parser(in):
16055  * value(in):
16056  * data_type(in):
16057  *
16058  */
16059 static int
16061 {
16062  int error = NO_ERROR;
16063 
16064  assert (value != NULL && data_type != NULL && data_type->node_type == PT_DATA_TYPE);
16065 
16066  if (value->type_enum != data_type->type_enum
16067  || (PT_IS_STRING_TYPE (value->type_enum) && value->data_type != NULL
16068  && value->data_type->info.data_type.collation_id != data_type->info.data_type.collation_id))
16069  {
16070  error = pt_coerce_value (parser, value, value, data_type->type_enum, data_type);
16071  }
16072 
16073  return error;
16074 }
16075 
16076 /*
16077  * pt_try_remove_order_by - verify and remove order_by clause after it has been decided it is unnecessary
16078  * return: void
16079  * parser(in): Parser context
16080  * query(in/out): Processed query
16081  */
16082 void
16084 {
16085  PT_NODE *col, *next;
16086 
16088 
16089  if (query->info.query.order_by == NULL || query->info.query.orderby_for != NULL || query->info.query.limit != NULL)
16090  {
16091  /* order_by can not be removed when query has orderby_for or limit */
16092  return;
16093  }
16094 
16095  /* if select list has orderby_num(), can not remove ORDER BY clause for example:
16096  * (i, j) = (select i, orderby_num() from t order by i)
16097  */
16098  for (col = pt_get_select_list (parser, query); col; col = col->next)
16099  {
16100  if (col->node_type == PT_EXPR && col->info.expr.op == PT_ORDERBY_NUM)
16101  {
16102  break; /* can not remove ORDER BY clause */
16103  }
16104  }
16105 
16106  if (!col)
16107  {
16108  /* no column is ORDERBY_NUM, order_by can be removed */
16109  parser_free_tree (parser, query->info.query.order_by);
16110  query->info.query.order_by = NULL;
16111  query->info.query.flag.order_siblings = 0;
16112 
16113  for (col = pt_get_select_list (parser, query); col && col->next; col = next)
16114  {
16115  next = col->next;
16116  if (next->flag.is_hidden_column)
16117  {
16118  parser_free_tree (parser, next);
16119  col->next = NULL;
16120  break;
16121  }
16122  }
16123  }
16124 }
16125 
16126 
16127 /*
16128  * pt_check_union_is_foldable - decide if union can be folded
16129  *
16130  * return : union foldability
16131  * parser(in) : Parser context.
16132  * union_node(in) : Union node.
16133  */
16136 {
16137  PT_NODE *arg1, *arg2;
16138  bool arg1_is_null, arg2_is_null;
16139  STATEMENT_SET_FOLD fold_as;
16140 
16141  assert (union_node->node_type == PT_UNION || union_node->node_type == PT_INTERSECTION
16142  || union_node->node_type == PT_DIFFERENCE || union_node->node_type == PT_CTE);
16143 
16144  if (union_node->node_type == PT_CTE)
16145  {
16146  /* A CTE is a union between the non_recursive and recursive parts */
16148  }
16149 
16150  arg1 = union_node->info.query.q.union_.arg1;
16151  arg2 = union_node->info.query.q.union_.arg2;
16152 
16153  arg1_is_null = pt_false_where (parser, arg1);
16154  arg2_is_null = pt_false_where (parser, arg2);
16155 
16156  if (!arg1_is_null && !arg2_is_null)
16157  {
16158  /* nothing to fold at this moment. */
16159  fold_as = STATEMENT_SET_FOLD_NOTHING;
16160  }
16161  else if (arg1_is_null && arg2_is_null)
16162  {
16163  /* fold the entire node as null */
16164  fold_as = STATEMENT_SET_FOLD_AS_NULL;
16165  }
16166  else if (arg1_is_null && !arg2_is_null)
16167  {
16168  if (union_node->node_type == PT_UNION)
16169  {
16170  fold_as = STATEMENT_SET_FOLD_AS_ARG2;
16171  }
16172  else
16173  {
16174  fold_as = STATEMENT_SET_FOLD_AS_NULL;
16175  }
16176  }
16177  else
16178  {
16179  assert (!arg1_is_null && arg2_is_null);
16180 
16181  if (union_node->node_type == PT_UNION || union_node->node_type == PT_DIFFERENCE)
16182  {
16183  fold_as = STATEMENT_SET_FOLD_AS_ARG1;
16184  }
16185  else
16186  {
16187  assert (union_node->node_type == PT_INTERSECTION);
16188  fold_as = STATEMENT_SET_FOLD_AS_NULL;
16189  }
16190  }
16191 
16192  /* check if folding would require merging WITH clauses; in this case we give up folding */
16193  if (fold_as == STATEMENT_SET_FOLD_AS_ARG1 || fold_as == STATEMENT_SET_FOLD_AS_ARG2)
16194  {
16195  PT_NODE *active = (fold_as == STATEMENT_SET_FOLD_AS_ARG1 ? arg1 : arg2);
16196 
16197  if (PT_IS_QUERY_NODE_TYPE (active->node_type) && active->info.query.with != NULL
16198  && union_node->info.query.with != NULL)
16199  {
16200  fold_as = STATEMENT_SET_FOLD_NOTHING;
16201  }
16202  }
16203 
16204  return fold_as;
16205 }
16206 
16207 /*
16208  * pt_fold_union - fold union node following indicated method
16209  *
16210  * return : union node folded
16211  * parser (in) : Parser context.
16212  * union_node (in) : Union node.
16213  * fold_as (in) : indicated folding method
16214  */
16215 PT_NODE *
16216 pt_fold_union (PARSER_CONTEXT * parser, PT_NODE * union_node, STATEMENT_SET_FOLD fold_as)
16217 {
16218  PT_NODE *new_node, *next;
16219  int line, column;
16220  const char *alias_print;
16221 
16222  assert (union_node->node_type == PT_UNION || union_node->node_type == PT_INTERSECTION
16223  || union_node->node_type == PT_DIFFERENCE);
16224 
16225  line = union_node->line_number;
16226  column = union_node->column_number;
16227  alias_print = union_node->alias_print;
16228  next = union_node->next;
16229  union_node->next = NULL;
16230 
16231  if (fold_as == STATEMENT_SET_FOLD_AS_NULL)
16232  {
16233  /* fold the statement set as null, we don't need to fold orderby clause because we return null. */
16234  parser_free_tree (parser, union_node);
16235  new_node = parser_new_node (parser, PT_VALUE);
16236  new_node->type_enum = PT_TYPE_NULL;
16237  }
16238  else if (fold_as == STATEMENT_SET_FOLD_AS_ARG1 || fold_as == STATEMENT_SET_FOLD_AS_ARG2)
16239  {
16240  PT_NODE *active;
16241  PT_NODE *union_orderby, *union_orderby_for, *union_limit, *union_with_clause;
16242  unsigned int union_rewrite_limit;
16243 
16244  if (fold_as == STATEMENT_SET_FOLD_AS_ARG1)
16245  {
16246  pt_move_node (active, union_node->info.query.q.union_.arg1);
16247  }
16248  else
16249  {
16250  pt_move_node (active, union_node->info.query.q.union_.arg2);
16251  }
16252 
16253  /* to save union's orderby or limit clause to arg1 or arg2 */
16254  pt_move_node (union_orderby, union_node->info.query.order_by);
16255  pt_move_node (union_orderby_for, union_node->info.query.orderby_for);
16256  pt_move_node (union_limit, union_node->info.query.limit);
16257  union_rewrite_limit = union_node->info.query.flag.rewrite_limit;
16258  pt_move_node (union_with_clause, union_node->info.query.with);
16259 
16260  /* When active node has a limit or orderby_for clause and union node has a limit or ORDERBY clause, need a
16261  * derived table to keep both conflicting clauses. When a subquery has orderby clause without
16262  * limit/orderby_for, it may be ignored for meaningless cases. */
16263  if ((active->info.query.limit || active->info.query.orderby_for) && (union_limit || union_orderby))
16264  {
16265  PT_NODE *derived;
16266 
16267  derived = mq_rewrite_query_as_derived (parser, active);
16268  if (derived == NULL)
16269  {
16270  assert (pt_has_error (parser));
16271  return NULL;
16272  }
16273 
16274  new_node = derived;
16275  }
16276  else
16277  {
16278  /* just use active node */
16279  new_node = active;
16280  }
16281 
16282  /* free union node */
16283  parser_free_tree (parser, union_node);
16284 
16285  /* to fold the query with remaining parts */
16286  if (union_orderby != NULL)
16287  {
16288  new_node->info.query.order_by = union_orderby;
16289  new_node->info.query.orderby_for = union_orderby_for;
16290  }
16291  if (union_limit != NULL)
16292  {
16293  new_node->info.query.limit = union_limit;
16294  new_node->info.query.flag.rewrite_limit = union_rewrite_limit;
16295  }
16296  if (union_with_clause)
16297  {
16298  assert (new_node->info.query.with == NULL);
16299  new_node->info.query.with = union_with_clause;
16300  }
16301 
16302  /* check the union's orderby or limit clause if present */
16303  pt_check_order_by (parser, new_node);
16304  }
16305  else
16306  {
16307  assert (fold_as == STATEMENT_SET_FOLD_NOTHING);
16308 
16309  /* do nothing */
16310  new_node = union_node;
16311  }
16312 
16313  new_node->line_number = line;
16314  new_node->column_number = column;
16315  new_node->alias_print = alias_print;
16316  new_node->next = next;
16317 
16318  return new_node;
16319 }
PT_NODE * mq_clear_ids(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *spec)
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
#define PT_NAME_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2575
#define MSGCAT_SEMANTIC_NO_LTZ_IN_FUNCTION_FILTER_INDEX
const SHOWSTMT_METADATA * showstmt_get_metadata(SHOWSTMT_TYPE show_type)
Definition: show_meta.c:734
#define MSGCAT_SEMANTIC_DATA_LOSS_IS_NOT_ALLOWED
PT_NODE * pt_name(PARSER_CONTEXT *parser_ptr, const char *name)
PT_MISC_TYPE attr_type
Definition: parse_tree.h:1864
PT_NODE * order_by
Definition: parse_tree.h:2769
#define MSGCAT_SEMANTIC_INVALID_ORDERBY_WITH_DISTINCT
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
static PT_NODE * pt_check_with_info(PARSER_CONTEXT *parser, PT_NODE *node, SEMANTIC_CHK_INFO *info)
#define pt_is_output_hostvar(n)
Definition: parse_tree.h:270
PT_NODE * pt_compile(PARSER_CONTEXT *parser, PT_NODE *volatile statement)
Definition: compile.c:380
#define MSGCAT_SEMANTIC_TRANSACTION_ID_WANT_INTEGER
PT_NODE * next
Definition: parse_tree.h:3447
PT_NODE * internal_stmts
Definition: parse_tree.h:2066
#define MSGCAT_SEMANTIC_IS_NOT_DEFINED
#define MAX_PARTITIONS
Definition: partition.h:26
PT_NAME_INFO name
Definition: parse_tree.h:3318
#define MSGCAT_SEMANTIC_ALREADY_SUBCLASS
#define RESET_HOST_VARIABLES_IF_INTERNAL_STATEMENT(parser_)
Definition: parse_tree.h:539
#define MSGCAT_SEMANTIC_INVALID_PARTITION_INFO
DB_OBJECT * db_attribute_class(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1189
const char * expr
Definition: class_object.h:697
QFILE_TUPLE_VALUE_POSITION pos_descr
Definition: parse_tree.h:2829
PT_NODE * pt_find_spec_in_statement(PARSER_CONTEXT *parser, const PT_NODE *stmt, const PT_NODE *name)
#define MSGCAT_SEMANTIC_FUNCTION_CANNOT_BE_USED_FOR_FILTER_INDEX
PT_NODE * mq_rewrite_aggregate_as_derived(PARSER_CONTEXT *parser, PT_NODE *agg_sel)
struct pt_alter_info::@111::@115 rename
#define PT_IS_QUERY(n)
Definition: parse_tree.h:296
PT_NODE * target_classes
Definition: parse_tree.h:2060
static PT_NODE * pt_check_vclass_query_spec(PARSER_CONTEXT *parser, PT_NODE *qry, PT_NODE *attrs, const char *self, const bool do_semantic_check)
unsigned with_rollup
Definition: parse_tree.h:3472
PT_NODE * arg_list
Definition: parse_tree.h:2258
int db_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const DB_DOMAIN *desired_domain)
Definition: db_macro.c:1779
#define NO_ERROR
Definition: error_code.h:46
PT_UNION_INFO union_
Definition: parse_tree.h:2782
int set_get_element_nocopy(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2616
#define MSGCAT_SEMANTIC_INS_EXPR_IN_INSERT
int pt_quick_resolve_names(PARSER_CONTEXT *parser, PT_NODE **spec_p, PT_NODE **node_p, SEMANTIC_CHK_INFO *sc_info)
PT_CAST_VAL
PT_NODE * resolution_list
Definition: parse_tree.h:1908
#define PT_EXPR_INFO_CAST_SHOULD_FOLD
Definition: parse_tree.h:2227
PT_METHOD_CALL_INFO method_call
Definition: parse_tree.h:3316
static PT_NODE * pt_count_iso_nodes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_NON_REFERABLE_VIOLATION
#define LANG_SYS_COLLATION
bool pt_is_aggregate_function(PARSER_CONTEXT *parser, const PT_NODE *node)
#define LANG_GET_BINARY_COLLATION(c)
PT_NODE * pt_find_order_value_in_list(PARSER_CONTEXT *parser, const PT_NODE *sort_value, const PT_NODE *order_list)
PT_UPDATE_INFO update
Definition: parse_tree.h:3353
PT_MERGE_INFO merge
Definition: parse_tree.h:3315
struct seman_compatible_info SEMAN_COMPATIBLE_INFO
UINTPTR id
Definition: parse_tree.h:2144
#define MSGCAT_SEMANTIC_QSPEC_COL_NOT_NA
static SEMAN_COMPATIBLE_INFO * pt_get_values_query_compatible_info(PARSER_CONTEXT *parser, PT_NODE *node, bool *need_cast)
static void pt_check_method(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * as_attr_list
Definition: parse_tree.h:1976
PT_MISC_TYPE schema
Definition: parse_tree.h:2354
#define MSGCAT_SEMANTIC_ONLYONE_PARTITION_COLUMN
static void pt_check_alter_partition(PARSER_CONTEXT *parser, PT_NODE *stmt, MOP dbobj)
#define PT_WARNINGmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:84
PT_NODE * attr_name
Definition: parse_tree.h:1858
PT_NODE ** parser_parse_string_use_sys_charset(PARSER_CONTEXT *parser, const char *buffer)
PT_NODE * pt_check_orderbynum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_CANNOT_USE_GROUPBYNUM_WITH_ROLLUP
#define PT_IS_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:164
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
TP_DOMAIN * expected_domain
Definition: parse_tree.h:3452
void db_get_tran_settings(int *lock_wait, DB_TRAN_ISOLATION *tran_isolation)
Definition: db_admin.c:1554
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
#define MSGCAT_SEMANTIC_CONSTANT_TYPE_MISMATCH
#define PT_CHAIN_LENGTH
PT_NODE * internal_stmts
Definition: parse_tree.h:1827
#define ASSERT_ERROR()
PT_NODE * using_index
Definition: parse_tree.h:2693
enum json_table_column_function func
Definition: parse_tree.h:3240
PT_NODE * into_list
Definition: parse_tree.h:2771
#define MSGCAT_SEMANTIC_COLLATE_NOT_ALLOWED
PT_NODE * values
Definition: parse_tree.h:2029
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
PT_NODE * default_value
Definition: parse_tree.h:2004
#define MSGCAT_SEMANTIC_USER_IS_NOT_IN_DB
#define MSGCAT_SEMANTIC_PREFIX_LENGTH_COLLATION
void * parser_alloc(const PARSER_CONTEXT *parser, const int length)
Definition: parse_tree.c:951
PT_NODE * assignment
Definition: parse_tree.h:2861
#define MSGCAT_SEMANTIC_NOT_CLASS_ATTR_MTHD
PT_NODE * table_option_list
Definition: parse_tree.h:1905
static PT_NODE * pt_derive_attribute(PARSER_CONTEXT *parser, PT_NODE *c)
#define pt_is_input_hostvar(n)
Definition: parse_tree.h:269
STATEMENT_SET_FOLD
PT_NODE * expr
Definition: parse_tree.h:3188
PT_NODE * spec
Definition: parse_tree.h:3182
static bool pt_has_parameters(PARSER_CONTEXT *parser, PT_NODE *stmt)
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
struct db_value * m_default_value
#define MSGCAT_SEMANTIC_NONEXISTENT_SUPCLASS
int pt_check_enum_data_type(PARSER_CONTEXT *parser, PT_NODE *dt)
PT_MISC_TYPE call_or_expr
Definition: parse_tree.h:2367
DB_OBJECT * db_get_owner(DB_OBJECT *class_obj)
Definition: db_admin.c:1892
unsigned char codeset
Definition: object_domain.h:91
#define MSGCAT_SEMANTIC_ILLEGAL_RHS
#define MSGCAT_SEMANTIC_IS_NOT_PARTITIONED_CLASS
#define MSGCAT_SEMANTIC_ORDERBYNUM_SELECT_LIST_ERR
static int pt_normalize_path(PARSER_CONTEXT *parser, REFPTR(char, c))
STATEMENT_SET_FOLD pt_check_union_is_foldable(PARSER_CONTEXT *parser, PT_NODE *union_node)
bool pt_is_analytic_function(PARSER_CONTEXT *parser, const PT_NODE *node)
DB_ATTRIBUTE * db_get_class_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:878
static bool pt_is_compatible_without_cast(PARSER_CONTEXT *parser, SEMAN_COMPATIBLE_INFO *dest_sci, PT_NODE *src, bool *is_cast_allowed)
#define TP_IS_SET_TYPE(typenum)
static int pt_class_compatible(PARSER_CONTEXT *parser, const PT_NODE *class1, const PT_NODE *class2, bool view_definition_context)
#define MSGCAT_SEMANTIC_VARIABLE_NOT_ALLOWED
bool is_collate_allowed
Definition: parse_tree.h:3067
static PT_NODE * pt_to_compatible_cast(PARSER_CONTEXT *parser, PT_NODE *node, SEMAN_COMPATIBLE_INFO *cinfo, int num_cinfo)
DB_DOMAIN * pt_type_enum_to_db_domain(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:1549
PT_MISC_TYPE
Definition: parse_tree.h:983
#define PT_ERROR(parser, node, msg)
Definition: parse_tree.h:54
static PT_NODE * pt_check_and_replace_hostvar(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int db_get_int(const DB_VALUE *value)
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
DB_TYPE
Definition: dbtype_def.h:670
PT_NODE * xaction_modes
Definition: parse_tree.h:2802
PT_NODE * assignment
Definition: parse_tree.h:2928
static PT_NODE * pt_find_matching_sort_spec(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *spec_list, PT_NODE *select_list)
#define PT_NAME_INFO_FILL_DEFAULT
Definition: parse_tree.h:2565
static PT_NODE * pt_expand_isnull_preds_helper(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define ER_FAILED
Definition: error_code.h:47
int pt_get_select_query_columns(PARSER_CONTEXT *parser, PT_NODE *create_select, DB_QUERY_TYPE **query_columns)
int db_json_normalize_path_string(const char *pointer_path, std::string &output)
Definition: db_json.cpp:2749
#define MSGCAT_SEMANTIC_OUT_OF_MEMORY
static PT_NODE * pt_find_aggregate_analytic_pre(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
#define PT_EXPR_INFO_SET_FLAG(e, f)
Definition: parse_tree.h:2239
int db_method_arg_count(DB_METHOD *method)
Definition: db_info.c:1710
static PT_NODE * pt_count_time_nodes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
struct json_table_column_behavior on_empty
Definition: parse_tree.h:3242
PT_NODE * chain[PT_CHAIN_LENGTH]
PT_NODE * search_cond
Definition: parse_tree.h:2925
PT_NODE * arg3
Definition: parse_tree.h:2202
TP_DOMAIN * domain
Definition: class_object.h:444
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
static PT_NODE * pt_check_filter_index_expr_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * pt_get_select_list(PARSER_CONTEXT *parser, PT_NODE *query)
Definition: query_result.c:404
static const char * attribute_name(PARSER_CONTEXT *parser, PT_NODE *att)
#define MSGCAT_SEMANTIC_SORT_SPEC_WANT_NUM
#define MSGCAT_SEMANTIC_DUPLICATE_TABLE_OPTION
static void pt_get_compatible_info_from_node(const PT_NODE *att, SEMAN_COMPATIBLE_INFO *cinfo)
PT_NODE * arg2
Definition: parse_tree.h:2664
#define PT_SELECT_INFO_DISABLE_LOOSE_SCAN
Definition: parse_tree.h:2731
int correlation_level
Definition: parse_tree.h:2745
static int pt_check_json_table_node(PARSER_CONTEXT *parser, PT_NODE *node)
int db_is_instance(MOP obj)
Definition: db_info.c:394
static bool pt_is_compatible_type(const PT_TYPE_ENUM arg1_type, const PT_TYPE_ENUM arg2_type)
#define MSGCAT_SEMANTIC_DEFAULT_NESTED_EXPR_NOT_ALLOWED
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
PT_TABLE_OPTION_INFO table_option
Definition: parse_tree.h:3347
enum pt_type_enum PT_TYPE_ENUM
Definition: parse_tree.h:962
SM_PARTITION * partition
Definition: class_object.h:760
DB_DOMAIN * db_domain_next(const DB_DOMAIN *domain)
Definition: db_macro.c:3974
PT_MISC_TYPE entity_type
Definition: parse_tree.h:2099
static int pt_check_auto_increment_table_option(PARSER_CONTEXT *parser, PT_NODE *create)
#define assert_release(e)
Definition: error_manager.h:96
static PT_UNION_COMPATIBLE pt_get_select_list_coll_compat(PARSER_CONTEXT *parser, PT_NODE *query, SEMAN_COMPATIBLE_INFO *cinfo, int num_cinfo)
void pt_move_node(REFPTR(PT_NODE, destp), REFPTR(PT_NODE, srcp))
#define pt_is_query(n)
Definition: parse_tree.h:258
static int pt_check_partition_values(PARSER_CONTEXT *parser, PT_TYPE_ENUM desired_type, PT_NODE *data_type, PT_VALUE_LINKS *ptl, PT_NODE *parts)
void pt_check_level_expr(PARSER_CONTEXT *parser, PT_NODE *expr, bool *has_greater, bool *has_lesser)
PT_NODE * spec
Definition: parse_tree.h:2859
static PT_NODE * pt_make_cast_with_compatible_info(PARSER_CONTEXT *parser, PT_NODE *att, PT_NODE *next_att, SEMAN_COMPATIBLE_INFO *cinfo, bool *new_cast_added)
static PT_NODE * pt_find_aggregate_analytic_in_where(PARSER_CONTEXT *parser, PT_NODE *node)
#define MSGCAT_SEMANTIC_INVALID_INDEX_COLUMN
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
PT_NODE * mq_rewrite_query_as_derived(PARSER_CONTEXT *parser, PT_NODE *query)
PT_NODE * pt_check_odku_assignments(PARSER_CONTEXT *parser, PT_NODE *insert)
PT_NODE * with_increment
Definition: parse_tree.h:2694
PARSER_CONTEXT * parser_create_parser(void)
Definition: parse_tree.c:1169
#define MSGCAT_SEMANTIC_CYCLIC_REFERENCE_VIEW_SPEC
int db_value_compare(const DB_VALUE *value1, const DB_VALUE *value2)
Definition: db_macro.c:1855
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
#define MSGCAT_SEMANTIC_CS_MATCH_COLLATE
DB_ATTRIBUTE * db_get_attribute_force(DB_OBJECT *obj, const char *name)
PT_GRANT_INFO grant
Definition: parse_tree.h:3306
static int class_type(DB_OBJECT *class_obj)
Definition: cas_execute.c:8143
PT_TYPE_ENUM pt_db_to_type_enum(const DB_TYPE t)
Definition: parse_dbi.c:2595
int intl_identifier_upper_string_size(const char *src)
int mq_is_real_class_of_vclass(PARSER_CONTEXT *parser, const PT_NODE *s_class, const PT_NODE *d_class)
static int pt_check_cume_dist_percent_rank_order_by(PARSER_CONTEXT *parser, PT_NODE *func)
#define pt_is_input_parameter(n)
Definition: parse_tree.h:273
#define PT_IS_LOB_TYPE(t)
Definition: parse_tree.h:239
struct pt_query_info::@123 flag
static int pt_value_links_add(PARSER_CONTEXT *parser, PT_NODE *val, PT_NODE *parts, PT_VALUE_LINKS *ptl)
PT_NODE * pt_get_end_path_node(PT_NODE *node)
bool pt_is_json_doc_type(PT_TYPE_ENUM type)
Definition: parse_tree.c:1442
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define MSGCAT_SEMANTIC_NOT_METHOD_OR_ATTR
#define PT_EXPR_INFO_INSTNUM_NC
Definition: parse_tree.h:2210
DB_OBJECT * db_find_user(const char *name)
Definition: db_admin.c:1606
static PT_NODE * pt_get_common_type_for_union(PARSER_CONTEXT *parser, PT_NODE *att1, PT_NODE *att2, SEMAN_COMPATIBLE_INFO *cinfo, int idx, bool *need_cast)
#define MSGCAT_SEMANTIC_NO_ORDERBY_ALLOWED
#define PT_IS_DATE_TIME_TYPE(t)
Definition: parse_tree.h:195
struct sm_component * next
Definition: class_object.h:384
void pt_no_double_updates(PARSER_CONTEXT *parser, PT_NODE *stmt)
#define MSGCAT_SEMANTIC_INSTNUM_COMPATIBILITY_ERR
union pt_query_info::@124 q
#define MSGCAT_SEMANTIC_INVALID_PARTITION_REQUEST
PT_NODE * path_entities
Definition: parse_tree.h:2138
#define MSGCAT_SEMANTIC_PARTITION_KEY_COLUMN
PT_NODE * pt_check_cyclic_reference_in_view_spec(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * as_attr_mthd_name
Definition: parse_tree.h:2642
PT_NODE * pt_has_using_index_clause(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_INVALID_CONSTANT_PARAMETER
static void pt_check_function_index_expr(PARSER_CONTEXT *parser, PT_NODE *node)
DB_OBJLIST * db_get_superclasses(DB_OBJECT *obj)
Definition: db_info.c:630
#define MSGCAT_SEMANTIC_WANT_NO_AGGREGATE
struct pt_merge_info::@125 update
#define PT_IS_DOT_NODE(n)
Definition: parse_tree.h:302
bool pt_false_search_condition(PARSER_CONTEXT *parser, const PT_NODE *statement)
const char * pname
Definition: class_object.h:694
unsigned int custom_print
Definition: parse_tree.h:3556
TP_DOMAIN * tp_domain_copy(const TP_DOMAIN *domain, bool check_cache)
PT_NODE * group_by
Definition: parse_tree.h:2688
#define MSGCAT_SEMANTIC_GT_1_TIMEOUT_CLAUSES
DB_DOMAIN * pt_node_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *node, const char *class_name)
Definition: parse_dbi.c:2244
unsigned set_host_var
Definition: parse_tree.h:3605
#define PT_IS_ASSIGN_NODE(n)
Definition: parse_tree.h:308
PT_NODE * pt_flat_spec_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void pt_fixup_column_type(PT_NODE *col)
#define MSGCAT_SEMANTIC_INVALID_PARTITION_COLUMN_TYPE
PT_NODE * pt_find_class_of_index(PARSER_CONTEXT *parser, const char *const index_name, const DB_CONSTRAINT_TYPE index_type)
static int pt_assignment_class_compatible(PARSER_CONTEXT *parser, PT_NODE *lhs, PT_NODE *rhs)
SM_NAME_SPACE name_space
Definition: class_object.h:386
int er_errid(void)
PT_ALTER_CODE
Definition: parse_tree.h:1224
#define PT_IS_STRING_TYPE(t)
Definition: parse_tree.h:148
static PT_NODE * pt_check_single_valued_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int db_is_subclass(MOP classmop, MOP supermop)
Definition: db_info.c:445
#define MSGCAT_SEMANTIC_SORT_SPEC_NOT_EXIST
SHOWSTMT_TYPE show_type
Definition: parse_tree.h:2815
static void pt_check_kill(PARSER_CONTEXT *parser, PT_NODE *node)
#define PT_NAME_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2574
PT_NODE_LIST_INFO node_list
Definition: parse_tree.h:3320
static void pt_check_assignments(PARSER_CONTEXT *parser, PT_NODE *stmt)
#define MSGCAT_SEMANTIC_WANT_SUBCLASS_CLAUSE
PT_NODE * attr_mthd_name
Definition: parse_tree.h:2640
static void pt_check_alter(PARSER_CONTEXT *parser, PT_NODE *alter)
#define MSGCAT_SEMANTIC_USER_NAME_TOO_LONG
SHOWSTMT_TYPE
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
#define MSGCAT_SEMANTIC_INVALID_PARTITION_DEFINITION
#define MSGCAT_SEMANTIC_INVALID_AUTO_INCREMENT_ON_DEFAULT_SHARED
#define MSGCAT_SEMANTIC_DEFAULT_JUST_COLUMN_NAME
#define MSGCAT_SEMANTIC_DUPLICATE_PARTITION_DEF
#define MSGCAT_SEMANTIC_NOT_ALLOWED_HERE
static int pt_is_real_class_of_vclass(PARSER_CONTEXT *parser, const PT_NODE *s_class, const PT_NODE *d_class)
#define MSGCAT_SEMANTIC_SELECT_INTO_IN_SUBQUERY
PT_NODE * internal_stmts
Definition: parse_tree.h:2868
PT_NODE * function_expr
Definition: parse_tree.h:1935
#define MSGCAT_SEMANTIC_SORT_SPEC_NAN_PATH
enum tp_domain_status TP_DOMAIN_STATUS
const char * pt_show_misc_type(PT_MISC_TYPE p)
static void pt_check_grant_revoke(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * tran_id_list
Definition: parse_tree.h:2822
PT_NODE * attr_list
Definition: parse_tree.h:2333
unsigned partition_pruned
Definition: parse_tree.h:3463
PT_NODE * spec_list
Definition: parse_tree.h:2097
static PT_MISC_TYPE pt_get_class_type(PARSER_CONTEXT *parser, const DB_OBJECT *cls)
#define MSGCAT_SEMANTIC_AMBIGUOUS_REF_TO
#define MSGCAT_SEMANTIC_UPDATE_DERIVED_TABLE
bool ws_is_same_object(MOP mop1, MOP mop2)
Definition: work_space.c:5065
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_SUBQUERY_NOT_ALLOWED_IN_DEFAULT_CLAUSE
int db_attribute_is_shared(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1429
static PT_NODE * pt_check_where(PARSER_CONTEXT *parser, PT_NODE *node)
static int pt_objects_assignable(PARSER_CONTEXT *parser, const PT_NODE *d_class_dt, const PT_NODE *s_class)
#define SET_HOST_VARIABLES_IF_INTERNAL_STATEMENT(parser_)
Definition: parse_tree.h:528
PT_NODE * data_type
Definition: parse_tree.h:3453
#define MSGCAT_SEMANTIC_IS_NOT_A
int db_attribute_is_non_null(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1355
#define PT_IS_OID_NAME(n)
Definition: parse_tree.h:323
const char * pt_get_name(PT_NODE *nam)
INTL_CODESET codeset
Definition: parse_tree.h:3673
#define pt_is_instnum(n)
Definition: parse_tree.h:277
DB_ATTRIBUTE * db_get_attribute_by_name(const char *class_name, const char *attribute_name)
Definition: db_info.c:823
#define MSGCAT_SEMANTIC_ATT_INCOMPATIBLE_COL
struct parser_context::@134 flag
#define MSGCAT_SEMANTIC_PARTITION_RANGE_ERROR
#define pt_is_dot_node(n)
Definition: parse_tree.h:260
static PT_NODE * pt_get_assignments(PT_NODE *node)
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: parse_tree.h:2006
static void pt_check_drop(PARSER_CONTEXT *parser, PT_NODE *node)
PT_DOT_INFO dot
Definition: parse_tree.h:3287
#define MSGCAT_SEMANTIC_ORDERBY_IS_NOT_INT
PT_NODE * arg2
Definition: parse_tree.h:2086
#define MSGCAT_SEMANTIC_WANT_TYPE
PT_NODE * pt_wrap_with_cast_op(PARSER_CONTEXT *parser, PT_NODE *arg, PT_TYPE_ENUM new_type, int p, int s, PT_NODE *desired_dt)
TP_DOMAIN * pt_xasl_node_to_domain(PARSER_CONTEXT *parser, const PT_NODE *node)
bool pt_false_where(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned has_system_class
Definition: parse_tree.h:2767
#define MSGCAT_SEMANTIC_NESTED_ANALYTIC_FUNCTIONS
#define MSGCAT_SEMANTIC_CANT_COERCE_TO
PT_JSON_TABLE_INFO json_table_info
Definition: parse_tree.h:3312
DB_QUERY_TYPE * db_query_format_next(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1577
PT_CTE_INFO cte
Definition: parse_tree.h:3282
void parser_free_parser(PARSER_CONTEXT *parser)
Definition: parse_tree.c:1240
static int db_value_list_finddel(DB_VALUE_PLIST **phead, DB_VALUE *val)
static PT_NODE * pt_values_query_to_compatible_cast(PARSER_CONTEXT *parser, PT_NODE *node, SEMAN_COMPATIBLE_INFO *cinfo, int num_cinfo)
#define MSGCAT_SEMANTIC_HOSTVAR_IN_DDL
#define MSGCAT_SEMANTIC_PARTITION_VAL_CODESET
PT_NODE * group_by
Definition: parse_tree.h:3371
int jsp_is_exist_stored_procedure(const char *name)
Definition: jsp_cl.c:267
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
const char * pt_get_proxy_spec_name(const char *qspec)
PT_KILLSTMT_INFO killstmt
Definition: parse_tree.h:3361
int er_get_severity(void)
FUNC_TYPE function_type
Definition: parse_tree.h:2259
int pr_free_ext_value(DB_VALUE *value)
PT_TYPE_ENUM type_enum
Definition: parse_tree.h:3457
void pt_report_to_ersys(const PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type)
Definition: query_result.c:287
PT_NODE * indexed_class
Definition: parse_tree.h:1927
const char * mq_generate_name(PARSER_CONTEXT *parser, const char *root, int *version)
DB_TYPE pt_type_enum_to_db(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:2314
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
int db_is_superclass(MOP supermop, MOP classmop)
Definition: db_info.c:466
#define MSGCAT_SEMANTIC_UPDATE_MIX_CLASS_NON_CLASS
bool pr_is_set_type(DB_TYPE type)
PT_NODE * limit
Definition: parse_tree.h:2773
DB_DATA data
Definition: dbtype_def.h:1083
#define MSGCAT_SEMANTIC_CAN_NOT_BE_VCLASS
INTL_CODESET lang_charset(void)
const char TEXT_CONSTRAINT_PREFIX[]
PT_NODE * pt_semantic_check(PARSER_CONTEXT *parser, PT_NODE *node)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
#define MSGCAT_SEMANTIC_INVALID_CREATE_INDEX
static PT_NODE * pt_is_parameter_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_MISC_TYPE derived_table_type
Definition: parse_tree.h:2147
#define PT_NAME_DEFAULTF_ACCEPTS
Definition: parse_tree.h:2571
#define MSGCAT_SEMANTIC_NO_PARTITION_COLUMN
PT_NODE * partition_info
Definition: parse_tree.h:1914
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
PT_NODE * cast_type
Definition: parse_tree.h:2203
union pt_alter_info::@111 alter_clause
PT_NODE * arg1
Definition: parse_tree.h:2663
#define MSGCAT_SEMANTIC_RESOLUTION_FAILED
int pt_check_grammar_charset_collation(PARSER_CONTEXT *parser, PT_NODE *charset_node, PT_NODE *coll_node, int *charset, int *coll_id)
PT_NODE * pt_expr_to_sort_spec(PARSER_CONTEXT *parser, PT_NODE *expr)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
PT_ALTER_INFO alter
Definition: parse_tree.h:3268
#define MSGCAT_SEMANTIC_WANT_NO_VOBJ_IN_SETS
void pt_no_attr_and_meta_attr_updates(PARSER_CONTEXT *parser, PT_NODE *statement)
INTL_CODESET codeset
PT_NODE * arg2
Definition: parse_tree.h:2198
PT_MISC_TYPE instances
Definition: parse_tree.h:2355
LANG_COLLATION * lang_get_collation(const int coll_id)
PT_NODE * del_search_cond
Definition: parse_tree.h:2930
PT_NODE * cte_definition_list
Definition: parse_tree.h:3221
PT_FUNCTION_INFO function
Definition: parse_tree.h:3301
PT_CONNECT_BY_CHECK_CYCLES check_cycles
Definition: parse_tree.h:2710
short constrain_not_null
Definition: parse_tree.h:1866
#define NUM_F_GENERIC_ARGS
#define MSGCAT_SEMANTIC_NONVCLASS_PARENT
#define PT_IS_VACUUM_NODE(n)
Definition: parse_tree.h:497
DB_OBJECT * db_object
Definition: parse_tree.h:2546
#define DB_MAX_NUMERIC_PRECISION
Definition: dbtype_def.h:522
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
static PT_NODE * pt_check_function_index_expr_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_PARTITION_RANGE_INVALID
#define assert(x)
static PT_NODE * pt_check_data_default(PARSER_CONTEXT *parser, PT_NODE *data_default_list)
PT_NODE * constraint_list
Definition: parse_tree.h:1912
static bool pt_update_compatible_info(PARSER_CONTEXT *parser, SEMAN_COMPATIBLE_INFO *cinfo, PT_TYPE_ENUM common_type, SEMAN_COMPATIBLE_INFO *att1_info, SEMAN_COMPATIBLE_INFO *att2_info)
DB_CONSTRAINT_TYPE
Definition: dbtype_def.h:452
static void pt_check_truncate(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_find_spec(PARSER_CONTEXT *parser, const PT_NODE *from, const PT_NODE *name)
PT_NODE * pt_check_groupbynum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
struct pt_alter_info::@111::@113 attr_mthd
#define ER_LC_UNKNOWN_CLASSNAME
Definition: error_code.h:121
#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_NODE * query
Definition: parse_tree.h:1762
PT_PARTITION_TYPE type
Definition: parse_tree.h:2030
unsigned order_siblings
Definition: parse_tree.h:2765
int pt_check_order_by(PARSER_CONTEXT *parser, PT_NODE *query)
int pt_validate_query_spec(PARSER_CONTEXT *parser, PT_NODE *s, DB_OBJECT *c)
#define pt_is_select(n)
Definition: parse_tree.h:254
int db_make_set(DB_VALUE *value, DB_C_SET *set)
#define MSGCAT_SEMANTIC_NOT_SINGLE_VALUED
PT_MISC_TYPE asc_or_desc
Definition: parse_tree.h:2830
#define ER_GENERIC_ERROR
Definition: error_code.h:49
bool pt_check_cast_op(PARSER_CONTEXT *parser, PT_NODE *node)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
static void pt_resolve_default_external(PARSER_CONTEXT *parser, PT_NODE *alter)
int sm_class_has_triggers(DB_OBJECT *classop, int *status_ptr, DB_TRIGGER_EVENT event_type)
int tp_domain_status_er_set(TP_DOMAIN_STATUS status, const char *file_name, const int line_no, const DB_VALUE *src, const TP_DOMAIN *domain)
static PT_NODE * pt_find_query(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
DB_VALUE db_value
Definition: parse_tree.h:3059
PT_NODE * odku_assignments
Definition: parse_tree.h:2341
static void pt_check_vacuum(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_find_op_type_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define PT_IS_CLASSOID_NAME(x)
Definition: parse_tree.h:119
PT_NODE * of_sup_class_name
Definition: parse_tree.h:2641
PT_NODE * hashsize
Definition: parse_tree.h:2021
#define MSGCAT_SEMANTIC_METH_TARGET_NOT_OBJ
#define PT_NAME_ALLOW_REUSABLE_OID
Definition: parse_tree.h:2568
static int db_value_list_add(DB_VALUE_PLIST **ptail, DB_VALUE *val)
const char * pt_show_type_enum(PT_TYPE_ENUM t)
#define PT_GET_COLLATION_MODIFIER(p)
Definition: parse_tree.h:619
PT_SET_XACTION_INFO set_xaction
Definition: parse_tree.h:3341
PT_NODE * entity
Definition: parse_tree.h:2038
#define REFPTR(T, name)
Definition: porting.h:1089
#define MSGCAT_SET_PARSER_RUNTIME
PT_NODE * pt_check_orderbynum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PARSER_CONTEXT * parent_parser
PT_INCLUDE_OID_TYPE oid_included
Definition: parse_tree.h:3586
int db_attribute_is_primary_key(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1255
bool pt_eval_path_expr(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *val)
DB_TYPE db_value_type(const DB_VALUE *value)
#define MSGCAT_SEMANTIC_NO_ISOLATION_LVL_MSG
#define MSGCAT_SEMANTIC_USER_DOESNT_OWN_CLS
DB_OBJECT * pt_check_user_owns_class(PARSER_CONTEXT *parser, PT_NODE *cls_ref)
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
PT_NODE * recursive_part
Definition: parse_tree.h:1978
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
PT_NODE ** parser_parse_string(PARSER_CONTEXT *parser, const char *buffer)
static PT_NODE * pt_check_filter_index_expr_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_WANT_NO_INTO_CLAUSE
PT_NODE * top_node
Definition: parse_tree.h:1707
PT_NODE * pt_check_type_compatibility_of_values_query(PARSER_CONTEXT *parser, PT_NODE *node)
PT_MISC_TYPE all_distinct
Definition: parse_tree.h:2746
bool pt_has_analytic(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * method_name
Definition: parse_tree.h:2363
static int pt_json_str_codeset_normalization(PARSER_CONTEXT *parser, REFPTR(char, c))
static PT_UNION_COMPATIBLE pt_union_compatible(PARSER_CONTEXT *parser, PT_NODE *item1, PT_NODE *item2, bool view_definition_context, bool *is_object_type)
const char * original
Definition: parse_tree.h:2544
PT_NODE * using_index
Definition: parse_tree.h:2064
#define PT_ERRORmf4(parser, node, setNo, msgNo, arg1, arg2, arg3, arg4)
Definition: parse_tree.h:67
#define PT_IS_PARAMETERIZED_TYPE(t)
Definition: parse_tree.h:229
PT_NODE * pt_semantic_quick_check_node(PARSER_CONTEXT *parser, PT_NODE **spec_p, PT_NODE **node_p)
PT_MISC_TYPE nulls_first_or_last
Definition: parse_tree.h:2831
PT_NODE * into_var
Definition: parse_tree.h:2335
int intl_identifier_casecmp(const char *str1, const char *str2)
PT_NODE * pt_make_string_value(PARSER_CONTEXT *parser, const char *value_string)
PT_PARTITION_INFO partition
Definition: parse_tree.h:3321
#define MSGCAT_SEMANTIC_MERGE_CANT_AFFECT_SOURCE_TABLE
struct json_table_column_behavior on_error
Definition: parse_tree.h:3241
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
static PT_NODE * pt_replace_referenced_attributes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_check_isolation_lvl(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_check_default_vclass_query_spec(PARSER_CONTEXT *parser, PT_NODE *qry, PT_NODE *attrs)
bool print_collation
Definition: parse_tree.h:3065
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
#define DB_IS_STRING(value)
Definition: dbtype.h:65
static void pt_check_mutable_attributes(PARSER_CONTEXT *parser, DB_OBJECT *cls, PT_NODE *attr_defs)
#define PT_IS_NATIONAL_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:156
const char * db_error_string(int level)
Definition: db_admin.c:2116
DB_TRAN_ISOLATION
Definition: dbtran_def.h:26
#define MSGCAT_SEMANTIC_NOT_SINGLE_COL
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 PT_IS_VALUE_QUERY(n)
Definition: parse_tree.h:476
unsigned do_cache
Definition: parse_tree.h:2763
PT_PARTITION_TYPE type
Definition: parse_tree.h:2023
PT_NODE * pt_expr_disallow_op_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define SM_COMPARE_NAMES
Definition: class_object.h:47
PT_NODE * pt_semantic_type(PARSER_CONTEXT *parser, PT_NODE *tree, SEMANTIC_CHK_INFO *sc_info)
#define MSGCAT_SEMANTIC_SORT_SPEC_RANGE_ERR
DB_SEQ * values
Definition: class_object.h:696
PT_PARTS_INFO parts
Definition: parse_tree.h:3322
#define MSGCAT_SEMANTIC_VIEW_CASCADE_CONSTRAINTS_NOT_ALLOWED
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
PT_SHOWSTMT_INFO showstmt
Definition: parse_tree.h:3342
const char * db_query_spec_string(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:651
PT_NODE * having
Definition: parse_tree.h:2692
DB_DOMAIN * pt_data_type_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *dt, const char *class_name)
Definition: parse_dbi.c:1805
DB_OBJECT * db_get_object(const DB_VALUE *value)
static void pt_check_into_clause(PARSER_CONTEXT *parser, PT_NODE *qry)
PT_NODE * from
Definition: parse_tree.h:2686
const char * pt_show_binopcode(PT_OP_TYPE n)
#define MSGCAT_SEMANTIC_HOSTVAR_NOT_ALLOWED_ON_QUERY_SPEC
PT_ISOLATION_LVL_INFO isolation_lvl
Definition: parse_tree.h:3311
void parser_free_subtrees(PARSER_CONTEXT *parser, PT_NODE *tree)
static int pt_coerce_partition_value_with_data_type(PARSER_CONTEXT *parser, PT_NODE *value, PT_NODE *data_type)
#define PT_IS_CONST(n)
Definition: parse_tree.h:364
static PT_NODE * pt_find_aggregate_function(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * enumeration
Definition: parse_tree.h:2039
UINTPTR spec_id
Definition: parse_tree.h:2543
DB_VALUE * db_value_copy(DB_VALUE *value)
Definition: db_macro.c:1537
PT_NODE * value_clauses
Definition: parse_tree.h:2938
#define MSGCAT_SEMANTIC_PARTITION_TYPE_MISMATCH
int pt_check_path_eq(PARSER_CONTEXT *parser, const PT_NODE *p, const PT_NODE *q)
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
#define MSGCAT_SEMANTIC_NOT_SUPERCLASS_OF
static void pt_check_xaction_list(PARSER_CONTEXT *parser, PT_NODE *node)
#define TP_DOMAIN_TYPE(dom)
#define MSGCAT_SEMANTIC_ATT_CNT_COL_CNT_NE
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
static PT_NODE * pt_check_analytic_function(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
DB_VALUE * db_value_create(void)
Definition: db_macro.c:1517
#define MSGCAT_SEMANTIC_SORT_DIR_CONFLICT
PT_COLL_INFER coll_infer
PARSER_VARCHAR * str
Definition: parse_tree.h:3036
static int partition_range_min_max(DB_VALUE **dest, DB_VALUE *inval, int min_max)
SHOW_SEMANTIC_CHECK_FUNC semantic_check_func
Definition: show_meta.h:77
static PT_NODE * pt_coerce_insert_values(PARSER_CONTEXT *parser, PT_NODE *stmt)
int pt_str_compare(const char *p, const char *q, CASE_SENSITIVENESS case_flag)
SP_PARSER_CTX * parser
static PT_NODE * pt_find_default_expression(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * arg1
Definition: parse_tree.h:2197
#define MSGCAT_SEMANTIC_INVALID_AUTO_INCREMENT_DOMAIN
PT_ATTR_DEF_INFO attr_def
Definition: parse_tree.h:3272
unsigned rewrite_limit
Definition: parse_tree.h:2766
PT_DO_INFO do_
Definition: parse_tree.h:3286
#define NULL
Definition: freelistheap.h:34
PT_ALTER_CODE code
Definition: parse_tree.h:1751
PT_NODE * as_attr_list
Definition: parse_tree.h:2136
#define MSGCAT_SEMANTIC_MISSING_ATTR_NAME
const char * er_msg(void)
bool pt_is_const_expr_node(PT_NODE *node)
#define MSGCAT_SEMANTIC_GT_1_ISOLATION_LVL
PT_NODE * pt_check_groupbynum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define ER_OBJ_ATTRIBUTE_CANT_BE_NULL
Definition: error_code.h:276
int db_is_class(MOP obj)
Definition: db_info.c:310
struct pr_type * type
Definition: object_domain.h:76
PT_NODE * pt_count_input_markers(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * order_by
Definition: parse_tree.h:2875
PT_NODE * internal_stmts
Definition: parse_tree.h:2338
PT_NODE * value_clauses
Definition: parse_tree.h:2334
#define ER_REGU_NOT_IMPLEMENTED
Definition: error_code.h:194
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
PT_JSON_TABLE_NODE_INFO json_table_node_info
Definition: parse_tree.h:3313
bool allow_prefix_index
static void pt_check_unique_attr(PARSER_CONTEXT *parser, const char *entity_name, PT_NODE *att, PT_NODE_TYPE att_type)
PT_NODE * where
Definition: parse_tree.h:1934
PT_TABLE_OPTION_TYPE option
Definition: parse_tree.h:2916
unsigned do_not_replace_orderby
Definition: parse_tree.h:3480
struct pr_type * type
Definition: class_object.h:443
#define MSGCAT_SEMANTIC_UNION_INCOMPATIBLE
#define MSGCAT_RUNTIME_NOT_ALLOWED_ACCESS_TO_PARTITION
char * pt_append_string(const PARSER_CONTEXT *parser, const char *old_string, const char *new_tail)
Definition: parse_tree.c:980
PT_CREATE_ENTITY_INFO create_entity
Definition: parse_tree.h:3279
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
#define err(fd,...)
Definition: porting.h:431
#define PT_ERRORc(parser, node, msg)
Definition: parse_tree.h:55
#define MSGCAT_SEMANTIC_METH_MIX_CLASS_INST
PT_ZZ_ERROR_MSG_INFO error_msg
Definition: parse_tree.h:3267
static DB_OBJECT * pt_find_class(PARSER_CONTEXT *parser, PT_NODE *p, bool for_update)
#define MSGCAT_SEMANTIC_CLASS_DOES_NOT_EXIST
struct pt_alter_info::@110 super
static PT_UNION_COMPATIBLE pt_apply_union_select_list_collation(PARSER_CONTEXT *parser, PT_NODE *query, SEMAN_COMPATIBLE_INFO *cinfo, int num_cinfo)
static PT_NODE * pt_type_cast_vclass_query_spec(PARSER_CONTEXT *parser, PT_NODE *qry, PT_NODE *attrs)
#define MSGCAT_SEMANTIC_INVALID_INTERNAL_FUNCTION
#define MSGCAT_SEMANTIC_HEIR_CANT_CHANGE_IT
DB_SET * db_set_create_basic(MOP classop, const char *name)
Definition: db_set.c:134
int db_attribute_is_auto_increment(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1309
static SEMAN_COMPATIBLE_INFO * pt_get_compatible_info(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_list1, PT_NODE *select_list2, bool *need_cast)
#define PT_IS_COLLECTION_TYPE(t)
Definition: parse_tree.h:143
#define MSGCAT_SEMANTIC_WANT_NO_CONSTRAINTS
#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)
static bool pt_compare_sort_spec_expr(PARSER_CONTEXT *parser, PT_NODE *expr1, PT_NODE *expr2)
static int pt_collection_compatible(PARSER_CONTEXT *parser, const PT_NODE *col1, const PT_NODE *col2, bool view_definition_context)
#define MSGCAT_SEMANTIC_ALREADY_SUPERCLASS
int pt_find_attribute(PARSER_CONTEXT *parser, const PT_NODE *name, const PT_NODE *attributes)
struct db_value_plist * next
PT_NODE * with
Definition: parse_tree.h:2778
PT_NODE * pt_get_next_assignment(PT_ASSIGNMENTS_HELPER *ea)
Definition: parse_tree.c:1360
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
static PT_NODE * pt_check_vclass_union_spec(PARSER_CONTEXT *parser, PT_NODE *qry, PT_NODE *attrds)
#define MSGCAT_SEMANTIC_ARITY_OF_VALUES_CLAUSE_MISMATCH
static PT_NODE * pt_mark_union_leaf_nodes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
bool pt_has_aggregate(PARSER_CONTEXT *parser, PT_NODE *node)
struct db_objlist * next
Definition: dbtype_def.h:442
#define PT_IS_DIFFERENCE(n)
Definition: parse_tree.h:293
#define MSGCAT_SEMANTIC_METH_MIX_INST_CLASS
PT_AUTO_INCREMENT_INFO auto_increment
Definition: parse_tree.h:3275
#define MSGCAT_SEMANTIC_GT_1_ASSIGNMENT_TO
static bool pt_vclass_compatible(PARSER_CONTEXT *parser, const PT_NODE *att, const PT_NODE *qcol)
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
PT_CONSTRAINT_TYPE type
Definition: parse_tree.h:3096
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
void db_free_query_format(DB_QUERY_TYPE *q)
Definition: db_query.c:154
const char * text
Definition: parse_tree.h:3056
#define MSGCAT_SEMANTIC_INVALID_FUNCTION_INDEX
DB_TYPE pt_node_to_db_type(PT_NODE *node)
Definition: parse_dbi.c:2453
bool pt_get_collation_info(const PT_NODE *node, PT_COLL_INFER *coll_infer)
#define MSGCAT_SEMANTIC_PARTITION_DOES_NOT_EXIST
#define PT_NAME_INFO_EXTERNAL
Definition: parse_tree.h:2563
TP_DOMAIN ** host_var_expected_domains
Definition: parse_tree.h:3561
PT_NODE * prefix_length
Definition: parse_tree.h:1933
#define MSGCAT_SEMANTIC_ATT_CNT_VAL_CNT_NE
DB_DOMAIN * db_attribute_domain(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1165
#define MSGCAT_SEMANTIC_IS_NOT_A_CLASS
#define DB_DEFAULT_SCALE
Definition: dbtype_def.h:561
static PT_NODE * pt_check_constraints(PARSER_CONTEXT *parser, const PT_NODE *create)
void pt_preset_hostvar(PARSER_CONTEXT *parser, PT_NODE *hv_node)
DB_OBJECT * db_find_class_of_index(const char *const index_name, const DB_CONSTRAINT_TYPE index_type)
Definition: db_info.c:74
PT_NODE * pt_make_integer_value(PARSER_CONTEXT *parser, const int value_int)
bool is_cascade_constraints
Definition: parse_tree.h:2101
static DB_OBJECT * pt_check_user_exists(PARSER_CONTEXT *parser, PT_NODE *cls_ref)
PT_NODE * partition_by
Definition: parse_tree.h:2270
#define MSGCAT_SEMANTIC_NO_GROUPBY_ALLOWED
DB_METHOD * db_get_method(DB_OBJECT *obj, const char *name)
Definition: db_info.c:1454
DB_DEFAULT_EXPR_TYPE on_update
Definition: parse_tree.h:1860
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)
unsigned do_not_cache
Definition: parse_tree.h:2764
MOP Au_user
Definition: authenticate.c:343
const PT_NODE * ref_att
PT_NODE *(* SHOW_SEMANTIC_CHECK_FUNC)(PARSER_CONTEXT *parser, PT_NODE *node)
Definition: show_meta.h:63
#define ER_DO_INSERT_TOO_MANY
Definition: error_code.h:890
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
#define MSGCAT_SEMANTIC_COERCE_UNSUPPORTED
PT_NODE * pt_table_option(PARSER_CONTEXT *parser, const PT_TABLE_OPTION_TYPE option, PT_NODE *val)
#define PT_NODE_MOVE_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:572
DB_DEFAULT_EXPR_TYPE on_update_default_expr
Definition: class_object.h:452
void parser_free_node(const PARSER_CONTEXT *parser, PT_NODE *node)
Definition: parse_tree.c:869
#define MSGCAT_SEMANTIC_INCOMP_TYPE_ON_ATTR
PT_NODE * pt_get_node_from_list(PT_NODE *list, int index)
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
void pt_no_double_insert_assignments(PARSER_CONTEXT *parser, PT_NODE *stmt)
PT_NODE * column_names
Definition: parse_tree.h:1928
#define PT_IS_SIMPLE_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:160
PT_NODE * internal_stmts
Definition: parse_tree.h:2098
#define TP_TYPE_HAS_COLLATION(typeid)
unsigned is_leaf_node
Definition: parse_tree.h:2666
int pt_find_var(PT_NODE *p, PT_NODE **result)
#define MSGCAT_SEMANTIC_ALREADY_PARTITIONED_CLASS
short db_value_is_initialized
Definition: parse_tree.h:3060
#define AU_SELECT
Definition: authenticate.h:69
static PT_NODE * pt_path_chain(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SET_ERROR
static int pt_number_of_attributes(PARSER_CONTEXT *parser, PT_NODE *stmt, PT_NODE **attrs)
PT_SORT_SPEC_INFO sort_spec
Definition: parse_tree.h:3343
#define ARG_FILE_LINE
Definition: error_manager.h:44
PT_NODE * auto_increment
Definition: parse_tree.h:1861
#define MSGCAT_SEMANTIC_NULL_NOT_ALLOWED_ON_QUERY_SPEC
static int pt_check_range_partition_strict_increasing(PARSER_CONTEXT *parser, PT_NODE *stmt, PT_NODE *part, PT_NODE *part_next, PT_NODE *column_dt)
static void pt_check_create_view(PARSER_CONTEXT *parser, PT_NODE *stmt)
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
const char * lang_get_codeset_name(int codeset_id)
bool pt_name_equal(PARSER_CONTEXT *parser, const PT_NODE *name1, const PT_NODE *name2)
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
const char * default_expr_format
Definition: dbtype_def.h:1206
#define PT_NAME_INFO_GENERATED_OID
Definition: parse_tree.h:2566
static void warning(const char *cptr, const char *msg)
Definition: gencat.c:310
#define MSGCAT_SEMANTIC_NOT_IN_SUBCLASS_LIST
PT_DROP_INFO drop
Definition: parse_tree.h:3288
PT_NODE * user_list
Definition: parse_tree.h:2650
DB_ATTRIBUTE * db_get_attributes_force(DB_OBJECT *obj)
static void pt_check_create_user(PARSER_CONTEXT *parser, PT_NODE *node)
int pt_attr_check_default_cs_coll(PARSER_CONTEXT *parser, PT_NODE *attr, int default_cs, int default_coll)
const char * fcode_get_lowercase_name(FUNC_TYPE ftype)
PT_COLL_COERC_LEV coerc_level
Definition: parse_tree.h:3674
PT_NODE * pt_resolve_names(PARSER_CONTEXT *parser, PT_NODE *statement, SEMANTIC_CHK_INFO *sc_info)
PT_NODE * into
Definition: parse_tree.h:2923
PT_NODE * user_list
Definition: parse_tree.h:2308
#define MSGCAT_SET_PARSER_SEMANTIC
void pt_try_remove_order_by(PARSER_CONTEXT *parser, PT_NODE *query)
PT_NODE * pt_remove_from_list(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *list)
PT_NODE ** chain_ptr
PT_NODE * pt_set_is_view_spec(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * internal_stmts
Definition: parse_tree.h:1915
PT_NODE * using_index
Definition: parse_tree.h:2863
#define MSGCAT_SEMANTIC_MEDIAN_FUNC_NOT_ALLOW_ORDER_BY
PT_NODE * pt_check_union_compatibility(PARSER_CONTEXT *parser, PT_NODE *node)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
struct pt_merge_info::@126 insert
#define PT_IS_EXPR_NODE(n)
Definition: parse_tree.h:305
#define strlen(s1)
Definition: intl_support.c:43
struct db_value_plist DB_VALUE_PLIST
bool print_charset
Definition: parse_tree.h:3064
PT_RESOLUTION_INFO resolution
Definition: parse_tree.h:3329
enum json_table_column_behavior_type m_behavior
char * prm_get_string_value(PARAM_ID prm_id)
bool sm_is_reuse_oid_class(MOP op)
static PT_NODE * pt_expand_isnull_preds(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_NODE * pt_gen_isnull_preds(PARSER_CONTEXT *parser, PT_NODE *pred, PT_CHAIN_INFO *chain)
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
#define MSGCAT_SEMANTIC_INVALID_AGGREGATE
#define MSGCAT_SEMANTIC_INVALID_PARTITION_INHERITED_ATTR
PT_NODE * non_recursive_part
Definition: parse_tree.h:1977
#define MSGCAT_SEMANTIC_CLASS_EXISTS
bool pt_is_function_index_expr(PARSER_CONTEXT *parser, PT_NODE *expr, bool report_error)
PT_NODE * attr_list
Definition: parse_tree.h:2937
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
void pt_register_orphan(PARSER_CONTEXT *parser, const PT_NODE *orphan)
PT_OP_TYPE
Definition: parse_tree.h:1320
PT_MISC_TYPE entity_type
Definition: parse_tree.h:1899
#define MSGCAT_SEMANTIC_VCLASS_ATT_CANT_BE_AUTOINC
#define PT_IS_LTZ_TYPE(t)
Definition: parse_tree.h:223
static bool pt_combine_compatible_info(PARSER_CONTEXT *parser, SEMAN_COMPATIBLE_INFO *cinfo1, SEMAN_COMPATIBLE_INFO *cinfo2, PT_NODE *att1, PT_NODE *att2, int index)
#define PT_SELECT_INFO_SET_FLAG(s, f)
Definition: parse_tree.h:2737
PT_NODE * connect_by
Definition: parse_tree.h:2689
static void free_node(T_NODE_INFO *node)
Definition: cas_runner.c:1444
#define MSGCAT_SEMANTIC_INDEX_ATTR_DUPLICATED
unsigned single_tuple
Definition: parse_tree.h:2760
#define ER_AUTO_INCREMENT_SINGLE_COL_AMBIGUITY
Definition: error_code.h:1317
#define MSGCAT_SEMANTIC_HAVE_NO_QUERY_SPEC
#define PT_IS_FUNCTION(n)
Definition: parse_tree.h:311
int db_string_convert_to(const DB_VALUE *src_str_dbval, DB_VALUE *dest_str_dbval, INTL_CODESET dest_codeset, int dest_col)
#define MSGCAT_SEMANTIC_GROUP_CONCAT_ORDERBY_SAME_EXPR
#define MSGCAT_SEMANTIC_SELECT_AUTH_FAILURE
void pt_resolve_object(PARSER_CONTEXT *parser, PT_NODE *node)
enum intl_codeset INTL_CODESET
Definition: intl_support.h:190
void pt_init_assignments_helper(PARSER_CONTEXT *parser, PT_ASSIGNMENTS_HELPER *helper, PT_NODE *assignment)
Definition: parse_tree.c:1336
struct pt_function_info::@122 analytic
#define MSGCAT_SEMANTIC_IS_NOT_END_OF_PARTITION
static int db_value_list_find(const DB_VALUE_PLIST *phead, const DB_VALUE *val)
int lang_set_flag_from_lang(const char *lang_str, bool has_user_format, bool has_user_lang, int *flag)
PT_ROLLBACK_WORK_INFO rollback_work
Definition: parse_tree.h:3331
PT_NODE * search_cond
Definition: parse_tree.h:2063
PT_MISC_TYPE shared
Definition: parse_tree.h:2005
bool prm_get_bool_value(PARAM_ID prm_id)
PT_MISC_TYPE entity_type
Definition: parse_tree.h:1752
static PT_NODE * pt_semantic_check_local(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define MSGCAT_SEMANTIC_CANNOT_DROP_ALL_PARTITIONS
int pt_is_attr(PT_NODE *node)
int db_get_string_size(const DB_VALUE *value)
int pt_is_single_tuple(PARSER_CONTEXT *parser, PT_NODE *select_node)
PT_MISC_TYPE only_all
Definition: parse_tree.h:2145
static PT_NODE * pt_check_with_clause(PARSER_CONTEXT *parser, PT_NODE *node)
PT_TYPE_ENUM pt_common_type(PT_TYPE_ENUM arg1_type, PT_TYPE_ENUM arg2_type)
PT_MISC_TYPE list_type
Definition: parse_tree.h:2324
DB_VALUE * db_attribute_default(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1209
void er_clear(void)
#define MSGCAT_SEMANTIC_MERGE_DERIVED_TABLE
#define PT_IS_N_COLUMN_UPDATE_EXPR(n)
Definition: parse_tree.h:422
int pt_common_collation(PT_COLL_INFER *arg1_coll_infer, PT_COLL_INFER *arg2_coll_infer, PT_COLL_INFER *arg3_coll_infer, const int args_w_coll, bool op_has_3_args, int *common_coll, INTL_CODESET *common_cs)
static PT_NODE * pt_remove_unusable_sort_specs(PARSER_CONTEXT *parser, PT_NODE *list)
unsigned cannot_prepare
Definition: parse_tree.h:3462
PT_DELETE_INFO delete_
Definition: parse_tree.h:3285
void pt_set_expected_domain(PT_NODE *node, TP_DOMAIN *domain)
static PT_NODE * pt_replace_names_in_update_values(PARSER_CONTEXT *parser, PT_NODE *update)
static PT_NODE * pt_assignment_compatible(PARSER_CONTEXT *parser, PT_NODE *lhs, PT_NODE *rhs)
#define MSGCAT_SEMANTIC_INVALID_FILTER_INDEX
#define PT_IS_UNION(n)
Definition: parse_tree.h:287
void * etc
Definition: parse_tree.h:3450
DB_TYPE db_attribute_type(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1000
PT_NODE * error_msgs
Definition: parse_tree.h:3550
static PT_NODE * pt_check_sub_insert(PARSER_CONTEXT *parser, PT_NODE *node, void *void_arg, int *continue_walk)
#define MSGCAT_SEMANTIC_UNIMPLEMENTED_CONSTRAINT
char * parser_print_tree(PARSER_CONTEXT *parser, const PT_NODE *node)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
PT_NODE * spec
Definition: parse_tree.h:2061
#define MSGCAT_SEMANTIC_ARITY_MISMATCH
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
PT_VALUE_INFO value
Definition: parse_tree.h:3358
bool pt_check_compatible_node_for_orderby(PARSER_CONTEXT *parser, PT_NODE *order, PT_NODE *column)
int pt_length_of_select_list(PT_NODE *list, int hidden_col)
int db_make_null(DB_VALUE *value)
PT_NODE * pt_fold_union(PARSER_CONTEXT *parser, PT_NODE *union_node, STATEMENT_SET_FOLD fold_as)
DB_TYPE id
PT_NODE * list
Definition: parse_tree.h:2685
int sm_get_class_collation(MOP classop, int *collation_id)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
DB_QUERY_SPEC * db_get_query_specs(DB_OBJECT *obj)
Definition: db_virt.c:608
static int pt_find_partition_column_count(PT_NODE *expr, PT_NODE **name_node)
PT_OP_TYPE op
Definition: parse_tree.h:2200
int do_is_partitioned_subclass(int *is_partitioned, const char *classname, char *keyattr)
struct pt_alter_info::@111::@114 ch_attr_def
char * au_get_user_name(MOP obj)
PT_NODE * sup_class_list
Definition: parse_tree.h:1755
PT_NODE * data_default
Definition: parse_tree.h:1859
#define pt_is_set_type(n)
Definition: parse_tree.h:267
const char * name
Definition: class_object.h:385
PT_NODE * path_conjuncts
Definition: parse_tree.h:2139
TP_DOMAIN * tp_domain_resolve(DB_TYPE domain_type, DB_OBJECT *class_obj, int precision, int scale, TP_DOMAIN *setdomain, int collation)
#define MSGCAT_SEMANTIC_INVALID_PREFIX_LENGTH
PT_NODE * parser_reinit_node(PT_NODE *node)
PT_TRUNCATE_INFO truncate
Definition: parse_tree.h:3351
PT_NODE * orderby_for
Definition: parse_tree.h:2770
const char * lang_charset_introducer(const INTL_CODESET codeset)
#define MSGCAT_SEMANTIC_ALTER_VIEW_IN_HIERARCHY
PT_NODE * create_index
Definition: parse_tree.h:1826
DB_VALUE * val
unsigned is_value_query
Definition: parse_tree.h:3478
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
#define PT_IS_NUMERIC_TYPE(t)
Definition: parse_tree.h:125
static int pt_associate_label_with_value(const char *label, DB_VALUE *val)
void pt_to_pos_descr(PARSER_CONTEXT *parser, QFILE_TUPLE_VALUE_POSITION *pos_p, PT_NODE *node, PT_NODE *root, PT_NODE **referred_node)
int pt_coerce_value(PARSER_CONTEXT *parser, PT_NODE *src, PT_NODE *dest, PT_TYPE_ENUM desired_type, PT_NODE *elem_type_list)
#define pt_has_error(parser)
Definition: parser.h:507
PT_SAVEPOINT_INFO savepoint
Definition: parse_tree.h:3332
#define MSGCAT_SEMANTIC_GEN_FUNC_TOO_MANY_ARGS
const char * alias_print
Definition: parse_tree.h:3455
enum pt_node_type PT_NODE_TYPE
Definition: parse_tree.h:904
static void pt_check_create_index(PARSER_CONTEXT *parser, PT_NODE *node)
#define MSGCAT_SEMANTIC_ALTER_CHANGE_ONLY_TABLE
PT_NODE * pt_domain_to_data_type(PARSER_CONTEXT *parser, DB_DOMAIN *domain)
#define MSGCAT_SEMANTIC_UPDATE_NO_AGGREGATE
PT_TYPE_ENUM type_enum
const char * resolved
Definition: parse_tree.h:2545
PT_NODE * entity_name
Definition: parse_tree.h:1750
SORT_NULLS pt_to_null_ordering(PT_NODE *sort_spec)
#define MSGCAT_SEMANTIC_CLASS_NO_QUERY_SPEC
#define MSGCAT_SEMANTIC_METH_DOESNT_EXIST
#define LANG_SYS_CODESET
#define PT_HAS_COLLATION(t)
Definition: parse_tree.h:243
int collation_id
Definition: object_domain.h:92
PT_CONSTRAINT_INFO constraint
Definition: parse_tree.h:3278
static void pt_check_attribute_domain(PARSER_CONTEXT *parser, PT_NODE *attr_defs, PT_MISC_TYPE class_type, const char *self, const bool reuse_oid, PT_NODE *stmt)
static PT_NODE * pt_resolve_sort_spec_expr(PARSER_CONTEXT *parser, PT_NODE *sort_spec, PT_NODE *select_list)
PT_UNION_COMPATIBLE
PT_REVOKE_INFO revoke
Definition: parse_tree.h:3330
struct PT_VALUE_LINKS PT_VALUE_LINKS
int pt_check_class_eq(PARSER_CONTEXT *parser, PT_NODE *p, PT_NODE *q)
#define INTL_CAN_COERCE_CS(cs_from, cs_to)
Definition: intl_support.h:97
static PT_NODE * pt_get_attributes(PARSER_CONTEXT *parser, const DB_OBJECT *c)
static int is_shared_attribute(PARSER_CONTEXT *parser, PT_NODE *att)
PT_NODE * pt_check_union_type_compatibility_of_values_query(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_dbval_to_value(PARSER_CONTEXT *parser, const DB_VALUE *val)
Definition: parse_dbi.c:574
#define MSGCAT_SEMANTIC_SUPERCLASS_CYCLE
RANGE_MIN_MAX_ENUM
DB_VALUE * default_value
Definition: esql_cli.c:348
PT_SET_SESSION_VARIABLE_INFO set_variables
Definition: parse_tree.h:3340
int pt_is_method_call(PT_NODE *node)
PT_NODE * pt_invert(PARSER_CONTEXT *parser, PT_NODE *name_expr, PT_NODE *result)
DB_VALUE_COMPARE_RESULT
Definition: dbtype_def.h:199
int column_number
Definition: parse_tree.h:3442
int pt_length_of_list(const PT_NODE *list)
struct parser_node::@132 flag
PT_NODE * entity_name
Definition: parse_tree.h:2130
#define MSGCAT_SEMANTIC_UPDATE_SUBVCLASS_NOT_ALLOWED
#define PT_IS_INTERSECTION(n)
Definition: parse_tree.h:290
PT_NODE * object_parameter
Definition: parse_tree.h:2865
static PT_NODE * pt_check_single_valued_node_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PT_UNION_COMPATIBLE pt_check_vclass_attr_qspec_compatible(PARSER_CONTEXT *parser, PT_NODE *attr, PT_NODE *col)
static PT_NODE * pt_append_statements_on_add_attribute(PARSER_CONTEXT *parser, PT_NODE *statement_list, PT_NODE *stmt_node, const char *class_name, const char *attr_name, PT_NODE *attr)
PT_NODE * order_by
Definition: parse_tree.h:2263
PT_SELECT_INFO select
Definition: parse_tree.h:2781
DB_VALUE * pt_value_to_db(PARSER_CONTEXT *parser, PT_NODE *value)
Definition: parse_dbi.c:1088
#define DB_MAX_USER_LENGTH
Definition: dbtype_def.h:498
#define MSGCAT_SEMANTIC_COL_CNT_NE_INTO_CNT
PT_DATA_DEFAULT_INFO data_default
Definition: parse_tree.h:3283
struct pt_alter_info::@111::@116 partition
int pt_class_assignable(PARSER_CONTEXT *parser, const PT_NODE *d_class_dt, const PT_NODE *s_class)
#define MSGCAT_SEMANTIC_CANT_PARTITION_MNG_TRIGGERS
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
PT_NODE * pt_count_output_markers(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_HOST_VAR_INFO host_var
Definition: parse_tree.h:3307
#define MSGCAT_SEMANTIC_NONCLASS_PARENT
#define MSGCAT_SEMANTIC_INVALID_FUNCTION_ORDERBY
int db_json_convert_to_utf8(DB_VALUE *dbval)
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
#define MSGCAT_SEMANTIC_METH_ARG_NE_DEFINED
static PT_NODE * pt_find_aggregate_analytic_post(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * spec_parent
Definition: parse_tree.h:3421
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
#define ER_OBJ_INVALID_METHOD
Definition: error_code.h:279
PT_NODE * pt_type_cast_vclass_query_spec_column(PARSER_CONTEXT *parser, PT_NODE *attr, PT_NODE *col)
#define MSGCAT_SEMANTIC_ILLEGAL_LHS
#define MSGCAT_SEMANTIC_FUNCTION_NO_ARGS
#define MSGCAT_SEMANTIC_ATT_CNT_NE_COL_CNT
#define MSGCAT_SEMANTIC_DEFAULT_EXPR_NOT_ALLOWED
PT_NODE * parser_copy_tree_list(PARSER_CONTEXT *parser, PT_NODE *tree)
static void pt_check_create_entity(PARSER_CONTEXT *parser, PT_NODE *node)
#define MSGCAT_SEMANTIC_DELETE_DERIVED_TABLE
static int pt_type_assignable(PARSER_CONTEXT *parser, const PT_NODE *d_type, const PT_NODE *s_type)
static bool pt_attr_refers_to_self(PARSER_CONTEXT *parser, PT_NODE *attr, const char *self)
const char ** p
Definition: dynamic_load.c:945
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
PT_NODE * name
Definition: parse_tree.h:2028
unsigned is_hidden_column
Definition: parse_tree.h:3470
static void pt_check_filter_index_expr(PARSER_CONTEXT *parser, PT_NODE *atts, PT_NODE *node, MOP db_obj)
static int pt_collection_assignable(PARSER_CONTEXT *parser, const PT_NODE *d_col, const PT_NODE *s_col)
unsigned reexecute
Definition: parse_tree.h:2762
static PT_NODE * pt_check_constraint(PARSER_CONTEXT *parser, const PT_NODE *create, const PT_NODE *constraint)
PT_CREATE_USER_INFO create_user
Definition: parse_tree.h:3281
#define MSGCAT_SEMANTIC_CLASS_ATTR_DUPLICATED
DB_DOMAIN * db_domain_set(const DB_DOMAIN *domain)
Definition: db_macro.c:4060
static int pt_check_defaultf(PARSER_CONTEXT *parser, PT_NODE *node)
const char * rel_major_release_string(void)
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
#define PT_EXPR_INFO_CAST_COLL_MODIFIER
Definition: parse_tree.h:2231
#define MSGCAT_SEMANTIC_METH_NO_TARGET
PT_NODE * derived_table
Definition: parse_tree.h:2134
#define MSGCAT_SEMANTIC_NOT_ATTRIBUTE_OF
PT_NODE * save_name
Definition: parse_tree.h:2672
#define MSGCAT_SEMANTIC_UNMACHTED_ARG_ORDER
static void pt_check_partitions(PARSER_CONTEXT *parser, PT_NODE *stmt, MOP dbobj)
PT_NODE * search_cond
Definition: parse_tree.h:2862
PT_NODE * range_var
Definition: parse_tree.h:2135
static int pt_find_partition_column_count_func(PT_NODE *func, PT_NODE **name_node)
PT_NODE * keycol
Definition: parse_tree.h:2020
char * pt_short_print_l(PARSER_CONTEXT *parser, const PT_NODE *node)
static int pt_check_group_concat_order_by(PARSER_CONTEXT *parser, PT_NODE *func)
DB_QUERY_SPEC * db_query_spec_next(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:632
DB_OBJLIST * db_get_subclasses(DB_OBJECT *obj)
Definition: db_info.c:659
#define MSGCAT_SEMANTIC_INVALID_PARTITION_SIZE
#define MSGCAT_SEMANTIC_NO_INDEX_ON_VCLASS