CUBRID Engine  latest
xasl_generation.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  * xasl_generation.c - Generate XASL from the parse tree
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <assert.h>
29 #include <search.h>
30 
31 #include "xasl_generation.h"
32 
33 #include "authenticate.h"
34 #include "misc_string.h"
35 #include "error_manager.h"
36 #include "parser.h"
37 #include "xasl_aggregate.hpp"
38 #include "xasl_analytic.hpp"
39 #include "xasl_predicate.hpp"
40 #include "xasl_regu_alloc.hpp"
41 #include "db.h"
42 #include "environment_variable.h"
43 #include "parser.h"
44 #include "schema_manager.h"
45 #include "view_transform.h"
46 #include "locator_cl.h"
47 #include "optimizer.h"
48 #include "parser_message.h"
49 #include "virtual_object.h"
50 #include "set_object.h"
51 #include "object_primitive.h"
52 #include "object_print.h"
53 #include "object_representation.h"
54 #include "intl_support.h"
55 #include "system_parameter.h"
56 #include "execute_schema.h"
57 #include "porting.h"
58 #include "execute_statement.h"
59 #include "query_graph.h"
60 #include "transform.h"
61 #include "query_planner.h"
62 #include "semantic_check.h"
63 #include "query_dump.h"
64 #include "parser_support.h"
65 #include "compile_context.h"
66 #include "db_json.hpp"
67 
68 #if defined(WINDOWS)
69 #include "wintcp.h"
70 #endif /* WINDOWS */
71 
72 #include "dbtype.h"
73 
74 extern void qo_plan_lite_print (QO_PLAN * plan, FILE * f, int howfar);
75 
76 /* maximum number of unique columns that can be optimized */
77 #define ANALYTIC_OPT_MAX_SORT_LIST_COLUMNS 32
78 
79 /* maximum number of functions that can be optimized */
80 #define ANALYTIC_OPT_MAX_FUNCTIONS 32
81 
82 typedef struct hashable HASHABLE;
83 struct hashable
84 {
85  bool is_PRIOR;
87 };
88 
89 typedef enum
90 {
95 } HASH_ATTR;
96 
97 #define CHECK_HASH_ATTR(hashable_arg, hash_attr) \
98  do \
99  { \
100  if (hashable_arg.is_PRIOR && hashable_arg.is_NAME_without_prior) \
101  { \
102  hash_attr = UNHASHABLE; \
103  } \
104  else if (hashable_arg.is_PRIOR && !hashable_arg.is_NAME_without_prior) \
105  { \
106  hash_attr = PROBE; \
107  } \
108  else if (!hashable_arg.is_PRIOR && hashable_arg.is_NAME_without_prior) \
109  { \
110  hash_attr = BUILD; \
111  } \
112  else \
113  { \
114  hash_attr = CONSTANT; \
115  } \
116  } \
117  while (0)
118 
121 {
122  /* indexed sort list */
123  unsigned char key[ANALYTIC_OPT_MAX_FUNCTIONS];
124 
125  /* sort list size */
126  int key_size;
127 
128  /* partition prefix size */
130 
131  /* compatibility links */
134 
135  /* if composite metadomain then the two children, otherwise null */
137 
138  /* true if metadomain is now part of composite metadomain */
139  bool demoted;
140 
141  /* level of metadomain */
142  int level;
143 
144  /* source function */
146 };
147 
148 /* metadomain initializer */
149 static ANALYTIC_KEY_METADOMAIN analitic_key_metadomain_Initializer = { {0}, 0, 0, {NULL}, 0, {NULL}, false, 0, NULL };
150 
151 typedef enum
152 {
159 
161 {
165 
168 {
169  PRED_REGU_VARIABLE_P_LIST next; /* next node */
170  const REGU_VARIABLE *pvalue; /* pointer to regulator variable */
171  bool is_prior; /* is it in PRIOR argument? */
172 };
173 
174 #define SORT_SPEC_EQ(a, b) \
175  ((a)->info.sort_spec.pos_descr.pos_no == (b)->info.sort_spec.pos_descr.pos_no \
176  && (a)->info.sort_spec.asc_or_desc == (b)->info.sort_spec.asc_or_desc \
177  && (a)->info.sort_spec.nulls_first_or_last == (b)->info.sort_spec.nulls_first_or_last)
178 
179 static PRED_EXPR *pt_make_pred_term_not (const PRED_EXPR * arg1);
180 static PRED_EXPR *pt_make_pred_term_comp (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REL_OP rop,
181  const DB_TYPE data_type);
182 static PRED_EXPR *pt_make_pred_term_some_all (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REL_OP rop,
183  const DB_TYPE data_type, const QL_FLAG some_all);
184 static PRED_EXPR *pt_make_pred_term_like (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2,
185  const REGU_VARIABLE * arg3);
186 static PRED_EXPR *pt_make_pred_term_rlike (REGU_VARIABLE * arg1, REGU_VARIABLE * arg2, REGU_VARIABLE * case_sensitive);
187 static PRED_EXPR *pt_make_pred_term_is (PARSER_CONTEXT * parser, PT_NODE * arg1, PT_NODE * arg2, const BOOL_OP bop);
189 
190 #if defined (ENABLE_UNUSED_FUNCTION)
191 static int hhhhmmss (const DB_TIME * time, char *buf, int buflen);
192 static int hhmiss (const DB_TIME * time, char *buf, int buflen);
193 static int yyyymmdd (const DB_DATE * date, char *buf, int buflen);
194 static int yymmdd (const DB_DATE * date, char *buf, int buflen);
195 static int yymmddhhmiss (const DB_UTIME * utime, char *buf, int buflen);
196 static int mmddyyyyhhmiss (const DB_UTIME * utime, char *buf, int buflen);
197 static int yyyymmddhhmissms (const DB_DATETIME * datetime, char *buf, int buflen);
198 static int mmddyyyyhhmissms (const DB_DATETIME * datetime, char *buf, int buflen);
199 
200 static char *host_var_name (unsigned int custom_print);
201 #endif
202 static PT_NODE *pt_table_compatible_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_info, int *continue_walk);
203 static int pt_table_compatible (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * spec);
204 static TABLE_INFO *pt_table_info_alloc (void);
206 static PT_NODE *pt_is_hash_agg_eligible (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
207 static PT_NODE *pt_to_aggregate_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
210  int *instnum_flag);
211 static PT_NODE *pt_expand_analytic_node (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * select_list);
213 static void pt_adjust_analytic_sort_specs (PARSER_CONTEXT * parser, PT_NODE * node, int idx, int adjust);
215  VAL_LIST * vallist);
217 static SYMBOL_INFO *pt_push_fetch_spec_info (PARSER_CONTEXT * parser, SYMBOL_INFO * symbols, PT_NODE * fetch_spec);
218 static ACCESS_SPEC_TYPE *pt_make_access_spec (TARGET_TYPE spec_type, ACCESS_METHOD access, INDX_INFO * indexptr,
219  PRED_EXPR * where_key, PRED_EXPR * where_pred, PRED_EXPR * where_range);
220 static int pt_cnt_attrs (const REGU_VARIABLE_LIST attr_list);
221 static void pt_fill_in_attrid_array (REGU_VARIABLE_LIST attr_list, ATTR_ID * attr_array, int *next_pos);
222 static SORT_LIST *pt_to_sort_list (PARSER_CONTEXT * parser, PT_NODE * node_list, PT_NODE * col_list,
223  SORT_LIST_MODE sort_mode);
224 
225 static int *pt_to_method_arglist (PARSER_CONTEXT * parser, PT_NODE * target, PT_NODE * node_list,
226  PT_NODE * subquery_as_attr_list);
227 
228 static int regu_make_constant_vid (DB_VALUE * val, DB_VALUE ** dbvalptr);
229 static int set_has_objs (DB_SET * seq);
230 static int setof_mop_to_setof_vobj (PARSER_CONTEXT * parser, DB_SET * seq, DB_VALUE * new_val);
234  const PT_NODE * node);
235 static REGU_VARIABLE *pt_make_regu_pred (const PRED_EXPR * pred);
236 static REGU_VARIABLE *pt_make_function (PARSER_CONTEXT * parser, int function_code, const REGU_VARIABLE_LIST arg_list,
237  const DB_TYPE result_type, const PT_NODE * node);
240  const PT_NODE * node);
242 static PT_NODE *pt_set_numbering_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
244 static void pt_to_misc_operand (REGU_VARIABLE * regu, PT_MISC_TYPE misc_specifier);
247  HEAP_CACHE_ATTRINFO * cache_attrinfo, PT_NODE * attr);
248 static REGU_VARIABLE *pt_make_vid (PARSER_CONTEXT * parser, const PT_NODE * data_type, const REGU_VARIABLE * regu3);
250  PT_NODE * where_part, QO_XASL_INDEX_INFO * index_pred);
251 static REGU_VARIABLE *pt_make_pos_regu_var_from_scratch (TP_DOMAIN * dom, DB_VALUE * fetch_to, int pos_no);
252 static PT_NODE *pt_set_level_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
254 static PT_NODE *pt_set_isleaf_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
256 static PT_NODE *pt_set_iscycle_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
259  int *continue_walk);
260 static PT_NODE *pt_set_qprior_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
262  REGU_VARIABLE_LIST regu_list);
263 static XASL_NODE *pt_find_oid_scan_block (XASL_NODE * xasl, OID * oid);
264 static PT_NODE *pt_numbering_set_continue_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
266  PT_NODE ** term_exprs);
268  PT_NODE ** term_exprs);
269 static int pt_create_iss_range (INDX_INFO * indx_infop, TP_DOMAIN * domain);
270 static int pt_init_pred_expr_context (PARSER_CONTEXT * parser, PT_NODE * predicate, PT_NODE * spec,
271  PRED_EXPR_WITH_CONTEXT * pred_expr);
272 static bool validate_regu_key_function_index (REGU_VARIABLE * regu_var);
273 static XASL_NODE *pt_to_merge_update_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_attrs);
274 static XASL_NODE *pt_to_merge_insert_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * non_null_attrs,
275  PT_NODE * default_expr_attrs);
277  PT_NODE * select_list);
278 static ODKU_INFO *pt_to_odku_info (PARSER_CONTEXT * parser, PT_NODE * insert, XASL_NODE * xasl);
280 
283 static void pt_mark_spec_list_for_update_clause (PARSER_CONTEXT * parser, PT_NODE * statement, PT_SPEC_FLAG spec_flag);
284 
285 static void pt_aggregate_info_append_value_list (AGGREGATE_INFO * info, VAL_LIST * value_list);
286 
288  REGU_VARIABLE_LIST regu_position_list,
289  REGU_VARIABLE_LIST regu_constant_list);
290 
292 
294  REGU_VARIABLE_LIST * regu_position_list);
295 
297  REGU_VARIABLE_LIST * regu_list);
298 
300  REGU_VARIABLE_LIST * regu_list);
301 
302 /* *INDENT-OFF* */
303 static void pt_set_regu_list_pos_descr_from_idx (REGU_VARIABLE_LIST & regu_list, size_t starting_index);
304 /* *INDENT-ON* */
305 
308  AGGREGATE_INFO * info, REGU_VARIABLE * regu);
309 
310 
311 #define APPEND_TO_XASL(xasl_head, list, xasl_tail) \
312  do \
313  { \
314  if (xasl_head) \
315  { \
316  /* append xasl_tail to end of linked list denoted by list */ \
317  XASL_NODE **NAME2(list, ptr) = &xasl_head->list; \
318  while ((*NAME2(list, ptr))) \
319  { \
320  NAME2(list, ptr) = &(*NAME2(list, ptr))->list; \
321  } \
322  (*NAME2(list, ptr)) = xasl_tail; \
323  } \
324  else \
325  { \
326  xasl_head = xasl_tail; \
327  } \
328  } \
329  while (0)
330 
331 #define VALIDATE_REGU_KEY_HELPER(r) \
332  ((r)->type == TYPE_CONSTANT || (r)->type == TYPE_DBVAL || (r)->type == TYPE_POS_VALUE || (r)->type == TYPE_INARITH)
333 
334 #define VALIDATE_REGU_KEY(r) \
335  ((r)->type == TYPE_CONSTANT || (r)->type == TYPE_DBVAL || (r)->type == TYPE_POS_VALUE \
336  || ((r)->type == TYPE_INARITH && validate_regu_key_function_index ((r))))
337 
338 typedef struct xasl_supp_info
339 {
340  PT_NODE *query_list; /* ??? */
341 
342  /* XASL cache related information */
343  OID *class_oid_list; /* list of class/serial OIDs referenced in the XASL */
344  int *class_locks; /* list of locks required for each class in class_oid_list. */
345  int *tcard_list; /* list of #pages of the class OIDs */
346  int n_oid_list; /* number OIDs in the list */
347  int oid_list_size; /* size of the list */
348  int includes_tde_class; /* whether there are some tde class in class_oid_list: 0 or 1 */
350 
351 typedef struct uncorr_info
352 {
354  int level;
355 } UNCORR_INFO;
356 
357 typedef struct corr_info
358 {
360  UINTPTR id;
361 } CORR_INFO;
362 
365 
366 static XASL_SUPP_INFO xasl_Supp_info = { NULL, NULL, NULL, NULL, 0, 0, 0 };
367 
368 static const int OID_LIST_GROWTH = 10;
369 
370 
371 static RANGE op_type_to_range (const PT_OP_TYPE op_type, const int nterms);
372 static int pt_to_single_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col,
373  KEY_INFO * key_infop, int *multi_col_pos);
374 static int pt_to_range_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col,
375  KEY_INFO * key_infop);
376 static int pt_to_list_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col,
377  KEY_INFO * key_infop);
378 static int pt_to_rangelist_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col,
379  KEY_INFO * key_infop, int rangelist_idx, int *multi_col_pos);
380 static int pt_to_key_limit (PARSER_CONTEXT * parser, PT_NODE * key_limit, QO_LIMIT_INFO * limit_infop,
381  KEY_INFO * key_infop, bool key_limit_reset);
382 static int pt_instnum_to_key_limit (PARSER_CONTEXT * parser, QO_PLAN * plan, XASL_NODE * xasl);
384 static INDX_INFO *pt_to_index_info (PARSER_CONTEXT * parser, DB_OBJECT * class_, PRED_EXPR * where_pred, QO_PLAN * plan,
385  QO_XASL_INDEX_INFO * qo_index_infop);
386 static ACCESS_SPEC_TYPE *pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_key_part,
387  PT_NODE * where_part, QO_PLAN * plan, QO_XASL_INDEX_INFO * index_pred);
389  PT_NODE * where_part, PT_NODE * where_hash_part);
392  PT_NODE * where_part);
394  PT_NODE * src_derived_tbl);
396  PT_NODE * src_derived_tbl, PT_NODE * where_p);
398  PRED_EXPR * where_pred, PT_JSON_TABLE_INFO * json_table,
399  TABLE_INFO * tbl_info);
401  size_t & start_id, TABLE_INFO * tbl_info);
403  size_t & current_id, TABLE_INFO * tbl_info,
404  json_table_node & result);
405 static XASL_NODE *pt_find_xasl (XASL_NODE * list, XASL_NODE * match);
406 static void pt_set_aptr (PARSER_CONTEXT * parser, PT_NODE * select_node, XASL_NODE * xasl);
407 static XASL_NODE *pt_append_scan (const XASL_NODE * to, const XASL_NODE * from);
408 static PT_NODE *pt_uncorr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
409 static PT_NODE *pt_uncorr_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
411 static PT_NODE *pt_corr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
412 static XASL_NODE *pt_to_corr_subquery_list (PARSER_CONTEXT * parser, PT_NODE * node, UINTPTR id);
414  SELUPD_LIST * selupd_list, DB_OBJECT * target_class);
415 static OUTPTR_LIST *pt_to_outlist (PARSER_CONTEXT * parser, PT_NODE * node_list, SELUPD_LIST ** selupd_list_ptr,
416  UNBOX unbox);
418 static void pt_to_fetch_proc_list (PARSER_CONTEXT * parser, PT_NODE * spec, XASL_NODE * root);
420 static XASL_NODE *pt_gen_optimized_plan (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN * plan,
421  XASL_NODE * xasl);
422 static XASL_NODE *pt_gen_simple_plan (PARSER_CONTEXT * parser, PT_NODE * select_node, QO_PLAN * plan, XASL_NODE * xasl);
427  PT_NODE ** index, int *index_size);
429  ANALYTIC_KEY_METADOMAIN * out, int *lost_link_count, int level);
430 static void pt_metadomain_build_comp_graph (ANALYTIC_KEY_METADOMAIN * af_meta, int af_count, int level);
432  PT_NODE ** sort_list_index, PT_NODE * select_list);
435  ANALYTIC_EVAL_TYPE * eval, PT_NODE ** sort_list_index,
436  ANALYTIC_INFO * info);
438 static XASL_NODE *pt_plan_set_query (PARSER_CONTEXT * parser, PT_NODE * node, PROC_TYPE proc_type);
439 static XASL_NODE *pt_plan_query (PARSER_CONTEXT * parser, PT_NODE * select_node);
440 static XASL_NODE *pt_plan_schema (PARSER_CONTEXT * parser, PT_NODE * select_node);
441 static XASL_NODE *parser_generate_xasl_proc (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * query_list);
442 static PT_NODE *parser_generate_xasl_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
443 static int pt_spec_to_xasl_class_oid_list (PARSER_CONTEXT * parser, const PT_NODE * spec, OID ** oid_listp,
444  int **lock_listp, int **tcard_listp, int *nump, int *sizep,
445  int includes_tde_class);
446 static int pt_serial_to_xasl_class_oid_list (PARSER_CONTEXT * parser, const PT_NODE * serial, OID ** oid_listp,
447  int **lock_listp, int **tcard_listp, int *nump, int *sizep);
448 static PT_NODE *parser_generate_xasl_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
450 static int pt_to_constraint_pred (PARSER_CONTEXT * parser, XASL_NODE * xasl, PT_NODE * spec, PT_NODE * non_null_attrs,
451  PT_NODE * attr_list, int attr_offset);
453  XASL_NODE * xasl_to_scan);
454 
456  VAL_LIST * value_list, int *attr_offsets);
457 
459 
461 static DB_VALUE *pt_index_value (const VAL_LIST * value, int index);
462 
464 
466 
468  VAL_LIST * value_list, int *attr_offsets);
469 
471 
472 #if defined (ENABLE_UNUSED_FUNCTION)
473 static int look_for_unique_btid (DB_OBJECT * classop, const char *name, BTID * btid);
474 #endif
475 
476 static void pt_split_access_if_instnum (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where,
477  PT_NODE ** access_part, PT_NODE ** if_part, PT_NODE ** instnum_part);
478 
479 static void pt_split_if_instnum (PARSER_CONTEXT * parser, PT_NODE * where, PT_NODE ** if_part, PT_NODE ** instnum_part);
480 
481 static void pt_split_having_grbynum (PARSER_CONTEXT * parser, PT_NODE * having, PT_NODE ** having_part,
482  PT_NODE ** grbynum_part);
483 
484 static int pt_split_attrs (PARSER_CONTEXT * parser, TABLE_INFO * table_info, PT_NODE * pred, PT_NODE ** pred_attrs,
485  PT_NODE ** rest_attrs, PT_NODE ** reserved_attrs, int **pred_offsets, int **rest_offsets,
486  int **reserved_offsets);
487 
489  PT_NODE ** build_attrs, PT_NODE ** probe_attrs);
490 
491 static int pt_split_hash_attrs_for_HQ (PARSER_CONTEXT * parser, PT_NODE * pred, PT_NODE ** build_attrs,
492  PT_NODE ** probe_attrs, PT_NODE ** pred_without_HQ);
493 
495  PT_NODE * pred, PT_NODE ** pred_attrs, int **pred_offsets);
496 static int pt_get_pred_attrs (PARSER_CONTEXT * parser, TABLE_INFO * table_info, PT_NODE * pred, PT_NODE ** pred_attrs);
497 
498 static PT_NODE *pt_flush_class_and_null_xasl (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg,
499  int *continue_walk);
500 
501 static PT_NODE *pt_null_xasl (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk);
502 
503 static PT_NODE *pt_is_spec_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk);
504 
505 static PT_NODE *pt_check_hashable (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk);
506 
507 static PT_NODE *pt_find_hq_op_except_prior (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
508 
509 static VAL_LIST *pt_clone_val_list (PARSER_CONTEXT * parser, PT_NODE * attribute_list);
510 
511 static AGGREGATE_TYPE *pt_to_aggregate (PARSER_CONTEXT * parser, PT_NODE * select_node, OUTPTR_LIST * out_list,
512  VAL_LIST * value_list, REGU_VARIABLE_LIST regu_list,
513  REGU_VARIABLE_LIST scan_regu_list, PT_NODE * out_names,
514  DB_VALUE ** grbynum_valp);
515 
516 static SYMBOL_INFO *pt_push_symbol_info (PARSER_CONTEXT * parser, PT_NODE * select_node);
517 
519 
521  TARGET_TYPE scan_type, ACCESS_METHOD access, INDX_INFO * indexptr,
522  PRED_EXPR * where_key, PRED_EXPR * where_pred,
523  PRED_EXPR * where_range, REGU_VARIABLE_LIST attr_list_key,
524  REGU_VARIABLE_LIST attr_list_pred,
525  REGU_VARIABLE_LIST attr_list_rest,
526  REGU_VARIABLE_LIST attr_list_range,
527  OUTPTR_LIST * output_val_list, REGU_VARIABLE_LIST regu_val_list,
528  HEAP_CACHE_ATTRINFO * cache_key, HEAP_CACHE_ATTRINFO * cache_pred,
529  HEAP_CACHE_ATTRINFO * cache_rest, HEAP_CACHE_ATTRINFO * cache_range,
530  ACCESS_SCHEMA_TYPE schema_type, DB_VALUE ** cache_recordinfo,
531  REGU_VARIABLE_LIST reserved_val_list);
532 
534  PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list_pred,
535  REGU_VARIABLE_LIST attr_list_rest,
536  REGU_VARIABLE_LIST attr_list_build,
537  REGU_VARIABLE_LIST attr_list_probe);
538 
540  REGU_VARIABLE_LIST arg_list);
541 
542 static ACCESS_SPEC_TYPE *pt_make_set_access_spec (REGU_VARIABLE * set_expr, ACCESS_METHOD access, INDX_INFO * indexptr,
543  PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list);
544 
546  ACCESS_METHOD access, INDX_INFO * indexptr,
547  PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list);
548 
549 static SORT_LIST *pt_to_after_iscan (PARSER_CONTEXT * parser, PT_NODE * iscan_list, PT_NODE * root);
550 
551 static SORT_LIST *pt_to_groupby (PARSER_CONTEXT * parser, PT_NODE * group_list, PT_NODE * root);
552 
553 static SORT_LIST *pt_to_after_groupby (PARSER_CONTEXT * parser, PT_NODE * group_list, PT_NODE * root);
554 
555 static TABLE_INFO *pt_find_table_info (UINTPTR spec_id, TABLE_INFO * exposed_list);
556 
557 static PT_NODE *pt_build_do_stmt_aptr_list_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
558 
560 
562  PT_NODE * subquery_as_attr_list);
563 
564 static int pt_is_subquery (PT_NODE * node);
565 
566 static int *pt_make_identity_offsets (PT_NODE * attr_list);
567 
568 static void pt_to_pred_terms (PARSER_CONTEXT * parser, PT_NODE * terms, UINTPTR id, PRED_EXPR ** pred);
569 
570 static VAL_LIST *pt_make_val_list (PARSER_CONTEXT * parser, PT_NODE * attribute_list);
571 
572 static TABLE_INFO *pt_make_table_info (PARSER_CONTEXT * parser, PT_NODE * table_spec);
573 
574 static SYMBOL_INFO *pt_symbol_info_alloc (void);
575 
576 static PRED_EXPR *pt_make_pred_expr_pred (const PRED_EXPR * arg1, const PRED_EXPR * arg2, const BOOL_OP bop);
577 
578 static XASL_NODE *pt_set_connect_by_xasl (PARSER_CONTEXT * parser, PT_NODE * select_node, XASL_NODE * xasl);
579 
580 static XASL_NODE *pt_make_connect_by_proc (PARSER_CONTEXT * parser, PT_NODE * select_node, XASL_NODE * select_xasl);
581 
582 static int pt_add_pseudocolumns_placeholders (PARSER_CONTEXT * parser, OUTPTR_LIST * outptr_list, bool alloc_vals);
583 
585 
587 
588 static VAL_LIST *pt_copy_val_list (PARSER_CONTEXT * parser, VAL_LIST * val_list_p);
589 
590 static int pt_split_pred_regu_list (PARSER_CONTEXT * parser, const VAL_LIST * val_list, const PRED_EXPR * pred,
591  REGU_VARIABLE_LIST * regu_list_rest, REGU_VARIABLE_LIST * regu_list_pred,
592  REGU_VARIABLE_LIST * prior_regu_list_rest,
593  REGU_VARIABLE_LIST * prior_regu_list_pred, bool split_prior);
594 
595 static void pt_add_regu_var_to_list (REGU_VARIABLE_LIST * destination, REGU_VARIABLE_LIST source);
596 static void pt_merge_regu_var_lists (REGU_VARIABLE_LIST * destination, REGU_VARIABLE_LIST source);
597 
598 static PRED_REGU_VARIABLE_P_LIST pt_get_pred_regu_variable_p_list (const PRED_EXPR * pred, int *err);
599 
600 static PRED_REGU_VARIABLE_P_LIST pt_get_var_regu_variable_p_list (const REGU_VARIABLE * regu, bool is_prior, int *err);
601 
603 
604 static SORT_LIST *pt_to_order_siblings_by (PARSER_CONTEXT * parser, XASL_NODE * xasl, XASL_NODE * connect_by_xasl);
605 static SORT_LIST *pt_agg_orderby_to_sort_list (PARSER_CONTEXT * parser, PT_NODE * order_list, PT_NODE * agg_args_list);
607  int *continue_walk);
608 static bool pt_is_sort_list_covered (PARSER_CONTEXT * parser, SORT_LIST * covering_list_p, SORT_LIST * covered_list_p);
611 static int pt_mvcc_flag_specs_cond_reev (PARSER_CONTEXT * parser, PT_NODE * spec_list, PT_NODE * cond);
612 static int pt_mvcc_flag_specs_assign_reev (PARSER_CONTEXT * parser, PT_NODE * spec_list, PT_NODE * assign_list);
614  PT_NODE * spec_list, PT_NODE * assign_list, int *indexes,
615  int indexes_alloc_size);
618  QO_XASL_INDEX_INFO * index_pred, PRED_EXPR ** where_range,
619  REGU_VARIABLE_LIST * regu_attributes_range, HEAP_CACHE_ATTRINFO ** cache_range);
620 static PT_NODE *pt_has_reev_in_subquery_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
621 static PT_NODE *pt_has_reev_in_subquery_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk);
622 static bool pt_has_reev_in_subquery (PARSER_CONTEXT * parser, PT_NODE * statement);
623 
624 
625 static void
627 {
628  /* XASL cache related information */
629  if (xasl_Supp_info.class_oid_list)
630  {
631  free_and_init (xasl_Supp_info.class_oid_list);
632  }
633 
634  if (xasl_Supp_info.class_locks)
635  {
636  free_and_init (xasl_Supp_info.class_locks);
637  }
638 
639  if (xasl_Supp_info.tcard_list)
640  {
641  free_and_init (xasl_Supp_info.tcard_list);
642  }
643 
644  xasl_Supp_info.n_oid_list = xasl_Supp_info.oid_list_size = 0;
645  xasl_Supp_info.includes_tde_class = 0;
646 }
647 
648 
649 /*
650  * pt_make_connect_by_proc () - makes the XASL of the CONNECT BY node
651  * return:
652  * parser(in):
653  * select_node(in):
654  */
655 static XASL_NODE *
657 {
658  XASL_NODE *xasl, *xptr;
659  PT_NODE *from, *where, *if_part, *instnum_part, *build_attrs = NULL, *probe_attrs = NULL, *pred_without_HQ = NULL;
660  QPROC_DB_VALUE_LIST dblist1, dblist2;
661  CONNECTBY_PROC_NODE *connect_by;
662  int level, flag;
663  REGU_VARIABLE_LIST regu_attributes_build, regu_attributes_probe;
664  PRED_EXPR *where_without_HQ = NULL;
665 
666  if (!parser->symbols)
667  {
668  return NULL;
669  }
670 
671  if (!select_node->info.query.q.select.connect_by)
672  {
673  return NULL;
674  }
675 
676  /* must not be a merge node */
677  if (select_node->info.query.q.select.flavor != PT_USER_SELECT)
678  {
679  return NULL;
680  }
681 
683  if (!xasl)
684  {
685  goto exit_on_error;
686  }
687 
688  connect_by = &xasl->proc.connect_by;
689  connect_by->single_table_opt = false;
690 
691  if (connect_by->start_with_list_id == NULL || connect_by->input_list_id == NULL)
692  {
693  goto exit_on_error;
694  }
695 
696  pt_set_level_node_etc (parser, select_node->info.query.q.select.connect_by, &xasl->level_val);
697 
699  if (select_node->info.query.q.select.single_table_opt && OPTIMIZATION_ENABLED (level))
700  {
701  /* handle special case of query without joins */
702  PT_NODE *save_where, *save_from;
703 
704  save_where = select_node->info.query.q.select.where;
705  select_node->info.query.q.select.where = select_node->info.query.q.select.connect_by;
706  save_from = select_node->info.query.q.select.from->next;
707  select_node->info.query.q.select.from->next = NULL;
708 
709  xasl = pt_plan_single_table_hq_iterations (parser, select_node, xasl);
710 
711  select_node->info.query.q.select.where = save_where;
712  select_node->info.query.q.select.from->next = save_from;
713 
714  if (xasl == NULL)
715  {
716  PT_INTERNAL_ERROR (parser, "generate hq xasl");
717  return NULL;
718  }
719 
720  connect_by->single_table_opt = true;
721  }
722  else
723  {
724  /* make START WITH pred */
725 
726  from = select_node->info.query.q.select.from;
727  where = select_node->info.query.q.select.start_with;
728 
729  while (from)
730  {
731  pt_to_pred_terms (parser, where, from->info.spec.id, &connect_by->start_with_pred);
732  from = from->next;
733  }
734  pt_to_pred_terms (parser, where, 0, &connect_by->start_with_pred);
735 
736  /* make CONNECT BY pred */
737 
738  from = select_node->info.query.q.select.from;
739  where = select_node->info.query.q.select.connect_by;
740 
741  while (from)
742  {
743  pt_to_pred_terms (parser, where, from->info.spec.id, &xasl->if_pred);
744  from = from->next;
745  }
746  pt_to_pred_terms (parser, where, 0, &xasl->if_pred);
747  }
748 
749  /* make after_connect_by_pred */
750 
751  from = select_node->info.query.q.select.from;
752  pt_set_numbering_node_etc (parser, select_node->info.query.q.select.after_cb_filter, &select_xasl->instnum_val,
753  &select_xasl->ordbynum_val);
754  where = parser_copy_tree_list (parser, select_node->info.query.q.select.after_cb_filter);
755 
756  pt_split_if_instnum (parser, where, &if_part, &instnum_part);
757 
758  /* first set 'etc' field for pseudo-columns, operators and function nodes, to support them in after_connect_by_pred */
759  pt_set_level_node_etc (parser, if_part, &select_xasl->level_val);
760  pt_set_isleaf_node_etc (parser, if_part, &select_xasl->isleaf_val);
761  pt_set_iscycle_node_etc (parser, if_part, &select_xasl->iscycle_val);
762  pt_set_connect_by_operator_node_etc (parser, if_part, select_xasl);
763  pt_set_qprior_node_etc (parser, if_part, select_xasl);
764 
765  while (from)
766  {
767  pt_to_pred_terms (parser, if_part, from->info.spec.id, &connect_by->after_connect_by_pred);
768  from = from->next;
769  }
770  pt_to_pred_terms (parser, if_part, 0, &connect_by->after_connect_by_pred);
771 
772  select_xasl = pt_to_instnum_pred (parser, select_xasl, instnum_part);
773 
774  if (if_part)
775  {
776  parser_free_tree (parser, if_part);
777  }
778  if (instnum_part)
779  {
780  parser_free_tree (parser, instnum_part);
781  }
782 
783  /* make val_list as a list of pointers to all DB_VALUEs of scanners val lists */
784 
785  regu_alloc (xasl->val_list);
786  if (!xasl->val_list)
787  {
788  goto exit_on_error;
789  }
790 
791  dblist2 = NULL;
792  xasl->val_list->val_cnt = 0;
793  for (xptr = select_xasl; xptr; xptr = xptr->scan_ptr)
794  {
795  if (xptr->val_list)
796  {
797  for (dblist1 = xptr->val_list->valp; dblist1; dblist1 = dblist1->next)
798  {
799  if (!dblist2)
800  {
801  regu_alloc (xasl->val_list->valp);
802  // xasl->val_list->valp = regu_dbvlist_alloc (); /* don't alloc DB_VALUE */
803  dblist2 = xasl->val_list->valp;
804  }
805  else
806  {
807  regu_alloc (dblist2->next);
808  dblist2 = dblist2->next;
809  }
810 
811  dblist2->val = dblist1->val;
812  dblist2->dom = dblist1->dom;
813  xasl->val_list->val_cnt++;
814  }
815  }
816  }
817 
818  /* make val_list for use with parent tuple */
819  connect_by->prior_val_list = pt_copy_val_list (parser, xasl->val_list);
820  if (!connect_by->prior_val_list)
821  {
822  goto exit_on_error;
823  }
824 
825  /* make outptr list from val_list */
826  xasl->outptr_list = pt_make_outlist_from_vallist (parser, xasl->val_list);
827  if (!xasl->outptr_list)
828  {
829  goto exit_on_error;
830  }
831 
832  /* make outlist for use with parent tuple */
833  connect_by->prior_outptr_list = pt_make_outlist_from_vallist (parser, connect_by->prior_val_list);
834  if (!connect_by->prior_outptr_list)
835  {
836  goto exit_on_error;
837  }
838 
839  /* make regu_list list from val_list (list of positional regu variables for fetching val_list from a tuple) */
840  connect_by->regu_list_rest = pt_make_pos_regu_list (parser, xasl->val_list);
841 
842  /* do the same for fetching prior_val_list from parent tuple */
843  connect_by->prior_regu_list_rest = pt_make_pos_regu_list (parser, connect_by->prior_val_list);
844 
845  /* make regu list for after CONNECT BY iteration */
846  connect_by->after_cb_regu_list_rest = pt_make_pos_regu_list (parser, xasl->val_list);
847 
848  /* sepparate CONNECT BY predicate regu list; obs: we split prior_regu_list too, for possible future optimizations */
849  if (pt_split_pred_regu_list (parser, xasl->val_list, xasl->if_pred, &connect_by->regu_list_rest,
850  &connect_by->regu_list_pred, &connect_by->prior_regu_list_rest,
851  &connect_by->prior_regu_list_pred, true) != NO_ERROR)
852  {
853  goto exit_on_error;
854  }
855 
856  /* add spec of list scan for join query */
857  if (!connect_by->single_table_opt)
858  {
859  /* check hashable predicate and split into build and probe attrs */
860  where = select_node->info.query.q.select.connect_by;
861  if (pt_split_hash_attrs_for_HQ (parser, where, &build_attrs, &probe_attrs, &pred_without_HQ) != NO_ERROR)
862  {
863  goto exit_on_error;;
864  }
865  regu_attributes_build = pt_to_regu_variable_list (parser, build_attrs, UNBOX_AS_VALUE, xasl->val_list, NULL);
866  regu_attributes_probe = pt_to_regu_variable_list (parser, probe_attrs, UNBOX_AS_VALUE, xasl->val_list, NULL);
867 
868  /* make predicate without HQ */
869  where_without_HQ = pt_to_pred_expr (parser, pred_without_HQ);
870 
871  parser_free_tree (parser, probe_attrs);
872  parser_free_tree (parser, build_attrs);
873  parser_free_tree (parser, pred_without_HQ);
874 
875  /* make list scan spec. */
876  xasl->spec_list =
877  pt_make_list_access_spec (xasl, ACCESS_METHOD_SEQUENTIAL, NULL, where_without_HQ, connect_by->regu_list_pred,
878  connect_by->regu_list_rest, regu_attributes_build, regu_attributes_probe);
879  if (xasl->spec_list == NULL)
880  {
881  PT_INTERNAL_ERROR (parser, "generate hq(join) xasl");
882  return NULL;
883  }
884  /* if the user asked for NO_HASH_LIST_SCAN, force it on all list scan */
885  if (select_node->info.query.q.select.hint & PT_HINT_NO_HASH_LIST_SCAN)
886  {
888  }
889  }
890 
891  /* sepparate after CONNECT BY predicate regu list */
892  if (pt_split_pred_regu_list (parser, xasl->val_list, connect_by->after_connect_by_pred,
893  &connect_by->after_cb_regu_list_rest, &connect_by->after_cb_regu_list_pred, NULL, NULL,
894  false) != NO_ERROR)
895  {
896  goto exit_on_error;
897  }
898 
899  /* add pseudocols placeholders to outptr_list */
900  if (pt_add_pseudocolumns_placeholders (parser, xasl->outptr_list, true) != NO_ERROR)
901  {
902  goto exit_on_error;
903  }
904 
905  /* add pseudocols placeholders to prior_outptr_list */
906  if (pt_add_pseudocolumns_placeholders (parser, connect_by->prior_outptr_list, false) != NO_ERROR)
907  {
908  goto exit_on_error;
909  }
910 
911  /* set NOCYCLE */
913  {
915  }
916  else if (select_node->info.query.q.select.check_cycles == CONNECT_BY_CYCLES_IGNORE
918  {
920  }
921 
922  if (pt_has_error (parser))
923  {
924  return NULL;
925  }
926 
927  return xasl;
928 
929 exit_on_error:
930 
931  /* the errors here come from memory allocation */
932  PT_ERROR (parser, select_node,
934 
935  return NULL;
936 }
937 
938 /*
939  * pt_add_pseudocolumns_placeholders() - add placeholders regu vars
940  * for pseudocolumns into outptr_list
941  * return:
942  * outptr_list(in):
943  * alloc_vals(in):
944  */
945 static int
947 {
948  REGU_VARIABLE_LIST regu_list, regu_list_pc;
949 
950  if (outptr_list == NULL)
951  {
952  return ER_FAILED;
953  }
954 
955  regu_list = outptr_list->valptrp;
956  while (regu_list && regu_list->next)
957  {
958  regu_list = regu_list->next;
959  }
960 
961  /* add parent pos pseudocolumn placeholder */
962 
963  outptr_list->valptr_cnt++;
964 
965  regu_alloc (regu_list_pc);
966  if (regu_list_pc == NULL)
967  {
968  return ER_FAILED;
969  }
970 
971  if (regu_list)
972  {
973  regu_list->next = regu_list_pc;
974  }
975  else
976  {
977  regu_list = outptr_list->valptrp = regu_list_pc;
978  }
979 
980  regu_list_pc->next = NULL;
981  regu_list_pc->value.type = TYPE_CONSTANT;
982  regu_list_pc->value.domain = &tp_Bit_domain;
983  if (alloc_vals)
984  {
985  regu_alloc (regu_list_pc->value.value.dbvalptr);
986  if (!regu_list_pc->value.value.dbvalptr)
987  {
988  return ER_FAILED;
989  }
990  pt_register_orphan_db_value (parser, regu_list_pc->value.value.dbvalptr);
991  }
992  else
993  {
994  regu_list_pc->value.value.dbvalptr = NULL;
995  }
996 
997  /* add string placeholder for computing node's path from parent */
998 
999  outptr_list->valptr_cnt++;
1000  if (regu_list->next)
1001  {
1002  regu_list = regu_list->next;
1003  }
1004 
1005  regu_alloc (regu_list_pc);
1006  if (regu_list_pc == NULL)
1007  {
1008  return ER_FAILED;
1009  }
1010 
1011  regu_list_pc->next = NULL;
1012  regu_list_pc->value.type = TYPE_CONSTANT;
1013  regu_list_pc->value.domain = &tp_String_domain;
1014  if (alloc_vals)
1015  {
1016  regu_alloc (regu_list_pc->value.value.dbvalptr);
1017  if (!regu_list_pc->value.value.dbvalptr)
1018  {
1019  return ER_FAILED;
1020  }
1021  pt_register_orphan_db_value (parser, regu_list_pc->value.value.dbvalptr);
1022  }
1023  else
1024  {
1025  regu_list_pc->value.value.dbvalptr = NULL;
1026  }
1027 
1028  regu_list->next = regu_list_pc;
1029 
1030  /* add LEVEL placeholder */
1031 
1032  outptr_list->valptr_cnt++;
1033  regu_list = regu_list->next;
1034 
1035  regu_alloc (regu_list_pc);
1036  if (regu_list_pc == NULL)
1037  {
1038  return ER_FAILED;
1039  }
1040 
1041  regu_list->next = regu_list_pc;
1042 
1043  regu_list_pc->next = NULL;
1044  regu_list_pc->value.type = TYPE_CONSTANT;
1045  regu_list_pc->value.domain = &tp_Integer_domain;
1046  if (alloc_vals)
1047  {
1048  regu_alloc (regu_list_pc->value.value.dbvalptr);
1049  if (!regu_list_pc->value.value.dbvalptr)
1050  {
1051  return ER_FAILED;
1052  }
1053  pt_register_orphan_db_value (parser, regu_list_pc->value.value.dbvalptr);
1054  }
1055  else
1056  {
1057  regu_list_pc->value.value.dbvalptr = NULL;
1058  }
1059 
1060  /* add CONNECT_BY_ISLEAF placeholder */
1061 
1062  outptr_list->valptr_cnt++;
1063  regu_list = regu_list->next;
1064 
1065  regu_alloc (regu_list_pc);
1066  if (regu_list_pc == NULL)
1067  {
1068  return ER_FAILED;
1069  }
1070 
1071  regu_list->next = regu_list_pc;
1072 
1073  regu_list_pc->next = NULL;
1074  regu_list_pc->value.type = TYPE_CONSTANT;
1075  regu_list_pc->value.domain = &tp_Integer_domain;
1076  if (alloc_vals)
1077  {
1078  regu_alloc (regu_list_pc->value.value.dbvalptr);
1079  if (!regu_list_pc->value.value.dbvalptr)
1080  {
1081  return ER_FAILED;
1082  }
1083  pt_register_orphan_db_value (parser, regu_list_pc->value.value.dbvalptr);
1084  }
1085  else
1086  {
1087  regu_list_pc->value.value.dbvalptr = NULL;
1088  }
1089 
1090  /* add CONNECT_BY_ISCYCLE placeholder */
1091 
1092  outptr_list->valptr_cnt++;
1093  regu_list = regu_list->next;
1094 
1095  regu_alloc (regu_list_pc);
1096  if (regu_list_pc == NULL)
1097  {
1098  return ER_FAILED;
1099  }
1100 
1101  regu_list->next = regu_list_pc;
1102 
1103  regu_list_pc->next = NULL;
1104  regu_list_pc->value.type = TYPE_CONSTANT;
1105  regu_list_pc->value.domain = &tp_Integer_domain;
1106  if (alloc_vals)
1107  {
1108  regu_alloc (regu_list_pc->value.value.dbvalptr);
1109  if (!regu_list_pc->value.value.dbvalptr)
1110  {
1111  return ER_FAILED;
1112  }
1113  pt_register_orphan_db_value (parser, regu_list_pc->value.value.dbvalptr);
1114  }
1115  else
1116  {
1117  regu_list_pc->value.value.dbvalptr = NULL;
1118  }
1119 
1120  return NO_ERROR;
1121 }
1122 
1123 /*
1124  * pt_plan_single_table_hq_iterations () - makes plan for single table
1125  * hierarchical query iterations
1126  * return:
1127  * select_node(in):
1128  * xasl(in):
1129  */
1130 static XASL_NODE *
1132 {
1133  QO_PLAN *plan;
1134  int level;
1135 
1136  plan = qo_optimize_query (parser, select_node);
1137 
1138  if (!plan && select_node->info.query.q.select.hint != PT_HINT_NONE)
1139  {
1140  PT_NODE *ordered, *use_nl, *use_idx, *index_ss, *index_ls, *use_merge;
1141  PT_HINT_ENUM hint;
1142  const char *alias_print;
1143 
1144  /* save hint information */
1145  hint = select_node->info.query.q.select.hint;
1146  select_node->info.query.q.select.hint = PT_HINT_NONE;
1147 
1148  ordered = select_node->info.query.q.select.ordered;
1149  select_node->info.query.q.select.ordered = NULL;
1150 
1151  use_nl = select_node->info.query.q.select.use_nl;
1152  select_node->info.query.q.select.use_nl = NULL;
1153 
1154  use_idx = select_node->info.query.q.select.use_idx;
1155  select_node->info.query.q.select.use_idx = NULL;
1156 
1157  index_ss = select_node->info.query.q.select.index_ss;
1158  select_node->info.query.q.select.index_ss = NULL;
1159 
1160  index_ls = select_node->info.query.q.select.index_ls;
1161  select_node->info.query.q.select.index_ls = NULL;
1162 
1163  use_merge = select_node->info.query.q.select.use_merge;
1164  select_node->info.query.q.select.use_merge = NULL;
1165 
1166  alias_print = select_node->alias_print;
1167  select_node->alias_print = NULL;
1168 
1169  /* retry optimization */
1170  plan = qo_optimize_query (parser, select_node);
1171 
1172  /* restore hint information */
1173  select_node->info.query.q.select.hint = hint;
1174  select_node->info.query.q.select.ordered = ordered;
1175  select_node->info.query.q.select.use_nl = use_nl;
1176  select_node->info.query.q.select.use_idx = use_idx;
1177  select_node->info.query.q.select.index_ss = index_ss;
1178  select_node->info.query.q.select.index_ls = index_ls;
1179  select_node->info.query.q.select.use_merge = use_merge;
1180 
1181  select_node->alias_print = alias_print;
1182  }
1183 
1184  if (!plan)
1185  {
1186  return NULL;
1187  }
1188 
1189  xasl = qo_add_hq_iterations_access_spec (plan, xasl);
1190 
1191  if (xasl != NULL)
1192  {
1193  /* dump plan */
1195  if (level >= 0x100 && plan)
1196  {
1197  if (query_Plan_dump_fp == NULL)
1198  {
1199  query_Plan_dump_fp = stdout;
1200  }
1201  fputs ("\nPlan for single table hierarchical iterations:\n", query_Plan_dump_fp);
1203  }
1204  }
1205 
1206  /* discard plan */
1207  qo_plan_discard (plan);
1208 
1209  return xasl;
1210 }
1211 
1212 /*
1213  * pt_make_pred_expr_pred () - makes a pred expr logical node (AND/OR)
1214  * return:
1215  * arg1(in):
1216  * arg2(in):
1217  * bop(in):
1218  */
1219 static PRED_EXPR *
1220 pt_make_pred_expr_pred (const PRED_EXPR * arg1, const PRED_EXPR * arg2, const BOOL_OP bop)
1221 {
1222  PRED_EXPR *pred = NULL;
1223 
1224  if (arg1 != NULL && arg2 != NULL)
1225  {
1226  regu_alloc (pred);
1227 
1228  if (pred)
1229  {
1230  pred->type = T_PRED;
1231  pred->pe.m_pred.lhs = (PRED_EXPR *) arg1;
1232  pred->pe.m_pred.rhs = (PRED_EXPR *) arg2;
1233  pred->pe.m_pred.bool_op = bop;
1234  }
1235  }
1236 
1237  return pred;
1238 }
1239 
1240 /*
1241  * pt_make_pred_term_not () - makes a pred expr one argument term (NOT)
1242  * return:
1243  * arg1(in):
1244  *
1245  * Note :
1246  * This can make a predicate term for an indirect term
1247  */
1248 static PRED_EXPR *
1250 {
1251  PRED_EXPR *pred = NULL;
1252 
1253  if (arg1 != NULL)
1254  {
1255  regu_alloc (pred);
1256 
1257  if (pred)
1258  {
1259  pred->type = T_NOT_TERM;
1260  pred->pe.m_not_term = (PRED_EXPR *) arg1;
1261  }
1262  }
1263 
1264  return pred;
1265 }
1266 
1267 
1268 /*
1269  * pt_make_pred_term_comp () - makes a pred expr term comparison node
1270  * return:
1271  * arg1(in):
1272  * arg2(in):
1273  * rop(in):
1274  * data_type(in):
1275  */
1276 static PRED_EXPR *
1277 pt_make_pred_term_comp (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REL_OP rop,
1278  const DB_TYPE data_type)
1279 {
1280  PRED_EXPR *pred = NULL;
1281 
1282  if (arg1 != NULL && (arg2 != NULL || rop == R_EXISTS || rop == R_NULL))
1283  {
1284  regu_alloc (pred);
1285 
1286  if (pred)
1287  {
1288  COMP_EVAL_TERM *et_comp = &pred->pe.m_eval_term.et.et_comp;
1289 
1290  pred->type = T_EVAL_TERM;
1292  et_comp->lhs = (REGU_VARIABLE *) arg1;
1293  et_comp->rhs = (REGU_VARIABLE *) arg2;
1294  et_comp->rel_op = rop;
1295  et_comp->type = data_type;
1296  }
1297  }
1298 
1299  return pred;
1300 }
1301 
1302 /*
1303  * pt_make_pred_term_some_all () - makes a pred expr term some/all
1304  * comparison node
1305  * return:
1306  * arg1(in):
1307  * arg2(in):
1308  * rop(in):
1309  * data_type(in):
1310  * some_all(in):
1311  */
1312 static PRED_EXPR *
1313 pt_make_pred_term_some_all (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REL_OP rop,
1314  const DB_TYPE data_type, const QL_FLAG some_all)
1315 {
1316  PRED_EXPR *pred = NULL;
1317 
1318  if (arg1 != NULL && arg2 != NULL)
1319  {
1320  regu_alloc (pred);
1321 
1322  if (pred)
1323  {
1324  ALSM_EVAL_TERM *et_alsm = &pred->pe.m_eval_term.et.et_alsm;
1325 
1326  pred->type = T_EVAL_TERM;
1328  et_alsm->elem = (REGU_VARIABLE *) arg1;
1329  et_alsm->elemset = (REGU_VARIABLE *) arg2;
1330  et_alsm->rel_op = rop;
1331  et_alsm->item_type = data_type;
1332  et_alsm->eq_flag = some_all;
1333  }
1334  }
1335 
1336  return pred;
1337 }
1338 
1339 /*
1340  * pt_make_pred_term_like () - makes a pred expr term like comparison node
1341  * return:
1342  * arg1(in):
1343  * arg2(in):
1344  * esc(in):
1345  */
1346 static PRED_EXPR *
1347 pt_make_pred_term_like (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REGU_VARIABLE * arg3)
1348 {
1349  PRED_EXPR *pred = NULL;
1350 
1351  if (arg1 != NULL && arg2 != NULL)
1352  {
1353  regu_alloc (pred);
1354 
1355  if (pred)
1356  {
1357  LIKE_EVAL_TERM *et_like = &pred->pe.m_eval_term.et.et_like;
1358 
1359  pred->type = T_EVAL_TERM;
1361  et_like->src = (REGU_VARIABLE *) arg1;
1362  et_like->pattern = (REGU_VARIABLE *) arg2;
1363  et_like->esc_char = (REGU_VARIABLE *) arg3;
1364  }
1365  }
1366 
1367  return pred;
1368 }
1369 
1370 /*
1371  * pt_make_pred_term_rlike () - makes a pred expr term of regex comparison node
1372  * return: predicate expression
1373  * arg1(in): source string regu var
1374  * arg2(in): pattern regu var
1375  * case_sensitive(in): sensitivity flag regu var
1376  */
1377 static PRED_EXPR *
1379 {
1380  PRED_EXPR *pred = NULL;
1381  RLIKE_EVAL_TERM *et_rlike = NULL;
1382 
1383  if (arg1 == NULL || arg2 == NULL || case_sensitive == NULL)
1384  {
1385  return NULL;
1386  }
1387 
1388  regu_alloc (pred);
1389  if (pred == NULL)
1390  {
1391  return NULL;
1392  }
1393 
1394  et_rlike = &pred->pe.m_eval_term.et.et_rlike;
1395  pred->type = T_EVAL_TERM;
1397  et_rlike->src = arg1;
1398  et_rlike->pattern = arg2;
1399  et_rlike->case_sensitive = case_sensitive;
1400  et_rlike->compiled_regex = NULL;
1401  et_rlike->compiled_pattern = NULL;
1402 
1403  return pred;
1404 }
1405 
1406 /*
1407  * pt_make_pred_term_is () - makes a pred expr term for IS/IS NOT
1408  * return:
1409  * parser(in):
1410  * arg1(in):
1411  * arg2(in):
1412  * op(in):
1413  *
1414  */
1415 static PRED_EXPR *
1417 {
1418  PT_NODE *dummy1, *dummy2;
1419  PRED_EXPR *pred_rhs, *pred = NULL;
1421 
1422  if (arg1 != NULL && arg2 != NULL)
1423  {
1424  dummy1 = parser_new_node (parser, PT_VALUE);
1425  dummy2 = parser_new_node (parser, PT_VALUE);
1426 
1427  if (dummy1 && dummy2)
1428  {
1429  dummy2->type_enum = PT_TYPE_INTEGER;
1430  dummy2->info.value.data_value.i = 1;
1431 
1432  if (arg2->type_enum == PT_TYPE_LOGICAL)
1433  {
1434  /* term for TRUE/FALSE */
1435  dummy1->type_enum = PT_TYPE_INTEGER;
1436  dummy1->info.value.data_value.i = arg2->info.value.data_value.i;
1437  data_type = DB_TYPE_INTEGER;
1438  }
1439  else
1440  {
1441  /* term for UNKNOWN */
1442  dummy1->type_enum = PT_TYPE_NULL;
1443  data_type = DB_TYPE_NULL;
1444  }
1445 
1446  /* make a R_EQ pred term for rhs boolean val */
1447  pred_rhs =
1449  pt_to_regu_variable (parser, dummy2, UNBOX_AS_VALUE), R_EQ, data_type);
1450 
1451  pred = pt_make_pred_expr_pred (pt_to_pred_expr (parser, arg1), pred_rhs, bop);
1452  }
1453  else
1454  {
1455  PT_INTERNAL_ERROR (parser, "allocate new node");
1456  }
1457  }
1458 
1459  return pred;
1460 }
1461 
1462 
1463 /*
1464  * pt_to_pred_expr_local_with_arg () - converts a parse expression tree
1465  * to pred expressions
1466  * return: A NULL return indicates an error occurred
1467  * parser(in):
1468  * node(in): should be something that will evaluate into a boolean
1469  * argp(out):
1470  */
1471 static PRED_EXPR *
1473 {
1474  PRED_EXPR *pred = NULL;
1476  void *saved_etc;
1477  int dummy;
1478  PT_NODE *save_node;
1479  REGU_VARIABLE *regu_var1 = NULL, *regu_var2 = NULL, *regu_var3 = NULL;
1480 
1481  if (!argp)
1482  {
1483  argp = &dummy;
1484  }
1485 
1486  if (node)
1487  {
1488  save_node = node;
1489 
1490  CAST_POINTER_TO_NODE (node);
1491 
1492  if (node->node_type == PT_EXPR)
1493  {
1494  if (node->info.expr.arg1 && node->info.expr.arg2
1495  && (node->info.expr.arg1->type_enum == node->info.expr.arg2->type_enum))
1496  {
1497  data_type = pt_node_to_db_type (node->info.expr.arg1);
1498  }
1499  else
1500  {
1501  data_type = DB_TYPE_NULL; /* let the back end figure it out */
1502  }
1503 
1504  /* to get information for inst_num() scan typr from pt_to_regu_variable(), borrow 'parser->etc' field */
1505  saved_etc = parser->etc;
1506  parser->etc = NULL;
1507 
1508  /* set regu variables */
1509  if (node->info.expr.op == PT_SETEQ || node->info.expr.op == PT_EQ || node->info.expr.op == PT_SETNEQ
1510  || node->info.expr.op == PT_NE || node->info.expr.op == PT_GE || node->info.expr.op == PT_GT
1511  || node->info.expr.op == PT_LT || node->info.expr.op == PT_LE || node->info.expr.op == PT_SUBSET
1512  || node->info.expr.op == PT_SUBSETEQ || node->info.expr.op == PT_SUPERSET
1513  || node->info.expr.op == PT_SUPERSETEQ || node->info.expr.op == PT_NULLSAFE_EQ)
1514  {
1515  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1516  regu_var2 = pt_to_regu_variable (parser, node->info.expr.arg2, UNBOX_AS_VALUE);
1517  }
1518  else if (node->info.expr.op == PT_IS_NOT_IN || node->info.expr.op == PT_IS_IN
1519  || node->info.expr.op == PT_EQ_SOME || node->info.expr.op == PT_NE_SOME
1520  || node->info.expr.op == PT_GE_SOME || node->info.expr.op == PT_GT_SOME
1521  || node->info.expr.op == PT_LT_SOME || node->info.expr.op == PT_LE_SOME
1522  || node->info.expr.op == PT_EQ_ALL || node->info.expr.op == PT_NE_ALL
1523  || node->info.expr.op == PT_GE_ALL || node->info.expr.op == PT_GT_ALL
1524  || node->info.expr.op == PT_LT_ALL || node->info.expr.op == PT_LE_ALL)
1525  {
1526  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1527  regu_var2 = pt_to_regu_variable (parser, node->info.expr.arg2, UNBOX_AS_TABLE);
1528  }
1529 
1530  switch (node->info.expr.op)
1531  {
1532  /* Logical operators */
1533  case PT_AND:
1534  pred =
1536  pt_to_pred_expr (parser, node->info.expr.arg2), B_AND);
1537  break;
1538 
1539  case PT_OR:
1540  /* set information for inst_num() scan type */
1544  pred =
1546  pt_to_pred_expr (parser, node->info.expr.arg2), B_OR);
1547  break;
1548 
1549  case PT_NOT:
1550  /* We cannot certain what we have to do if NOT predicate set information for inst_num() scan type */
1554  pred = pt_make_pred_term_not (pt_to_pred_expr (parser, node->info.expr.arg1));
1555  break;
1556 
1557  /* one to one comparisons */
1558  case PT_SETEQ:
1559  case PT_EQ:
1560  pred =
1561  pt_make_pred_term_comp (regu_var1, regu_var2,
1562  ((node->info.expr.qualifier == PT_EQ_TORDER) ? R_EQ_TORDER : R_EQ), data_type);
1563  break;
1564 
1565  case PT_NULLSAFE_EQ:
1566  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_NULLSAFE_EQ, data_type);
1567  break;
1568 
1569  case PT_IS:
1570  pred = pt_make_pred_term_is (parser, node->info.expr.arg1, node->info.expr.arg2, B_IS);
1571  break;
1572 
1573  case PT_IS_NOT:
1574  pred = pt_make_pred_term_is (parser, node->info.expr.arg1, node->info.expr.arg2, B_IS_NOT);
1575  break;
1576 
1577  case PT_ISNULL:
1578  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1579  pred = pt_make_pred_term_comp (regu_var1, NULL, R_NULL, data_type);
1580  break;
1581 
1582  case PT_XOR:
1583  pred =
1585  pt_to_pred_expr (parser, node->info.expr.arg2), B_XOR);
1586  break;
1587 
1588  case PT_SETNEQ:
1589  case PT_NE:
1590  /* We cannot certain what we have to do if NOT predicate */
1591  /* set information for inst_num() scan type */
1595  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_NE, data_type);
1596  break;
1597 
1598  case PT_GE:
1599  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_GE, data_type);
1600  break;
1601 
1602  case PT_GT:
1603  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_GT, data_type);
1604  break;
1605 
1606  case PT_LT:
1607  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_LT, data_type);
1608  break;
1609 
1610  case PT_LE:
1611  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_LE, data_type);
1612  break;
1613 
1614  case PT_SUBSET:
1615  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_SUBSET, data_type);
1616  break;
1617 
1618  case PT_SUBSETEQ:
1619  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_SUBSETEQ, data_type);
1620  break;
1621 
1622  case PT_SUPERSET:
1623  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_SUPERSET, data_type);
1624  break;
1625 
1626  case PT_SUPERSETEQ:
1627  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_SUPERSETEQ, data_type);
1628  break;
1629 
1630  case PT_EXISTS:
1631  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_TABLE);
1632  pred = pt_make_pred_term_comp (regu_var1, NULL, R_EXISTS, data_type);
1633 
1634  /* exists op must fetch one tuple */
1635  if (regu_var1 && regu_var1->xasl)
1636  {
1637  XASL_SET_FLAG (regu_var1->xasl, XASL_NEED_SINGLE_TUPLE_SCAN);
1638  }
1639  break;
1640 
1641  case PT_IS_NULL:
1642  case PT_IS_NOT_NULL:
1643  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1644  pred = pt_make_pred_term_comp (regu_var1, NULL, R_NULL, data_type);
1645 
1646  if (node->info.expr.op == PT_IS_NOT_NULL)
1647  {
1648  pred = pt_make_pred_term_not (pred);
1649  }
1650  break;
1651 
1652  case PT_NOT_BETWEEN:
1653  /* set information for inst_num() scan type */
1657  /* FALLTHRU */
1658 
1659  case PT_BETWEEN:
1660  case PT_RANGE:
1661  /* set information for inst_num() scan type */
1662  if (node->info.expr.arg2 && node->info.expr.arg2->or_next)
1663  {
1667  }
1668 
1669  {
1670  PT_NODE *arg1, *arg2, *lower, *upper;
1671  PRED_EXPR *pred1, *pred2;
1672  REGU_VARIABLE *regu;
1673  REL_OP op1 = R_NONE, op2 = R_NONE;
1674 
1675  arg1 = node->info.expr.arg1;
1676  regu = pt_to_regu_variable (parser, arg1, UNBOX_AS_VALUE);
1677 
1678  /* only PT_RANGE has 'or_next' link; PT_BETWEEN and PT_NOT_BETWEEN do not have 'or_next' */
1679 
1680  /* for each range spec of RANGE node */
1681  for (arg2 = node->info.expr.arg2; arg2; arg2 = arg2->or_next)
1682  {
1683  if (!arg2 || arg2->node_type != PT_EXPR || !pt_is_between_range_op (arg2->info.expr.op))
1684  {
1685  /* error! */
1686  break;
1687  }
1688  lower = arg2->info.expr.arg1;
1689  upper = arg2->info.expr.arg2;
1690 
1691  switch (arg2->info.expr.op)
1692  {
1693  case PT_BETWEEN_AND:
1694  case PT_BETWEEN_GE_LE:
1695  op1 = R_GE;
1696  op2 = R_LE;
1697  break;
1698  case PT_BETWEEN_GE_LT:
1699  op1 = R_GE;
1700  op2 = R_LT;
1701  break;
1702  case PT_BETWEEN_GT_LE:
1703  op1 = R_GT;
1704  op2 = R_LE;
1705  break;
1706  case PT_BETWEEN_GT_LT:
1707  op1 = R_GT;
1708  op2 = R_LT;
1709  break;
1710  case PT_BETWEEN_EQ_NA:
1711  /* special case; if this range spec is derived from '=' or 'IN' */
1712  op1 = R_EQ;
1713  op2 = (REL_OP) 0;
1714  break;
1715  case PT_BETWEEN_INF_LE:
1716  op1 = R_LE;
1717  op2 = (REL_OP) 0;
1718  break;
1719  case PT_BETWEEN_INF_LT:
1720  op1 = R_LT;
1721  op2 = (REL_OP) 0;
1722  break;
1723  case PT_BETWEEN_GE_INF:
1724  op1 = R_GE;
1725  op2 = (REL_OP) 0;
1726  break;
1727  case PT_BETWEEN_GT_INF:
1728  op1 = R_GT;
1729  op2 = (REL_OP) 0;
1730  break;
1731  default:
1732  break;
1733  }
1734 
1735  if (op1)
1736  {
1737  regu_var1 = pt_to_regu_variable (parser, lower, UNBOX_AS_VALUE);
1738  pred1 = pt_make_pred_term_comp (regu, regu_var1, op1, data_type);
1739  }
1740  else
1741  {
1742  pred1 = NULL;
1743  }
1744 
1745  if (op2)
1746  {
1747  regu_var2 = pt_to_regu_variable (parser, upper, UNBOX_AS_VALUE);
1748  pred2 = pt_make_pred_term_comp (regu, regu_var2, op2, data_type);
1749  }
1750  else
1751  {
1752  pred2 = NULL;
1753  }
1754 
1755  /* make AND predicate of both two expressions */
1756  if (pred1 && pred2)
1757  {
1758  pred1 = pt_make_pred_expr_pred (pred1, pred2, B_AND);
1759  }
1760 
1761  /* make NOT predicate of BETWEEN predicate */
1762  if (node->info.expr.op == PT_NOT_BETWEEN)
1763  {
1764  pred1 = pt_make_pred_term_not (pred1);
1765  }
1766 
1767  /* make OR predicate */
1768  pred = (pred) ? pt_make_pred_expr_pred (pred1, pred, B_OR) : pred1;
1769  } /* for (arg2 = node->info.expr.arg2; ...) */
1770  }
1771  break;
1772 
1773  /* one to many comparisons */
1774  case PT_IS_NOT_IN:
1775  case PT_IS_IN:
1776  case PT_EQ_SOME:
1777  /* set information for inst_num() scan type */
1781  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_EQ, data_type, F_SOME);
1782 
1783  if (node->info.expr.op == PT_IS_NOT_IN)
1784  {
1785  pred = pt_make_pred_term_not (pred);
1786  }
1787  break;
1788 
1789  case PT_NE_SOME:
1790  /* set information for inst_num() scan type */
1794  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_NE, data_type, F_SOME);
1795  break;
1796 
1797  case PT_GE_SOME:
1798  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_GE, data_type, F_SOME);
1799  break;
1800 
1801  case PT_GT_SOME:
1802  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_GT, data_type, F_SOME);
1803  break;
1804 
1805  case PT_LT_SOME:
1806  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_LT, data_type, F_SOME);
1807  break;
1808 
1809  case PT_LE_SOME:
1810  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_LE, data_type, F_SOME);
1811  break;
1812 
1813  case PT_EQ_ALL:
1814  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_EQ, data_type, F_ALL);
1815  break;
1816 
1817  case PT_NE_ALL:
1818  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_NE, data_type, F_ALL);
1819  break;
1820 
1821  case PT_GE_ALL:
1822  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_GE, data_type, F_ALL);
1823  break;
1824 
1825  case PT_GT_ALL:
1826  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_GT, data_type, F_ALL);
1827  break;
1828 
1829  case PT_LT_ALL:
1830  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_LT, data_type, F_ALL);
1831  break;
1832 
1833  case PT_LE_ALL:
1834  pred = pt_make_pred_term_some_all (regu_var1, regu_var2, R_LE, data_type, F_ALL);
1835  break;
1836 
1837  /* like comparison */
1838  case PT_NOT_LIKE:
1839  case PT_LIKE:
1840  /* set information for inst_num() scan type */
1844  {
1845  REGU_VARIABLE *regu_escape = NULL;
1846  PT_NODE *arg2 = node->info.expr.arg2;
1847 
1848  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1849 
1850  if (arg2 && arg2->node_type == PT_EXPR && arg2->info.expr.op == PT_LIKE_ESCAPE)
1851  {
1852  /* this should be an escape character expression */
1853  if ((arg2->info.expr.arg2->node_type != PT_VALUE)
1854  && (arg2->info.expr.arg2->node_type != PT_HOST_VAR))
1855  {
1857  break;
1858  }
1859 
1860  regu_escape = pt_to_regu_variable (parser, arg2->info.expr.arg2, UNBOX_AS_VALUE);
1861  arg2 = arg2->info.expr.arg1;
1862  }
1864  {
1865  PT_NODE *arg1 = node->info.expr.arg1;
1866  PT_NODE *node = pt_make_string_value (parser, "\\");
1867 
1869 
1870  switch (arg1->type_enum)
1871  {
1872  case PT_TYPE_MAYBE:
1874  {
1875  break;
1876  }
1877  /* FALLTHRU */
1878  case PT_TYPE_NCHAR:
1879  case PT_TYPE_VARNCHAR:
1880  node->type_enum = PT_TYPE_NCHAR;
1881  node->info.value.string_type = 'N';
1882  break;
1883  default:
1884  break;
1885  }
1886 
1887  regu_escape = pt_to_regu_variable (parser, node, UNBOX_AS_VALUE);
1888  parser_free_node (parser, node);
1889  }
1890 
1891  regu_var2 = pt_to_regu_variable (parser, arg2, UNBOX_AS_VALUE);
1892 
1893  pred = pt_make_pred_term_like (regu_var1, regu_var2, regu_escape);
1894 
1895  if (node->info.expr.op == PT_NOT_LIKE)
1896  {
1897  pred = pt_make_pred_term_not (pred);
1898  }
1899  }
1900  break;
1901 
1902  /* regex like comparison */
1903  case PT_RLIKE:
1904  case PT_NOT_RLIKE:
1905  case PT_RLIKE_BINARY:
1906  case PT_NOT_RLIKE_BINARY:
1907  /* set information for inst_num() scan type */
1911  {
1912  regu_var1 = pt_to_regu_variable (parser, node->info.expr.arg1, UNBOX_AS_VALUE);
1913 
1914  regu_var2 = pt_to_regu_variable (parser, node->info.expr.arg2, UNBOX_AS_VALUE);
1915 
1916  regu_var3 = pt_to_regu_variable (parser, node->info.expr.arg3, UNBOX_AS_VALUE);
1917 
1918  pred = pt_make_pred_term_rlike (regu_var1, regu_var2, regu_var3);
1919 
1920  if (node->info.expr.op == PT_NOT_RLIKE || node->info.expr.op == PT_NOT_RLIKE_BINARY)
1921  {
1922  pred = pt_make_pred_term_not (pred);
1923  }
1924  }
1925  break;
1926 
1927  /* this is an error ! */
1928  default:
1929  pred = NULL;
1930  break;
1931  } /* switch (node->info.expr.op) */
1932 
1933  /* to get information for inst_num() scan typr from pt_to_regu_variable(), borrow 'parser->etc' field */
1934  if (parser->etc)
1935  {
1939  }
1940 
1941  parser->etc = saved_etc;
1942  }
1943  else if (node->node_type == PT_HOST_VAR)
1944  {
1945  /* It should be ( ? ). */
1946  /* The predicate expression is ( ( ? <> 0 ) ). */
1947 
1948  PT_NODE *arg2;
1949  bool is_logical = false;
1950 
1951  /* we may have type_enum set to PT_TYPE_LOGICAL by type checking, if this is the case set it to
1952  * PT_TYPE_INTEGER to avoid recursion */
1953  if (node->type_enum == PT_TYPE_LOGICAL)
1954  {
1955  node->type_enum = PT_TYPE_INTEGER;
1956  is_logical = true;
1957  }
1958 
1959  arg2 = parser_new_node (parser, PT_VALUE);
1960 
1961  if (arg2)
1962  {
1963  arg2->type_enum = PT_TYPE_INTEGER;
1964  arg2->info.value.data_value.i = 0;
1965  data_type = DB_TYPE_INTEGER;
1966 
1967  regu_var1 = pt_to_regu_variable (parser, node, UNBOX_AS_VALUE);
1968  regu_var2 = pt_to_regu_variable (parser, arg2, UNBOX_AS_VALUE);
1969  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_NE, data_type);
1970  }
1971  else
1972  {
1973  PT_INTERNAL_ERROR (parser, "allocate new node");
1974  }
1975 
1976  /* restore original type */
1977  if (is_logical)
1978  {
1979  node->type_enum = PT_TYPE_LOGICAL;
1980  }
1981  }
1982  else if (PT_IS_POINTER_REF_NODE (node))
1983  {
1984  /* reference pointer node */
1985  PT_NODE *zero, *real_node;
1986 
1987  real_node = node->info.pointer.node;
1988  CAST_POINTER_TO_NODE (real_node);
1989 
1990  if (real_node != NULL && real_node->type_enum == PT_TYPE_LOGICAL)
1991  {
1992  zero = parser_new_node (parser, PT_VALUE);
1993 
1994  if (zero != NULL)
1995  {
1996  zero->type_enum = PT_TYPE_INTEGER;
1997  zero->info.value.data_value.i = 0;
1998 
1999  data_type = DB_TYPE_INTEGER;
2000 
2001  regu_var1 = pt_to_regu_variable (parser, zero, UNBOX_AS_VALUE);
2002  regu_var2 = pt_to_regu_variable (parser, node, UNBOX_AS_VALUE);
2003 
2004  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_NE, data_type);
2005  }
2006  else
2007  {
2008  PT_INTERNAL_ERROR (parser, "allocate new node");
2009  }
2010  }
2011  else
2012  {
2013  PT_INTERNAL_ERROR (parser, "pred expr must be logical");
2014  }
2015  }
2016  else
2017  {
2018  /* We still need to generate a predicate so that hierarchical queries or aggregate queries with false
2019  * predicates return the correct answer. */
2020  PT_NODE *arg1 = parser_new_node (parser, PT_VALUE);
2021  PT_NODE *arg2 = parser_new_node (parser, PT_VALUE);
2022 
2023  if (arg1 && arg2)
2024  {
2025  arg1->type_enum = PT_TYPE_INTEGER;
2026  if (node->type_enum == PT_TYPE_LOGICAL && node->info.value.data_value.i != 0)
2027  {
2028  arg1->info.value.data_value.i = 1;
2029  }
2030  else
2031  {
2032  arg1->info.value.data_value.i = 0;
2033  }
2034  arg2->type_enum = PT_TYPE_INTEGER;
2035  arg2->info.value.data_value.i = 1;
2036  data_type = DB_TYPE_INTEGER;
2037 
2038  regu_var1 = pt_to_regu_variable (parser, arg1, UNBOX_AS_VALUE);
2039  regu_var2 = pt_to_regu_variable (parser, arg2, UNBOX_AS_VALUE);
2040  pred = pt_make_pred_term_comp (regu_var1, regu_var2, R_EQ, data_type);
2041  }
2042  else
2043  {
2044  PT_INTERNAL_ERROR (parser, "allocate new node");
2045  }
2046  }
2047 
2048  node = save_node; /* restore */
2049  }
2050 
2051  if (node && pred == NULL)
2052  {
2053  if (!pt_has_error (parser))
2054  {
2055  PT_INTERNAL_ERROR (parser, "generate predicate");
2056  }
2057  }
2058 
2059  return pred;
2060 }
2061 
2062 /*
2063  * pt_to_pred_expr_with_arg () - converts a list of expression tree to
2064  * xasl 'pred' expressions, where each item of the list represents
2065  * a conjunctive normal form term
2066  * return: A NULL return indicates an error occurred
2067  * parser(in):
2068  * node_list(in):
2069  * argp(out):
2070  */
2071 PRED_EXPR *
2073 {
2074  PRED_EXPR *cnf_pred, *dnf_pred, *temp;
2075  PT_NODE *node, *cnf_node, *dnf_node;
2076  int dummy;
2077  int num_dnf, i;
2078 
2079  if (!argp)
2080  {
2081  argp = &dummy;
2082  }
2083  *argp = 0;
2084 
2085  /* convert CNF list into right-linear chains of AND terms */
2086  cnf_pred = NULL;
2087  for (node = node_list; node; node = node->next)
2088  {
2089  cnf_node = node;
2090 
2091  CAST_POINTER_TO_NODE (cnf_node);
2092 
2093  if (cnf_node->or_next)
2094  {
2095  /* if term has OR, set information for inst_num() scan type */
2099  }
2100 
2101 
2102  dnf_pred = NULL;
2103 
2104  num_dnf = 0;
2105  for (dnf_node = cnf_node; dnf_node; dnf_node = dnf_node->or_next)
2106  {
2107  num_dnf++;
2108  }
2109 
2110  while (num_dnf)
2111  {
2112  dnf_node = cnf_node;
2113  for (i = 1; i < num_dnf; i++)
2114  {
2115  dnf_node = dnf_node->or_next;
2116  }
2117 
2118  /* get the last dnf_node */
2119  temp = pt_to_pred_expr_local_with_arg (parser, dnf_node, argp);
2120  if (temp == NULL)
2121  {
2122  goto error;
2123  }
2124 
2125  /* set PT_PRED_ARG_INSTNUM_CONTINUE flag for numbering in each node of the predicate */
2126  parser_walk_tree (parser, dnf_node, NULL, NULL, pt_numbering_set_continue_post, argp);
2127 
2128  dnf_pred = (dnf_pred) ? pt_make_pred_expr_pred (temp, dnf_pred, B_OR) : temp;
2129 
2130  if (dnf_pred == NULL)
2131  {
2132  goto error;
2133  }
2134 
2135  num_dnf--; /* decrease to the previous dnf_node */
2136  } /* while (num_dnf) */
2137 
2138  cnf_pred = (cnf_pred) ? pt_make_pred_expr_pred (dnf_pred, cnf_pred, B_AND) : dnf_pred;
2139 
2140  if (cnf_pred == NULL)
2141  {
2142  goto error;
2143  }
2144  } /* for (node = node_list; ...) */
2145 
2146  return cnf_pred;
2147 
2148 error:
2149  PT_INTERNAL_ERROR (parser, "predicate");
2150  return NULL;
2151 }
2152 
2153 /*
2154  * pt_to_pred_expr () -
2155  * return:
2156  * parser(in):
2157  * node(in):
2158  */
2159 PRED_EXPR *
2161 {
2162  return pt_to_pred_expr_with_arg (parser, node, NULL);
2163 }
2164 
2165 #if defined (ENABLE_UNUSED_FUNCTION)
2166 /*
2167  * look_for_unique_btid () - Search for a UNIQUE constraint B-tree ID
2168  * return: 1 on a UNIQUE BTID is found
2169  * classop(in): Class object pointer
2170  * name(in): Attribute name
2171  * btid(in): BTID pointer (BTID is returned)
2172  */
2173 static int
2174 look_for_unique_btid (DB_OBJECT * classop, const char *name, BTID * btid)
2175 {
2176  SM_CLASS *class_;
2177  SM_ATTRIBUTE *att;
2178  int error = NO_ERROR;
2179  int ok = 0;
2180 
2181  error = au_fetch_class (classop, &class_, AU_FETCH_READ, AU_SELECT);
2182  if (error == NO_ERROR)
2183  {
2184  att = classobj_find_attribute (class_, name, 0);
2185  if (att != NULL)
2186  {
2189  {
2190  ok = 1;
2191  }
2192  }
2193  }
2194 
2195  return ok;
2196 } /* look_for_unique_btid */
2197 #endif /* ENABLE_UNUSED_FUNCTION */
2198 
2199 /*
2200  * pt_xasl_type_enum_to_domain () - Given a PT_TYPE_ENUM generate a domain
2201  * for it and cache it
2202  * return:
2203  * type(in):
2204  */
2205 TP_DOMAIN *
2207 {
2208  TP_DOMAIN *dom;
2209 
2210  dom = pt_type_enum_to_db_domain (type);
2211  return tp_domain_cache (dom);
2212 }
2213 
2214 /*
2215  * pt_xasl_node_to_domain () - Given a PT_NODE generate a domain
2216  * for it and cache it
2217  * return:
2218  * parser(in):
2219  * node(in):
2220  */
2221 TP_DOMAIN *
2223 {
2224  TP_DOMAIN *dom;
2225 
2226  dom = pt_node_to_db_domain (parser, (PT_NODE *) node, NULL);
2227  if (dom)
2228  {
2229  return tp_domain_cache (dom);
2230  }
2231  else
2232  {
2233  PT_ERRORc (parser, node, er_msg ());
2234  return NULL;
2235  }
2236 }
2237 
2238 /*
2239  * pt_xasl_data_type_to_domain () - Given a PT_DATA_TYPE node generate
2240  * a domain for it and cache it
2241  * return:
2242  * parser(in):
2243  * node(in):
2244  */
2245 static TP_DOMAIN *
2247 {
2248  TP_DOMAIN *dom;
2249 
2250  dom = pt_data_type_to_db_domain (parser, (PT_NODE *) node, NULL);
2251  return tp_domain_cache (dom);
2252 }
2253 
2254 #if defined (ENABLE_UNUSED_FUNCTION)
2255 /*
2256  * hhhhmmss () - print a time value as 'hhhhmmss'
2257  * return:
2258  * time(in):
2259  * buf(out):
2260  * buflen(in):
2261  */
2262 static int
2263 hhhhmmss (const DB_TIME * time, char *buf, int buflen)
2264 {
2265  const char date_fmt[] = "00%H%M%S";
2266  DB_DATE date;
2267 
2268  /* pick any valid date, even though we're interested only in time, to pacify db_strftime */
2269  db_date_encode (&date, 12, 31, 1970);
2270 
2271  return db_strftime (buf, buflen, date_fmt, &date, (DB_TIME *) time);
2272 }
2273 
2274 /*
2275  * hhmiss () - print a time value as 'hh:mi:ss'
2276  * return:
2277  * time(in):
2278  * buf(out):
2279  * buflen(in):
2280  */
2281 static int
2282 hhmiss (const DB_TIME * time, char *buf, int buflen)
2283 {
2284  const char date_fmt[] = "%H:%M:%S";
2285  DB_DATE date;
2286 
2287  /* pick any valid date, even though we're interested only in time, to pacify db_strftime */
2288  db_date_encode (&date, 12, 31, 1970);
2289 
2290  return db_strftime (buf, buflen, date_fmt, &date, (DB_TIME *) time);
2291 }
2292 
2293 /*
2294  * hhmissms () - print a time value as 'hh:mi:ss.ms'
2295  * return:
2296  * time(in):
2297  * buf(out):
2298  * buflen(in):
2299  */
2300 static int
2301 hhmissms (const unsigned int mtime, char *buf, int buflen)
2302 {
2303  DB_DATETIME datetime;
2304  int month, day, year;
2305  int hour, minute, second, millisecond;
2306  int retval;
2307 
2308  datetime.date = 0;
2309  datetime.time = mtime;
2310 
2311  db_datetime_decode (&datetime, &month, &day, &year, &hour, &minute, &second, &millisecond);
2312 
2313  /* "H:%M:%S.MS"; */
2314  retval = sprintf (buf, "%d:%d:%d.%d", hour, minute, second, millisecond);
2315 
2316  return retval;
2317 }
2318 
2319 /*
2320  * yyyymmdd () - print a date as 'yyyymmdd'
2321  * return:
2322  * date(in):
2323  * buf(out):
2324  * buflen(in):
2325  */
2326 static int
2327 yyyymmdd (const DB_DATE * date, char *buf, int buflen)
2328 {
2329  const char date_fmt[] = "%Y%m%d";
2330  DB_TIME time = 0;
2331 
2332  return db_strftime (buf, buflen, date_fmt, (DB_DATE *) date, &time);
2333 }
2334 
2335 
2336 /*
2337  * yymmdd () - print a date as 'yyyy-mm-dd'
2338  * return:
2339  * date(in):
2340  * buf(out):
2341  * buflen(in):
2342  */
2343 static int
2344 yymmdd (const DB_DATE * date, char *buf, int buflen)
2345 {
2346  const char date_fmt[] = "%Y-%m-%d";
2347  DB_TIME time = 0;
2348 
2349  return db_strftime (buf, buflen, date_fmt, (DB_DATE *) date, &time);
2350 }
2351 
2352 
2353 /*
2354  * yymmddhhmiss () - print utime as 'yyyy-mm-dd:hh:mi:ss'
2355  * return:
2356  * utime(in):
2357  * buf(out):
2358  * buflen(in):
2359  */
2360 static int
2361 yymmddhhmiss (const DB_UTIME * utime, char *buf, int buflen)
2362 {
2363  DB_DATE date;
2364  DB_TIME time;
2365  const char fmt[] = "%Y-%m-%d:%H:%M:%S";
2366 
2367  /* extract date & time from utime */
2368  db_utime_decode (utime, &date, &time);
2369 
2370  return db_strftime (buf, buflen, fmt, &date, &time);
2371 }
2372 
2373 
2374 /*
2375  * mmddyyyyhhmiss () - print utime as 'mm/dd/yyyy hh:mi:ss'
2376  * return:
2377  * utime(in):
2378  * buf(in):
2379  * buflen(in):
2380  */
2381 static int
2382 mmddyyyyhhmiss (const DB_UTIME * utime, char *buf, int buflen)
2383 {
2384  DB_DATE date;
2385  DB_TIME time;
2386  const char fmt[] = "%m/%d/%Y %H:%M:%S";
2387 
2388  /* extract date & time from utime */
2389  db_utime_decode (utime, &date, &time);
2390 
2391  return db_strftime (buf, buflen, fmt, &date, &time);
2392 }
2393 
2394 /*
2395  * yyyymmddhhmissms () - print utime as 'yyyy-mm-dd:hh:mi:ss.ms'
2396  * return:
2397  * datetime(in):
2398  * buf(out):
2399  * buflen(in):
2400  */
2401 static int
2402 yyyymmddhhmissms (const DB_DATETIME * datetime, char *buf, int buflen)
2403 {
2404  int month, day, year;
2405  int hour, minute, second, millisecond;
2406  int retval;
2407 
2408  /* extract date & time from datetime */
2409  db_datetime_decode (datetime, &month, &day, &year, &hour, &minute, &second, &millisecond);
2410 
2411  /* "%Y-%m-%d:%H:%M:%S.MS"; */
2412  retval = sprintf (buf, "%d-%d-%d:%d:%d:%d.%d", year, month, day, hour, minute, second, millisecond);
2413 
2414  return retval;
2415 }
2416 
2417 
2418 /*
2419  * mmddyyyyhhmissms () - print utime as 'mm/dd/yyyy hh:mi:ss.ms'
2420  * return:
2421  * datetime(in):
2422  * buf(in):
2423  * buflen(in):
2424  */
2425 static int
2426 mmddyyyyhhmissms (const DB_DATETIME * datetime, char *buf, int buflen)
2427 {
2428  int month, day, year;
2429  int hour, minute, second, millisecond;
2430  int retval;
2431 
2432  /* extract date & time from datetime */
2433  db_datetime_decode (datetime, &month, &day, &year, &hour, &minute, &second, &millisecond);
2434 
2435  /* "%m/%d/%Y %H:%M:%S.MS"; */
2436  retval = sprintf (buf, "%d/%d/%d %d:%d:%d.%d", month, day, year, hour, minute, second, millisecond);
2437 
2438  return retval;
2439 }
2440 #endif
2441 
2442 #if defined (ENABLE_UNUSED_FUNCTION)
2443 /*
2444  * host_var_name () - manufacture a host variable name
2445  * return: a host variable name
2446  * custom_print(in): a custom_print member
2447  */
2448 static char *
2449 host_var_name (unsigned int custom_print)
2450 {
2451  return (char *) "?";
2452 }
2453 #endif
2454 
2455 /*
2456  * pt_table_compatible_node () - Returns compatible if node is non-subquery
2457  * and has matching spec id
2458  * return:
2459  * parser(in):
2460  * tree(in):
2461  * void_info(in/out):
2462  * continue_walk(in/out):
2463  */
2464 static PT_NODE *
2465 pt_table_compatible_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_info, int *continue_walk)
2466 {
2467  COMPATIBLE_INFO *info = (COMPATIBLE_INFO *) void_info;
2468 
2469  if (info && tree)
2470  {
2471  switch (tree->node_type)
2472  {
2473  case PT_SELECT:
2474  case PT_UNION:
2475  case PT_DIFFERENCE:
2476  case PT_INTERSECTION:
2477  info->compatible = NOT_COMPATIBLE;
2478  *continue_walk = PT_STOP_WALK;
2479  break;
2480 
2481  case PT_NAME:
2482  /* check ids match */
2483  if (tree->info.name.spec_id != info->spec_id)
2484  {
2485  info->compatible = NOT_COMPATIBLE;
2486  *continue_walk = PT_STOP_WALK;
2487  }
2488  break;
2489 
2490  case PT_EXPR:
2491  if (tree->info.expr.op == PT_INST_NUM || tree->info.expr.op == PT_ROWNUM || tree->info.expr.op == PT_LEVEL
2493  || tree->info.expr.op == PT_CONNECT_BY_ROOT || tree->info.expr.op == PT_QPRIOR
2494  || tree->info.expr.op == PT_SYS_CONNECT_BY_PATH)
2495  {
2496  info->compatible = NOT_COMPATIBLE;
2497  *continue_walk = PT_STOP_WALK;
2498  }
2499  break;
2500 
2501  default:
2502  break;
2503  }
2504  }
2505 
2506  return tree;
2507 }
2508 
2509 
2510 /*
2511  * pt_table_compatible () - Tests the compatibility of the given sql tree
2512  * with a given class specification
2513  * return:
2514  * parser(in):
2515  * node(in):
2516  * spec(in):
2517  */
2518 static int
2520 {
2521  COMPATIBLE_INFO info;
2523 
2524  info.spec_id = spec->info.spec.id;
2525 
2527 
2528  return info.compatible;
2529 }
2530 
2531 static PT_NODE *
2533 {
2534  PT_NODE *query, *spec, *temp;
2535 
2536  query = node;
2537  while (query
2538  && (query->node_type == PT_UNION || query->node_type == PT_INTERSECTION || query->node_type == PT_DIFFERENCE))
2539  {
2540  query = query->info.query.q.union_.arg1;
2541  }
2542 
2543  if (query)
2544  {
2545  spec = query->info.query.q.select.from;
2546  }
2547  if (query && spec)
2548  {
2549  /* recalculate referenced attributes */
2550  for (temp = spec; temp; temp = temp->next)
2551  {
2552  node = mq_set_references (parser, node, temp);
2553  }
2554  }
2555 
2556  return node;
2557 }
2558 
2559 /*
2560  * pt_split_access_if_instnum () - Make a two lists of predicates,
2561  * one "simply" compatible with the given table,
2562  * one containing any other constructs, one instnum predicates
2563  * return:
2564  * parser(in):
2565  * spec(in):
2566  * where(in/out):
2567  * access_part(out):
2568  * if_part(out):
2569  * instnum_part(out):
2570  */
2571 static void
2573  PT_NODE ** if_part, PT_NODE ** instnum_part)
2574 {
2575  PT_NODE *next;
2576  bool inst_num;
2577 
2578  *access_part = NULL;
2579  *if_part = NULL;
2580  *instnum_part = NULL;
2581 
2582  while (where)
2583  {
2584  next = where->next;
2585  where->next = NULL;
2586  if (pt_table_compatible (parser, where, spec) == ENTITY_COMPATIBLE)
2587  {
2588  where->next = *access_part;
2589  *access_part = where;
2590  }
2591  else
2592  {
2593  /* check for instnum_predicate */
2594  inst_num = false;
2595  (void) parser_walk_tree (parser, where, pt_check_instnum_pre, NULL, pt_check_instnum_post, &inst_num);
2596  if (inst_num)
2597  {
2598  where->next = *instnum_part;
2599  *instnum_part = where;
2600  }
2601  else
2602  {
2603  where->next = *if_part;
2604  *if_part = where;
2605  }
2606  }
2607  where = next;
2608  }
2609 }
2610 
2611 /*
2612  * pt_split_if_instnum () - Make a two lists of predicates, one containing
2613  * any other constructs (subqueries, other tables, etc.
2614  * except for instnum predicates),
2615  * one instnum predicates.
2616  * return:
2617  * parser(in):
2618  * where(in/out):
2619  * if_part(out):
2620  * instnum_part(out):
2621  */
2622 static void
2623 pt_split_if_instnum (PARSER_CONTEXT * parser, PT_NODE * where, PT_NODE ** if_part, PT_NODE ** instnum_part)
2624 {
2625  PT_NODE *next;
2626  bool inst_num;
2627 
2628  *if_part = NULL;
2629  *instnum_part = NULL;
2630 
2631  while (where)
2632  {
2633  next = where->next;
2634  where->next = NULL;
2635 
2636  /* check for instnum_predicate */
2637  inst_num = false;
2638  (void) parser_walk_tree (parser, where, pt_check_instnum_pre, NULL, pt_check_instnum_post, &inst_num);
2639  if (inst_num)
2640  {
2641  where->next = *instnum_part;
2642  *instnum_part = where;
2643  }
2644  else
2645  {
2646  where->next = *if_part;
2647  *if_part = where;
2648  }
2649  where = next;
2650  }
2651 }
2652 
2653 /*
2654  * pt_split_having_grbynum () - Make a two lists of predicates, one "simply"
2655  * having predicates, and one containing groupby_num() function
2656  * return:
2657  * parser(in):
2658  * having(in/out):
2659  * having_part(out):
2660  * grbynum_part(out):
2661  */
2662 static void
2663 pt_split_having_grbynum (PARSER_CONTEXT * parser, PT_NODE * having, PT_NODE ** having_part, PT_NODE ** grbynum_part)
2664 {
2665  PT_NODE *next;
2666  bool grbynum_flag;
2667 
2668  *having_part = NULL;
2669  *grbynum_part = NULL;
2670 
2671  while (having)
2672  {
2673  next = having->next;
2674  having->next = NULL;
2675 
2676  grbynum_flag = false;
2677  (void) parser_walk_tree (parser, having, pt_check_groupbynum_pre, NULL, pt_check_groupbynum_post, &grbynum_flag);
2678 
2679  if (grbynum_flag)
2680  {
2681  having->next = *grbynum_part;
2682  *grbynum_part = having;
2683  }
2684  else
2685  {
2686  having->next = *having_part;
2687  *having_part = having;
2688  }
2689 
2690  having = next;
2691  }
2692 }
2693 
2694 
2695 /*
2696  * pt_make_identity_offsets () - Create an attr_offset array that
2697  * has 0 for position 0, 1 for position 1, etc
2698  * return:
2699  * attr_list(in):
2700  */
2701 static int *
2703 {
2704  int *offsets;
2705  int num_attrs, i;
2706 
2707  num_attrs = pt_length_of_list (attr_list);
2708  if (num_attrs == 0)
2709  {
2710  return NULL;
2711  }
2712 
2713  offsets = (int *) malloc ((num_attrs + 1) * sizeof (int));
2714  if (offsets == NULL)
2715  {
2716  return NULL;
2717  }
2718 
2719  for (i = 0; i < num_attrs; i++)
2720  {
2721  offsets[i] = i;
2722  }
2723  offsets[i] = -1;
2724 
2725  return offsets;
2726 }
2727 
2728 
2729 /*
2730  * pt_split_attrs () - Split the attr_list into two lists without destroying
2731  * the original list
2732  * return:
2733  * parser(in):
2734  * table_info(in):
2735  * pred(in):
2736  * pred_attrs(out):
2737  * rest_attrs(out):
2738  * reserved_attrs(out):
2739  * pred_offsets(out):
2740  * rest_offsets(out):
2741  * reserved_offsets(out):
2742  *
2743  * Note :
2744  * Those attrs that are found in the pred are put on the pred_attrs list,
2745  * those attrs not found in the pred are put on the rest_attrs list.
2746  * There are special spec flags that activate reserved attributes, which are
2747  * handled differently compared with regular attributes.
2748  * For now only reserved names of record information and page information are
2749  * used.
2750  */
2751 static int
2753  PT_NODE ** rest_attrs, PT_NODE ** reserved_attrs, int **pred_offsets, int **rest_offsets,
2754  int **reserved_offsets)
2755 {
2756  PT_NODE *tmp = NULL, *pointer = NULL, *real_attrs = NULL;
2757  PT_NODE *pred_nodes = NULL;
2758  int cur_pred, cur_rest, cur_reserved, num_attrs, i;
2759  PT_NODE *attr_list = NULL;
2760  PT_NODE *node = NULL, *save_node = NULL, *save_next = NULL;
2761  PT_NODE *ref_node = NULL;
2762  bool has_reserved = false;
2763 
2764  pred_nodes = NULL; /* init */
2765  *pred_attrs = NULL;
2766  *rest_attrs = NULL;
2767  *pred_offsets = NULL;
2768  *rest_offsets = NULL;
2769  cur_pred = 0;
2770  cur_rest = 0;
2771  if (reserved_attrs != NULL)
2772  {
2773  *reserved_attrs = NULL;
2774  }
2775  if (reserved_offsets != NULL)
2776  {
2777  *reserved_offsets = NULL;
2778  }
2779  cur_reserved = 0;
2780 
2781  if (table_info->attribute_list == NULL)
2782  return NO_ERROR; /* nothing to do */
2783 
2784  num_attrs = pt_length_of_list (table_info->attribute_list);
2785  attr_list = table_info->attribute_list;
2786 
2787  has_reserved = PT_SHOULD_BIND_RESERVED_NAME (table_info->class_spec);
2788  if (has_reserved)
2789  {
2790  assert (reserved_attrs != NULL);
2791  assert (reserved_offsets != NULL);
2792  *reserved_offsets = (int *) malloc (num_attrs * sizeof (int));
2793  if (*reserved_offsets == NULL)
2794  {
2795  goto exit_on_error;
2796  }
2797  }
2798 
2799  if ((*pred_offsets = (int *) malloc (num_attrs * sizeof (int))) == NULL)
2800  {
2801  goto exit_on_error;
2802  }
2803 
2804  if ((*rest_offsets = (int *) malloc (num_attrs * sizeof (int))) == NULL)
2805  {
2806  goto exit_on_error;
2807  }
2808 
2809  if (pred)
2810  {
2811  /* mq_get_references() is destructive to the real set of referenced attrs, so we need to squirrel it away. */
2812  real_attrs = table_info->class_spec->info.spec.referenced_attrs;
2813  table_info->class_spec->info.spec.referenced_attrs = NULL;
2814 
2815  /* Traverse pred */
2816  for (node = pred; node; node = node->next)
2817  {
2818  save_node = node; /* save */
2819 
2820  CAST_POINTER_TO_NODE (node);
2821 
2822  if (node)
2823  {
2824  /* save and cut-off node link */
2825  save_next = node->next;
2826  node->next = NULL;
2827 
2828  ref_node = mq_get_references_helper (parser, node, table_info->class_spec, false);
2829  pred_nodes = parser_append_node (ref_node, pred_nodes);
2830 
2831  /* restore node link */
2832  node->next = save_next;
2833  }
2834 
2835  node = save_node; /* restore */
2836  } /* for (node = ...) */
2837 
2838  table_info->class_spec->info.spec.referenced_attrs = real_attrs;
2839  }
2840 
2841  tmp = attr_list;
2842  i = 0;
2843  while (tmp)
2844  {
2845  if (has_reserved && tmp->node_type == PT_NAME && tmp->info.name.meta_class == PT_RESERVED)
2846  {
2847  /* add to reserved */
2848  pointer = pt_point (parser, tmp);
2849  if (pointer == NULL)
2850  {
2851  goto exit_on_error;
2852  }
2853  *reserved_attrs = parser_append_node (pointer, *reserved_attrs);
2854  (*reserved_offsets)[cur_reserved++] = i;
2855  tmp = tmp->next;
2856  i++;
2857  continue;
2858  }
2859 
2860  pointer = pt_point (parser, tmp);
2861  if (pointer == NULL)
2862  {
2863  goto exit_on_error;
2864  }
2865 
2866  if (pt_find_attribute (parser, tmp, pred_nodes) != -1)
2867  {
2868  *pred_attrs = parser_append_node (pointer, *pred_attrs);
2869  (*pred_offsets)[cur_pred++] = i;
2870  }
2871  else
2872  {
2873  *rest_attrs = parser_append_node (pointer, *rest_attrs);
2874  (*rest_offsets)[cur_rest++] = i;
2875  }
2876  tmp = tmp->next;
2877  i++;
2878  }
2879 
2880  if (pred_nodes)
2881  {
2882  parser_free_tree (parser, pred_nodes);
2883  }
2884 
2885  return NO_ERROR;
2886 
2887 exit_on_error:
2888 
2889  parser_free_tree (parser, *pred_attrs);
2890  parser_free_tree (parser, *rest_attrs);
2891  if (reserved_attrs != NULL)
2892  {
2893  parser_free_tree (parser, *reserved_attrs);
2894  }
2895  if (*pred_offsets != NULL)
2896  {
2897  free_and_init (*pred_offsets);
2898  }
2899  if (*rest_offsets != NULL)
2900  {
2901  free_and_init (*rest_offsets);
2902  }
2903  if (reserved_offsets != NULL && *reserved_offsets != NULL)
2904  {
2905  free_and_init (*reserved_offsets);
2906  }
2907  if (pred_nodes)
2908  {
2909  parser_free_tree (parser, pred_nodes);
2910  }
2911 
2912  return ER_FAILED;
2913 }
2914 
2915 /*
2916  * pt_split_hash_attrs () - Split the attr_list into two lists without destroying
2917  * the original list
2918  * return:
2919  * parser(in):
2920  * table_info(in):
2921  * pred(in):
2922  * build_attrs(out):
2923  * probe_attrs(out):
2924  *
2925  * Note :
2926  */
2927 static int
2929  PT_NODE ** probe_attrs)
2930 {
2931  PT_NODE *node = NULL, *save_node = NULL, *save_next = NULL;
2932  PT_NODE *arg1 = NULL, *arg2 = NULL;
2933 
2934  assert (build_attrs != NULL && *build_attrs == NULL);
2935  assert (probe_attrs != NULL && *probe_attrs == NULL);
2936  *build_attrs = NULL;
2937  *probe_attrs = NULL;
2938 
2939  if (table_info->attribute_list == NULL)
2940  {
2941  return NO_ERROR; /* nothing to do */
2942  }
2943 
2944  if (pred)
2945  {
2946  /* Traverse pred */
2947  for (node = pred; node; node = node->next)
2948  {
2949  save_node = node; /* save */
2950 
2951  CAST_POINTER_TO_NODE (node);
2952 
2953  if (!pt_is_expr_node (node))
2954  {
2955  continue;
2956  }
2957  else
2958  {
2959  /* save and cut-off node link */
2960  save_next = node->next;
2961  node->next = NULL;
2962 
2963  arg1 = node->info.expr.arg1;
2964  arg2 = node->info.expr.arg2;
2965  assert (arg1 != NULL && arg2 != NULL);
2966 
2967  UINTPTR spec_id[2], spec_id2[2];
2968  spec_id[0] = spec_id2[0] = table_info->spec_id;
2969  spec_id[1] = spec_id2[1] = 0;
2970  parser_walk_tree (parser, arg1, pt_is_spec_node, &spec_id, NULL, NULL);
2971  parser_walk_tree (parser, arg2, pt_is_spec_node, &spec_id2, NULL, NULL);
2972 
2973  if (spec_id[1] == spec_id2[1])
2974  {
2975  continue;
2976  }
2977 
2978  if (spec_id[1])
2979  {
2980  /* arg1 is current spec */
2981  *build_attrs = parser_append_node (parser_copy_tree (parser, arg1), *build_attrs);
2982  *probe_attrs = parser_append_node (parser_copy_tree (parser, arg2), *probe_attrs);
2983  }
2984  else
2985  {
2986  /* arg2 is current spec */
2987  *build_attrs = parser_append_node (parser_copy_tree (parser, arg2), *build_attrs);
2988  *probe_attrs = parser_append_node (parser_copy_tree (parser, arg1), *probe_attrs);
2989  }
2990 
2991  /* restore node link */
2992  node->next = save_next;
2993  }
2994 
2995  node = save_node; /* restore */
2996  } /* for (node = ...) */
2997  }
2998 
2999  return NO_ERROR;
3000 
3001 exit_on_error:
3002 
3003  parser_free_tree (parser, *probe_attrs);
3004  parser_free_tree (parser, *build_attrs);
3005 
3006  return ER_FAILED;
3007 }
3008 
3009 /*
3010  * pt_split_hash_attrs_for_HQ () - Split the attr_list into two lists without destroying
3011  * the original list for HQ
3012  * return:
3013  * parser(in):
3014  * pred(in):
3015  * build_attrs(out):
3016  * probe_attrs(out):
3017  *
3018  * Note :
3019  * is_PRIOR | NAME_without_prior | characteristic
3020  * O | O | unhashable
3021  * O | X | probe attr
3022  * X | O | build attr
3023  * X | X | constant (can be probe or build attr)
3024  */
3025 static int
3026 pt_split_hash_attrs_for_HQ (PARSER_CONTEXT * parser, PT_NODE * pred, PT_NODE ** build_attrs, PT_NODE ** probe_attrs,
3027  PT_NODE ** pred_without_HQ)
3028 {
3029  PT_NODE *node = NULL, *save_node = NULL, *save_next = NULL;
3030  PT_NODE *arg1 = NULL, *arg2 = NULL;
3031 
3032  assert (build_attrs != NULL && *build_attrs == NULL);
3033  assert (probe_attrs != NULL && *probe_attrs == NULL);
3034  *build_attrs = NULL;
3035  *probe_attrs = NULL;
3036  bool is_hierarchical_op;
3037 
3038  if (pred)
3039  {
3040  /* Traverse pred */
3041  for (node = pred; node; node = node->next)
3042  {
3043  /* save and cut-off node link */
3044  save_next = node->next;
3045  node->next = NULL;
3046 
3047  /* find Reserved words for HQ */
3048  is_hierarchical_op = false;
3049  parser_walk_tree (parser, node, pt_find_hq_op_except_prior, &is_hierarchical_op, NULL, NULL);;
3050 
3051  /* Predicates containing HQ are not hashable because they have to be evaluated in the HQ proc. */
3052  /* Reserved words for HQ is not allowed (LEVEL, CONNECT_BY_ISLEAF....) */
3053  if (!is_hierarchical_op)
3054  {
3055  *pred_without_HQ = parser_append_node (parser_copy_tree (parser, node), *pred_without_HQ);
3056  }
3057 
3058  /* restore node link */
3059  node->next = save_next;
3060  }
3061  }
3062 
3063  if (*pred_without_HQ)
3064  {
3065  /* Traverse pred */
3066  for (node = *pred_without_HQ; node; node = node->next)
3067  {
3068  save_node = node; /* save */
3069 
3070  CAST_POINTER_TO_NODE (node);
3071 
3072  if (!PT_IS_EXPR_NODE_WITH_OPERATOR (node, PT_EQ) || node->or_next)
3073  {
3074  /* HASH LIST SCAN for HQ is possible under the following conditions */
3075  /* 1. CNF predicate (node is NOT PT_AND, PT_OR) */
3076  /* 2. only equal operation */
3077  /* 3. predicate without OR (or_next is null) */
3078  /* 4. symmetric predicate (having PRIOR, probe. having NAME, build. Having these two makes it unhashable) */
3079  /* 5. subquery is not allowed in syntax check */
3080  /* 6. Reserved words for HQ is not allowed (LEVEL, CONNECT_BY_ISLEAF....) */
3081  continue;
3082  }
3083  else
3084  {
3085  /* save and cut-off node link */
3086  save_next = node->next;
3087  node->next = NULL;
3088 
3089  arg1 = node->info.expr.arg1;
3090  arg2 = node->info.expr.arg2;
3091  assert (arg1 != NULL && arg2 != NULL);
3092 
3093  // *INDENT-OFF*
3094  HASHABLE hashable_arg1, hashable_arg2;
3095  hashable_arg1 = hashable_arg2 = {false, false};
3096  HASH_ATTR hash_arg1, hash_arg2;
3097  // *INDENT-ON*
3098 
3099  parser_walk_tree (parser, arg1, pt_check_hashable, &hashable_arg1, NULL, NULL);
3100  parser_walk_tree (parser, arg2, pt_check_hashable, &hashable_arg2, NULL, NULL);
3101 
3102  CHECK_HASH_ATTR (hashable_arg1, hash_arg1);
3103  CHECK_HASH_ATTR (hashable_arg2, hash_arg2);
3104 
3105  if ((hash_arg1 == PROBE && hash_arg2 == BUILD) ||
3106  (hash_arg1 == PROBE && hash_arg2 == CONSTANT) || (hash_arg1 == CONSTANT && hash_arg2 == BUILD))
3107  {
3108  /* arg1 is probe attr and arg2 is build attr */
3109  *build_attrs = parser_append_node (parser_copy_tree (parser, arg2), *build_attrs);
3110  *probe_attrs = parser_append_node (parser_copy_tree (parser, arg1), *probe_attrs);
3111  }
3112  else if ((hash_arg1 == BUILD && hash_arg2 == PROBE) ||
3113  (hash_arg1 == BUILD && hash_arg2 == CONSTANT) || (hash_arg1 == CONSTANT && hash_arg2 == PROBE))
3114  {
3115  /* arg1 is build attr and arg2 is probe attr */
3116  *build_attrs = parser_append_node (parser_copy_tree (parser, arg1), *build_attrs);
3117  *probe_attrs = parser_append_node (parser_copy_tree (parser, arg2), *probe_attrs);
3118  }
3119  else
3120  {
3121  /* unhashable predicate */
3122  }
3123 
3124  /* restore node link */
3125  node->next = save_next;
3126  }
3127 
3128  node = save_node; /* restore */
3129  } /* for (node = ...) */
3130  }
3131 
3132  return NO_ERROR;
3133 
3134 exit_on_error:
3135 
3136  parser_free_tree (parser, *probe_attrs);
3137  parser_free_tree (parser, *build_attrs);
3138  parser_free_tree (parser, *pred_without_HQ);
3139 
3140  return ER_FAILED;
3141 }
3142 
3143 /*
3144  * pt_to_index_attrs () - Those attrs that are found in the key-range pred
3145  * and key-filter pred are put on the pred_attrs list
3146  * return:
3147  * parser(in):
3148  * table_info(in):
3149  * index_pred(in):
3150  * key_filter_pred(in):
3151  * pred_attrs(out):
3152  * pred_offsets(out):
3153  */
3154 static int
3156  PT_NODE * key_filter_pred, PT_NODE ** pred_attrs, int **pred_offsets)
3157 {
3158  PT_NODE *tmp, *pointer, *real_attrs;
3159  PT_NODE *pred_nodes;
3160  int cur_pred, num_attrs, i;
3161  PT_NODE *attr_list = table_info->attribute_list;
3162  PT_NODE **term_exprs;
3163  int nterms;
3164  PT_NODE *node, *save_node, *save_next, *ref_node;
3165 
3166  pred_nodes = NULL; /* init */
3167  *pred_attrs = NULL;
3168  *pred_offsets = NULL;
3169  cur_pred = 0;
3170 
3171  if (!attr_list)
3172  return 1; /* nothing to do */
3173 
3174  num_attrs = pt_length_of_list (attr_list);
3175  *pred_offsets = (int *) malloc (num_attrs * sizeof (int));
3176  if (*pred_offsets == NULL)
3177  {
3178  goto exit_on_error;
3179  }
3180 
3181  /* mq_get_references() is destructive to the real set of referenced attrs, so we need to squirrel it away. */
3182  real_attrs = table_info->class_spec->info.spec.referenced_attrs;
3183  table_info->class_spec->info.spec.referenced_attrs = NULL;
3184 
3186  {
3187  nterms = qo_xasl_get_num_terms (index_pred);
3188  term_exprs = qo_xasl_get_terms (index_pred);
3189 
3190  /* Traverse key-range pred */
3191  for (i = 0; i < nterms; i++)
3192  {
3193  save_node = node = term_exprs[i];
3194 
3195  CAST_POINTER_TO_NODE (node);
3196 
3197  if (node)
3198  {
3199  /* save and cut-off node link */
3200  save_next = node->next;
3201  node->next = NULL;
3202 
3203  /* exclude path entities */
3204  ref_node = mq_get_references_helper (parser, node, table_info->class_spec, false);
3205 
3206  assert (ref_node != NULL);
3207 
3208  /* need to check zero-length empty string */
3209  if (ref_node != NULL
3210  && (ref_node->type_enum == PT_TYPE_VARCHAR || ref_node->type_enum == PT_TYPE_VARNCHAR
3211  || ref_node->type_enum == PT_TYPE_VARBIT))
3212  {
3213  pred_nodes = parser_append_node (ref_node, pred_nodes);
3214  }
3215 
3216  /* restore node link */
3217  node->next = save_next;
3218  }
3219 
3220  term_exprs[i] = save_node; /* restore */
3221  } /* for (i = 0; ...) */
3222  }
3223 
3224  /* Traverse key-filter pred */
3225  for (node = key_filter_pred; node; node = node->next)
3226  {
3227  save_node = node; /* save */
3228 
3229  CAST_POINTER_TO_NODE (node);
3230 
3231  if (node)
3232  {
3233  /* save and cut-off node link */
3234  save_next = node->next;
3235  node->next = NULL;
3236 
3237  /* exclude path entities */
3238  ref_node = mq_get_references_helper (parser, node, table_info->class_spec, false);
3239  pred_nodes = parser_append_node (ref_node, pred_nodes);
3240 
3241  /* restore node link */
3242  node->next = save_next;
3243  }
3244 
3245  node = save_node; /* restore */
3246  } /* for (node = ...) */
3247 
3248  table_info->class_spec->info.spec.referenced_attrs = real_attrs;
3249 
3250  if (!pred_nodes) /* there is not key-filter pred */
3251  {
3252  return 1;
3253  }
3254 
3255  tmp = attr_list;
3256  i = 0;
3257  while (tmp)
3258  {
3259  if (pt_find_attribute (parser, tmp, pred_nodes) != -1)
3260  {
3261  if ((pointer = pt_point (parser, tmp)) == NULL)
3262  {
3263  goto exit_on_error;
3264  }
3265  *pred_attrs = parser_append_node (pointer, *pred_attrs);
3266  (*pred_offsets)[cur_pred++] = i;
3267  }
3268  tmp = tmp->next;
3269  i++;
3270  }
3271 
3272  if (pred_nodes)
3273  {
3274  parser_free_tree (parser, pred_nodes);
3275  }
3276 
3277  return 1;
3278 
3279 exit_on_error:
3280 
3281  parser_free_tree (parser, *pred_attrs);
3282  free_and_init (*pred_offsets);
3283  if (pred_nodes)
3284  {
3285  parser_free_tree (parser, pred_nodes);
3286  }
3287  return 0;
3288 }
3289 
3290 
3291 /*
3292  * pt_flush_classes () - Flushes each class encountered
3293  * return:
3294  * parser(in):
3295  * node(in):
3296  * void_arg(in):
3297  * continue_walk(in/out):
3298  */
3299 PT_NODE *
3300 pt_flush_classes (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
3301 {
3302  PT_NODE *class_;
3303  int isvirt;
3304  MOP clsmop = NULL;
3305  SM_CLASS *smcls = NULL;
3306 
3307  /* If parser->dont_flush is asserted, skip the flushing. */
3308  if (node->node_type == PT_SPEC)
3309  {
3310  for (class_ = node->info.spec.flat_entity_list; class_; class_ = class_->next)
3311  {
3312  clsmop = class_->info.name.db_object;
3313  if (clsmop == NULL)
3314  {
3315  assert (false);
3316  PT_ERROR (parser, node, "Generic error");
3317  }
3318  /* if class object is not dirty and doesn't contain any dirty instances, do not flush the class and its
3319  * instances */
3320  if (WS_ISDIRTY (class_->info.name.db_object) || ws_has_dirty_objects (class_->info.name.db_object, &isvirt))
3321  {
3322  if (sm_flush_objects (class_->info.name.db_object) != NO_ERROR)
3323  {
3324  PT_ERRORc (parser, class_, er_msg ());
3325  }
3326  }
3327  /* Also test if we need to flush partitions of each class */
3328  if (locator_is_class (clsmop, DB_FETCH_READ) <= 0)
3329  {
3330  continue;
3331  }
3332  if (au_fetch_class_force (clsmop, &smcls, AU_FETCH_READ) != NO_ERROR)
3333  {
3334  PT_ERRORc (parser, class_, er_msg ());
3335  }
3336  if (smcls != NULL && smcls->partition != NULL)
3337  {
3338  /* flush all partitions */
3339  DB_OBJLIST *user = NULL;
3340 
3341  for (user = smcls->users; user != NULL; user = user->next)
3342  {
3343  if (WS_ISDIRTY (user->op) || ws_has_dirty_objects (user->op, &isvirt))
3344  {
3345  if (sm_flush_objects (user->op) != NO_ERROR)
3346  {
3347  PT_ERRORc (parser, class_, er_msg ());
3348  }
3349  }
3350  }
3351  }
3352  }
3353  }
3354 
3355  return node;
3356 }
3357 
3358 /*
3359  * pt_set_is_system_generated_stmt () -
3360  * return:
3361  * parser(in):
3362  * tree(in):
3363  * void_arg(in):
3364  * continue_walk(in):
3365  */
3366 static PT_NODE *
3367 pt_set_is_system_generated_stmt (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk)
3368 {
3369  if (PT_IS_QUERY_NODE_TYPE (tree->node_type))
3370  {
3371  bool is_system_generated_stmt;
3372 
3373  is_system_generated_stmt = *(bool *) void_arg;
3374  tree->flag.is_system_generated_stmt = is_system_generated_stmt;
3375  }
3376 
3377  return tree;
3378 }
3379 
3380 /*
3381  * pt_flush_class_and_null_xasl () - Flushes each class encountered
3382  * Partition pruning is applied to PT_SELECT nodes
3383  * return:
3384  * parser(in):
3385  * tree(in):
3386  * void_arg(in):
3387  * continue_walk(in):
3388  */
3389 static PT_NODE *
3390 pt_flush_class_and_null_xasl (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk)
3391 {
3392  if (ws_has_updated ())
3393  {
3394  tree = pt_flush_classes (parser, tree, void_arg, continue_walk);
3395  }
3396 
3397  if (PT_IS_QUERY_NODE_TYPE (tree->node_type))
3398  {
3399  tree->info.query.xasl = NULL;
3400  }
3401  else if (tree->node_type == PT_DATA_TYPE)
3402  {
3403  PT_NODE *entity;
3404 
3405  /* guard against proxies & views not correctly tagged in data type nodes */
3406  entity = tree->info.data_type.entity;
3407  if (entity)
3408  {
3409  if (entity->info.name.meta_class != PT_META_CLASS && db_is_vclass (entity->info.name.db_object) > 0
3410  && !tree->info.data_type.virt_object)
3411  {
3412  tree->info.data_type.virt_object = entity->info.name.db_object;
3413  }
3414  }
3415  }
3416 
3417  return tree;
3418 }
3419 
3420 /*
3421  * pt_null_xasl () - Set all the query node's xasl to NULL
3422  * return:
3423  * parser(in):
3424  * tree(in):
3425  * void_arg(in):
3426  * continue_walk(in):
3427  */
3428 static PT_NODE *
3429 pt_null_xasl (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk)
3430 {
3431  if (PT_IS_QUERY_NODE_TYPE (tree->node_type))
3432  {
3433  tree->info.query.xasl = NULL;
3434  }
3435 
3436  return tree;
3437 }
3438 
3439 /*
3440  * pt_is_spec_node () - return node with the same spec id
3441  * return:
3442  * parser(in):
3443  * tree(in):
3444  * void_arg(in):
3445  * continue_walk(in):
3446  */
3447 static PT_NODE *
3448 pt_is_spec_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk)
3449 {
3450  if (pt_is_name_node (tree))
3451  {
3452  UINTPTR *spec_id = (UINTPTR *) void_arg;
3453  if (tree->info.name.spec_id == spec_id[0])
3454  {
3455  *continue_walk = PT_STOP_WALK;
3456  spec_id[1] = 1;
3457  }
3458  }
3459  return tree;
3460 }
3461 
3462 /*
3463  * pt_check_hashable () - check whether hashable or not
3464  * return:
3465  * parser(in):
3466  * tree(in):
3467  * void_arg(in):
3468  * continue_walk(in):
3469  */
3470 static PT_NODE *
3471 pt_check_hashable (PARSER_CONTEXT * parser, PT_NODE * tree, void *void_arg, int *continue_walk)
3472 {
3473  *continue_walk = PT_CONTINUE_WALK;
3474  HASHABLE *hashable = (HASHABLE *) void_arg;
3475 
3477  {
3478  hashable->is_PRIOR = true;
3479  *continue_walk = PT_LIST_WALK;
3480  }
3481  else if (pt_is_name_node (tree))
3482  {
3483  hashable->is_NAME_without_prior = true;
3484  }
3485 
3486  return tree;
3487 }
3488 
3489 /*
3490  * pt_find_hq_op_except_prior() - Check expression tree for hierarchical op except PRIOR
3491  * return:
3492  * parser(in):
3493  * node(in):
3494  * arg(in/out):
3495  * continue_walk(in):
3496  */
3497 static PT_NODE *
3498 pt_find_hq_op_except_prior (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
3499 {
3500  bool *is_hierarchical_op = (bool *) arg;
3501 
3502  if (node->node_type != PT_EXPR)
3503  {
3504  *continue_walk = PT_STOP_WALK;
3505  }
3506  else
3507  {
3509  {
3510  *is_hierarchical_op = true;
3511  *continue_walk = PT_STOP_WALK;
3512  }
3513  }
3514 
3515  return node;
3516 }
3517 
3518 /*
3519  * pt_is_subquery () -
3520  * return: true if symbols comes from a subquery of a UNION-type thing
3521  * node(in):
3522  */
3523 static int
3525 {
3526  PT_MISC_TYPE subquery_type = node->info.query.is_subquery;
3527 
3528  return (subquery_type != 0);
3529 }
3530 
3531 /*
3532  * pt_table_info_alloc () - Allocates and inits an TABLE_INFO structure
3533  * from temporary memory
3534  * return:
3535  * pt_table_info_alloc(in):
3536  */
3537 static TABLE_INFO *
3539 {
3541 
3542  table_info = (TABLE_INFO *) pt_alloc_packing_buf (sizeof (TABLE_INFO));
3543 
3544  if (table_info)
3545  {
3546  table_info->next = NULL;
3547  table_info->class_spec = NULL;
3548  table_info->exposed = NULL;
3549  table_info->spec_id = 0;
3550  table_info->attribute_list = NULL;
3551  table_info->value_list = NULL;
3552  table_info->is_fetch = 0;
3553  }
3554 
3555  return table_info;
3556 }
3557 
3558 /*
3559  * pt_symbol_info_alloc () - Allocates and inits an SYMBOL_INFO structure
3560  * from temporary memory
3561  * return:
3562  */
3563 static SYMBOL_INFO *
3565 {
3566  SYMBOL_INFO *symbols;
3567 
3568  symbols = (SYMBOL_INFO *) pt_alloc_packing_buf (sizeof (SYMBOL_INFO));
3569 
3570  if (symbols)
3571  {
3572  symbols->stack = NULL;
3573  symbols->table_info = NULL;
3574  symbols->current_class = NULL;
3575  symbols->cache_attrinfo = NULL;
3576  symbols->current_listfile = NULL;
3577  symbols->listfile_unbox = UNBOX_AS_VALUE;
3578  symbols->listfile_value_list = NULL;
3579  symbols->reserved_values = NULL;
3580 
3581  /* only used for server inserts and updates */
3582  symbols->listfile_attr_offset = 0;
3583 
3584  symbols->query_node = NULL;
3585  }
3586 
3587  return symbols;
3588 }
3589 
3590 
3591 /*
3592  * pt_is_single_tuple () -
3593  * return: true if select can be determined to return exactly one tuple
3594  * This means an aggregate function was used with no group_by clause
3595  * parser(in):
3596  * select_node(in):
3597  */
3598 int
3600 {
3601  if (select_node->info.query.q.select.group_by != NULL)
3602  {
3603  return false;
3604  }
3605 
3606  return pt_has_aggregate (parser, select_node);
3607 }
3608 
3609 
3610 /*
3611  * pt_filter_pseudo_specs () - Returns list of specs to participate
3612  * in a join cross product
3613  * return:
3614  * parser(in):
3615  * spec(in/out):
3616  */
3617 static PT_NODE *
3619 {
3620  PT_NODE **last, *temp1, *temp2;
3621  PT_FLAT_SPEC_INFO info;
3622 
3623  if (spec)
3624  {
3625  last = &spec;
3626  temp2 = *last;
3627  while (temp2)
3628  {
3629  if ((temp1 = temp2->info.spec.derived_table) && temp1->node_type == PT_VALUE
3630  && temp1->type_enum == PT_TYPE_NULL)
3631  {
3632  /* fix this derived table so that it is generatable */
3633  temp1->type_enum = PT_TYPE_SET;
3634  temp1->info.value.db_value_is_initialized = 0;
3635  temp1->info.value.data_value.set = NULL;
3637  }
3638 
3640  {
3641  /* remove it */
3642  *last = temp2->next;
3643  }
3644  else
3645  {
3646  /* keep it */
3647  last = &temp2->next;
3648  }
3649  temp2 = *last;
3650  }
3651  }
3652 
3653  if (!spec)
3654  {
3655  spec = parser_new_node (parser, PT_SPEC);
3656  if (spec == NULL)
3657  {
3658  PT_INTERNAL_ERROR (parser, "allocate new node");
3659  return NULL;
3660  }
3661 
3662  spec->info.spec.id = (UINTPTR) spec;
3663  spec->info.spec.only_all = PT_ONLY;
3664  spec->info.spec.meta_class = PT_CLASS;
3665  spec->info.spec.entity_name = pt_name (parser, "dual");
3666  if (spec->info.spec.entity_name == NULL)
3667  {
3668  parser_free_node (parser, spec);
3669  return NULL;
3670  }
3671 
3672  info.spec_parent = NULL;
3673  info.for_update = false;
3674  spec = parser_walk_tree (parser, spec, pt_flat_spec_pre, &info, pt_continue_walk, NULL);
3675  }
3676  return spec;
3677 }
3678 
3679 /*
3680  * pt_to_method_arglist () - converts a parse expression tree list of
3681  * method call arguments to method argument array
3682  * return: A NULL on error occurred
3683  * parser(in):
3684  * target(in):
3685  * node_list(in): should be parse name nodes
3686  * subquery_as_attr_list(in):
3687  */
3688 static int *
3689 pt_to_method_arglist (PARSER_CONTEXT * parser, PT_NODE * target, PT_NODE * node_list, PT_NODE * subquery_as_attr_list)
3690 {
3691  int *arg_list = NULL;
3692  int i = 1;
3693  int num_args = pt_length_of_list (node_list) + 1;
3694  PT_NODE *node;
3695 
3696  arg_list = regu_int_array_alloc (num_args);
3697  if (!arg_list)
3698  {
3699  return NULL;
3700  }
3701 
3702  if (target != NULL)
3703  {
3704  /* the method call target is the first element in the array */
3705  arg_list[0] = pt_find_attribute (parser, target, subquery_as_attr_list);
3706  if (arg_list[0] == -1)
3707  {
3708  return NULL;
3709  }
3710  }
3711  else
3712  {
3713  i = 0;
3714  }
3715 
3716  for (node = node_list; node != NULL; node = node->next)
3717  {
3718  arg_list[i] = pt_find_attribute (parser, node, subquery_as_attr_list);
3719  if (arg_list[i] == -1)
3720  {
3721  return NULL;
3722  }
3723  i++;
3724  }
3725 
3726  return arg_list;
3727 }
3728 
3729 
3730 /*
3731  * pt_to_method_sig_list () - converts a parse expression tree list of
3732  * method calls to method signature list
3733  * return: A NULL return indicates a (memory) error occurred
3734  * parser(in):
3735  * node_list(in): should be parse method nodes
3736  * subquery_as_attr_list(in):
3737  */
3738 static METHOD_SIG_LIST *
3739 pt_to_method_sig_list (PARSER_CONTEXT * parser, PT_NODE * node_list, PT_NODE * subquery_as_attr_list)
3740 {
3741  METHOD_SIG_LIST *sig_list = NULL;
3742  METHOD_SIG **tail = NULL;
3743  PT_NODE *node;
3744 
3745  regu_alloc (sig_list);
3746  if (!sig_list)
3747  {
3748  return NULL;
3749  }
3750 
3751  tail = &(sig_list->method_sig);
3752 
3753 
3754  for (node = node_list; node != NULL; node = node->next)
3755  {
3756  regu_alloc (*tail);
3757 
3758  if (*tail && node->node_type == PT_METHOD_CALL && node->info.method_call.method_name)
3759  {
3760  (sig_list->num_methods)++;
3761 
3762  (*tail)->method_name = (char *) node->info.method_call.method_name->info.name.original;
3763 
3765  {
3766  (*tail)->class_name = NULL;
3767  }
3768  else
3769  {
3771  /* beware of virtual classes */
3772  if (dt->info.data_type.virt_object)
3773  {
3774  (*tail)->class_name = (char *) db_get_class_name (dt->info.data_type.virt_object);
3775  }
3776  else
3777  {
3778  (*tail)->class_name = (char *) dt->info.data_type.entity->info.name.original;
3779  }
3780  }
3781 
3782  (*tail)->method_type = ((node->info.method_call.class_or_inst == PT_IS_CLASS_MTHD)
3784 
3785  /* num_method_args does not include the target by convention */
3786  (*tail)->num_method_args = pt_length_of_list (node->info.method_call.arg_list);
3787  (*tail)->method_arg_pos =
3789  subquery_as_attr_list);
3790 
3791  tail = &(*tail)->next;
3792  }
3793  else
3794  {
3795  /* something failed */
3796  sig_list = NULL;
3797  break;
3798  }
3799  }
3800 
3801  return sig_list;
3802 }
3803 
3804 /*
3805  * pt_make_val_list () - Makes a val list with a DB_VALUE place holder
3806  * for every attribute on an attribute list
3807  * return:
3808  * attribute_list(in):
3809  */
3810 static VAL_LIST *
3812 {
3813  VAL_LIST *value_list = NULL;
3814  QPROC_DB_VALUE_LIST dbval_list;
3815  QPROC_DB_VALUE_LIST *dbval_list_tail;
3816  PT_NODE *attribute;
3817 
3818  regu_alloc (value_list);
3819  if (value_list == NULL)
3820  {
3821  return NULL;
3822  }
3823 
3824  value_list->val_cnt = 0;
3825  value_list->valp = NULL;
3826  dbval_list_tail = &value_list->valp;
3827 
3828  for (attribute = attribute_list; attribute != NULL; attribute = attribute->next)
3829  {
3830  // init regu
3831  regu_alloc (dbval_list);
3832  regu_alloc (dbval_list->val);
3833  // init value with expected type
3834  pt_data_type_init_value (attribute, dbval_list->val);
3835  dbval_list->dom = pt_xasl_node_to_domain (parser, attribute);
3836 
3837  value_list->val_cnt++;
3838  (*dbval_list_tail) = dbval_list;
3839  dbval_list_tail = &dbval_list->next;
3840  dbval_list->next = NULL;
3841  }
3842 
3843  return value_list;
3844 }
3845 
3846 
3847 /*
3848  * pt_clone_val_list () - Makes a val list with a DB_VALUE place holder
3849  * for every attribute on an attribute list
3850  * return:
3851  * parser(in):
3852  * attribute_list(in):
3853  */
3854 static VAL_LIST *
3856 {
3857  VAL_LIST *value_list = NULL;
3858  QPROC_DB_VALUE_LIST dbval_list;
3859  QPROC_DB_VALUE_LIST *dbval_list_tail;
3860  PT_NODE *attribute;
3861  REGU_VARIABLE *regu = NULL;
3862 
3863  regu_alloc (value_list);
3864  if (value_list == NULL)
3865  {
3866  return NULL;
3867  }
3868 
3869  value_list->val_cnt = 0;
3870  value_list->valp = NULL;
3871  dbval_list_tail = &value_list->valp;
3872 
3873  for (attribute = attribute_list; attribute != NULL; attribute = attribute->next)
3874  {
3875  regu_alloc (dbval_list);
3876  regu = pt_attribute_to_regu (parser, attribute);
3877  if (dbval_list && regu)
3878  {
3879  dbval_list->val = pt_regu_to_dbvalue (parser, regu);
3880  dbval_list->dom = regu->domain;
3881 
3882  value_list->val_cnt++;
3883  (*dbval_list_tail) = dbval_list;
3884  dbval_list_tail = &dbval_list->next;
3885  dbval_list->next = NULL;
3886  }
3887  else
3888  {
3889  return NULL;
3890  }
3891  }
3892 
3893  return value_list;
3894 }
3895 
3896 
3897 /*
3898  * pt_find_table_info () - Finds the table_info associated with an exposed name
3899  * return:
3900  * spec_id(in):
3901  * exposed_list(in):
3902  */
3903 static TABLE_INFO *
3904 pt_find_table_info (UINTPTR spec_id, TABLE_INFO * exposed_list)
3905 {
3907 
3908  table_info = exposed_list;
3909 
3910  /* look down list until name matches, or NULL reached */
3911  while (table_info && table_info->spec_id != spec_id)
3912  {
3913  table_info = table_info->next;
3914  }
3915 
3916  return table_info;
3917 }
3918 
3919 /*
3920  * pt_is_hash_agg_eligible () - determine if query is eligible for hash
3921  * aggregate evaluation
3922  * return: tree node
3923  * parser(in): parser context
3924  * tree(in): tree node to check for eligibility
3925  * arg(in/out): pointer to int, eligibility
3926  * continue_walk(in/out): continue walk
3927  */
3928 static PT_NODE *
3929 pt_is_hash_agg_eligible (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
3930 {
3931  int *eligible = (int *) arg;
3932 
3933  if (tree && eligible && pt_is_aggregate_function (parser, tree))
3934  {
3940  {
3941  *eligible = 0;
3942  *continue_walk = PT_STOP_WALK;
3943  }
3944  }
3945 
3946  return tree;
3947 }
3948 
3949 /*
3950  * pt_to_aggregate_node () - test for aggregate function nodes,
3951  * convert them to aggregate_list_nodes
3952  * return:
3953  * parser(in):
3954  * tree(in):
3955  * arg(in/out):
3956  * continue_walk(in/out):
3957  */
3958 static PT_NODE *
3959 pt_to_aggregate_node (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
3960 {
3961  bool is_agg = 0;
3962  REGU_VARIABLE *regu = NULL;
3963  REGU_VARIABLE *percentile_regu = NULL;
3964  AGGREGATE_TYPE *aggregate_list;
3965  AGGREGATE_INFO *info = (AGGREGATE_INFO *) arg;
3966  VAL_LIST *value_list;
3967  MOP classop;
3968  PT_NODE *group_concat_sep_node_save = NULL;
3969  PT_NODE *pointer = NULL;
3970  PT_NODE *pt_val = NULL;
3971  PT_NODE *percentile = NULL;
3972 
3973  // it contains a list of positions
3974  REGU_VARIABLE_LIST regu_position_list = NULL;
3975  // it contains a list of constants, which will be used for the operands
3976  REGU_VARIABLE_LIST regu_constant_list = NULL;
3977 
3978  REGU_VARIABLE_LIST scan_regu_constant_list = NULL;
3979  int error_code = NO_ERROR;
3980 
3981  *continue_walk = PT_CONTINUE_WALK;
3982 
3983  is_agg = pt_is_aggregate_function (parser, tree);
3984  if (is_agg)
3985  {
3986  FUNC_TYPE code = tree->info.function.function_type;
3987 
3988  if (code == PT_GROUPBY_NUM)
3989  {
3990  regu_alloc (aggregate_list);
3991  if (aggregate_list == NULL)
3992  {
3993  PT_ERROR (parser, tree,
3996  return tree;
3997  }
3998  aggregate_list->next = info->head_list;
3999  aggregate_list->option = Q_ALL;
4000  aggregate_list->domain = &tp_Integer_domain;
4001  if (info->grbynum_valp)
4002  {
4003  if (!(*(info->grbynum_valp)))
4004  {
4005  regu_alloc (*(info->grbynum_valp));
4007  }
4008  aggregate_list->accumulator.value = *(info->grbynum_valp);
4009  }
4010  aggregate_list->function = code;
4011  aggregate_list->opr_dbtype = DB_TYPE_NULL;
4012  }
4013  else
4014  {
4015  regu_alloc (aggregate_list);
4016  if (aggregate_list == NULL)
4017  {
4020  return tree;
4021  }
4022  if (aggregate_list->accumulator.value == NULL || aggregate_list->accumulator.value2 == NULL
4023  || aggregate_list->list_id == NULL)
4024  {
4027  return tree;
4028  }
4029  aggregate_list->next = info->head_list;
4030  aggregate_list->option = (tree->info.function.all_or_distinct == PT_ALL) ? Q_ALL : Q_DISTINCT;
4031  aggregate_list->function = code;
4032  /* others will be set after resolving arg_list */
4033  }
4034 
4035  aggregate_list->flag_agg_optimize = false;
4036  BTID_SET_NULL (&aggregate_list->btid);
4037  if (info->flag_agg_optimize
4038  && (aggregate_list->function == PT_COUNT_STAR || aggregate_list->function == PT_COUNT
4039  || aggregate_list->function == PT_MAX || aggregate_list->function == PT_MIN))
4040  {
4041  bool need_unique_index;
4042 
4043  classop = sm_find_class (info->class_name);
4044  if (aggregate_list->function == PT_COUNT_STAR || aggregate_list->function == PT_COUNT)
4045  {
4046  need_unique_index = true;
4047  }
4048  else
4049  {
4050  need_unique_index = false;
4051  }
4052 
4053  /* enable count optimization in MVCC if have unique index */
4054  if (aggregate_list->function == PT_COUNT_STAR)
4055  {
4056  BTID *btid = NULL;
4057  btid = sm_find_index (classop, NULL, 0, need_unique_index, false, &aggregate_list->btid);
4058  if (btid != NULL)
4059  {
4060  /* If btree does not exist, optimize with heap in non-MVCC */
4061  aggregate_list->flag_agg_optimize = true;
4062  }
4063  }
4064  }
4065 
4066  if (aggregate_list->function != PT_COUNT_STAR && aggregate_list->function != PT_GROUPBY_NUM)
4067  {
4068  if (aggregate_list->function != PT_CUME_DIST && aggregate_list->function != PT_PERCENT_RANK)
4069  {
4070  regu_constant_list = pt_to_regu_variable_list (parser, tree->info.function.arg_list, UNBOX_AS_VALUE,
4071  NULL, NULL);
4072 
4073  scan_regu_constant_list = pt_to_regu_variable_list (parser, tree->info.function.arg_list, UNBOX_AS_VALUE,
4074  NULL, NULL);
4075 
4076  if (!regu_constant_list || !scan_regu_constant_list)
4077  {
4078  return NULL;
4079  }
4080  }
4081  else
4082  {
4083  /* for CUME_DIST and PERCENT_RANK function, take sort list as variables as well */
4085  if (!regu)
4086  {
4087  return NULL;
4088  }
4089 
4090  REGU_VARIABLE_LIST to_add;
4091  regu_alloc (to_add);
4092  to_add->value = *regu;
4093 
4094  // insert also in the regu_constant_list to ensure compatibility
4095  pt_add_regu_var_to_list (&regu_constant_list, to_add);
4096  }
4097 
4098  aggregate_list->domain = pt_xasl_node_to_domain (parser, tree);
4099  regu_dbval_type_init (aggregate_list->accumulator.value, pt_node_to_db_type (tree));
4100  if (aggregate_list->function == PT_GROUP_CONCAT)
4101  {
4102  group_concat_sep_node_save = tree->info.function.arg_list->next;
4103  /* store SEPARATOR for GROUP_CONCAT */
4104  if (group_concat_sep_node_save != NULL)
4105  {
4106  if (group_concat_sep_node_save->node_type == PT_VALUE
4107  && PT_IS_STRING_TYPE (group_concat_sep_node_save->type_enum))
4108  {
4109  pr_clone_value (&group_concat_sep_node_save->info.value.db_value,
4110  aggregate_list->accumulator.value2);
4111  /* set the next argument pointer (the separator argument) to NULL in order to avoid impacting the
4112  * regu vars generation. */
4113  tree->info.function.arg_list->next = NULL;
4114  pt_register_orphan_db_value (parser, aggregate_list->accumulator.value2);
4115  }
4116  else
4117  {
4118  assert (false);
4119  }
4120  }
4121  else
4122  {
4123  PT_TYPE_ENUM arg_type;
4124  /* set default separator, if one is not specified , only if argument is not bit */
4125  arg_type = tree->type_enum;
4126  if (arg_type != PT_TYPE_BIT && arg_type != PT_TYPE_VARBIT)
4127  {
4128  char *buf = NULL;
4129  /* create a default separator with same type as result */
4130  /* size in bytes for ',' is always 1 even for nchar */
4131  buf = (char *) db_private_alloc (NULL, 1 + 1);
4132  if (buf == NULL)
4133  {
4134  PT_ERROR (parser, tree,
4137  return tree;
4138  }
4139  strcpy (buf, ",");
4140  qstr_make_typed_string (pt_type_enum_to_db (arg_type), aggregate_list->accumulator.value2,
4141  DB_DEFAULT_PRECISION, buf, 1, TP_DOMAIN_CODESET (aggregate_list->domain),
4142  TP_DOMAIN_COLLATION (aggregate_list->domain));
4143  aggregate_list->accumulator.value2->need_clear = true;
4144  pt_register_orphan_db_value (parser, aggregate_list->accumulator.value2);
4145  }
4146  else
4147  {
4148  db_make_null (aggregate_list->accumulator.value2);
4149  }
4150  }
4151  }
4152  else
4153  {
4154  regu_dbval_type_init (aggregate_list->accumulator.value2, pt_node_to_db_type (tree));
4155  }
4156  aggregate_list->opr_dbtype = pt_node_to_db_type (tree->info.function.arg_list);
4157 
4158  if (info->out_list && info->value_list && info->regu_list)
4159  {
4160  /* handle the buildlist case. append regu to the out_list, and create a new value to append to the
4161  * value_list Note: cume_dist() and percent_rank() also need special operations. */
4162  if (aggregate_list->function != PT_CUME_DIST && aggregate_list->function != PT_PERCENT_RANK)
4163  {
4164  // add dummy output name nodes, one for each argument
4165  for (PT_NODE * it_args = tree->info.function.arg_list; it_args != NULL; it_args = it_args->next)
4166  {
4167  pt_val = parser_new_node (parser, PT_VALUE);
4168  if (pt_val == NULL)
4169  {
4170  PT_INTERNAL_ERROR (parser, "allocate new node");
4171  return NULL;
4172  }
4173 
4174  pt_val->type_enum = PT_TYPE_INTEGER;
4175  pt_val->info.value.data_value.i = 0;
4176  parser_append_node (pt_val, info->out_names);
4177  }
4178 
4179  // for each element from arg_list we create a corresponding node in the value_list and regu_list
4181  &value_list, &regu_position_list) == NULL)
4182  {
4185  return NULL;
4186  }
4187 
4188  error_code = pt_make_constant_regu_list_from_val_list (parser, value_list, &aggregate_list->operands);
4189  if (error_code != NO_ERROR)
4190  {
4193  return NULL;
4194  }
4195 
4196  // this regu_list has the TYPE_POSITION type so we need to set the corresponding indexes for elements
4197  pt_set_regu_list_pos_descr_from_idx (regu_position_list, info->out_list->valptr_cnt);
4198 
4199  // until now we have constructed the value_list, regu_list and out_list
4200  // they are based on the current aggregate node information and we need to append them to the global
4201  // information, i.e in info
4202  pt_aggregate_info_update_value_and_reguvar_lists (info, value_list, regu_position_list,
4203  regu_constant_list);
4204 
4205  // also we need to update the scan_regu_list from info
4206  pt_aggregate_info_update_scan_regu_list (info, scan_regu_constant_list);
4207  }
4208  else
4209  {
4210  assert (regu_constant_list != NULL && regu_constant_list->next == NULL);
4211 
4212  /* for buildlist CUME_DIST/PERCENT_RANK, we have special treatment */
4214  regu) != NO_ERROR)
4215  {
4216  return NULL;
4217  }
4218 
4219  aggregate_list->operands = regu_constant_list;
4220  }
4221  }
4222  else
4223  {
4224  // handle the buildvalue case, simply uses regu as the operand
4225  aggregate_list->operands = regu_constant_list;
4226  }
4227  }
4228  else
4229  {
4230  /* We are set up for count(*). Make sure that Q_DISTINCT isn't set in this case. Even though it is ignored
4231  * by the query processing proper, it seems to cause the setup code to build the extendible hash table it
4232  * needs for a "select count(distinct foo)" query, which adds a lot of unnecessary overhead. */
4233  aggregate_list->option = Q_ALL;
4234 
4235  aggregate_list->domain = &tp_Integer_domain;
4238  aggregate_list->opr_dbtype = DB_TYPE_INTEGER;
4239 
4240  regu_alloc (aggregate_list->operands);
4241  if (aggregate_list->operands == NULL)
4242  {
4243  PT_INTERNAL_ERROR (parser, "allocate new node");
4244  return NULL;
4245  }
4246  /* hack. we need to pack some domain even though we don't need one, so we'll pack the int. */
4247  aggregate_list->operands->value.domain = &tp_Integer_domain;
4248  }
4249 
4250  /* record the value for pt_to_regu_variable to use in "out arith" */
4251  tree->etc = (void *) aggregate_list->accumulator.value;
4252 
4253  info->head_list = aggregate_list;
4254 
4255  *continue_walk = PT_LIST_WALK;
4256 
4257  /* set percentile value for PT_PERCENTILE_CONT, PT_PERCENTILE_DISC */
4258  if (aggregate_list->function == PT_PERCENTILE_CONT || aggregate_list->function == PT_PERCENTILE_DISC)
4259  {
4260  percentile = tree->info.function.percentile;
4261 
4262  assert (percentile != NULL);
4263 
4264  regu = pt_to_regu_variable (parser, percentile, UNBOX_AS_VALUE);
4265  if (regu == NULL)
4266  {
4267  return NULL;
4268  }
4269 
4270  REGU_VARIABLE_LIST to_add;
4271  regu_alloc (to_add);
4272  to_add->value = *regu;
4273 
4274  /* build list */
4275  if (!PT_IS_CONST (percentile) && info->out_list != NULL && info->value_list != NULL
4276  && info->regu_list != NULL)
4277  {
4278  pointer = pt_point (parser, percentile);
4279  if (pointer == NULL)
4280  {
4281  PT_ERROR (parser, pointer,
4284  return NULL;
4285  }
4286 
4287  /* append the name on the out list */
4288  info->out_names = parser_append_node (pointer, info->out_names);
4289 
4290  /* put percentile in value_list, out_list and regu_list */
4291  if (pt_node_list_to_value_and_reguvar_list (parser, pointer, &value_list, &regu_position_list) == NULL)
4292  {
4293  PT_ERROR (parser, percentile,
4296  return NULL;
4297  }
4298 
4299  /* set aggregate_list->info.percentile.percentile_reguvar */
4300  regu_alloc (percentile_regu);
4301  if (percentile_regu == NULL)
4302  {
4303  return NULL;
4304  }
4305 
4306  percentile_regu->type = TYPE_CONSTANT;
4307  percentile_regu->domain = pt_xasl_node_to_domain (parser, pointer);
4308  percentile_regu->value.dbvalptr = value_list->valp->val;
4309 
4310  aggregate_list->info.percentile.percentile_reguvar = percentile_regu;
4311 
4312  /* fix count for list position */
4313  regu_position_list->value.value.pos_descr.pos_no = info->out_list->valptr_cnt;
4314 
4315  pt_aggregate_info_update_value_and_reguvar_lists (info, value_list, regu_position_list, to_add);
4316  }
4317  else
4318  {
4319  aggregate_list->info.percentile.percentile_reguvar = regu;
4320  }
4321  }
4322 
4323  /* GROUP_CONCAT : process ORDER BY and restore SEPARATOR node (just to keep original tree) */
4324  if (aggregate_list->function == PT_GROUP_CONCAT || aggregate_list->function == PT_CUME_DIST
4325  || aggregate_list->function == PT_PERCENT_RANK || (QPROC_IS_INTERPOLATION_FUNC (aggregate_list)
4326  && !PT_IS_CONST (tree->info.function.arg_list)))
4327  {
4328  /* Separator of GROUP_CONCAT is not a 'real' argument of GROUP_CONCAT, but for convenience it is kept in
4329  * 'arg_list' of PT_FUNCTION. It is not involved in sorting process, so conversion of ORDER BY to SORT_LIST
4330  * must be performed before restoring separator argument into the arg_list */
4332  if (tree == NULL)
4333  {
4334  /* error must be set */
4335  assert (pt_has_error (parser));
4336 
4337  return NULL;
4338  }
4339 
4340  if (tree->info.function.order_by != NULL)
4341  {
4342  /* convert to SORT_LIST */
4343  aggregate_list->sort_list =
4345  }
4346  else
4347  {
4348  aggregate_list->sort_list = NULL;
4349  }
4350 
4351  /* restore group concat separator node */
4352  tree->info.function.arg_list->next = group_concat_sep_node_save;
4353  }
4354  else
4355  {
4356  /* GROUP_CONCAT, MEDIAN, PERCENTILE_CONT and PERCENTILE_DISC aggs support ORDER BY. We ignore ORDER BY for
4357  * MEDIAN/PERCENTILE_CONT/PERCENTILE_DISC, when arg_list is a constant. */
4358  assert (QPROC_IS_INTERPOLATION_FUNC (aggregate_list) || tree->info.function.order_by == NULL);
4359 
4360  assert (group_concat_sep_node_save == NULL);
4361  }
4362  }
4363 
4364  if (tree->node_type == PT_DOT_)
4365  {
4366  /* This path must have already appeared in the group-by, and is resolved. Convert it to a name so that we can use
4367  * it to get the correct list position later. */
4368  PT_NODE *next = tree->next;
4369  tree = tree->info.dot.arg2;
4370  tree->next = next;
4371  }
4372 
4373  if (tree->node_type == PT_SELECT || tree->node_type == PT_UNION || tree->node_type == PT_INTERSECTION
4374  || tree->node_type == PT_DIFFERENCE)
4375  {
4376  /* this is a sub-query. It has its own aggregation scope. Do not proceed down the leaves. */
4377  *continue_walk = PT_LIST_WALK;
4378  }
4379  else if (tree->node_type == PT_EXPR
4380  && (tree->info.expr.op == PT_CURRENT_VALUE || tree->info.expr.op == PT_NEXT_VALUE))
4381  {
4382  /* Do not proceed down the leaves. */
4383  *continue_walk = PT_LIST_WALK;
4384  }
4385  else if (tree->node_type == PT_METHOD_CALL)
4386  {
4387  /* Do not proceed down the leaves */
4388  *continue_walk = PT_LIST_WALK;
4389  }
4390 
4391  if (tree->node_type == PT_NAME)
4392  {
4393  if (!pt_find_name (parser, tree, info->out_names) && (info->out_list && info->value_list && info->regu_list))
4394  {
4395  pointer = pt_point (parser, tree);
4396  if (pointer == NULL)
4397  {
4398  PT_ERROR (parser, pointer,
4401  return NULL;
4402  }
4403 
4404  /* append the name on the out list */
4405  info->out_names = parser_append_node (pointer, info->out_names);
4406 
4407  if (pt_node_list_to_value_and_reguvar_list (parser, pointer, &value_list, &regu_position_list) == NULL)
4408  {
4409  PT_ERROR (parser, tree,
4412  return NULL;
4413  }
4414 
4415  /* fix count for list position */
4416  regu_position_list->value.value.pos_descr.pos_no = info->out_list->valptr_cnt;
4417 
4418  regu = pt_to_regu_variable (parser, tree, UNBOX_AS_VALUE);
4419  if (regu == NULL)
4420  {
4421  return NULL;
4422  }
4423 
4424  REGU_VARIABLE_LIST to_add;
4425  regu_alloc (to_add);
4426  to_add->value = *regu;
4427 
4428  // insert also in the regu_constant_list to ensure compatibility
4429  pt_add_regu_var_to_list (&regu_constant_list, to_add);
4430 
4431  pt_aggregate_info_update_value_and_reguvar_lists (info, value_list, regu_position_list, regu_constant_list);
4432  }
4433  *continue_walk = PT_LIST_WALK;
4434  }
4435 
4436  if (tree->node_type == PT_SPEC || tree->node_type == PT_DATA_TYPE)
4437  {
4438  /* These node types cannot have sub-expressions. Do not proceed down the leaves */
4439  *continue_walk = PT_LIST_WALK;
4440  }
4441  return tree;
4442 }
4443 
4444 /*
4445  * pt_find_attribute () -
4446  * return: index of a name in an attribute symbol list,
4447  * or -1 if the name is not found in the list
4448  * parser(in):
4449  * name(in):
4450  * attributes(in):
4451  */
4452 int
4453 pt_find_attribute (PARSER_CONTEXT * parser, const PT_NODE * name, const PT_NODE * attributes)
4454 {
4455  PT_NODE *attr, *save_attr;
4456  int i = 0;
4457 
4458  if (name)
4459  {
4460  CAST_POINTER_TO_NODE (name);
4461 
4462  if (name->node_type == PT_NAME)
4463  {
4464  for (attr = (PT_NODE *) attributes; attr != NULL; attr = attr->next)
4465  {
4466  save_attr = attr; /* save */
4467 
4468  CAST_POINTER_TO_NODE (attr);
4469 
4470  /* are we looking up sort_spec list ? currently only group by causes this case. */
4471  if (attr->node_type == PT_SORT_SPEC)
4472  {
4473  attr = attr->info.sort_spec.expr;
4474  }
4475 
4476  if (!name->info.name.resolved)
4477  {
4478  /* are we looking up a path expression name? currently only group by causes this case. */
4479  if (attr->node_type == PT_DOT_ && pt_name_equal (parser, (PT_NODE *) name, attr->info.dot.arg2))
4480  {
4481  return i;
4482  }
4483  }
4484 
4485  if (pt_name_equal (parser, (PT_NODE *) name, attr))
4486  {
4487  return i;
4488  }
4489  i++;
4490 
4491  attr = save_attr; /* restore */
4492  }
4493  }
4494  }
4495 
4496  return -1;
4497 }
4498 
4499 /*
4500  * pt_index_value () -
4501  * return: the DB_VALUE at the index position in a VAL_LIST
4502  * value(in):
4503  * index(in):
4504  */
4505 static DB_VALUE *
4506 pt_index_value (const VAL_LIST * value, int index)
4507 {
4508  QPROC_DB_VALUE_LIST dbval_list;
4509  DB_VALUE *dbval = NULL;
4510 
4511  if (value && index >= 0)
4512  {
4513  dbval_list = value->valp;
4514  while (dbval_list && index)
4515  {
4516  dbval_list = dbval_list->next;
4517  index--;
4518  }
4519 
4520  if (dbval_list)
4521  {
4522  dbval = dbval_list->val;
4523  }
4524  }
4525 
4526  return dbval;
4527 }
4528 
4529 /*
4530  * pt_to_aggregate () - Generates an aggregate list from a select node
4531  * return: aggregate XASL node
4532  * parser(in): parser context
4533  * select_node(in): SELECT statement node
4534  * out_list(in): outptr list to generate intermediate file
4535  * value_list(in): value list
4536  * regu_list(in): regulist to read values from intermediate file
4537  * scan_regu_list(in): regulist to read values during initial scan
4538  * out_names(in): outptr name nodes
4539  * grbynum_valp(in): groupby_num() dbvalue
4540  */
4541 static AGGREGATE_TYPE *
4542 pt_to_aggregate (PARSER_CONTEXT * parser, PT_NODE * select_node, OUTPTR_LIST * out_list, VAL_LIST * value_list,
4543  REGU_VARIABLE_LIST regu_list, REGU_VARIABLE_LIST scan_regu_list, PT_NODE * out_names,
4544  DB_VALUE ** grbynum_valp)
4545 {
4546  PT_NODE *select_list, *from, *where, *having;
4547  AGGREGATE_INFO info;
4548 
4549  select_list = select_node->info.query.q.select.list;
4550  from = select_node->info.query.q.select.from;
4551  where = select_node->info.query.q.select.where;
4552  having = select_node->info.query.q.select.having;
4553 
4554  info.head_list = NULL;
4555  info.out_list = out_list;
4556  info.value_list = value_list;
4557  info.regu_list = regu_list;
4558  info.scan_regu_list = scan_regu_list;
4559  info.out_names = out_names;
4560  info.grbynum_valp = grbynum_valp;
4561 
4562  /* init */
4563  info.class_name = NULL;
4564  info.flag_agg_optimize = false;
4565 
4566  if (pt_is_single_tuple (parser, select_node))
4567  {
4568  if (where == NULL && pt_length_of_list (from) == 1 && pt_length_of_list (from->info.spec.flat_entity_list) == 1
4569  && from->info.spec.only_all != PT_ALL)
4570  {
4571  if (from->info.spec.entity_name)
4572  {
4574  info.flag_agg_optimize = true;
4575  }
4576  }
4577  }
4578 
4579  select_node->info.query.q.select.list =
4580  parser_walk_tree (parser, select_list, pt_to_aggregate_node, &info, pt_continue_walk, NULL);
4581 
4582  select_node->info.query.q.select.having =
4583  parser_walk_tree (parser, having, pt_to_aggregate_node, &info, pt_continue_walk, NULL);
4584 
4585  return info.head_list;
4586 }
4587 
4588 
4589 /*
4590  * pt_make_table_info () - Sets up symbol table entry for an entity spec
4591  * return:
4592  * parser(in):
4593  * table_spec(in):
4594  */
4595 static TABLE_INFO *
4597 {
4599 
4600  table_info = pt_table_info_alloc ();
4601  if (table_info == NULL)
4602  {
4603  return NULL;
4604  }
4605 
4606  table_info->class_spec = table_spec;
4607  if (table_spec->info.spec.range_var)
4608  {
4609  table_info->exposed = table_spec->info.spec.range_var->info.name.original;
4610  }
4611 
4612  table_info->spec_id = table_spec->info.spec.id;
4613 
4614  /* for classes, it is safe to prune unreferenced attributes. we do not have the same luxury with derived tables, so
4615  * get them all (and in order). */
4616  table_info->attribute_list = (table_spec->info.spec.flat_entity_list != NULL && PT_SPEC_IS_ENTITY (table_spec))
4617  ? table_spec->info.spec.referenced_attrs : table_spec->info.spec.as_attr_list;
4618 
4619  table_info->value_list = pt_make_val_list (parser, table_info->attribute_list);
4620 
4621  if (!table_info->value_list)
4622  {
4624  return NULL;
4625  }
4626 
4627  return table_info;
4628 }
4629 
4630 
4631 /*
4632  * pt_push_fetch_spec_info () - Sets up symbol table information
4633  * for a select statement
4634  * return:
4635  * parser(in):
4636  * symbols(in):
4637  * fetch_spec(in):
4638  */
4639 static SYMBOL_INFO *
4641 {
4642  PT_NODE *spec;
4644 
4645  for (spec = fetch_spec; spec != NULL; spec = spec->next)
4646  {
4647  table_info = pt_make_table_info (parser, spec);
4648  if (table_info == NULL)
4649  {
4650  symbols = NULL;
4651  break;
4652  }
4653  else if (symbols != NULL)
4654  {
4655  table_info->next = symbols->table_info;
4656  table_info->is_fetch = 1;
4657  }
4658 
4659  if (symbols != NULL)
4660  {
4661  symbols->table_info = table_info;
4662  }
4663 
4664  symbols = pt_push_fetch_spec_info (parser, symbols, spec->info.spec.path_entities);
4665  }
4666 
4667  return symbols;
4668 }
4669 
4670 /*
4671  * pt_push_symbol_info () - Sets up symbol table information
4672  * for a select statement
4673  * return:
4674  * parser(in):
4675  * select_node(in):
4676  */
4677 static SYMBOL_INFO *
4679 {
4680  PT_NODE *table_spec;
4681  SYMBOL_INFO *symbols = NULL;
4683  PT_NODE *from_list;
4684 
4685  symbols = pt_symbol_info_alloc ();
4686 
4687  if (symbols)
4688  {
4689  /* push symbols on stack */
4690  symbols->stack = parser->symbols;
4691  parser->symbols = symbols;
4692 
4693  symbols->query_node = select_node;
4694 
4695  if (select_node->node_type == PT_SELECT)
4696  {
4697  /* remove pseudo specs */
4698  select_node->info.query.q.select.from =
4699  pt_filter_pseudo_specs (parser, select_node->info.query.q.select.from);
4700 
4701  from_list = select_node->info.query.q.select.from;
4702 
4703  for (table_spec = from_list; table_spec != NULL; table_spec = table_spec->next)
4704  {
4705  table_info = pt_make_table_info (parser, table_spec);
4706  if (!table_info)
4707  {
4708  symbols = NULL;
4709  break;
4710  }
4711  table_info->next = symbols->table_info;
4712  symbols->table_info = table_info;
4713 
4714  symbols = pt_push_fetch_spec_info (parser, symbols, table_spec->info.spec.path_entities);
4715  if (!symbols)
4716  {
4717  break;
4718  }
4719  }
4720 
4721  if (symbols)
4722  {
4723  symbols->current_class = NULL;
4724  symbols->current_listfile = NULL;
4725  symbols->listfile_unbox = UNBOX_AS_VALUE;
4726  }
4727  }
4728  }
4729 
4730  return symbols;
4731 }
4732 
4733 
4734 /*
4735  * pt_pop_symbol_info () - Cleans up symbol table information
4736  * for a select statement
4737  * return: none
4738  * parser(in):
4739  * select_node(in):
4740  */
4741 static void
4743 {
4744  SYMBOL_INFO *symbols = NULL;
4745 
4746  if (parser->symbols)
4747  {
4748  /* allocated from pt_alloc_packing_buf */
4749  symbols = parser->symbols->stack;
4750  parser->symbols = symbols;
4751  }
4752  else
4753  {
4754  if (!pt_has_error (parser))
4755  {
4756  PT_INTERNAL_ERROR (parser, "generate");
4757  }
4758  }
4759 }
4760 
4761 
4762 /*
4763  * pt_make_access_spec () - Create an initialized ACCESS_SPEC_TYPE structure,
4764  * ready to be specialized for class or list
4765  * return:
4766  * spec_type(in):
4767  * access(in):
4768  * indexptr(in):
4769  * where_key(in):
4770  * where_pred(in):
4771  * where_range(in):
4772  */
4773 static ACCESS_SPEC_TYPE *
4774 pt_make_access_spec (TARGET_TYPE spec_type, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_key,
4775  PRED_EXPR * where_pred, PRED_EXPR * where_range)
4776 {
4777  ACCESS_SPEC_TYPE *spec = NULL;
4778 
4779  /* validation check */
4780  if (access == ACCESS_METHOD_INDEX)
4781  {
4782  assert (indexptr != NULL);
4783  if (indexptr)
4784  {
4785  if (indexptr->coverage)
4786  {
4787  assert (where_pred == NULL); /* no data-filter */
4788  if (where_pred == NULL)
4789  {
4790  spec = regu_spec_alloc (spec_type);
4791  }
4792  }
4793  else
4794  {
4795  spec = regu_spec_alloc (spec_type);
4796  }
4797  }
4798  }
4799  else
4800  {
4801  spec = regu_spec_alloc (spec_type);
4802  }
4803 
4804  if (spec)
4805  {
4806  spec->type = spec_type;
4807  spec->access = access;
4808  spec->indexptr = indexptr;
4809  spec->where_key = where_key;
4810  spec->where_pred = where_pred;
4811  spec->where_range = where_range;
4812  spec->next = NULL;
4814  }
4815 
4816  return spec;
4817 }
4818 
4819 
4820 /*
4821  * pt_cnt_attrs () - Count the number of regu variables in the list that
4822  * are coming from the heap (ATTR_ID)
4823  * return:
4824  * attr_list(in):
4825  */
4826 static int
4828 {
4829  int cnt = 0;
4830  REGU_VARIABLE_LIST tmp;
4831 
4832  for (tmp = attr_list; tmp; tmp = tmp->next)
4833  {
4834  if ((tmp->value.type == TYPE_ATTR_ID) || (tmp->value.type == TYPE_SHARED_ATTR_ID)
4835  || (tmp->value.type == TYPE_CLASS_ATTR_ID))
4836  {
4837  cnt++;
4838  }
4839  else if (tmp->value.type == TYPE_FUNC)
4840  {
4841  /* need to check all the operands for the function */
4842  cnt += pt_cnt_attrs (tmp->value.value.funcp->operand);
4843  }
4844  }
4845 
4846  return cnt;
4847 }
4848 
4849 
4850 /*
4851  * pt_fill_in_attrid_array () - Fill in the attrids of the regu variables
4852  * in the list that are comming from the heap
4853  * return:
4854  * attr_list(in):
4855  * attr_array(in):
4856  * next_pos(in): holds the next spot in the array to be filled in with the
4857  * next attrid
4858  */
4859 static void
4860 pt_fill_in_attrid_array (REGU_VARIABLE_LIST attr_list, ATTR_ID * attr_array, int *next_pos)
4861 {
4862  REGU_VARIABLE_LIST tmp;
4863 
4864  for (tmp = attr_list; tmp; tmp = tmp->next)
4865  {
4866  if ((tmp->value.type == TYPE_ATTR_ID) || (tmp->value.type == TYPE_SHARED_ATTR_ID)
4867  || (tmp->value.type == TYPE_CLASS_ATTR_ID))
4868  {
4869  attr_array[*next_pos] = tmp->value.value.attr_descr.id;
4870  *next_pos = *next_pos + 1;
4871  }
4872  else if (tmp->value.type == TYPE_FUNC)
4873  {
4874  /* need to check all the operands for the function */
4875  pt_fill_in_attrid_array (tmp->value.value.funcp->operand, attr_array, next_pos);
4876  }
4877  }
4878 }
4879 
4880 /*
4881  * pt_make_class_access_spec () - Create an initialized
4882  * ACCESS_SPEC_TYPE TARGET_CLASS structure
4883  * return:
4884  * parser(in):
4885  * flat(in):
4886  * class(in):
4887  * scan_type(in):
4888  * access(in):
4889  * indexptr(in):
4890  * where_key(in):
4891  * where_pred(in):
4892  * where_range(in):
4893  * attr_list_key(in):
4894  * attr_list_pred(in):
4895  * attr_list_rest(in):
4896  * attr_list_range(in):
4897  * cache_key(in):
4898  * cache_pred(in):
4899  * cache_rest(in):
4900  * cache_range(in):
4901  * schema_type(in):
4902  */
4903 static ACCESS_SPEC_TYPE *
4905  ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_key, PRED_EXPR * where_pred,
4906  PRED_EXPR * where_range, REGU_VARIABLE_LIST attr_list_key, REGU_VARIABLE_LIST attr_list_pred,
4907  REGU_VARIABLE_LIST attr_list_rest, REGU_VARIABLE_LIST attr_list_range,
4908  OUTPTR_LIST * output_val_list, REGU_VARIABLE_LIST regu_val_list,
4909  HEAP_CACHE_ATTRINFO * cache_key, HEAP_CACHE_ATTRINFO * cache_pred,
4910  HEAP_CACHE_ATTRINFO * cache_rest, HEAP_CACHE_ATTRINFO * cache_range,
4911  ACCESS_SCHEMA_TYPE schema_type, DB_VALUE ** cache_recordinfo,
4912  REGU_VARIABLE_LIST reserved_val_list)
4913 {
4914  ACCESS_SPEC_TYPE *spec;
4915  HFID *hfid;
4916  OID *cls_oid;
4917  int attrnum;
4918 
4919  spec = pt_make_access_spec (scan_type, access, indexptr, where_key, where_pred, where_range);
4920  if (spec == NULL)
4921  {
4922  return NULL;
4923  }
4924 
4925  assert (class_ != NULL);
4926 
4927  if (locator_fetch_class (class_, DB_FETCH_READ) == NULL)
4928  {
4929  PT_ERRORc (parser, flat, er_msg ());
4930  return NULL;
4931  }
4932 
4933  hfid = sm_get_ch_heap (class_);
4934  if (hfid == NULL)
4935  {
4936  return NULL;
4937  }
4938 
4939  cls_oid = WS_OID (class_);
4940  if (cls_oid == NULL || OID_ISNULL (cls_oid))
4941  {
4942  return NULL;
4943  }
4944 
4945  if (sm_partitioned_class_type (class_, &spec->pruning_type, NULL, NULL) != NO_ERROR)
4946  {
4947  PT_ERRORc (parser, flat, er_msg ());
4948  return NULL;
4949  }
4950 
4951  spec->s.cls_node.cls_regu_list_key = attr_list_key;
4952  spec->s.cls_node.cls_regu_list_pred = attr_list_pred;
4953  spec->s.cls_node.cls_regu_list_rest = attr_list_rest;
4954  spec->s.cls_node.cls_regu_list_range = attr_list_range;
4955  spec->s.cls_node.cls_output_val_list = output_val_list;
4956  spec->s.cls_node.cls_regu_val_list = regu_val_list;
4957  spec->s.cls_node.hfid = *hfid;
4958  spec->s.cls_node.cls_oid = *cls_oid;
4959 
4960  spec->s.cls_node.num_attrs_key = pt_cnt_attrs (attr_list_key);
4962 
4964  || (spec->s.cls_node.num_attrs_key == 0 && attr_list_key == NULL));
4965 
4966  attrnum = 0;
4967  /* for multi-column index, need to modify attr_id */
4968  pt_fill_in_attrid_array (attr_list_key, spec->s.cls_node.attrids_key, &attrnum);
4969  spec->s.cls_node.cache_key = cache_key;
4970  spec->s.cls_node.num_attrs_pred = pt_cnt_attrs (attr_list_pred);
4972  attrnum = 0;
4973  pt_fill_in_attrid_array (attr_list_pred, spec->s.cls_node.attrids_pred, &attrnum);
4974  spec->s.cls_node.cache_pred = cache_pred;
4975  spec->s.cls_node.num_attrs_rest = pt_cnt_attrs (attr_list_rest);
4977  attrnum = 0;
4978  pt_fill_in_attrid_array (attr_list_rest, spec->s.cls_node.attrids_rest, &attrnum);
4979  spec->s.cls_node.cache_rest = cache_rest;
4980  spec->s.cls_node.num_attrs_range = pt_cnt_attrs (attr_list_range);
4982  attrnum = 0;
4983  pt_fill_in_attrid_array (attr_list_range, spec->s.cls_node.attrids_range, &attrnum);
4984  spec->s.cls_node.cache_range = cache_range;
4985  spec->s.cls_node.schema_type = schema_type;
4986  spec->s.cls_node.cache_reserved = cache_recordinfo;
4988  {
4990  }
4991  else if (access == ACCESS_METHOD_SEQUENTIAL_PAGE_SCAN)
4992  {
4994  }
4995  else if (access == ACCESS_METHOD_INDEX_KEY_INFO)
4996  {
4998  }
4999  else if (access == ACCESS_METHOD_INDEX_NODE_INFO)
5000  {
5002  }
5003  else
5004  {
5005  spec->s.cls_node.num_attrs_reserved = 0;
5006  }
5007  spec->s.cls_node.cls_regu_list_reserved = reserved_val_list;
5008 
5009  return spec;
5010 }
5011 
5012 static void
5014  json_table_column & col_result)
5015 {
5016  col_result.m_function = jt_column->info.json_table_column_info.func;
5017  col_result.m_output_value_pointer = pt_index_value (tbl_info->value_list,
5018  pt_find_attribute (parser,
5019  jt_column->info.json_table_column_info.name,
5020  tbl_info->attribute_list));
5021  if (col_result.m_output_value_pointer == NULL)
5022  {
5023  assert (false);
5024  }
5025 
5026  col_result.m_domain = pt_xasl_node_to_domain (parser, jt_column);
5027 
5028  if (jt_column->info.json_table_column_info.path != NULL)
5029  {
5030  col_result.m_path = jt_column->info.json_table_column_info.path;
5031  }
5032 
5033  col_result.m_column_name = (char *) jt_column->info.json_table_column_info.name->info.name.original;
5034 
5035  col_result.m_on_empty = jt_column->info.json_table_column_info.on_empty;
5036  col_result.m_on_error = jt_column->info.json_table_column_info.on_error;
5037 }
5038 
5039 //
5040 // pt_make_json_table_spec_node_internal () - recursive function to generate json table access tree
5041 //
5042 // parser (in) : parser context
5043 // jt_node_info (in) : json table parser node info
5044 // current_id (in/out) : as input ID for this node, output next ID (after all nested nodes in current branch)
5045 // tbl_info (in) : table info cache
5046 // result (out) : a node in json table access tree based on json table node info
5047 //
5048 static void
5050  size_t & current_id, TABLE_INFO * tbl_info, json_table_node & result)
5051 {
5052  size_t i = 0;
5053  PT_NODE *itr;
5054 
5055  // copy path
5056  result.m_path = (char *) jt_node_info->path;
5057 
5058  // after set the id, increment
5059  result.m_id = current_id++;
5060 
5061  // nodes that have wildcard in their paths are the only ones that are iterable
5062  result.m_is_iterable_node = false;
5063  if (result.m_path)
5064  {
5066  }
5067 
5068  // create columns
5069  result.m_output_columns_size = 0;
5070  for (itr = jt_node_info->columns; itr != NULL; itr = itr->next, ++result.m_output_columns_size)
5071  ;
5072 
5073  result.m_output_columns =
5075 
5076  for (itr = jt_node_info->columns, i = 0; itr != NULL; itr = itr->next, i++)
5077  {
5078  pt_create_json_table_column (parser, itr, tbl_info, result.m_output_columns[i]);
5079  }
5080 
5081  // create children
5082  result.m_nested_nodes_size = 0;
5083  for (itr = jt_node_info->nested_paths; itr != NULL; itr = itr->next, ++result.m_nested_nodes_size)
5084  ;
5085 
5086  result.m_nested_nodes =
5088 
5089  for (itr = jt_node_info->nested_paths, i = 0; itr != NULL; itr = itr->next, i++)
5090  {
5091  pt_make_json_table_spec_node_internal (parser, &itr->info.json_table_node_info, current_id, tbl_info,
5092  result.m_nested_nodes[i]);
5093  }
5094 }
5095 
5096 //
5097 // pt_make_json_table_spec_node () - create json table access tree
5098 //
5099 // return : pointer to generated json_table_node
5100 // parser (in) : parser context
5101 // json_table (in) : json table parser node info
5102 // start_id (in/out) : output total node count (root + nested)
5103 // tbl_info (in) : table info cache
5104 //
5105 static json_table_node *
5107  TABLE_INFO * tbl_info)
5108 {
5110  pt_make_json_table_spec_node_internal (parser, &json_table->tree->info.json_table_node_info, start_id, tbl_info,
5111  *root_node);
5112  return root_node;
5113 }
5114 
5115 //
5116 // pt_make_json_table_access_spec () - make json access spec
5117 //
5118 // return : pointer to access spec
5119 // parser (in) : parser context
5120 // json_reguvar (in) : reguvar for json table expression
5121 // where_pred (in) : json table scan filter predicate
5122 // json_table (in) : json table parser node info
5123 // tbl_info (in) : table info cache
5124 //
5125 static ACCESS_SPEC_TYPE *
5127  PT_JSON_TABLE_INFO * json_table, TABLE_INFO * tbl_info)
5128 {
5129  ACCESS_SPEC_TYPE *spec;
5130  size_t start_id = 0;
5131 
5133 
5134  if (spec)
5135  {
5136  spec->s.json_table_node.m_root_node = pt_make_json_table_spec_node (parser, json_table, start_id, tbl_info);
5137  spec->s.json_table_node.m_json_reguvar = json_reguvar;
5138  // each node will have its own incremental id, so we can count the nr of nodes based on this identifier
5139  spec->s.json_table_node.m_node_count = start_id;
5140  }
5141 
5142  return spec;
5143 }
5144 
5145 /*
5146  * pt_make_list_access_spec () - Create an initialized
5147  * ACCESS_SPEC_TYPE TARGET_LIST structure
5148  * return:
5149  * xasl(in):
5150  * access(in):
5151  * indexptr(in):
5152  * where_pred(in):
5153  * attr_list_pred(in):
5154  * attr_list_rest(in):
5155  */
5156 static ACCESS_SPEC_TYPE *
5157 pt_make_list_access_spec (XASL_NODE * xasl, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_pred,
5158  REGU_VARIABLE_LIST attr_list_pred, REGU_VARIABLE_LIST attr_list_rest,
5159  REGU_VARIABLE_LIST attr_list_build, REGU_VARIABLE_LIST attr_list_probe)
5160 {
5161  ACCESS_SPEC_TYPE *spec;
5162 
5163  if (!xasl)
5164  {
5165  return NULL;
5166  }
5167 
5168  spec = pt_make_access_spec (TARGET_LIST, access, indexptr, NULL, where_pred, NULL);
5169 
5170  if (spec)
5171  {
5172  spec->s.list_node.list_regu_list_pred = attr_list_pred;
5173  spec->s.list_node.list_regu_list_rest = attr_list_rest;
5174  spec->s.list_node.list_regu_list_build = attr_list_build;
5175  spec->s.list_node.list_regu_list_probe = attr_list_probe;
5176  spec->s.list_node.xasl_node = xasl;
5177  }
5178 
5179  return spec;
5180 }
5181 
5182 /*
5183  * pt_make_showstmt_access_spec () - Create an initialized
5184  * ACCESS_SPEC_TYPE TARGET_SHOWSTMT structure
5185  * return:
5186  * where_pred(in):
5187  * show_type(in):
5188  * arg_list(in):
5189  */
5190 static ACCESS_SPEC_TYPE *
5192 {
5193  ACCESS_SPEC_TYPE *spec;
5194 
5196 
5197  if (spec)
5198  {
5199  spec->s.showstmt_node.show_type = show_type;
5200  spec->s.showstmt_node.arg_list = arg_list;
5201  }
5202 
5203  return spec;
5204 }
5205 
5206 
5207 /*
5208  * pt_make_set_access_spec () - Create an initialized
5209  * ACCESS_SPEC_TYPE TARGET_SET structure
5210  * return:
5211  * set_expr(in):
5212  * access(in):
5213  * indexptr(in):
5214  * where_pred(in):
5215  * attr_list(in):
5216  */
5217 static ACCESS_SPEC_TYPE *
5218 pt_make_set_access_spec (REGU_VARIABLE * set_expr, ACCESS_METHOD access, INDX_INFO * indexptr, PRED_EXPR * where_pred,
5219  REGU_VARIABLE_LIST attr_list)
5220 {
5221  ACCESS_SPEC_TYPE *spec;
5222 
5223  if (!set_expr)
5224  {
5225  return NULL;
5226  }
5227 
5228  spec = pt_make_access_spec (TARGET_SET, access, indexptr, NULL, where_pred, NULL);
5229 
5230  if (spec)
5231  {
5232  spec->s.set_node.set_regu_list = attr_list;
5233  spec->s.set_node.set_ptr = set_expr;
5234  }
5235 
5236  return spec;
5237 }
5238 
5239 
5240 /*
5241  * pt_make_cselect_access_spec () - Create an initialized
5242  * ACCESS_SPEC_TYPE TARGET_METHOD structure
5243  * return:
5244  * xasl(in):
5245  * method_sig_list(in):
5246  * access(in):
5247  * indexptr(in):
5248  * where_pred(in):
5249  * attr_list(in):
5250  */
5251 static ACCESS_SPEC_TYPE *
5253  INDX_INFO * indexptr, PRED_EXPR * where_pred, REGU_VARIABLE_LIST attr_list)
5254 {
5255  ACCESS_SPEC_TYPE *spec;
5256 
5257  if (!xasl)
5258  {
5259  return NULL;
5260  }
5261 
5262  spec = pt_make_access_spec (TARGET_METHOD, access, indexptr, NULL, where_pred, NULL);
5263 
5264  if (spec)
5265  {
5266  spec->s.method_node.method_regu_list = attr_list;
5267  spec->s.method_node.xasl_node = xasl;
5268  spec->s.method_node.method_sig_list = method_sig_list;
5269  }
5270 
5271  return spec;
5272 }
5273 
5274 
5275 /*
5276  * pt_to_pos_descr () - Translate PT_SORT_SPEC node to QFILE_TUPLE_VALUE_POSITION node
5277  * return:
5278  * parser(in):
5279  * pos_p(out):
5280  * node(in):
5281  * root(in):
5282  * referred_node(in/out): optional parameter to get real name or expression node
5283  * referred by a position
5284  */
5285 void
5287  PT_NODE ** referred_node)
5288 {
5289  PT_NODE *temp;
5290  char *node_str = NULL;
5291  int i;
5292 
5293  pos_p->pos_no = -1; /* init */
5294  pos_p->dom = NULL; /* init */
5295 
5296  if (referred_node != NULL)
5297  {
5298  *referred_node = NULL;
5299  }
5300 
5301  switch (root->node_type)
5302  {
5303  case PT_SELECT:
5304 
5305  if (node->node_type == PT_EXPR || node->node_type == PT_DOT_)
5306  {
5307  unsigned int save_custom;
5308 
5309  save_custom = parser->custom_print; /* save */
5310  parser->custom_print |= PT_CONVERT_RANGE;
5311 
5312  node_str = parser_print_tree (parser, node);
5313 
5314  parser->custom_print = save_custom; /* restore */
5315  }
5316 
5317  /* when do lex analysis, will CHECK nodes in groupby or orderby list whether in select_item list by alias and
5318  * positions,if yes,some substitution will done,so can not just compare by node_type, alias_print also be
5319  * considered. As function resolve_alias_in_name_node(), two round comparison will be done : first compare with
5320  * node_type, if not found, second round check will execute if alias_print is not NULL, compare it with
5321  * select_item whose alias_print is also not NULL. */
5322 
5323  /* first round search */
5324  i = 1; /* PT_SORT_SPEC pos_no start from 1 */
5325  for (temp = root->info.query.q.select.list; temp != NULL; temp = temp->next)
5326  {
5327  if (node->node_type == temp->node_type)
5328  {
5329  if (node->node_type == PT_NAME)
5330  {
5331  if (pt_name_equal (parser, node, temp))
5332  {
5333  pos_p->pos_no = i;
5334  }
5335  }
5336  else if (node->node_type == PT_EXPR || node->node_type == PT_DOT_)
5337  {
5338  if (pt_str_compare (node_str, parser_print_tree (parser, temp), CASE_INSENSITIVE) == 0)
5339  {
5340  pos_p->pos_no = i;
5341  }
5342  }
5343  }
5344  else if (pt_check_compatible_node_for_orderby (parser, temp, node))
5345  {
5346  pos_p->pos_no = i;
5347  }
5348 
5349  if (pos_p->pos_no == -1)
5350  { /* not found match */
5351  if (node->node_type == PT_VALUE && node->alias_print == NULL)
5352  {
5354  if (node->node_type == PT_VALUE && node->type_enum == PT_TYPE_INTEGER)
5355  {
5356  if (node->info.value.data_value.i == i)
5357  {
5358  pos_p->pos_no = i;
5359 
5360  if (referred_node != NULL)
5361  {
5362  *referred_node = temp;
5363  }
5364  }
5365  }
5366  }
5367  }
5368 
5369  if (pos_p->pos_no != -1)
5370  { /* found match */
5371  if (temp->type_enum != PT_TYPE_NONE && temp->type_enum != PT_TYPE_MAYBE)
5372  { /* is resolved */
5373  pos_p->dom = pt_xasl_node_to_domain (parser, temp);
5374  }
5375  break;
5376  }
5377 
5378  i++;
5379  }
5380 
5381  /* if not found, second round search in select items with alias_print */
5382  if (pos_p->pos_no == -1 && node->alias_print != NULL)
5383  {
5384 
5385  for (i = 1, temp = root->info.query.q.select.list; temp != NULL; temp = temp->next, i++)
5386  {
5387  if (temp->alias_print == NULL)
5388  {
5389  continue;
5390  }
5391 
5392  if (pt_str_compare (node->alias_print, temp->alias_print, CASE_INSENSITIVE) == 0)
5393  {
5394  pos_p->pos_no = i;
5395  break;
5396  }
5397  }
5398 
5399  if (pos_p->pos_no != -1)
5400  { /* found match */
5401  if (temp->type_enum != PT_TYPE_NONE && temp->type_enum != PT_TYPE_MAYBE)
5402  { /* is resolved */
5403  pos_p->dom = pt_xasl_node_to_domain (parser, temp);
5404  }
5405  }
5406  }
5407 
5408  break;
5409 
5410  case PT_UNION:
5411  case PT_INTERSECTION:
5412  case PT_DIFFERENCE:
5413  pt_to_pos_descr (parser, pos_p, node, root->info.query.q.union_.arg1, referred_node);
5414  break;
5415 
5416  default:
5417  /* an error */
5418  break;
5419  }
5420 
5421  if (pos_p->pos_no == -1 || pos_p->dom == NULL)
5422  { /* an error */
5423  pos_p->pos_no = -1;
5424  pos_p->dom = NULL;
5425  }
5426 }
5427 
5428 
5429 /*
5430  * pt_to_sort_list () - Translate a list of PT_SORT_SPEC nodes
5431  * to SORT_LIST list
5432  * return:
5433  * parser(in):
5434  * node_list(in):
5435  * col_list(in):
5436  * sort_mode(in):
5437  */
5438 static SORT_LIST *
5439 pt_to_sort_list (PARSER_CONTEXT * parser, PT_NODE * node_list, PT_NODE * col_list, SORT_LIST_MODE sort_mode)
5440 {
5441  SORT_LIST *sort_list, *sort, *lastsort;
5442  PT_NODE *node, *expr, *col;
5443  int i, k;
5444  int adjust_for_hidden_col_from = -1;
5445  DB_TYPE dom_type;
5446  bool is_analytic_window = false;
5447 
5448  sort_list = sort = lastsort = NULL;
5449  i = 0; /* SORT_LIST pos_no start from 0 */
5450 
5451  if (sort_mode == SORT_LIST_ANALYTIC_WINDOW)
5452  {
5453  /* analytic sort specs behave just as ORDER BY sort specs, but error messages differ */
5454  sort_mode = SORT_LIST_ORDERBY;
5455  is_analytic_window = true;
5456  }
5457 
5458  /* check if a hidden column is in the select list; if it is the case, store the position in
5459  * 'adjust_for_hidden_col_from' - index starting from 1 !! Only one column is supported! If we deal with more than
5460  * two columns then we deal with SELECT ... FOR UPDATE and we must skip the check This adjustement is needed for
5461  * UPDATE statements with SELECT subqueries, executed on broker (ex: on tables with triggers); in this case, the
5462  * class OID field in select list is marked as hidden, and the coresponding sort value is skipped in
5463  * 'qdata_get_valptr_type_list', but the sorting position is not adjusted - this code anticipates the problem */
5464  if (sort_mode == SORT_LIST_ORDERBY)
5465  {
5466  for (col = col_list, k = 1; col && adjust_for_hidden_col_from != -2; col = col->next, k++)
5467  {
5468  switch (col->node_type)
5469  {
5470  case PT_FUNCTION:
5472  {
5473  if (adjust_for_hidden_col_from != -1)
5474  {
5475  adjust_for_hidden_col_from = -2;
5476  }
5477  else
5478  {
5479  adjust_for_hidden_col_from = k;
5480  }
5481  break;
5482  }
5483  break;
5484 
5485  case PT_NAME:
5486  if (col->info.name.hidden_column)
5487  {
5488  if (adjust_for_hidden_col_from != -1)
5489  {
5490  adjust_for_hidden_col_from = -2;
5491  }
5492  else
5493  {
5494  adjust_for_hidden_col_from = k;
5495  }
5496  break;
5497  }
5498 
5499  default:
5500  break;
5501  }
5502  }
5503  }
5504 
5505  for (node = node_list; node != NULL; node = node->next)
5506  {
5507  /* safe guard: invalid parse tree */
5508  if (node->node_type != PT_SORT_SPEC || (expr = node->info.sort_spec.expr) == NULL)
5509  {
5511  return NULL;
5512  }
5513 
5514  /* check for end-of-sort */
5515  if (node->info.sort_spec.pos_descr.pos_no <= 0)
5516  {
5517  if (sort_mode == SORT_LIST_AFTER_ISCAN || sort_mode == SORT_LIST_ORDERBY)
5518  { /* internal error */
5519  if (!pt_has_error (parser))
5520  {
5521  PT_INTERNAL_ERROR (parser, "generate order_by");
5522  }
5523  return NULL;
5524  }
5525  else if (sort_mode == SORT_LIST_AFTER_GROUPBY)
5526  {
5527  /* i-th GROUP BY element does not appear in the select list. stop building sort_list */
5528  break;
5529  }
5530  }
5531 
5532  /* check for domain info */
5533  if (node->info.sort_spec.pos_descr.dom == NULL)
5534  {
5535  if (sort_mode == SORT_LIST_GROUPBY)
5536  {
5537  /* get domain from sort_spec node */
5538  if (expr->type_enum != PT_TYPE_NONE)
5539  { /* is resolved */
5540  node->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, expr);
5541  }
5542  }
5543  else
5544  {
5545  /* get domain from corresponding column node */
5546  for (col = col_list, k = 1; col; col = col->next, k++)
5547  {
5548  if (node->info.sort_spec.pos_descr.pos_no == k)
5549  {
5550  break; /* match */
5551  }
5552  }
5553 
5554  if (col && col->type_enum != PT_TYPE_NONE)
5555  { /* is resolved */
5556  node->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, col);
5557  }
5558  }
5559 
5560  /* internal error */
5561  if (node->info.sort_spec.pos_descr.dom == NULL)
5562  {
5563  if (!pt_has_error (parser))
5564  {
5565  const char *sort_mode_str;
5566 
5567  if (sort_mode == SORT_LIST_AFTER_ISCAN)
5568  {
5569  sort_mode_str = "generate after_iscan";
5570  }
5571  else if (sort_mode == SORT_LIST_ORDERBY)
5572  {
5573  sort_mode_str = "generate order_by";
5574  }
5575  else if (sort_mode == SORT_LIST_GROUPBY)
5576  {
5577  sort_mode_str = "generate group_by";
5578  }
5579  else
5580  {
5581  sort_mode_str = "generate after_group_by";
5582  }
5583 
5584  PT_INTERNAL_ERROR (parser, sort_mode_str);
5585  }
5586  return NULL;
5587  }
5588  }
5589 
5590  /* GROUP BY ? or ORDER BY ? are not allowed */
5591  dom_type = TP_DOMAIN_TYPE (node->info.sort_spec.pos_descr.dom);
5592 
5593  if (is_analytic_window && (dom_type == DB_TYPE_BLOB || dom_type == DB_TYPE_CLOB || dom_type == DB_TYPE_VARIABLE))
5594  {
5595  /* analytic sort spec expressions have been moved to select list; check for host variable there */
5596  for (col = col_list, k = 1; col; col = col->next, k++)
5597  {
5598  if (node->info.sort_spec.pos_descr.pos_no == k)
5599  {
5600  break;
5601  }
5602  }
5603 
5604  if (col == NULL)
5605  {
5606  PT_INTERNAL_ERROR (parser, "sort spec out of bounds");
5607  return NULL;
5608  }
5609 
5610  if (col->node_type == PT_HOST_VAR || dom_type != DB_TYPE_VARIABLE)
5611  {
5613  pt_short_print (parser, col));
5614  return NULL;
5615  }
5616 
5617  /* we allow variable domain but no host var */
5618  }
5619  else if (dom_type == DB_TYPE_BLOB || dom_type == DB_TYPE_CLOB
5620  || (node->info.sort_spec.expr->node_type == PT_HOST_VAR && dom_type == DB_TYPE_VARIABLE))
5621  {
5622  if (sort_mode == SORT_LIST_ORDERBY)
5623  {
5624  for (col = col_list, k = 1; col; col = col->next, k++)
5625  {
5626  if (node->info.sort_spec.pos_descr.pos_no == k)
5627  {
5628  break;
5629  }
5630  }
5632  pt_short_print (parser, col));
5633  return NULL;
5634  }
5635  else if (sort_mode == SORT_LIST_GROUPBY)
5636  {
5638  pt_short_print (parser, expr));
5639  return NULL;
5640  }
5641  }
5642 
5643  regu_alloc (sort);
5644  if (!sort)
5645  {
5647  return NULL;
5648  }
5649 
5650  /* set values */
5651  sort->s_order = (node->info.sort_spec.asc_or_desc == PT_ASC) ? S_ASC : S_DESC;
5652  sort->s_nulls = pt_to_null_ordering (node);
5653  sort->pos_descr = node->info.sort_spec.pos_descr;
5654 
5655  /* PT_SORT_SPEC pos_no start from 1, SORT_LIST pos_no start from 0 */
5656  if (sort_mode == SORT_LIST_GROUPBY)
5657  {
5658  /* set i-th position */
5659  sort->pos_descr.pos_no = i++;
5660  }
5661  else
5662  {
5663  sort->pos_descr.pos_no--;
5664  if (adjust_for_hidden_col_from > -1)
5665  {
5666  assert (sort_mode == SORT_LIST_ORDERBY);
5667  /* adjust for hidden column */
5668  if (node->info.sort_spec.pos_descr.pos_no >= adjust_for_hidden_col_from)
5669  {
5670  sort->pos_descr.pos_no--;
5671  assert (sort->pos_descr.pos_no >= 0);
5672  }
5673  }
5674  }
5675 
5676  /* link up */
5677  if (sort_list)
5678  {
5679  lastsort->next = sort;
5680  }
5681  else
5682  {
5683  sort_list = sort;
5684  }
5685 
5686  lastsort = sort;
5687  }
5688 
5689  return sort_list;
5690 }
5691 
5692 
5693 /*
5694  * pt_to_after_iscan () - Translate a list of after iscan PT_SORT_SPEC nodes
5695  * to SORT_LIST list
5696  * return:
5697  * parser(in):
5698  * iscan_list(in):
5699  * root(in):
5700  */
5701 static SORT_LIST *
5703 {
5704  return pt_to_sort_list (parser, iscan_list, pt_get_select_list (parser, root), SORT_LIST_AFTER_ISCAN);
5705 }
5706 
5707 
5708 /*
5709  * pt_to_orderby () - Translate a list of order by PT_SORT_SPEC nodes
5710  * to SORT_LIST list
5711  * return:
5712  * parser(in):
5713  * order_list(in):
5714  * root(in):
5715  */
5716 SORT_LIST *
5718 {
5719  return pt_to_sort_list (parser, order_list, pt_get_select_list (parser, root), SORT_LIST_ORDERBY);
5720 }
5721 
5722 
5723 /*
5724  * pt_to_groupby () - Translate a list of group by PT_SORT_SPEC nodes
5725  * to SORT_LIST list.(ALL ascending)
5726  * return:
5727  * parser(in):
5728  * group_list(in):
5729  * root(in):
5730  */
5731 static SORT_LIST *
5733 {
5734  return pt_to_sort_list (parser, group_list, pt_get_select_list (parser, root), SORT_LIST_GROUPBY);
5735 }
5736 
5737 
5738 /*
5739  * pt_to_after_groupby () - Translate a list of after group by PT_SORT_SPEC
5740  * nodes to SORT_LIST list.(ALL ascending)
5741  * return:
5742  * parser(in):
5743  * group_list(in):
5744  * root(in):
5745  */
5746 static SORT_LIST *
5748 {
5749  return pt_to_sort_list (parser, group_list, pt_get_select_list (parser, root), SORT_LIST_AFTER_GROUPBY);
5750 }
5751 
5752 
5753 /*
5754  * pt_to_pred_terms () -
5755  * return:
5756  * parser(in):
5757  * terms(in): CNF tree
5758  * id(in): spec id to test term for
5759  * pred(in):
5760  */
5761 static void
5762 pt_to_pred_terms (PARSER_CONTEXT * parser, PT_NODE * terms, UINTPTR id, PRED_EXPR ** pred)
5763 {
5764  PRED_EXPR *pred1;
5765  PT_NODE *next;
5766 
5767  while (terms)
5768  {
5769  /* break links, they are a short-hand for 'AND' in CNF terms */
5770  next = terms->next;
5771  terms->next = NULL;
5772 
5773  if (terms->node_type == PT_EXPR && terms->info.expr.op == PT_AND)
5774  {
5775  pt_to_pred_terms (parser, terms->info.expr.arg1, id, pred);
5776  pt_to_pred_terms (parser, terms->info.expr.arg2, id, pred);
5777  }
5778  else
5779  {
5780  if (terms->spec_ident == (UINTPTR) id)
5781  {
5782  pred1 = pt_to_pred_expr (parser, terms);
5783  if (!*pred)
5784  {
5785  *pred = pred1;
5786  }
5787  else
5788  {
5789  *pred = pt_make_pred_expr_pred (pred1, *pred, B_AND);
5790  }
5791  }
5792  }
5793 
5794  /* repair link */
5795  terms->next = next;
5796  terms = next;
5797  }
5798 }
5799 
5800 
5801 /*
5802  * regu_make_constant_vid () - convert a vmop into a db_value
5803  * return: NO_ERROR on success, non-zero for ERROR
5804  * val(in): a virtual object instance
5805  * dbvalptr(out): pointer to a db_value
5806  */
5807 static int
5809 {
5810  DB_OBJECT *vmop, *cls, *proxy, *real_instance;
5811  DB_VALUE *keys = NULL, *virt_val, *proxy_val;
5812  OID virt_oid, proxy_oid;
5813  DB_IDENTIFIER *dbid;
5814  DB_SEQ *seq;
5815  int is_vclass = 0;
5816 
5817  assert (val != NULL);
5818 
5819  /* make sure we got a virtual MOP and a db_value */
5820  if (DB_VALUE_TYPE (val) != DB_TYPE_OBJECT || !(vmop = db_get_object (val)) || !WS_ISVID (vmop))
5821  {
5822  return ER_GENERIC_ERROR;
5823  }
5824 
5825  regu_alloc (*dbvalptr);
5826  regu_alloc (virt_val);
5827  regu_alloc (proxy_val);
5828  regu_alloc (keys);
5829  if (*dbvalptr == NULL || virt_val == NULL || proxy_val == NULL || keys == NULL)
5830  {
5831  return ER_GENERIC_ERROR;
5832  }
5833 
5834  /* compute vmop's three canonical values: virt, proxy, keys */
5835  cls = db_get_class (vmop);
5836  is_vclass = db_is_vclass (cls);
5837  if (is_vclass < 0)
5838  {
5839  return is_vclass;
5840  }
5841  if (!is_vclass)
5842  {
5843  OID_SET_NULL (&virt_oid);
5844  real_instance = vmop;
5845  OID_SET_NULL (&proxy_oid);
5846  *keys = *val;
5847  }
5848  else
5849  {
5850  /* make sure its oid is a good one */
5851  dbid = ws_identifier (cls);
5852  if (!dbid)
5853  {
5854  return ER_GENERIC_ERROR;
5855  }
5856 
5857  virt_oid = *dbid;
5858  real_instance = db_real_instance (vmop);
5859  if (!real_instance)
5860  {
5861  OID_SET_NULL (&proxy_oid);
5862  vid_get_keys (vmop, keys);
5863  }
5864  else
5865  {
5866  proxy = db_get_class (real_instance);
5867  OID_SET_NULL (&proxy_oid);
5868  vid_get_keys (vmop, keys);
5869  }
5870  }
5871 
5872  db_make_oid (virt_val, &virt_oid);
5873  db_make_oid (proxy_val, &proxy_oid);
5874 
5875  /* the DB_VALUE form of a VMOP is given a type of DB_TYPE_VOBJ and takes the form of a 3-element sequence: virt,
5876  * proxy, keys (Oh what joy to find out the secret encoding of a virtual object!) */
5877  if ((seq = db_seq_create (NULL, NULL, 3)) == NULL)
5878  {
5879  goto error_cleanup;
5880  }
5881 
5882  if (db_seq_put (seq, 0, virt_val) != NO_ERROR)
5883  {
5884  goto error_cleanup;
5885  }
5886 
5887  if (db_seq_put (seq, 1, proxy_val) != NO_ERROR)
5888  {
5889  goto error_cleanup;
5890  }
5891 
5892  /* this may be a nested sequence, so turn on nested sets */
5893  if (db_seq_put (seq, 2, keys) != NO_ERROR)
5894  {
5895  goto error_cleanup;
5896  }
5897 
5898  db_make_sequence (*dbvalptr, seq);
5899  db_value_alter_type (*dbvalptr, DB_TYPE_VOBJ);
5900 
5901  return NO_ERROR;
5902 
5903 error_cleanup:
5904  pr_clear_value (keys);
5905  return ER_GENERIC_ERROR;
5906 }
5907 
5908 /*
5909  * set_has_objs () - set dbvalptr to the DB_VALUE form of val
5910  * return: nonzero if set has some objs, zero otherwise
5911  * seq(in): a set/seq db_value
5912  */
5913 static int
5915 {
5916  int found = 0, i, siz;
5917  DB_VALUE elem;
5918 
5919  siz = db_seq_size (seq);
5920  for (i = 0; i < siz && !found; i++)
5921  {
5922  if (db_set_get (seq, i, &elem) < 0)
5923  {
5924  return 0;
5925  }
5926 
5927  if (DB_VALUE_DOMAIN_TYPE (&elem) == DB_TYPE_OBJECT)
5928  {
5929  found = 1;
5930  }
5931 
5932  db_value_clear (&elem);
5933  }
5934 
5935  return found;
5936 }
5937 
5938 /*
5939  * setof_mop_to_setof_vobj () - creates & fill new set/seq with converted
5940  * vobj elements of val
5941  * return: NO_ERROR on success, non-zero for ERROR
5942  * parser(in):
5943  * seq(in): a set/seq of mop-bearing elements
5944  * new_val(out):
5945  */
5946 static int
5948 {
5949  int i, siz;
5950  DB_VALUE elem, *new_elem;
5951  DB_SET *new_set;
5952  DB_OBJECT *obj;
5953  OID *oid;
5954  DB_TYPE typ;
5955 
5956  /* make sure we got a set/seq */
5957  typ = db_set_type (seq);
5958  if (!pr_is_set_type (typ))
5959  {
5960  goto failure;
5961  }
5962 
5963  /* create a new set/seq */
5964  siz = db_seq_size (seq);
5965  if (typ == DB_TYPE_SET)
5966  {
5967  new_set = db_set_create_basic (NULL, NULL);
5968  }
5969  else if (typ == DB_TYPE_MULTISET)
5970  {
5971  new_set = db_set_create_multi (NULL, NULL);
5972  }
5973  else
5974  {
5975  new_set = db_seq_create (NULL, NULL, siz);
5976  }
5977 
5978  /* fill the new_set with the vobj form of val's mops */
5979  for (i = 0; i < siz; i++)
5980  {
5981  if (db_set_get (seq, i, &elem) < 0)
5982  {
5983  goto failure;
5984  }
5985 
5986  if (DB_IS_NULL (&elem))
5987  {
5988  regu_alloc (new_elem);
5989  if (!new_elem)
5990  {
5991  goto failure;
5992  }
5994  }
5995  else if (DB_VALUE_DOMAIN_TYPE (&elem) != DB_TYPE_OBJECT || (obj = db_get_object (&elem)) == NULL)
5996  {
5997  /* the set has mixed object and non-object types. */
5998  new_elem = &elem;
5999  }
6000  else
6001  {
6002  /* convert val's mop into a vobj */
6003  if (WS_ISVID (obj))
6004  {
6005  if (regu_make_constant_vid (&elem, &new_elem) != NO_ERROR)
6006  {
6007  goto failure;
6008  }
6009 
6010  /* we need to register the constant vid as an orphaned db_value that the parser should free later. We
6011  * can't free it until after the xasl has been packed. */
6012  pt_register_orphan_db_value (parser, new_elem);
6013  }
6014  else
6015  {
6016  regu_alloc (new_elem);
6017  if (!new_elem)
6018  {
6019  goto failure;
6020  }
6021 
6022  if (WS_IS_DELETED (obj))
6023  {
6025  }
6026  else
6027  {
6028  oid = db_identifier (obj);
6029  if (oid == NULL)
6030  {
6031  if (er_errid () == ER_HEAP_UNKNOWN_OBJECT)
6032  {
6034  }
6035  else
6036  {
6037  goto failure;
6038  }
6039  }
6040  else
6041  {
6042  db_make_object (new_elem, ws_mop (oid, NULL));
6043  }
6044  }
6045  }
6046  }
6047 
6048  /* stuff the vobj form of the mop into new_set */
6049  if (typ == DB_TYPE_SET || typ == DB_TYPE_MULTISET)
6050  {
6051  if (db_set_add (new_set, new_elem) < 0)
6052  {
6053  goto failure;
6054  }
6055  }
6056  else if (db_seq_put (new_set, i, new_elem) < 0)
6057  {
6058  goto failure;
6059  }
6060 
6061  db_value_clear (&elem);
6062  }
6063 
6064  /* stuff new_set into new_val */
6065  if (typ == DB_TYPE_SET)
6066  {
6067  db_make_set (new_val, new_set);
6068  }
6069  else if (typ == DB_TYPE_MULTISET)
6070  {
6071  db_make_multiset (new_val, new_set);
6072  }
6073  else
6074  {
6075  db_make_sequence (new_val, new_set);
6076  }
6077 
6078  return NO_ERROR;
6079 
6080 failure:
6081  PT_INTERNAL_ERROR (parser, "generate var");
6082  return ER_FAILED;
6083 }
6084 
6085 
6086 /*
6087  * pt_make_regu_hostvar () - takes a pt_node of host variable and make
6088  * a regu_variable of host variable reference
6089  * return:
6090  * parser(in/out):
6091  * node(in):
6092  */
6093 static REGU_VARIABLE *
6095 {
6096  REGU_VARIABLE *regu;
6097  DB_VALUE *val;
6098  DB_TYPE typ, exptyp;
6099 
6100  regu_alloc (regu);
6101  if (regu)
6102  {
6103  val = &parser->host_variables[node->info.host_var.index];
6104  typ = DB_VALUE_DOMAIN_TYPE (val);
6105 
6106  regu->type = TYPE_POS_VALUE;
6107  regu->value.val_pos = node->info.host_var.index;
6108  if (parser->dbval_cnt <= node->info.host_var.index)
6109  {
6110  parser->dbval_cnt = node->info.host_var.index + 1;
6111  }
6112 
6113  /* determine the domain of this host var */
6114  regu->domain = NULL;
6115 
6116  if (node->data_type)
6117  {
6118  /* try to get domain info from its data_type */
6119  regu->domain = pt_xasl_node_to_domain (parser, node);
6120  }
6121 
6122  if (regu->domain == NULL && (parser->flag.set_host_var == 1 || typ != DB_TYPE_NULL))
6123  {
6124  /* if the host var DB_VALUE was initialized before, use its domain for regu variable */
6125  TP_DOMAIN *domain;
6126  if (TP_IS_CHAR_TYPE (typ))
6127  {
6129  regu->domain = tp_domain_copy (domain, false);
6130  if (regu->domain != NULL)
6131  {
6132  regu->domain->codeset = db_get_string_codeset (val);
6133  regu->domain->collation_id = db_get_string_collation (val);
6134  regu->domain->precision = db_value_precision (val);
6135  regu->domain->scale = db_value_scale (val);
6136  regu->domain = tp_domain_cache (regu->domain);
6137  if (regu->domain == NULL)
6138  {
6139  goto error_exit;
6140  }
6141  }
6142  else
6143  {
6144  goto error_exit;
6145  }
6146  }
6147  else
6148  {
6149  regu->domain = pt_xasl_type_enum_to_domain (pt_db_to_type_enum (typ));
6150  }
6151  }
6152 
6153  if (regu->domain == NULL && node->expected_domain)
6154  {
6155  /* try to get domain infor from its expected_domain */
6156  regu->domain = node->expected_domain;
6157  }
6158 
6159  if (regu->domain == NULL)
6160  {
6161  /* try to get domain info from its type_enum */
6162  regu->domain = pt_xasl_type_enum_to_domain (node->type_enum);
6163  }
6164 
6165  if (regu->domain == NULL)
6166  {
6167  PT_INTERNAL_ERROR (parser, "unresolved data type of host var");
6168  regu = NULL;
6169  }
6170  else
6171  {
6172  exptyp = TP_DOMAIN_TYPE (regu->domain);
6173  if (parser->flag.set_host_var == 0 && typ == DB_TYPE_NULL)
6174  {
6175  /* If the host variable was not given before by the user, preset it by the expected domain. When the user
6176  * set the host variable, its value will be casted to this domain if necessary. */
6177  (void) db_value_domain_init (val, exptyp, regu->domain->precision, regu->domain->scale);
6178  if (TP_IS_CHAR_TYPE (exptyp))
6179  {
6181  TP_DOMAIN_COLLATION (regu->domain));
6182  }
6183  }
6184  else if (typ != exptyp
6185  || (TP_TYPE_HAS_COLLATION (typ) && TP_TYPE_HAS_COLLATION (exptyp)
6186  && (db_get_string_collation (val) != TP_DOMAIN_COLLATION (regu->domain))))
6187  {
6188  if (tp_value_cast (val, val, regu->domain, false) != DOMAIN_COMPATIBLE)
6189  {
6190  PT_ERRORmf2 (parser, node, MSGCAT_SET_ERROR, -(ER_TP_CANT_COERCE),
6191  pr_type_name (DB_VALUE_DOMAIN_TYPE (val)), pr_type_name (TP_DOMAIN_TYPE (regu->domain)));
6192  regu = NULL;
6193  }
6194  }
6195  }
6196  }
6197  else
6198  {
6199  regu = NULL;
6200  }
6201 
6202  return regu;
6203 
6204 error_exit:
6205  return NULL;
6206 }
6207 
6208 /*
6209  * pt_make_regu_reguvalues_list () - takes a pt_node of host variable and make
6210  * a regu_variable of value list reference
6211  * return: A NULL return indicates an error occurred
6212  * parser(in):
6213  * node(in):
6214  */
6215 static REGU_VARIABLE *
6217 {
6218  REGU_VARIABLE *regu = NULL;
6219  REGU_VALUE_LIST *regu_list = NULL;
6220  REGU_VALUE_ITEM *list_node = NULL;
6221  PT_NODE *temp = NULL;
6222 
6223  assert (node);
6224 
6225  regu_alloc (regu);
6226  if (regu)
6227  {
6228  regu->type = TYPE_REGUVAL_LIST;
6229 
6230  regu_alloc (regu_list);
6231  if (regu_list == NULL)
6232  {
6233  return NULL;
6234  }
6235  regu->value.reguval_list = regu_list;
6236 
6237  for (temp = node->info.node_list.list; temp; temp = temp->next_row)
6238  {
6239  regu_alloc (list_node);
6240  if (list_node == NULL)
6241  {
6242  return NULL;
6243  }
6244 
6245  if (regu_list->current_value == NULL)
6246  {
6247  regu_list->regu_list = list_node;
6248  }
6249  else
6250  {
6251  regu_list->current_value->next = list_node;
6252  }
6253 
6254  regu_list->current_value = list_node;
6255  list_node->value = pt_to_regu_variable (parser, temp, unbox);
6256  if (list_node->value == NULL)
6257  {
6258  return NULL;
6259  }
6260  regu_list->count += 1;
6261  }
6262  regu_list->current_value = regu_list->regu_list;
6263  regu->domain = regu_list->regu_list->value->domain;
6264  }
6265 
6266  return regu;
6267 }
6268 
6269 /*
6270  * pt_make_regu_constant () - takes a db_value and db_type and makes
6271  * a regu_variable constant
6272  * return: A NULL return indicates an error occurred
6273  * parser(in):
6274  * db_value(in/out):
6275  * db_type(in):
6276  * node(in):
6277  */
6278 static REGU_VARIABLE *
6280 {
6281  REGU_VARIABLE *regu = NULL;
6282  DB_VALUE *dbvalptr = NULL;
6283  DB_VALUE tmp_val;
6284  DB_TYPE typ;
6285  int is_null;
6286  DB_SET *set = NULL;
6287 
6288  db_make_null (&tmp_val);
6289  if (db_value)
6290  {
6291  regu_alloc (regu);
6292  if (regu)
6293  {
6294  if (node)
6295  {
6296  regu->domain = pt_xasl_node_to_domain (parser, node);
6297  }
6298  else
6299  {
6300  /* just use the type to create the domain, this is a special case */
6301  regu->domain = tp_domain_resolve_default (db_type);
6302  }
6303 
6304  regu->type = TYPE_CONSTANT;
6305  typ = DB_VALUE_DOMAIN_TYPE (db_value);
6306  is_null = DB_IS_NULL (db_value);
6307  if (is_null)
6308  {
6309  regu->value.dbvalptr = db_value;
6310  }
6311  else if (typ == DB_TYPE_OBJECT)
6312  {
6313  if (db_get_object (db_value) && WS_ISVID (db_get_object (db_value)))
6314  {
6315  if (regu_make_constant_vid (db_value, &dbvalptr) != NO_ERROR)
6316  {
6317  return NULL;
6318  }
6319  else
6320  {
6321  regu->value.dbvalptr = dbvalptr;
6322  regu->domain = &tp_Vobj_domain;
6323 
6324  /* we need to register the constant vid as an orphaned db_value that the parser should free
6325  * later. We can't free it until after the xasl has been packed. */
6326  pt_register_orphan_db_value (parser, dbvalptr);
6327  }
6328  }
6329  else
6330  {
6331  OID *oid;
6332 
6333  oid = db_identifier (db_get_object (db_value));
6334  if (oid == NULL)
6335  {
6336  db_value_put_null (db_value);
6337  }
6338  else
6339  {
6340  db_make_object (db_value, ws_mop (oid, NULL));
6341  }
6342  regu->value.dbvalptr = db_value;
6343  }
6344  }
6345  else if (pr_is_set_type (typ) && (set = db_get_set (db_value)) != NULL && set_has_objs (set))
6346  {
6347  if (setof_mop_to_setof_vobj (parser, set, &tmp_val) != NO_ERROR)
6348  {
6349  return NULL;
6350  }
6351  regu->value.dbvalptr = &tmp_val;
6352  }
6353  else
6354  {
6355  regu->value.dbvalptr = db_value;
6356  }
6357 
6358  /* db_value may be in a pt_node that will be freed before mapping the xasl to a stream. This makes sure that
6359  * we have captured the contents of the variable. It also uses the in-line db_value of a regu variable,
6360  * saving xasl space. */
6361  db_value = regu->value.dbvalptr;
6362  regu->value.dbvalptr = NULL;
6363  regu->type = TYPE_DBVAL;
6364  db_value_clone (db_value, &regu->value.dbval);
6365 
6366  /* we need to register the dbvalue within the regu constant as an orphan that the parser should free later.
6367  * We can't free it until after the xasl has been packed. */
6368  pt_register_orphan_db_value (parser, &regu->value.dbval);
6369 
6370  /* if setof_mop_to_setof_vobj() was called, then a new set was created. The dbvalue needs to be cleared. */
6371  pr_clear_value (&tmp_val);
6372  }
6373  }
6374 
6375  return regu;
6376 }
6377 
6378 
6379 /*
6380  * pt_make_regu_arith () - takes a regu_variable pair,
6381  * and makes an regu arith type
6382  * return: A NULL return indicates an error occurred
6383  * arg1(in):
6384  * arg2(in):
6385  * arg3(in):
6386  * op(in):
6387  * domain(in):
6388  */
6389 REGU_VARIABLE *
6390 pt_make_regu_arith (const REGU_VARIABLE * arg1, const REGU_VARIABLE * arg2, const REGU_VARIABLE * arg3,
6391  const OPERATOR_TYPE op, const TP_DOMAIN * domain)
6392 {
6393  REGU_VARIABLE *regu = NULL;
6394  ARITH_TYPE *arith;
6395  DB_VALUE *dbval;
6396 
6397  if (domain == NULL)
6398  {
6399  return NULL;
6400  }
6401 
6402  regu_alloc (arith);
6403  regu_alloc (dbval);
6404  regu_alloc (regu);
6405 
6406  if (arith == NULL || dbval == NULL || regu == NULL)
6407  {
6408  return NULL;
6409  }
6410 
6411  regu_dbval_type_init (dbval, TP_DOMAIN_TYPE (domain));
6412  arith->domain = (TP_DOMAIN *) domain;
6413  arith->value = dbval;
6414  arith->opcode = op;
6415  arith->leftptr = (REGU_VARIABLE *) arg1;
6416  arith->rightptr = (REGU_VARIABLE *) arg2;
6417  arith->thirdptr = (REGU_VARIABLE *) arg3;
6418  arith->pred = NULL;
6419  arith->rand_seed = NULL;
6420  regu->type = TYPE_INARITH;
6421  regu->value.arithptr = arith;
6422 
6423  return regu;
6424 }
6425 
6426 /*
6427  * pt_make_regu_pred () - takes a pred expr and makes a special arith
6428  * regu variable, with T_PREDICATE as opcode,
6429  * that holds the predicate expression.
6430  *
6431  * return: A NULL return indicates an error occurred
6432  * pred(in):
6433  */
6434 static REGU_VARIABLE *
6436 {
6437  REGU_VARIABLE *regu = NULL;
6438  ARITH_TYPE *arith = NULL;
6439  DB_VALUE *dbval = NULL;
6440  TP_DOMAIN *domain = NULL;
6441 
6442  if (pred == NULL)
6443  {
6444  return NULL;
6445  }
6446 
6447  regu_alloc (arith);
6448  regu_alloc (dbval);
6449  regu_alloc (regu);
6450 
6451  if (arith == NULL || dbval == NULL || regu == NULL)
6452  {
6453  return NULL;
6454  }
6455 
6457  if (domain == NULL)
6458  {
6459  return NULL;
6460  }
6461  regu->domain = domain;
6462  regu_dbval_type_init (dbval, TP_DOMAIN_TYPE (domain));
6463  arith->domain = (TP_DOMAIN *) domain;
6464  arith->value = dbval;
6465  arith->opcode = T_PREDICATE;
6466  arith->leftptr = NULL;
6467  arith->rightptr = NULL;
6468  arith->thirdptr = NULL;
6469  arith->pred = (PRED_EXPR *) pred;
6470  arith->rand_seed = NULL;
6471  regu->type = TYPE_INARITH;
6472  regu->value.arithptr = arith;
6473 
6474  return regu;
6475 }
6476 
6477 /*
6478  * pt_make_vid () - takes a pt_data_type and a regu variable and makes
6479  * a regu vid function
6480  * return: A NULL return indicates an error occurred
6481  * parser(in):
6482  * data_type(in):
6483  * regu3(in):
6484  */
6485 static REGU_VARIABLE *
6487 {
6488  REGU_VARIABLE *regu = NULL;
6489  REGU_VARIABLE *regu1 = NULL;
6490  REGU_VARIABLE *regu2 = NULL;
6491  DB_VALUE *value1, *value2;
6492  DB_OBJECT *virt;
6493  OID virt_oid, proxy_oid;
6494  DB_IDENTIFIER *dbid;
6495 
6496  if (!data_type || !regu3)
6497  {
6498  return NULL;
6499  }
6500 
6501  virt = data_type->info.data_type.virt_object;
6502  if (virt)
6503  {
6504  /* make sure its oid is a good one */
6505  dbid = db_identifier (virt);
6506  if (!dbid)
6507  {
6508  return NULL;
6509  }
6510  virt_oid = *dbid;
6511  }
6512  else
6513  {
6514  OID_SET_NULL (&virt_oid);
6515  }
6516 
6517  OID_SET_NULL (&proxy_oid);
6518 
6519  regu_alloc (value1);
6520  regu_alloc (value2);
6521  if (!value1 || !value2)
6522  {
6523  return NULL;
6524  }
6525 
6526  db_make_oid (value1, &virt_oid);
6527  db_make_oid (value2, &proxy_oid);
6528 
6529  regu1 = pt_make_regu_constant (parser, value1, DB_TYPE_OID, NULL);
6530  regu2 = pt_make_regu_constant (parser, value2, DB_TYPE_OID, NULL);
6531  if (!regu1 || !regu2)
6532  {
6533  return NULL;
6534  }
6535 
6536  regu_alloc (regu);
6537  if (!regu)
6538  {
6539  PT_ERROR (parser, data_type,
6541  return NULL;
6542  }
6543 
6544  regu->type = TYPE_FUNC;
6545 
6546  /* we just use the standard vanilla vobj domain */
6547  regu->domain = &tp_Vobj_domain;
6548  regu_alloc (regu->value.funcp);
6549  if (!regu->value.funcp)
6550  {
6551  PT_ERROR (parser, data_type,
6553  return NULL;
6554  }
6555 
6556  regu->value.funcp->ftype = F_VID;
6557  regu_alloc (regu->value.funcp->operand);
6558  if (!regu->value.funcp->operand)
6559  {
6560  PT_ERROR (parser, data_type,
6562  return NULL;
6563  }
6564 
6565  regu->value.funcp->operand->value = *regu1;
6566  regu_alloc (regu->value.funcp->operand->next);
6567  if (!regu->value.funcp->operand->next)
6568  {
6569  PT_ERROR (parser, data_type,
6571  return NULL;
6572  }
6573 
6574  regu->value.funcp->operand->next->value = *regu2;
6575  regu_alloc (regu->value.funcp->operand->next->next);
6576  if (!regu->value.funcp->operand->next->next)
6577  {
6578  PT_ERROR (parser, data_type,
6580  return NULL;
6581  }
6582 
6583  regu->value.funcp->operand->next->next->value = *regu3;
6584  regu->value.funcp->operand->next->next->next = NULL;
6585 
6586  regu->flags = regu3->flags;
6587 
6588  regu_dbval_type_init (regu->value.funcp->value, DB_TYPE_VOBJ);
6589 
6590  return regu;
6591 }
6592 
6593 
6594 /*
6595  * pt_make_function () - takes a pt_data_type and a regu variable and makes
6596  * a regu function
6597  * return: A NULL return indicates an error occurred
6598  * parser(in):
6599  * function_code(in):
6600  * arg_list(in):
6601  * result_type(in):
6602  * node(in):
6603  */
6604 static REGU_VARIABLE *
6605 pt_make_function (PARSER_CONTEXT * parser, int function_code, const REGU_VARIABLE_LIST arg_list,
6606  const DB_TYPE result_type, const PT_NODE * node)
6607 {
6608  REGU_VARIABLE *regu;
6609  TP_DOMAIN *domain;
6610 
6611  regu_alloc (regu);
6612  if (!regu)
6613  {
6614  return NULL;
6615  }
6616 
6617  domain = pt_xasl_node_to_domain (parser, node);
6618  regu->type = TYPE_FUNC;
6619  regu->domain = domain;
6620  regu_alloc (regu->value.funcp);
6621 
6622  if (regu->value.funcp)
6623  {
6624  regu->value.funcp->operand = arg_list;
6625  regu->value.funcp->ftype = (FUNC_TYPE) function_code;
6626  if (node->info.function.hidden_column)
6627  {
6629  }
6630 
6631  regu_dbval_type_init (regu->value.funcp->value, result_type);
6632  regu->value.funcp->tmp_obj = NULL;
6633  }
6634 
6635  return regu;
6636 }
6637 
6638 
6639 /*
6640  * pt_function_to_regu () - takes a PT_FUNCTION and converts to a regu_variable
6641  * return: A NULL return indicates an error occurred
6642  * parser(in):
6643  * function(in/out):
6644  *
6645  * Note :
6646  * currently only aggregate functions are known and handled
6647  */
6648 static REGU_VARIABLE *
6650 {
6651  REGU_VARIABLE *regu = NULL;
6652  DB_VALUE *dbval;
6653  bool is_aggregate, is_analytic;
6654  REGU_VARIABLE_LIST args;
6655  DB_TYPE result_type = DB_TYPE_SET;
6656 
6657  is_aggregate = pt_is_aggregate_function (parser, function);
6658  is_analytic = function->info.function.analytic.is_analytic;
6659 
6660  if (is_aggregate || is_analytic)
6661  {
6662  /* This procedure assumes that pt_to_aggregate () / pt_to_analytic () has already run, setting up the DB_VALUE
6663  * for the aggregate value. */
6664  dbval = (DB_VALUE *) function->etc;
6665  if (dbval)
6666  {
6667  regu_alloc (regu);
6668  if (regu)
6669  {
6670  regu->type = TYPE_CONSTANT;
6671  regu->domain = pt_xasl_node_to_domain (parser, function);
6672  regu->value.dbvalptr = dbval;
6673  }
6674  else
6675  {
6676  PT_ERROR (parser, function,
6679  return NULL;
6680  }
6681  }
6682  else
6683  {
6685  }
6686  }
6687  else
6688  {
6689  /* change the generic code to the server side generic code */
6690  if (function->info.function.function_type == PT_GENERIC)
6691  {
6692  function->info.function.function_type = F_GENERIC;
6693  }
6694 
6695  if (function->info.function.function_type < F_TOP_TABLE_FUNC)
6696  {
6697  args = pt_to_regu_variable_list (parser, function->info.function.arg_list, UNBOX_AS_TABLE, NULL, NULL);
6698  }
6699  else
6700  {
6701  args = pt_to_regu_variable_list (parser, function->info.function.arg_list, UNBOX_AS_VALUE, NULL, NULL);
6702  }
6703 
6704  switch (function->info.function.function_type)
6705  {
6706  case F_SET:
6707  case F_TABLE_SET:
6708  result_type = DB_TYPE_SET;
6709  break;
6710  case F_MULTISET:
6711  case F_TABLE_MULTISET:
6712  result_type = DB_TYPE_MULTISET;
6713  break;
6714  case F_SEQUENCE:
6715  case F_TABLE_SEQUENCE:
6716  result_type = DB_TYPE_SEQUENCE;
6717  break;
6718  case F_MIDXKEY:
6719  result_type = DB_TYPE_MIDXKEY;
6720  break;
6721  case F_VID:
6722  result_type = DB_TYPE_VOBJ;
6723  break;
6724  case F_GENERIC:
6725  result_type = pt_node_to_db_type (function);
6726  break;
6727  case F_CLASS_OF:
6728  result_type = DB_TYPE_OID;
6729  break;
6730  case F_INSERT_SUBSTRING:
6731  case F_ELT:
6732  case F_REGEXP_COUNT:
6733  case F_REGEXP_INSTR:
6734  case F_REGEXP_LIKE:
6735  case F_REGEXP_REPLACE:
6736  case F_REGEXP_SUBSTR:
6737  result_type = pt_node_to_db_type (function);
6738  break;
6739  case F_BENCHMARK:
6740  case F_JSON_ARRAY:
6741  case F_JSON_ARRAY_APPEND:
6742  case F_JSON_ARRAY_INSERT:
6743  case F_JSON_CONTAINS:
6744  case F_JSON_CONTAINS_PATH:
6745  case F_JSON_DEPTH:
6746  case F_JSON_EXTRACT:
6747  case F_JSON_GET_ALL_PATHS:
6748  case F_JSON_KEYS:
6749  case F_JSON_INSERT:
6750  case F_JSON_LENGTH:
6751  case F_JSON_MERGE:
6752  case F_JSON_MERGE_PATCH:
6753  case F_JSON_OBJECT:
6754  case F_JSON_PRETTY:
6755  case F_JSON_QUOTE:
6756  case F_JSON_REMOVE:
6757  case F_JSON_REPLACE:
6758  case F_JSON_SEARCH:
6759  case F_JSON_SET:
6760  case F_JSON_TYPE:
6761  case F_JSON_UNQUOTE:
6762  case F_JSON_VALID:
6763  result_type = pt_node_to_db_type (function);
6764  break;
6765  default:
6766  PT_ERRORf (parser, function, "Internal error in generate(%d)", __LINE__);
6767  }
6768 
6769  if (args)
6770  {
6771  regu = pt_make_function (parser, function->info.function.function_type, args, result_type, function);
6772  if (DB_TYPE_VOBJ == pt_node_to_db_type (function) && function->info.function.function_type != F_VID)
6773  {
6774  regu = pt_make_vid (parser, function->data_type, regu);
6775  }
6776  }
6777  }
6778 
6779  return regu;
6780 }
6781 
6782 /*
6783  * pt_make_regu_subquery () - Creates a regu variable that executes a
6784  * sub-query and stores its results.
6785  *
6786  * return : Pointer to generated regu variable.
6787  * parser (in) : Parser context.
6788  * xasl (in) : XASL node for sub-query.
6789  * unbox (in) : UNBOX value (as table or as value).
6790  * node (in) : Parse tree node for sub-query.
6791  */
6792 static REGU_VARIABLE *
6793 pt_make_regu_subquery (PARSER_CONTEXT * parser, XASL_NODE * xasl, const UNBOX unbox, const PT_NODE * node)
6794 {
6795  REGU_VARIABLE *regu = NULL;
6796  QFILE_SORTED_LIST_ID *srlist_id = NULL;
6797 
6798  if (xasl)
6799  {
6800  regu_alloc (regu);
6801  if (!regu)
6802  {
6803  return NULL;
6804  }
6805 
6806  regu->domain = pt_xasl_node_to_domain (parser, node);
6807 
6808  /* set as linked to regu var */
6810  regu->xasl = xasl;
6811 
6812  xasl->is_single_tuple = (unbox != UNBOX_AS_TABLE);
6813  if (xasl->is_single_tuple)
6814  {
6815  if (!xasl->single_tuple)
6816  {
6817  xasl->single_tuple = pt_make_val_list (parser, (PT_NODE *) node);
6818  }
6819 
6820  if (xasl->single_tuple)
6821  {
6822  regu->type = TYPE_CONSTANT;
6823  regu->value.dbvalptr = xasl->single_tuple->valp->val;
6824  }
6825  else
6826  {
6828  regu = NULL;
6829  }
6830  }
6831  else
6832  {
6833  regu_alloc (srlist_id);
6834  if (srlist_id)
6835  {
6836  regu->type = TYPE_LIST_ID;
6837  regu->value.srlist_id = srlist_id;
6838  srlist_id->list_id = xasl->list_id;
6839  }
6840  else
6841  {
6842  regu = NULL;
6843  }
6844  }
6845  }
6846 
6847  return regu;
6848 }
6849 
6850 /*
6851  * pt_make_regu_insert () - Creates a regu variable that executes an insert
6852  * statement and stored the OID of inserted object.
6853  *
6854  * return : Pointer to generated regu variable.
6855  * parser (in) : Parser context.
6856  * statement (in) : Parse tree node for insert statement.
6857  */
6858 static REGU_VARIABLE *
6860 {
6861  XASL_NODE *xasl = NULL;
6862  REGU_VARIABLE *regu = NULL;
6863 
6864  if (statement == NULL || statement->node_type != PT_INSERT)
6865  {
6866  assert (false);
6867  return NULL;
6868  }
6869 
6870  /* Generate xasl for insert statement */
6871  xasl = pt_to_insert_xasl (parser, statement);
6872  if (xasl == NULL)
6873  {
6874  return NULL;
6875  }
6876 
6877  /* Create the value to store the inserted object */
6878  xasl->proc.insert.obj_oid = db_value_create ();
6879  if (xasl->proc.insert.obj_oid == NULL)
6880  {
6881  return NULL;
6882  }
6883 
6884  regu_alloc (regu);
6885  if (regu == NULL)
6886  {
6887  return regu;
6888  }
6889  regu->domain = pt_xasl_node_to_domain (parser, statement);
6890 
6891  /* set as linked to regu var */
6893  regu->xasl = xasl;
6894  regu->type = TYPE_CONSTANT;
6895  regu->value.dbvalptr = xasl->proc.insert.obj_oid;
6896 
6897  return regu;
6898 }
6899 
6900 /*
6901  * pt_set_numbering_node_etc_pre () -
6902  * return:
6903  * parser(in):
6904  * node(in/out):
6905  * arg(in/out):
6906  * continue_walk(in):
6907  */
6908 static PT_NODE *
6909 pt_set_numbering_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
6910 {
6912 
6913  if (node->node_type == PT_EXPR)
6914  {
6915  if (info->instnum_valp && (node->info.expr.op == PT_INST_NUM || node->info.expr.op == PT_ROWNUM))
6916  {
6917  if (*info->instnum_valp == NULL)
6918  {
6919  regu_alloc (*info->instnum_valp);
6920  }
6921 
6922  node->etc = *info->instnum_valp;
6923  }
6924 
6925  if (info->ordbynum_valp && node->info.expr.op == PT_ORDERBY_NUM)
6926  {
6927  if (*info->ordbynum_valp == NULL)
6928  {
6929  regu_alloc (*info->ordbynum_valp);
6930  }
6931 
6932  node->etc = *info->ordbynum_valp;
6933  }
6934  }
6935  else if (node->node_type != PT_FUNCTION && node->node_type != PT_SORT_SPEC)
6936  {
6937  /* don't continue if it's not an expression, function or sort spec (analytic window's ORDER BY ROWNUM and
6938  * PARTITION BY ROWNUM) */
6939  *continue_walk = PT_STOP_WALK;
6940  }
6941 
6942  return node;
6943 }
6944 
6945 /*
6946  * pt_get_numbering_node_etc () - get the DB_VALUE reference of the
6947  * ORDERBY_NUM expression
6948  * return : node
6949  * parser (in) : parser context
6950  * node (in) : node
6951  * arg (in) : pointer to DB_VALUE *
6952  * continue_walk (in) :
6953  */
6954 PT_NODE *
6955 pt_get_numbering_node_etc (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
6956 {
6957  if (node == NULL)
6958  {
6959  return node;
6960  }
6961 
6962  if (PT_IS_EXPR_NODE (node) && node->info.expr.op == PT_ORDERBY_NUM)
6963  {
6964  DB_VALUE **val_ptr = (DB_VALUE **) arg;
6965  *continue_walk = PT_STOP_WALK;
6966  *val_ptr = (DB_VALUE *) node->etc;
6967  }
6968 
6969  return node;
6970 }
6971 
6972 /*
6973  * pt_set_numbering_node_etc () - set etc values of parse tree nodes INST_NUM
6974  * and ORDERBY_NUM to pointers of corresponding
6975  * reguvars from XASL node
6976  * return:
6977  * parser(in):
6978  * node_list(in):
6979  * instnum_valp(out):
6980  * ordbynum_valp(out):
6981  */
6982 void
6984  DB_VALUE ** ordbynum_valp)
6985 {
6986  PT_NODE *node, *save_node, *save_next;
6988 
6989  if (node_list)
6990  {
6991  info.instnum_valp = instnum_valp;
6992  info.ordbynum_valp = ordbynum_valp;
6993 
6994  for (node = node_list; node; node = node->next)
6995  {
6996  save_node = node;
6997 
6998  CAST_POINTER_TO_NODE (node);
6999 
7000  if (node)
7001  {
7002  /* save and cut-off node link */
7003  save_next = node->next;
7004  node->next = NULL;
7005 
7006  (void) parser_walk_tree (parser, node, pt_set_numbering_node_etc_pre, &info, pt_continue_walk, NULL);
7007 
7008  node->next = save_next;
7009  }
7010 
7011  node = save_node;
7012  }
7013  }
7014 }
7015 
7016 
7017 /*
7018  * pt_make_regu_numbering () - make a regu_variable constant for
7019  * inst_num() and orderby_num()
7020  * return:
7021  * parser(in):
7022  * node(in):
7023  */
7024 static REGU_VARIABLE *
7026 {
7027  REGU_VARIABLE *regu = NULL;
7028  DB_VALUE *dbval;
7029 
7030  /* 'etc' field of PT_NODEs which belong to inst_num() or orderby_num() expression was set to points to
7031  * XASL_INSTNUM_VAL() or XASL_ORDBYNUM_VAL() by pt_set_numbering_node_etc() */
7032  dbval = (DB_VALUE *) node->etc;
7033 
7034  if (dbval)
7035  {
7036  regu_alloc (regu);
7037  if (regu)
7038  {
7039  regu->type = TYPE_CONSTANT;
7040  regu->domain = pt_xasl_node_to_domain (parser, node);
7041  regu->value.dbvalptr = dbval;
7042  }
7043  }
7044  else
7045  {
7046  if (parser && !pt_has_error (parser))
7047  {
7048  switch (node->info.expr.op)
7049  {
7050  case PT_INST_NUM:
7051  case PT_ROWNUM:
7053  "INST_NUM() or ROWNUM");
7054  break;
7055 
7056  case PT_ORDERBY_NUM:
7058  "ORDERBY_NUM()");
7059  break;
7060 
7061  default:
7062  assert (false);
7063 
7064  }
7065  }
7066  }
7067 
7068  return regu;
7069 }
7070 
7071 
7072 /*
7073  * pt_to_misc_operand () - maps PT_MISC_TYPE of PT_LEADING, PT_TRAILING,
7074  * PT_BOTH, PT_YEAR, PT_MONTH, PT_DAY, PT_HOUR, PT_MINUTE, and PT_SECOND
7075  * to the corresponding MISC_OPERAND
7076  * return:
7077  * regu(in/out):
7078  * misc_specifier(in):
7079  */
7080 static void
7082 {
7083  if (regu && regu->value.arithptr)
7084  {
7085  regu->value.arithptr->misc_operand = pt_misc_to_qp_misc_operand (misc_specifier);
7086  }
7087 }
7088 
7089 /*
7090  * pt_make_prim_data_type_fortonum () -
7091  * return:
7092  * parser(in):
7093  * prec(in):
7094  * scale(in):
7095  */
7096 PT_NODE *
7098 {
7099  PT_NODE *dt = NULL;
7100 
7101  dt = parser_new_node (parser, PT_DATA_TYPE);
7102  if (dt == NULL)
7103  {
7104  return NULL;
7105  }
7106 
7107  if (prec > DB_MAX_NUMERIC_PRECISION || scale > DB_MAX_NUMERIC_PRECISION || prec < 0 || scale < 0)
7108  {
7109  parser_free_tree (parser, dt);
7110  dt = NULL;
7111  return NULL;
7112  }
7113 
7114  dt->type_enum = PT_TYPE_NUMERIC;
7115  dt->info.data_type.precision = prec;
7116  dt->info.data_type.dec_precision = scale;
7117 
7118  return dt;
7119 }
7120 
7121 /*
7122  * pt_make_prim_data_type () -
7123  * return:
7124  * parser(in):
7125  * e(in):
7126  */
7127 PT_NODE *
7129 {
7130  PT_NODE *dt = NULL;
7131 
7132  dt = parser_new_node (parser, PT_DATA_TYPE);
7133 
7134  if (dt == NULL)
7135  {
7136  PT_INTERNAL_ERROR (parser, "allocate new node");
7137  return NULL;
7138  }
7139 
7140  dt->type_enum = e;
7142 
7143  if (PT_HAS_COLLATION (e))
7144  {
7147  }
7148 
7149  switch (e)
7150  {
7151  case PT_TYPE_INTEGER:
7152  case PT_TYPE_BIGINT:
7153  case PT_TYPE_SMALLINT:
7154  case PT_TYPE_DOUBLE:
7155  case PT_TYPE_DATE:
7156  case PT_TYPE_TIME:
7157  case PT_TYPE_TIMESTAMP:
7158  case PT_TYPE_TIMESTAMPTZ:
7159  case PT_TYPE_TIMESTAMPLTZ:
7160  case PT_TYPE_DATETIME:
7161  case PT_TYPE_DATETIMETZ:
7162  case PT_TYPE_DATETIMELTZ:
7163  case PT_TYPE_MONETARY:
7164  case PT_TYPE_BLOB:
7165  case PT_TYPE_CLOB:
7166  case PT_TYPE_JSON:
7167  dt->data_type = NULL;
7168  break;
7169 
7170  case PT_TYPE_CHAR:
7172  break;
7173 
7174  case PT_TYPE_NCHAR:
7176  break;
7177 
7178  case PT_TYPE_VARCHAR:
7180  break;
7181 
7182  case PT_TYPE_VARNCHAR:
7184  break;
7185 
7186  case PT_TYPE_BIT:
7189  break;
7190 
7191  case PT_TYPE_VARBIT:
7194  break;
7195 
7196  case PT_TYPE_NUMERIC:
7199  break;
7200 
7201  default:
7202  /* error handling is required.. */
7203  parser_free_tree (parser, dt);
7204  dt = NULL;
7205  }
7206 
7207  return dt;
7208 }
7209 
7210 /*
7211  * pt_to_regu_resolve_domain () -
7212  * return:
7213  * p_precision(out):
7214  * p_scale(out):
7215  * node(in):
7216  */
7217 void
7218 pt_to_regu_resolve_domain (int *p_precision, int *p_scale, const PT_NODE * node)
7219 {
7220  const char *format_buf;
7221  const char *fbuf_end_ptr;
7222  int format_sz;
7223  int precision, scale, maybe_sci_notation = 0;
7224 
7225  if (node == NULL)
7226  {
7227  *p_precision = DB_MAX_NUMERIC_PRECISION;
7228  *p_scale = DB_DEFAULT_NUMERIC_SCALE;
7229  }
7230  else
7231  {
7232  switch (node->info.value.db_value.data.ch.info.style)
7233  {
7234  case SMALL_STRING:
7235  format_sz = node->info.value.db_value.data.ch.sm.size;
7236  format_buf = (char *) node->info.value.db_value.data.ch.sm.buf;
7237  break;
7238 
7239  case MEDIUM_STRING:
7240  format_sz = node->info.value.db_value.data.ch.medium.size;
7241  format_buf = node->info.value.db_value.data.ch.medium.buf;
7242  break;
7243 
7244  default:
7245  format_sz = 0;
7246  format_buf = NULL;
7247  }
7248 
7249  fbuf_end_ptr = format_buf + format_sz - 1;
7250 
7251  precision = scale = 0;
7252 
7253  /* analyze format string */
7254  if (format_sz > 0)
7255  {
7256  /* skip white space or CR prefix */
7257  while (format_buf < fbuf_end_ptr && (*format_buf == ' ' || *format_buf == '\t' || *format_buf == '\n'))
7258  {
7259  format_buf++;
7260  }
7261 
7262  while (*format_buf != '.' && format_buf <= fbuf_end_ptr)
7263  {
7264  switch (*format_buf)
7265  {
7266  case '9':
7267  case '0':
7268  precision++;
7269  break;
7270  case '+':
7271  case '-':
7272  case ',':
7273  case ' ':
7274  case '\t':
7275  case '\n':
7276  break;
7277 
7278  case 'c':
7279  case 'C':
7280  case 's':
7281  case 'S':
7282  if (precision == 0)
7283  {
7284  break;
7285  }
7286  /* FALLTHRU */
7287 
7288  default:
7289  maybe_sci_notation = 1;
7290  }
7291  format_buf++;
7292  }
7293 
7294  if (*format_buf == '.')
7295  {
7296  format_buf++;
7297  while (format_buf <= fbuf_end_ptr)
7298  {
7299  switch (*format_buf)
7300  {
7301  case '9':
7302  case '0':
7303  scale++;
7304  case '+':
7305  case '-':
7306  case ',':
7307  case ' ':
7308  case '\t':
7309  case '\n':
7310  break;
7311 
7312  default:
7313  maybe_sci_notation = 1;
7314  }
7315  format_buf++;
7316  }
7317  }
7318 
7319  precision += scale;
7320  }
7321 
7322  if (!maybe_sci_notation && (precision + scale) < DB_MAX_NUMERIC_PRECISION)
7323  {
7324  *p_precision = precision;
7325  *p_scale = scale;
7326  }
7327  else
7328  {
7329  *p_precision = DB_MAX_NUMERIC_PRECISION;
7330  *p_scale = DB_DEFAULT_NUMERIC_PRECISION;
7331  }
7332  }
7333 }
7334 
7335 /*
7336  * pt_make_prefix_index_data_filter () - make data filter for index
7337  * with prefix
7338  * return: the resulting data filter for index with prefix
7339  * where_key_part(in): the key filter
7340  * where_part(in): the data filter
7341  * index_pred (in): the range
7342  */
7343 static PT_NODE *
7345  QO_XASL_INDEX_INFO * index_pred)
7346 {
7347  PT_NODE *ipl_where_part = NULL;
7348  PT_NODE *diff_part;
7349  PT_NODE *ipl_if_part, *ipl_instnum_part;
7350  int i;
7351  PT_NODE *save_next = NULL;
7352 
7353  assert (parser != NULL);
7354 
7355  ipl_where_part = parser_copy_tree_list (parser, where_part);
7356  if ((index_pred == NULL || (index_pred && index_pred->nterms <= 0)) && where_key_part == NULL)
7357  {
7358  return ipl_where_part;
7359  }
7360 
7361  if (where_key_part)
7362  {
7363  diff_part = parser_get_tree_list_diff (parser, where_key_part, where_part);
7364  ipl_where_part = parser_append_node (diff_part, ipl_where_part);
7365  }
7366 
7367  if (index_pred && index_pred->nterms > 0)
7368  {
7369  PT_NODE *save_last = NULL;
7370  if (where_part)
7371  {
7372  save_last = where_part;
7373  while (save_last->next)
7374  {
7375  save_last = save_last->next;
7376  }
7377  save_last->next = where_key_part;
7378  }
7379  else
7380  {
7381  where_part = where_key_part;
7382  }
7383 
7384  for (i = 0; i < index_pred->nterms; i++)
7385  {
7386  save_next = index_pred->term_exprs[i]->next;
7387  index_pred->term_exprs[i]->next = NULL;
7388  diff_part = parser_get_tree_list_diff (parser, index_pred->term_exprs[i], where_part);
7389  pt_split_if_instnum (parser, diff_part, &ipl_if_part, &ipl_instnum_part);
7390  ipl_where_part = parser_append_node (ipl_if_part, ipl_where_part);
7391  parser_free_tree (parser, ipl_instnum_part);
7392  index_pred->term_exprs[i]->next = save_next;
7393  }
7394 
7395  if (save_last)
7396  {
7397  save_last->next = NULL;
7398  }
7399  else
7400  {
7401  where_part = NULL;
7402  }
7403  }
7404 
7405  return ipl_where_part;
7406 }
7407 
7408 /*
7409  * pt_to_regu_variable () - converts a parse expression tree to regu_variables
7410  * return:
7411  * parser(in):
7412  * node(in): should be something that will evaluate to an expression
7413  * of names and constant
7414  * unbox(in):
7415  */
7416 REGU_VARIABLE *
7418 {
7419  REGU_VARIABLE *regu = NULL;
7420  XASL_NODE *xasl;
7421  DB_VALUE *value, *val = NULL;
7422  TP_DOMAIN *domain;
7423  PT_NODE *data_type = NULL;
7424  PT_NODE *save_node = NULL, *save_next = NULL;
7425  REGU_VARIABLE *r1 = NULL, *r2 = NULL, *r3 = NULL;
7426 
7427  if (node == NULL)
7428  {
7429  regu_alloc (val);
7431  {
7432  regu = pt_make_regu_constant (parser, val, DB_TYPE_VARCHAR, NULL);
7433  }
7434  }
7435  else if (PT_IS_POINTER_REF_NODE (node))
7436  {
7437  PT_NODE *real_node = node->info.pointer.node;
7438 
7439  CAST_POINTER_TO_NODE (real_node);
7440 
7441  /* fetch domain from real node data type */
7442  domain = NULL;
7443  if (real_node != NULL && real_node->data_type != NULL)
7444  {
7445  domain = pt_node_data_type_to_db_domain (parser, real_node->data_type, real_node->type_enum);
7446 
7447  if (domain != NULL)
7448  {
7449  /* cache domain */
7450  domain = tp_domain_cache (domain);
7451  }
7452  }
7453 
7454  /* resolve to value domain if no domain was present */
7455  if (domain == NULL)
7456  {
7457  domain = tp_domain_resolve_value ((DB_VALUE *) node->etc, NULL);
7458  }
7459 
7460  /* set up regu var */
7461  regu_alloc (regu);
7462  regu->type = TYPE_CONSTANT;
7463  regu->domain = domain;
7464  regu->value.dbvalptr = (DB_VALUE *) node->etc;
7465  }
7466  else
7467  {
7468  save_node = node;
7469 
7470  CAST_POINTER_TO_NODE (node);
7471 
7472  if (node != NULL && node->type_enum == PT_TYPE_LOGICAL
7473  && (node->node_type == PT_EXPR || node->node_type == PT_VALUE))
7474  {
7475  regu = pt_make_regu_pred (pt_to_pred_expr (parser, node));
7476  }
7477  else if (node != NULL)
7478  {
7479  /* save and cut-off node link */
7480  save_next = node->next;
7481  node->next = NULL;
7482 
7483  switch (node->node_type)
7484  {
7485  case PT_DOT_:
7486  /* a path expression. XASL fetch procs or equivalent should already be done for it return the regu
7487  * variable for the right most name in the path expression. */
7488  switch (node->info.dot.arg2->info.name.meta_class)
7489  {
7490  case PT_PARAMETER:
7491  regu_alloc (val);
7492  pt_evaluate_tree (parser, node, val, 1);
7493  if (!pt_has_error (parser))
7494  {
7495  regu = pt_make_regu_constant (parser, val, pt_node_to_db_type (node), node);
7496  }
7497  break;
7498  case PT_META_ATTR:
7499  case PT_NORMAL:
7500  case PT_SHARED:
7501  default:
7502  regu = pt_attribute_to_regu (parser, node->info.dot.arg2);
7503  break;
7504  }
7505  break;
7506 
7507  case PT_METHOD_CALL:
7508  /* a method call that can be evaluated as a constant expression. */
7509  regu_alloc (val);
7510  pt_evaluate_tree (parser, node, val, 1);
7511  if (!pt_has_error (parser))
7512  {
7513  regu = pt_make_regu_constant (parser, val, pt_node_to_db_type (node), node);
7514  }
7515  break;
7516 
7517  case PT_EXPR:
7518  if (node->info.expr.op == PT_FUNCTION_HOLDER)
7519  {
7520  //TODO FIND WHY NEXT WASN'T RESTORED
7521  node->next = save_next;
7522  regu = pt_function_to_regu (parser, node->info.expr.arg1);
7523  return regu;
7524  }
7525 
7527  {
7528  if (parser->symbols && parser->symbols->query_node)
7529  {
7530  if ((parser->symbols->query_node->node_type != PT_SELECT)
7531  || (parser->symbols->query_node->info.query.q.select.connect_by == NULL))
7532  {
7533  const char *opcode = pt_show_binopcode (node->info.expr.op);
7534  char *temp_buffer = (char *) malloc (strlen (opcode) + 1);
7535  if (temp_buffer)
7536  {
7537  strcpy (temp_buffer, opcode);
7538  ustr_upper (temp_buffer);
7539  }
7541  temp_buffer ? temp_buffer : opcode);
7542  if (temp_buffer)
7543  {
7544  free (temp_buffer);
7545  }
7546  }
7547  if (node->info.expr.op == PT_CONNECT_BY_ISCYCLE
7548  && ((parser->symbols->query_node->node_type != PT_SELECT)
7549  || (parser->symbols->query_node->info.query.q.select.check_cycles !=
7551  && parser->symbols->query_node->info.query.q.select.check_cycles !=
7553  {
7554  PT_ERRORm (parser, node, MSGCAT_SET_PARSER_SEMANTIC,
7556  }
7557  }
7558  else
7559  {
7560  assert (false);
7561  }
7562  }
7563  domain = NULL;
7564  if (node->info.expr.op == PT_PLUS || node->info.expr.op == PT_MINUS || node->info.expr.op == PT_TIMES
7565  || node->info.expr.op == PT_DIVIDE || node->info.expr.op == PT_MODULUS
7566  || node->info.expr.op == PT_POWER || node->info.expr.op == PT_AES_ENCRYPT
7567  || node->info.expr.op == PT_AES_DECRYPT || node->info.expr.op == PT_SHA_TWO
7568  || node->info.expr.op == PT_ROUND || node->info.expr.op == PT_LOG || node->info.expr.op == PT_TRUNC
7569  || node->info.expr.op == PT_POSITION || node->info.expr.op == PT_FINDINSET
7570  || node->info.expr.op == PT_LPAD || node->info.expr.op == PT_RPAD || node->info.expr.op == PT_REPLACE
7571  || node->info.expr.op == PT_TRANSLATE || node->info.expr.op == PT_ADD_MONTHS
7572  || node->info.expr.op == PT_MONTHS_BETWEEN || node->info.expr.op == PT_FORMAT
7573  || node->info.expr.op == PT_ATAN || node->info.expr.op == PT_ATAN2
7574  || node->info.expr.op == PT_DATE_FORMAT || node->info.expr.op == PT_STR_TO_DATE
7575  || node->info.expr.op == PT_TIME_FORMAT || node->info.expr.op == PT_DATEDIFF
7576  || node->info.expr.op == PT_TIMEDIFF || node->info.expr.op == PT_TO_NUMBER
7577  || node->info.expr.op == PT_LEAST || node->info.expr.op == PT_GREATEST
7578  || node->info.expr.op == PT_CASE || node->info.expr.op == PT_NULLIF
7579  || node->info.expr.op == PT_COALESCE || node->info.expr.op == PT_NVL
7580  || node->info.expr.op == PT_DECODE || node->info.expr.op == PT_STRCAT
7581  || node->info.expr.op == PT_SYS_CONNECT_BY_PATH || node->info.expr.op == PT_BIT_AND
7582  || node->info.expr.op == PT_BIT_OR || node->info.expr.op == PT_BIT_XOR
7583  || node->info.expr.op == PT_BITSHIFT_LEFT || node->info.expr.op == PT_BITSHIFT_RIGHT
7584  || node->info.expr.op == PT_DIV || node->info.expr.op == PT_MOD || node->info.expr.op == PT_IFNULL
7585  || node->info.expr.op == PT_CONCAT || node->info.expr.op == PT_LEFT || node->info.expr.op == PT_RIGHT
7586  || node->info.expr.op == PT_STRCMP || node->info.expr.op == PT_REPEAT
7587  || node->info.expr.op == PT_WEEKF || node->info.expr.op == PT_MAKEDATE
7588  || node->info.expr.op == PT_ADDTIME || node->info.expr.op == PT_DEFINE_VARIABLE
7589  || node->info.expr.op == PT_CHR || node->info.expr.op == PT_CLOB_TO_CHAR
7590  || node->info.expr.op == PT_INDEX_PREFIX || node->info.expr.op == PT_FROM_TZ)
7591  {
7592  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7593  if ((node->info.expr.op == PT_CONCAT) && node->info.expr.arg2 == NULL)
7594  {
7595  r2 = NULL;
7596  }
7597  else
7598  {
7599  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7600  }
7601  if (node->info.expr.op != PT_ADD_MONTHS && node->info.expr.op != PT_MONTHS_BETWEEN
7602  && node->info.expr.op != PT_TO_NUMBER)
7603  {
7604  if (node->type_enum == PT_TYPE_MAYBE)
7605  {
7606  if (pt_is_op_hv_late_bind (node->info.expr.op))
7607  {
7608  domain = pt_xasl_node_to_domain (parser, node);
7609  }
7610  else
7611  {
7612  domain = node->expected_domain;
7613  }
7614  }
7615  else
7616  {
7617  domain = pt_xasl_node_to_domain (parser, node);
7618  }
7619  if (domain == NULL)
7620  {
7621  goto end_expr_op_switch;
7622  }
7623  }
7624 
7625  if (node->info.expr.op == PT_SYS_CONNECT_BY_PATH)
7626  {
7627  regu_alloc (r3);
7628  r3->domain = pt_xasl_node_to_domain (parser, node);
7629  r3->xasl = (XASL_NODE *) node->etc;
7630  r3->type = TYPE_CONSTANT;
7631  r3->value.dbvalptr = NULL;
7632  }
7633 
7634  if (node->info.expr.op == PT_ATAN && node->info.expr.arg2 == NULL)
7635  {
7636  /* If ATAN has only one arg, treat it as an unary op */
7637  r2 = r1;
7638  r1 = NULL;
7639  }
7640 
7641  if (node->info.expr.op == PT_DATE_FORMAT || node->info.expr.op == PT_STR_TO_DATE
7642  || node->info.expr.op == PT_TIME_FORMAT || node->info.expr.op == PT_FORMAT
7643  || node->info.expr.op == PT_INDEX_PREFIX)
7644  {
7645  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7646  }
7647  }
7648  else if (node->info.expr.op == PT_DEFAULTF)
7649  {
7650  assert (false);
7651  regu = NULL;
7652  }
7653  else if (node->info.expr.op == PT_UNIX_TIMESTAMP)
7654  {
7655  r1 = NULL;
7656  if (!node->info.expr.arg1)
7657  {
7658  r2 = NULL;
7659  }
7660  else
7661  {
7662  r2 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7663  }
7664  if (node->type_enum == PT_TYPE_MAYBE)
7665  {
7666  assert (false);
7667  domain = node->expected_domain;
7668  }
7669  else
7670  {
7671  domain = pt_xasl_node_to_domain (parser, node);
7672  }
7673  if (domain == NULL)
7674  {
7675  goto end_expr_op_switch;
7676  }
7677  }
7678  else if (node->info.expr.op == PT_UNARY_MINUS || node->info.expr.op == PT_RAND
7679  || node->info.expr.op == PT_DRAND || node->info.expr.op == PT_RANDOM
7680  || node->info.expr.op == PT_DRANDOM || node->info.expr.op == PT_FLOOR
7681  || node->info.expr.op == PT_CEIL || node->info.expr.op == PT_SIGN || node->info.expr.op == PT_EXP
7682  || node->info.expr.op == PT_SQRT || node->info.expr.op == PT_ACOS
7683  || node->info.expr.op == PT_ASIN || node->info.expr.op == PT_COS || node->info.expr.op == PT_SIN
7684  || node->info.expr.op == PT_TAN || node->info.expr.op == PT_COT
7685  || node->info.expr.op == PT_DEGREES || node->info.expr.op == PT_DATEF
7686  || node->info.expr.op == PT_TIMEF || node->info.expr.op == PT_RADIANS
7687  || node->info.expr.op == PT_LN || node->info.expr.op == PT_LOG2 || node->info.expr.op == PT_LOG10
7688  || node->info.expr.op == PT_ABS || node->info.expr.op == PT_OCTET_LENGTH
7689  || node->info.expr.op == PT_BIT_LENGTH || node->info.expr.op == PT_CHAR_LENGTH
7690  || node->info.expr.op == PT_LOWER || node->info.expr.op == PT_UPPER
7691  || node->info.expr.op == PT_HEX || node->info.expr.op == PT_ASCII
7692  || node->info.expr.op == PT_LAST_DAY || node->info.expr.op == PT_CAST
7693  || node->info.expr.op == PT_EXTRACT || node->info.expr.op == PT_ENCRYPT
7694  || node->info.expr.op == PT_DECRYPT || node->info.expr.op == PT_BIN
7695  || node->info.expr.op == PT_MD5 || node->info.expr.op == PT_SHA_ONE
7696  || node->info.expr.op == PT_SPACE || node->info.expr.op == PT_PRIOR
7697  || node->info.expr.op == PT_CONNECT_BY_ROOT || node->info.expr.op == PT_QPRIOR
7698  || node->info.expr.op == PT_BIT_NOT || node->info.expr.op == PT_REVERSE
7699  || node->info.expr.op == PT_BIT_COUNT || node->info.expr.op == PT_ISNULL
7700  || node->info.expr.op == PT_TYPEOF || node->info.expr.op == PT_YEARF
7701  || node->info.expr.op == PT_MONTHF || node->info.expr.op == PT_DAYF
7702  || node->info.expr.op == PT_DAYOFMONTH || node->info.expr.op == PT_HOURF
7703  || node->info.expr.op == PT_MINUTEF || node->info.expr.op == PT_SECONDF
7704  || node->info.expr.op == PT_QUARTERF || node->info.expr.op == PT_WEEKDAY
7705  || node->info.expr.op == PT_DAYOFWEEK || node->info.expr.op == PT_DAYOFYEAR
7706  || node->info.expr.op == PT_TODAYS || node->info.expr.op == PT_FROMDAYS
7707  || node->info.expr.op == PT_TIMETOSEC || node->info.expr.op == PT_SECTOTIME
7709  || node->info.expr.op == PT_INET_ATON || node->info.expr.op == PT_INET_NTOA
7710  || node->info.expr.op == PT_CHARSET || node->info.expr.op == PT_COLLATION
7711  || node->info.expr.op == PT_TO_BASE64 || node->info.expr.op == PT_FROM_BASE64
7712  || node->info.expr.op == PT_FROM_BASE64 || node->info.expr.op == PT_SLEEP
7713  || node->info.expr.op == PT_TZ_OFFSET || node->info.expr.op == PT_CRC32
7714  || node->info.expr.op == PT_DISK_SIZE || node->info.expr.op == PT_CONV_TZ)
7715  {
7716  r1 = NULL;
7717 
7718  if (node->info.expr.op == PT_PRIOR)
7719  {
7720  PT_NODE *saved_current_class;
7721 
7722  /* we want TYPE_CONSTANT regu vars in PRIOR arg expr */
7723  saved_current_class = parser->symbols->current_class;
7724  parser->symbols->current_class = NULL;
7725 
7726  r2 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7727 
7728  parser->symbols->current_class = saved_current_class;
7729  }
7730  else
7731  {
7732  r2 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7733  }
7734 
7735  if (node->info.expr.op == PT_CONNECT_BY_ROOT || node->info.expr.op == PT_QPRIOR)
7736  {
7737  regu_alloc (r3);
7738  r3->domain = pt_xasl_node_to_domain (parser, node);
7739  r3->xasl = (XASL_NODE *) node->etc;
7740  r3->type = TYPE_CONSTANT;
7741  r3->value.dbvalptr = NULL;
7742  }
7743 
7744  if (node->info.expr.op != PT_LAST_DAY && node->info.expr.op != PT_CAST)
7745  {
7746  if (node->type_enum == PT_TYPE_MAYBE)
7747  {
7748  if (pt_is_op_hv_late_bind (node->info.expr.op))
7749  {
7750  domain = pt_xasl_node_to_domain (parser, node);
7751  }
7752  else
7753  {
7754  domain = node->expected_domain;
7755  }
7756  }
7757  else
7758  {
7759  domain = pt_xasl_node_to_domain (parser, node);
7760  }
7761  if (domain == NULL)
7762  {
7763  goto end_expr_op_switch;
7764  }
7765  }
7766  }
7767  else if (node->info.expr.op == PT_TIMESTAMP || node->info.expr.op == PT_LIKE_LOWER_BOUND
7768  || node->info.expr.op == PT_LIKE_UPPER_BOUND)
7769  {
7770  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7771  if (!node->info.expr.arg2)
7772  {
7773  r2 = NULL;
7774  }
7775  else
7776  {
7777  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7778  }
7779 
7780  domain = pt_xasl_node_to_domain (parser, node);
7781  if (domain == NULL)
7782  {
7783  goto end_expr_op_switch;
7784  }
7785  }
7786  else if (node->info.expr.op == PT_DATE_ADD || node->info.expr.op == PT_DATE_SUB)
7787  {
7788  DB_VALUE *val;
7789 
7790  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7791  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7792  /* store the info.expr.qualifier which is the unit parameter into a constant regu variable */
7793  regu_alloc (val);
7794  if (val)
7795  {
7796  db_make_int (val, node->info.expr.arg3->info.expr.qualifier);
7797  r3 = pt_make_regu_constant (parser, val, DB_TYPE_INTEGER, NULL);
7798  }
7799 
7800  if (node->type_enum == PT_TYPE_MAYBE)
7801  {
7802  domain = node->expected_domain;
7803  }
7804  else
7805  {
7806  domain = pt_xasl_node_to_domain (parser, node);
7807  }
7808  if (domain == NULL)
7809  {
7810  goto end_expr_op_switch;
7811  }
7812  }
7813  else if (node->info.expr.op == PT_ADDDATE || node->info.expr.op == PT_SUBDATE)
7814  {
7815  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7816  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7817 
7818  if (node->type_enum == PT_TYPE_MAYBE)
7819  {
7820  domain = node->expected_domain;
7821  }
7822  else
7823  {
7824  domain = pt_xasl_node_to_domain (parser, node);
7825  }
7826  if (domain == NULL)
7827  {
7828  goto end_expr_op_switch;
7829  }
7830  }
7831  else if (node->info.expr.op == PT_INCR || node->info.expr.op == PT_DECR || node->info.expr.op == PT_INSTR
7832  || node->info.expr.op == PT_SUBSTRING || node->info.expr.op == PT_NVL2
7833  || node->info.expr.op == PT_CONCAT_WS || node->info.expr.op == PT_FIELD
7834  || node->info.expr.op == PT_LOCATE || node->info.expr.op == PT_MID
7835  || node->info.expr.op == PT_SUBSTRING_INDEX || node->info.expr.op == PT_MAKETIME
7836  || node->info.expr.op == PT_INDEX_CARDINALITY || node->info.expr.op == PT_NEW_TIME)
7837  {
7838  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7839  if (node->info.expr.arg2 == NULL && node->info.expr.op == PT_CONCAT_WS)
7840  {
7841  r2 = NULL;
7842  }
7843  else
7844  {
7845  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7846  }
7847 
7848  if (node->info.expr.arg3 == NULL
7849  && (node->info.expr.op == PT_LOCATE || node->info.expr.op == PT_SUBSTRING))
7850  {
7851  r3 = NULL;
7852  }
7853  else
7854  {
7855  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7856  }
7857  if (node->type_enum == PT_TYPE_MAYBE)
7858  {
7859  if (pt_is_op_hv_late_bind (node->info.expr.op))
7860  {
7861  domain = pt_xasl_node_to_domain (parser, node);
7862  }
7863  else
7864  {
7865  domain = node->expected_domain;
7866  }
7867  }
7868  else
7869  {
7870  domain = pt_xasl_node_to_domain (parser, node);
7871  }
7872  if (domain == NULL)
7873  {
7874  goto end_expr_op_switch;
7875  }
7876  }
7877  else if (node->info.expr.op == PT_CONV)
7878  {
7879  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7880  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7881  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7882  domain = pt_xasl_node_to_domain (parser, node);
7883  if (domain == NULL)
7884  {
7885  goto end_expr_op_switch;
7886  }
7887  }
7888  else if (node->info.expr.op == PT_TO_CHAR || node->info.expr.op == PT_TO_DATE
7889  || node->info.expr.op == PT_TO_TIME || node->info.expr.op == PT_TO_TIMESTAMP
7890  || node->info.expr.op == PT_TO_DATETIME || node->info.expr.op == PT_TO_DATETIME_TZ
7891  || node->info.expr.op == PT_TO_TIMESTAMP_TZ)
7892  {
7893  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7894  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7895  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7896  }
7897  else if (node->info.expr.op == PT_SYS_DATE || node->info.expr.op == PT_CURRENT_DATE
7898  || node->info.expr.op == PT_SYS_TIME || node->info.expr.op == PT_CURRENT_TIME
7899  || node->info.expr.op == PT_SYS_TIMESTAMP || node->info.expr.op == PT_CURRENT_TIMESTAMP
7900  || node->info.expr.op == PT_SYS_DATETIME || node->info.expr.op == PT_CURRENT_DATETIME
7901  || node->info.expr.op == PT_UTC_TIME || node->info.expr.op == PT_UTC_DATE
7902  || node->info.expr.op == PT_PI || node->info.expr.op == PT_LOCAL_TRANSACTION_ID
7903  || node->info.expr.op == PT_ROW_COUNT || node->info.expr.op == PT_LIST_DBS
7904  || node->info.expr.op == PT_SYS_GUID || node->info.expr.op == PT_LAST_INSERT_ID
7905  || node->info.expr.op == PT_DBTIMEZONE || node->info.expr.op == PT_SESSIONTIMEZONE
7906  || node->info.expr.op == PT_UTC_TIMESTAMP)
7907  {
7908  domain = pt_xasl_node_to_domain (parser, node);
7909  if (domain == NULL)
7910  {
7911  goto end_expr_op_switch;
7912  }
7913  }
7914  else if (node->info.expr.op == PT_BIT_TO_BLOB || node->info.expr.op == PT_CHAR_TO_BLOB
7915  || node->info.expr.op == PT_BLOB_LENGTH || node->info.expr.op == PT_CHAR_TO_CLOB
7916  || node->info.expr.op == PT_CLOB_LENGTH)
7917  {
7918  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7919  r2 = NULL;
7920  r3 = NULL;
7921  }
7922  else if (node->info.expr.op == PT_BLOB_TO_BIT)
7923  {
7924  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7925  if (node->info.expr.arg2 == NULL)
7926  {
7927  r2 = NULL;
7928  }
7929  else
7930  {
7931  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7932  }
7933  r3 = NULL;
7934  }
7935  else if (node->info.expr.op == PT_IF)
7936  {
7937  r1 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7938  r2 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7939 
7940  if (node->type_enum == PT_TYPE_MAYBE)
7941  {
7942  domain = node->expected_domain;
7943  }
7944  else
7945  {
7946  domain = pt_xasl_node_to_domain (parser, node);
7947  }
7948  if (domain == NULL)
7949  {
7950  goto end_expr_op_switch;
7951  }
7952  }
7953  else if (node->info.expr.op == PT_EXEC_STATS)
7954  {
7955  r1 = NULL;
7956  r2 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7957  r3 = NULL;
7958 
7959  domain = pt_xasl_node_to_domain (parser, node);
7960  if (domain == NULL)
7961  {
7962  goto end_expr_op_switch;
7963  }
7964  }
7965  else if (node->info.expr.op == PT_WIDTH_BUCKET)
7966  {
7967  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
7968  r2 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
7969  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
7970 
7971  domain = pt_xasl_node_to_domain (parser, node);
7972  if (domain == NULL)
7973  {
7974  goto end_expr_op_switch;
7975  }
7976  }
7977  else if (node->info.expr.op == PT_TRACE_STATS)
7978  {
7979  r1 = NULL;
7980  r2 = NULL;
7981  r3 = NULL;
7982 
7983  domain = pt_xasl_node_to_domain (parser, node);
7984  if (domain == NULL)
7985  {
7986  goto end_expr_op_switch;
7987  }
7988  }
7989 
7990  switch (node->info.expr.op)
7991  {
7992  case PT_PLUS:
7993  regu = pt_make_regu_arith (r1, r2, NULL, T_ADD, domain);
7994  break;
7995 
7996  case PT_MINUS:
7997  regu = pt_make_regu_arith (r1, r2, NULL, T_SUB, domain);
7998  break;
7999 
8000  case PT_TIMES:
8001  regu = pt_make_regu_arith (r1, r2, NULL, T_MUL, domain);
8002  break;
8003 
8004  case PT_DIVIDE:
8005  regu = pt_make_regu_arith (r1, r2, NULL, T_DIV, domain);
8006  break;
8007 
8008  case PT_UNARY_MINUS:
8009  regu = pt_make_regu_arith (r1, r2, NULL, T_UNMINUS, domain);
8010  break;
8011 
8012  case PT_BIT_NOT:
8013  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_NOT, domain);
8014  break;
8015 
8016  case PT_BIT_AND:
8017  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_AND, domain);
8018  break;
8019 
8020  case PT_BIT_OR:
8021  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_OR, domain);
8022  break;
8023 
8024  case PT_BIT_XOR:
8025  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_XOR, domain);
8026  break;
8027 
8028  case PT_BITSHIFT_LEFT:
8029  regu = pt_make_regu_arith (r1, r2, NULL, T_BITSHIFT_LEFT, domain);
8030  break;
8031 
8032  case PT_BITSHIFT_RIGHT:
8033  regu = pt_make_regu_arith (r1, r2, NULL, T_BITSHIFT_RIGHT, domain);
8034  break;
8035 
8036  case PT_DIV:
8037  regu = pt_make_regu_arith (r1, r2, NULL, T_INTDIV, domain);
8038  break;
8039 
8040  case PT_MOD:
8041  regu = pt_make_regu_arith (r1, r2, NULL, T_INTMOD, domain);
8042  break;
8043 
8044  case PT_IF:
8045  regu = pt_make_regu_arith (r1, r2, NULL, T_IF, domain);
8046  if (regu == NULL)
8047  {
8048  break;
8049  }
8050  regu->value.arithptr->pred = pt_to_pred_expr (parser, node->info.expr.arg1);
8051  break;
8052 
8053  case PT_IFNULL:
8054  regu = pt_make_regu_arith (r1, r2, NULL, T_IFNULL, domain);
8055  break;
8056 
8057  case PT_CONCAT:
8058  regu = pt_make_regu_arith (r1, r2, NULL, T_CONCAT, domain);
8059  break;
8060  case PT_CONCAT_WS:
8061  regu = pt_make_regu_arith (r1, r2, r3, T_CONCAT_WS, domain);
8062  break;
8063 
8064  case PT_FIELD:
8066  regu = pt_make_regu_arith (r1, r2, r3, T_FIELD, domain);
8067 
8068  if (node->info.expr.arg3 && node->info.expr.arg3->next
8069  && node->info.expr.arg3->next->info.value.data_value.i == 1)
8070  {
8071  /* bottom level T_FIELD */
8073  }
8074  break;
8075 
8076  case PT_LEFT:
8077  regu = pt_make_regu_arith (r1, r2, NULL, T_LEFT, domain);
8078  break;
8079 
8080  case PT_RIGHT:
8081  regu = pt_make_regu_arith (r1, r2, NULL, T_RIGHT, domain);
8082  break;
8083 
8084  case PT_REPEAT:
8085  regu = pt_make_regu_arith (r1, r2, NULL, T_REPEAT, domain);
8086  break;
8087 
8088  case PT_TIME_FORMAT:
8089  regu = pt_make_regu_arith (r1, r2, r3, T_TIME_FORMAT, domain);
8090  break;
8091 
8092  case PT_DATE_SUB:
8093  regu = pt_make_regu_arith (r1, r2, r3, T_DATE_SUB, domain);
8094  break;
8095 
8096  case PT_DATE_ADD:
8097  regu = pt_make_regu_arith (r1, r2, r3, T_DATE_ADD, domain);
8098  break;
8099 
8100  case PT_LOCATE:
8101  regu = pt_make_regu_arith (r1, r2, r3, T_LOCATE, domain);
8102  break;
8103 
8104  case PT_MID:
8105  regu = pt_make_regu_arith (r1, r2, r3, T_MID, domain);
8106  break;
8107 
8108  case PT_STRCMP:
8109  regu = pt_make_regu_arith (r1, r2, NULL, T_STRCMP, domain);
8110  break;
8111 
8112  case PT_REVERSE:
8113  regu = pt_make_regu_arith (r1, r2, NULL, T_REVERSE, domain);
8114  break;
8115 
8116  case PT_DISK_SIZE:
8117  regu = pt_make_regu_arith (r1, r2, NULL, T_DISK_SIZE, domain);
8118  break;
8119 
8120  case PT_BIT_COUNT:
8121  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_COUNT, domain);
8122  break;
8123 
8124  case PT_ISNULL:
8125  regu = pt_make_regu_arith (r1, r2, NULL, T_ISNULL, domain);
8126  break;
8127 
8128  case PT_EVALUATE_VARIABLE:
8129  regu = pt_make_regu_arith (r1, r2, NULL, T_EVALUATE_VARIABLE, domain);
8130  break;
8131 
8132  case PT_DEFINE_VARIABLE:
8133  regu = pt_make_regu_arith (r1, r2, NULL, T_DEFINE_VARIABLE, domain);
8134  break;
8135 
8136  case PT_YEARF:
8137  regu = pt_make_regu_arith (r1, r2, NULL, T_YEAR, domain);
8138  break;
8139 
8140  case PT_MONTHF:
8141  regu = pt_make_regu_arith (r1, r2, NULL, T_MONTH, domain);
8142  break;
8143 
8144  case PT_DAYOFMONTH:
8145  case PT_DAYF:
8146  regu = pt_make_regu_arith (r1, r2, NULL, T_DAY, domain);
8147  break;
8148 
8149  case PT_HOURF:
8150  regu = pt_make_regu_arith (r1, r2, NULL, T_HOUR, domain);
8151  break;
8152 
8153  case PT_MINUTEF:
8154  regu = pt_make_regu_arith (r1, r2, NULL, T_MINUTE, domain);
8155  break;
8156 
8157  case PT_SECONDF:
8158  regu = pt_make_regu_arith (r1, r2, NULL, T_SECOND, domain);
8159  break;
8160 
8161  case PT_UNIX_TIMESTAMP:
8162  regu = pt_make_regu_arith (NULL, r2, NULL, T_UNIX_TIMESTAMP, domain);
8163  break;
8164 
8165  case PT_TIMESTAMP:
8166  regu = pt_make_regu_arith (r1, r2, NULL, T_TIMESTAMP, domain);
8167  break;
8168 
8169  case PT_LIKE_LOWER_BOUND:
8170  regu = pt_make_regu_arith (r1, r2, NULL, T_LIKE_LOWER_BOUND, domain);
8171  break;
8172 
8173  case PT_LIKE_UPPER_BOUND:
8174  regu = pt_make_regu_arith (r1, r2, NULL, T_LIKE_UPPER_BOUND, domain);
8175  break;
8176 
8177  case PT_QUARTERF:
8178  regu = pt_make_regu_arith (r1, r2, NULL, T_QUARTER, domain);
8179  break;
8180 
8181  case PT_WEEKDAY:
8182  regu = pt_make_regu_arith (r1, r2, NULL, T_WEEKDAY, domain);
8183  break;
8184 
8185  case PT_DAYOFWEEK:
8186  regu = pt_make_regu_arith (r1, r2, NULL, T_DAYOFWEEK, domain);
8187  break;
8188 
8189  case PT_DAYOFYEAR:
8190  regu = pt_make_regu_arith (r1, r2, NULL, T_DAYOFYEAR, domain);
8191  break;
8192 
8193  case PT_TODAYS:
8194  regu = pt_make_regu_arith (r1, r2, NULL, T_TODAYS, domain);
8195  break;
8196 
8197  case PT_FROMDAYS:
8198  regu = pt_make_regu_arith (r1, r2, NULL, T_FROMDAYS, domain);
8199  break;
8200 
8201  case PT_TIMETOSEC:
8202  regu = pt_make_regu_arith (r1, r2, NULL, T_TIMETOSEC, domain);
8203  break;
8204 
8205  case PT_SECTOTIME:
8206  regu = pt_make_regu_arith (r1, r2, NULL, T_SECTOTIME, domain);
8207  break;
8208 
8209  case PT_MAKEDATE:
8210  regu = pt_make_regu_arith (r1, r2, NULL, T_MAKEDATE, domain);
8211  break;
8212 
8213  case PT_MAKETIME:
8214  regu = pt_make_regu_arith (r1, r2, r3, T_MAKETIME, domain);
8215  break;
8216 
8217  case PT_NEW_TIME:
8218  regu = pt_make_regu_arith (r1, r2, r3, T_NEW_TIME, domain);
8219  break;
8220 
8221  case PT_ADDTIME:
8222  regu = pt_make_regu_arith (r1, r2, NULL, T_ADDTIME, domain);
8223  break;
8224 
8225  case PT_FROM_TZ:
8226  regu = pt_make_regu_arith (r1, r2, NULL, T_FROM_TZ, domain);
8227  break;
8228 
8229  case PT_WEEKF:
8230  regu = pt_make_regu_arith (r1, r2, NULL, T_WEEK, domain);
8231  break;
8232 
8233  case PT_SCHEMA:
8234  case PT_DATABASE:
8235  {
8236  PT_NODE *dbname_val;
8237  char *dbname;
8238 
8239  dbname_val = parser_new_node (parser, PT_VALUE);
8240  if (dbname_val == NULL)
8241  {
8242  PT_INTERNAL_ERROR (parser, "allocate new node");
8243  return NULL;
8244  }
8245 
8246  dbname = db_get_database_name ();
8247  if (dbname)
8248  {
8249  dbname_val->type_enum = PT_TYPE_VARCHAR;
8250  dbname_val->info.value.string_type = ' ';
8251 
8252  dbname_val->info.value.data_value.str = pt_append_nulstring (parser, NULL, dbname);
8253  PT_NODE_PRINT_VALUE_TO_TEXT (parser, dbname_val);
8254 
8255  db_string_free (dbname);
8256 
8257  /* copy data type (to apply collation and codeset) */
8258  assert (dbname_val->data_type == NULL);
8259  dbname_val->data_type = parser_copy_tree (parser, node->data_type);
8260  assert (dbname_val->data_type->type_enum == dbname_val->type_enum);
8261  }
8262  else
8263  {
8264  dbname_val->type_enum = PT_TYPE_NULL;
8265  }
8266 
8267  regu = pt_to_regu_variable (parser, dbname_val, unbox);
8268  break;
8269  }
8270  case PT_VERSION:
8271  {
8272  PT_NODE *dbversion_val;
8273  char *dbversion;
8274 
8275  dbversion_val = parser_new_node (parser, PT_VALUE);
8276  if (dbversion_val == NULL)
8277  {
8278  PT_INTERNAL_ERROR (parser, "allocate new node");
8279  return NULL;
8280  }
8281 
8282  dbversion = db_get_database_version ();
8283  if (dbversion)
8284  {
8285  dbversion_val->type_enum = node->type_enum;
8286  dbversion_val->info.value.string_type = ' ';
8287 
8288  dbversion_val->info.value.data_value.str = pt_append_nulstring (parser, NULL, dbversion);
8289  PT_NODE_PRINT_VALUE_TO_TEXT (parser, dbversion_val);
8290 
8291  db_string_free (dbversion);
8292 
8293  /* copy data type (to apply collation and codeset) */
8294  assert (dbversion_val->data_type == NULL);
8295  dbversion_val->data_type = parser_copy_tree (parser, node->data_type);
8296  assert (dbversion_val->data_type->type_enum == dbversion_val->type_enum);
8297  }
8298  else
8299  {
8300  dbversion_val->type_enum = PT_TYPE_NULL;
8301  }
8302 
8303  regu = pt_to_regu_variable (parser, dbversion_val, unbox);
8304  break;
8305  }
8306 
8307  case PT_PRIOR:
8308  regu = pt_make_regu_arith (r1, r2, NULL, T_PRIOR, domain);
8309  break;
8310 
8311  case PT_CONNECT_BY_ROOT:
8312  regu = pt_make_regu_arith (r1, r2, r3, T_CONNECT_BY_ROOT, domain);
8313  break;
8314 
8315  case PT_QPRIOR:
8316  regu = pt_make_regu_arith (r1, r2, r3, T_QPRIOR, domain);
8317  break;
8318 
8319  case PT_MODULUS:
8320  regu = pt_make_regu_arith (r1, r2, NULL, T_MOD, domain);
8321  parser->etc = (void *) 1;
8322  break;
8323 
8324  case PT_PI:
8325  regu = pt_make_regu_arith (NULL, NULL, NULL, T_PI, domain);
8326  break;
8327 
8328  case PT_RAND:
8329  regu = pt_make_regu_arith (NULL, r2, NULL, T_RAND, domain);
8330  break;
8331 
8332  case PT_DRAND:
8333  regu = pt_make_regu_arith (NULL, r2, NULL, T_DRAND, domain);
8334  break;
8335 
8336  case PT_RANDOM:
8337  regu = pt_make_regu_arith (NULL, r2, NULL, T_RANDOM, domain);
8338  break;
8339 
8340  case PT_DRANDOM:
8341  regu = pt_make_regu_arith (NULL, r2, NULL, T_DRANDOM, domain);
8342  break;
8343 
8344  case PT_FLOOR:
8345  regu = pt_make_regu_arith (r1, r2, NULL, T_FLOOR, domain);
8346  break;
8347 
8348  case PT_CEIL:
8349  regu = pt_make_regu_arith (r1, r2, NULL, T_CEIL, domain);
8350  break;
8351 
8352  case PT_SIGN:
8353  regu = pt_make_regu_arith (r1, r2, NULL, T_SIGN, domain);
8354  break;
8355 
8356  case PT_POWER:
8357  regu = pt_make_regu_arith (r1, r2, NULL, T_POWER, domain);
8358  break;
8359 
8360  case PT_ROUND:
8361  regu = pt_make_regu_arith (r1, r2, NULL, T_ROUND, domain);
8362  break;
8363 
8364  case PT_LOG:
8365  regu = pt_make_regu_arith (r1, r2, NULL, T_LOG, domain);
8366  break;
8367 
8368  case PT_EXP:
8369  regu = pt_make_regu_arith (r1, r2, NULL, T_EXP, domain);
8370  break;
8371 
8372  case PT_SQRT:
8373  regu = pt_make_regu_arith (r1, r2, NULL, T_SQRT, domain);
8374  break;
8375 
8376  case PT_COS:
8377  regu = pt_make_regu_arith (r1, r2, NULL, T_COS, domain);
8378  break;
8379 
8380  case PT_SIN:
8381  regu = pt_make_regu_arith (r1, r2, NULL, T_SIN, domain);
8382  break;
8383 
8384  case PT_TAN:
8385  regu = pt_make_regu_arith (r1, r2, NULL, T_TAN, domain);
8386  break;
8387 
8388  case PT_COT:
8389  regu = pt_make_regu_arith (r1, r2, NULL, T_COT, domain);
8390  break;
8391 
8392  case PT_ACOS:
8393  regu = pt_make_regu_arith (r1, r2, NULL, T_ACOS, domain);
8394  break;
8395 
8396  case PT_ASIN:
8397  regu = pt_make_regu_arith (r1, r2, NULL, T_ASIN, domain);
8398  break;
8399 
8400  case PT_ATAN:
8401  regu = pt_make_regu_arith (r1, r2, NULL, T_ATAN, domain);
8402  break;
8403 
8404  case PT_ATAN2:
8405  regu = pt_make_regu_arith (r1, r2, NULL, T_ATAN2, domain);
8406  break;
8407 
8408  case PT_DEGREES:
8409  regu = pt_make_regu_arith (r1, r2, NULL, T_DEGREES, domain);
8410  break;
8411 
8412  case PT_DATEF:
8413  regu = pt_make_regu_arith (r1, r2, NULL, T_DATE, domain);
8414  break;
8415 
8416  case PT_TIMEF:
8417  regu = pt_make_regu_arith (r1, r2, NULL, T_TIME, domain);
8418  break;
8419 
8420  case PT_RADIANS:
8421  regu = pt_make_regu_arith (r1, r2, NULL, T_RADIANS, domain);
8422  break;
8423 
8424  case PT_DEFAULTF:
8425  regu = pt_make_regu_arith (r1, r2, NULL, T_DEFAULT, domain);
8426  break;
8427 
8429  /* We should never get here because this function should have disappeared in pt_fold_const_expr () */
8430  assert (false);
8431  regu = NULL;
8432  break;
8433 
8434  case PT_LN:
8435  regu = pt_make_regu_arith (r1, r2, NULL, T_LN, domain);
8436  break;
8437 
8438  case PT_LOG2:
8439  regu = pt_make_regu_arith (r1, r2, NULL, T_LOG2, domain);
8440  break;
8441 
8442  case PT_LOG10:
8443  regu = pt_make_regu_arith (r1, r2, NULL, T_LOG10, domain);
8444  break;
8445 
8446  case PT_FORMAT:
8447  regu = pt_make_regu_arith (r1, r2, r3, T_FORMAT, domain);
8448  break;
8449 
8450  case PT_DATE_FORMAT:
8451  regu = pt_make_regu_arith (r1, r2, r3, T_DATE_FORMAT, domain);
8452  break;
8453 
8454  case PT_STR_TO_DATE:
8455  regu = pt_make_regu_arith (r1, r2, r3, T_STR_TO_DATE, domain);
8456  break;
8457 
8458  case PT_ADDDATE:
8459  regu = pt_make_regu_arith (r1, r2, NULL, T_ADDDATE, domain);
8460  break;
8461 
8462  case PT_DATEDIFF:
8463  regu = pt_make_regu_arith (r1, r2, NULL, T_DATEDIFF, domain);
8464  break;
8465 
8466  case PT_TIMEDIFF:
8467  regu = pt_make_regu_arith (r1, r2, NULL, T_TIMEDIFF, domain);
8468  break;
8469 
8470  case PT_SUBDATE:
8471  regu = pt_make_regu_arith (r1, r2, NULL, T_SUBDATE, domain);
8472  break;
8473 
8474  case PT_TRUNC:
8475  regu = pt_make_regu_arith (r1, r2, NULL, T_TRUNC, domain);
8476  break;
8477 
8478  case PT_INCR:
8479  regu = pt_make_regu_arith (r1, r2, r3, T_INCR, domain);
8480  break;
8481 
8482  case PT_DECR:
8483  regu = pt_make_regu_arith (r1, r2, r3, T_DECR, domain);
8484  break;
8485 
8486  case PT_ABS:
8487  regu = pt_make_regu_arith (r1, r2, NULL, T_ABS, domain);
8488  break;
8489 
8490  case PT_CHR:
8491  regu = pt_make_regu_arith (r1, r2, NULL, T_CHR, domain);
8492  break;
8493 
8494  case PT_INSTR:
8495  regu = pt_make_regu_arith (r1, r2, r3, T_INSTR, domain);
8496  break;
8497 
8498  case PT_POSITION:
8499  regu = pt_make_regu_arith (r1, r2, NULL, T_POSITION, domain);
8500  break;
8501 
8502  case PT_FINDINSET:
8503  regu = pt_make_regu_arith (r1, r2, NULL, T_FINDINSET, domain);
8504  break;
8505 
8506  case PT_SUBSTRING:
8507  regu = pt_make_regu_arith (r1, r2, r3, T_SUBSTRING, domain);
8508  pt_to_misc_operand (regu, node->info.expr.qualifier);
8509  break;
8510 
8511  case PT_SUBSTRING_INDEX:
8512  regu = pt_make_regu_arith (r1, r2, r3, T_SUBSTRING_INDEX, domain);
8513  break;
8514 
8515  case PT_OCTET_LENGTH:
8516  regu = pt_make_regu_arith (r1, r2, NULL, T_OCTET_LENGTH, domain);
8517  break;
8518 
8519  case PT_BIT_LENGTH:
8520  regu = pt_make_regu_arith (r1, r2, NULL, T_BIT_LENGTH, domain);
8521  break;
8522 
8523  case PT_CHAR_LENGTH:
8524  regu = pt_make_regu_arith (r1, r2, NULL, T_CHAR_LENGTH, domain);
8525  break;
8526 
8527  case PT_LOWER:
8528  regu = pt_make_regu_arith (r1, r2, NULL, T_LOWER, domain);
8529  break;
8530 
8531  case PT_UPPER:
8532  regu = pt_make_regu_arith (r1, r2, NULL, T_UPPER, domain);
8533  break;
8534 
8535  case PT_HEX:
8536  regu = pt_make_regu_arith (r1, r2, NULL, T_HEX, domain);
8537  break;
8538 
8539  case PT_ASCII:
8540  regu = pt_make_regu_arith (r1, r2, NULL, T_ASCII, domain);
8541  break;
8542 
8543  case PT_CONV:
8544  regu = pt_make_regu_arith (r1, r2, r3, T_CONV, domain);
8545  break;
8546 
8547  case PT_BIN:
8548  regu = pt_make_regu_arith (r1, r2, NULL, T_BIN, domain);
8549  break;
8550 
8551  case PT_MD5:
8552  regu = pt_make_regu_arith (r1, r2, NULL, T_MD5, domain);
8553  break;
8554 
8555  case PT_SHA_ONE:
8556  regu = pt_make_regu_arith (r1, r2, NULL, T_SHA_ONE, domain);
8557  break;
8558 
8559  case PT_AES_ENCRYPT:
8560  regu = pt_make_regu_arith (r1, r2, NULL, T_AES_ENCRYPT, domain);
8561  break;
8562 
8563  case PT_AES_DECRYPT:
8564  regu = pt_make_regu_arith (r1, r2, NULL, T_AES_DECRYPT, domain);
8565  break;
8566 
8567  case PT_SHA_TWO:
8568  regu = pt_make_regu_arith (r1, r2, NULL, T_SHA_TWO, domain);
8569  break;
8570 
8571  case PT_FROM_BASE64:
8572  regu = pt_make_regu_arith (r1, r2, NULL, T_FROM_BASE64, domain);
8573  break;
8574 
8575  case PT_TO_BASE64:
8576  regu = pt_make_regu_arith (r1, r2, NULL, T_TO_BASE64, domain);
8577  break;
8578 
8579  case PT_SPACE:
8580  regu = pt_make_regu_arith (r1, r2, NULL, T_SPACE, domain);
8581  break;
8582 
8583  case PT_LTRIM:
8584  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
8585  r2 = (node->info.expr.arg2) ? pt_to_regu_variable (parser, node->info.expr.arg2, unbox) : NULL;
8586  domain = pt_xasl_node_to_domain (parser, node);
8587  if (domain == NULL)
8588  {
8589  break;
8590  }
8591  regu = pt_make_regu_arith (r1, r2, NULL, T_LTRIM, domain);
8592  break;
8593 
8594  case PT_RTRIM:
8595  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
8596  r2 = (node->info.expr.arg2) ? pt_to_regu_variable (parser, node->info.expr.arg2, unbox) : NULL;
8597  domain = pt_xasl_node_to_domain (parser, node);
8598  if (domain == NULL)
8599  {
8600  break;
8601  }
8602  regu = pt_make_regu_arith (r1, r2, NULL, T_RTRIM, domain);
8603  break;
8604 
8605  case PT_FROM_UNIXTIME:
8606  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
8607  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
8608  r2 = (node->info.expr.arg2) ? pt_to_regu_variable (parser, node->info.expr.arg2, unbox) : NULL;
8609  domain = pt_xasl_node_to_domain (parser, node);
8610  if (domain == NULL)
8611  {
8612  break;
8613  }
8614  regu = pt_make_regu_arith (r1, r2, r3, T_FROM_UNIXTIME, domain);
8615  break;
8616 
8617  case PT_LPAD:
8618  r3 = (node->info.expr.arg3) ? pt_to_regu_variable (parser, node->info.expr.arg3, unbox) : NULL;
8619  regu = pt_make_regu_arith (r1, r2, r3, T_LPAD, domain);
8620  break;
8621 
8622  case PT_RPAD:
8623  r3 = (node->info.expr.arg3) ? pt_to_regu_variable (parser, node->info.expr.arg3, unbox) : NULL;
8624  regu = pt_make_regu_arith (r1, r2, r3, T_RPAD, domain);
8625  break;
8626 
8627  case PT_REPLACE:
8628  r3 = (node->info.expr.arg3) ? pt_to_regu_variable (parser, node->info.expr.arg3, unbox) : NULL;
8629  regu = pt_make_regu_arith (r1, r2, r3, T_REPLACE, domain);
8630  break;
8631 
8632  case PT_TRANSLATE:
8633  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
8634  regu = pt_make_regu_arith (r1, r2, r3, T_TRANSLATE, domain);
8635  break;
8636 
8637  case PT_ADD_MONTHS:
8638  data_type = pt_make_prim_data_type (parser, PT_TYPE_DATE);
8639  domain = pt_xasl_data_type_to_domain (parser, data_type);
8640 
8641  regu = pt_make_regu_arith (r1, r2, NULL, T_ADD_MONTHS, domain);
8642  parser_free_tree (parser, data_type);
8643  break;
8644 
8645  case PT_LAST_DAY:
8646  data_type = pt_make_prim_data_type (parser, PT_TYPE_DATE);
8647  domain = pt_xasl_data_type_to_domain (parser, data_type);
8648 
8649  regu = pt_make_regu_arith (r1, r2, NULL, T_LAST_DAY, domain);
8650  parser_free_tree (parser, data_type);
8651  break;
8652 
8653  case PT_MONTHS_BETWEEN:
8654  data_type = pt_make_prim_data_type (parser, PT_TYPE_DOUBLE);
8655  domain = pt_xasl_data_type_to_domain (parser, data_type);
8656 
8657  regu = pt_make_regu_arith (r1, r2, NULL, T_MONTHS_BETWEEN, domain);
8658 
8659  parser_free_tree (parser, data_type);
8660  break;
8661 
8662  case PT_SYS_DATE:
8663  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SYS_DATE, domain);
8664  break;
8665 
8666  case PT_CURRENT_DATE:
8667  regu = pt_make_regu_arith (NULL, NULL, NULL, T_CURRENT_DATE, domain);
8668  break;
8669 
8670  case PT_SYS_TIME:
8671  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SYS_TIME, domain);
8672  break;
8673 
8674  case PT_CURRENT_TIME:
8675  regu = pt_make_regu_arith (NULL, NULL, NULL, T_CURRENT_TIME, domain);
8676  break;
8677 
8678  case PT_SYS_TIMESTAMP:
8679  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SYS_TIMESTAMP, domain);
8680  break;
8681 
8682  case PT_CURRENT_TIMESTAMP:
8683  regu = pt_make_regu_arith (NULL, NULL, NULL, T_CURRENT_TIMESTAMP, domain);
8684  break;
8685 
8686  case PT_SYS_DATETIME:
8687  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SYS_DATETIME, domain);
8688  break;
8689 
8690  case PT_CURRENT_DATETIME:
8691  regu = pt_make_regu_arith (NULL, NULL, NULL, T_CURRENT_DATETIME, domain);
8692  break;
8693 
8694  case PT_UTC_TIME:
8695  regu = pt_make_regu_arith (NULL, NULL, NULL, T_UTC_TIME, domain);
8696  break;
8697 
8698  case PT_UTC_DATE:
8699  regu = pt_make_regu_arith (NULL, NULL, NULL, T_UTC_DATE, domain);
8700  break;
8701 
8702  case PT_DBTIMEZONE:
8703  regu = pt_make_regu_arith (NULL, NULL, NULL, T_DBTIMEZONE, domain);
8704  break;
8705 
8706  case PT_SESSIONTIMEZONE:
8707  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SESSIONTIMEZONE, domain);
8708  break;
8709 
8712  break;
8713 
8714  case PT_CURRENT_USER:
8715  {
8716  PT_NODE *current_user_val;
8717  const char *username;
8718 
8719  username = au_user_name ();
8720  if (username == NULL)
8721  {
8722  PT_INTERNAL_ERROR (parser, "get user name");
8723  return NULL;
8724  }
8725 
8726  current_user_val = parser_new_node (parser, PT_VALUE);
8727  if (current_user_val == NULL)
8728  {
8729  db_string_free ((char *) username);
8730  PT_INTERNAL_ERROR (parser, "allocate new node");
8731  return NULL;
8732  }
8733 
8734  current_user_val->type_enum = PT_TYPE_VARCHAR;
8735  current_user_val->info.value.string_type = ' ';
8736  current_user_val->info.value.data_value.str = pt_append_nulstring (parser, NULL, username);
8737  PT_NODE_PRINT_VALUE_TO_TEXT (parser, current_user_val);
8738 
8739  /* copy data type (to apply collation and codeset) */
8740  assert (current_user_val->data_type == NULL);
8741  current_user_val->data_type = parser_copy_tree (parser, node->data_type);
8742  assert (current_user_val->data_type->type_enum == current_user_val->type_enum);
8743 
8744  regu = pt_to_regu_variable (parser, current_user_val, unbox);
8745 
8746  db_string_free ((char *) username);
8747  parser_free_node (parser, current_user_val);
8748  break;
8749  }
8750  case PT_SCHEMA_DEF:
8751  {
8752  /* cannot get here */
8753  assert (false);
8754 
8756  PT_ERRORc (parser, node, er_msg ());
8757 
8758  return NULL;
8759  }
8760  case PT_USER:
8761  {
8762  char *user = NULL;
8763  PT_NODE *current_user_val = NULL;
8764 
8765  user = db_get_user_and_host_name ();
8766  if (user == NULL)
8767  {
8768  assert (er_errid () != NO_ERROR);
8769  PT_INTERNAL_ERROR (parser, "get user name");
8770 
8771  return NULL;
8772  }
8773 
8774  current_user_val = parser_new_node (parser, PT_VALUE);
8775  if (current_user_val == NULL)
8776  {
8777  PT_INTERNAL_ERROR (parser, "allocate new node");
8778  db_private_free (NULL, user);
8779  return NULL;
8780  }
8781  current_user_val->type_enum = PT_TYPE_VARCHAR;
8782  current_user_val->info.value.string_type = ' ';
8783 
8784  current_user_val->info.value.data_value.str = pt_append_nulstring (parser, NULL, user);
8785  PT_NODE_PRINT_VALUE_TO_TEXT (parser, current_user_val);
8786 
8787  /* copy data type (to apply collation and codeset) */
8788  assert (current_user_val->data_type == NULL);
8789  current_user_val->data_type = parser_copy_tree (parser, node->data_type);
8790  assert (current_user_val->data_type->type_enum == current_user_val->type_enum);
8791 
8792  regu = pt_to_regu_variable (parser, current_user_val, unbox);
8793 
8795  parser_free_node (parser, current_user_val);
8796  break;
8797  }
8798 
8799  case PT_ROW_COUNT:
8800  {
8801  regu = pt_make_regu_arith (NULL, r1, NULL, T_ROW_COUNT, domain);
8802  break;
8803  }
8804 
8805  case PT_LAST_INSERT_ID:
8806  {
8807  regu = pt_make_regu_arith (NULL, r1, NULL, T_LAST_INSERT_ID, domain);
8808  break;
8809  }
8810 
8811  case PT_TO_CHAR:
8812  if (node->data_type != NULL)
8813  {
8814  data_type = node->data_type;
8815  }
8816  else
8817  {
8818  data_type = pt_make_prim_data_type (parser, PT_TYPE_VARCHAR);
8820  }
8821  domain = pt_xasl_data_type_to_domain (parser, data_type);
8822 
8823  regu = pt_make_regu_arith (r1, r2, r3, T_TO_CHAR, domain);
8824  if (data_type != node->data_type)
8825  {
8826  parser_free_tree (parser, data_type);
8827  }
8828  break;
8829 
8830  case PT_TO_DATE:
8831  data_type = pt_make_prim_data_type (parser, PT_TYPE_DATE);
8832  domain = pt_xasl_data_type_to_domain (parser, data_type);
8833 
8834  regu = pt_make_regu_arith (r1, r2, r3, T_TO_DATE, domain);
8835 
8836  parser_free_tree (parser, data_type);
8837  break;
8838 
8839  case PT_TO_TIME:
8840  data_type = pt_make_prim_data_type (parser, PT_TYPE_TIME);
8841  domain = pt_xasl_data_type_to_domain (parser, data_type);
8842 
8843  regu = pt_make_regu_arith (r1, r2, r3, T_TO_TIME, domain);
8844  parser_free_tree (parser, data_type);
8845  break;
8846 
8847  case PT_TO_TIMESTAMP:
8848  data_type = pt_make_prim_data_type (parser, PT_TYPE_TIMESTAMP);
8849  domain = pt_xasl_data_type_to_domain (parser, data_type);
8850 
8851  regu = pt_make_regu_arith (r1, r2, r3, T_TO_TIMESTAMP, domain);
8852  parser_free_tree (parser, data_type);
8853  break;
8854 
8855  case PT_TO_DATETIME:
8856  data_type = pt_make_prim_data_type (parser, PT_TYPE_DATETIME);
8857  domain = pt_xasl_data_type_to_domain (parser, data_type);
8858 
8859  regu = pt_make_regu_arith (r1, r2, r3, T_TO_DATETIME, domain);
8860  parser_free_tree (parser, data_type);
8861  break;
8862 
8863  case PT_TO_NUMBER:
8864  {
8865  int precision, scale;
8866 
8867  /* If 2nd argument of to_number() exists, modify domain. */
8868  pt_to_regu_resolve_domain (&precision, &scale, node->info.expr.arg2);
8869  data_type = pt_make_prim_data_type_fortonum (parser, precision, scale);
8870 
8871  /* create NUMERIC domain with default precision and scale. */
8872  domain = pt_xasl_data_type_to_domain (parser, data_type);
8873 
8874  /* If 2nd argument of to_number() exists, modify domain. */
8875  pt_to_regu_resolve_domain (&domain->precision, &domain->scale, node->info.expr.arg2);
8876 
8877  r3 = pt_to_regu_variable (parser, node->info.expr.arg3, unbox);
8878 
8879  /* Note that use the new domain */
8880  regu = pt_make_regu_arith (r1, r2, r3, T_TO_NUMBER, domain);
8881  parser_free_tree (parser, data_type);
8882 
8883  break;
8884  }
8885 
8886  case PT_CURRENT_VALUE:
8887  case PT_NEXT_VALUE:
8888  {
8889  MOP serial_mop;
8890  DB_VALUE dbval;
8891  PT_NODE *serial_obj_node_p = NULL;
8892  PT_NODE *cached_num_node_p = NULL;
8893  int cached_num;
8894  OPERATOR_TYPE op;
8895 
8896  data_type = pt_make_prim_data_type (parser, PT_TYPE_NUMERIC);
8897  domain = pt_xasl_data_type_to_domain (parser, data_type);
8898 
8899  serial_mop = pt_resolve_serial (parser, node->info.expr.arg1);
8900  if (serial_mop != NULL)
8901  {
8902  /* 1st regu var: serial object */
8903  serial_obj_node_p = parser_new_node (parser, PT_VALUE);
8904  if (serial_obj_node_p == NULL)
8905  {
8906  PT_INTERNAL_ERROR (parser, "allocate new node");
8907  return NULL;
8908  }
8909 
8910  serial_obj_node_p->type_enum = PT_TYPE_OBJECT;
8911  serial_obj_node_p->info.value.data_value.op = serial_mop;
8912  r1 = pt_to_regu_variable (parser, serial_obj_node_p, unbox);
8913 
8914  /* 2nd regu var: cached_num */
8915  if (do_get_serial_cached_num (&cached_num, serial_mop) != NO_ERROR)
8916  {
8917  PT_INTERNAL_ERROR (parser, "get serial cached_num");
8918  return NULL;
8919  }
8920 
8921  db_make_int (&dbval, cached_num);
8922  cached_num_node_p = pt_dbval_to_value (parser, &dbval);
8923  if (cached_num_node_p == NULL)
8924  {
8925  PT_INTERNAL_ERROR (parser, "allocate new node");
8926  return NULL;
8927  }
8928 
8929  r2 = pt_to_regu_variable (parser, cached_num_node_p, unbox);
8930 
8931  /* 3rd regu var: num_alloc */
8932  if (node->info.expr.op == PT_NEXT_VALUE)
8933  {
8934  r3 = pt_to_regu_variable (parser, node->info.expr.arg2, unbox);
8935  op = T_NEXT_VALUE;
8936  }
8937  else
8938  {
8939  r3 = NULL;
8940 
8941  op = T_CURRENT_VALUE;
8942  }
8943 
8944  regu = pt_make_regu_arith (r1, r2, r3, op, domain);
8945 
8946  parser_free_tree (parser, cached_num_node_p);
8947  }
8948  else
8949  {
8951  node->info.expr.arg1->info.name.original);
8952  }
8953 
8954  parser_free_tree (parser, data_type);
8955  break;
8956  }
8957 
8958  case PT_TRIM:
8959  r1 = pt_to_regu_variable (parser, node->info.expr.arg1, unbox);
8960  r2 = (node->info.expr.arg2) ? pt_to_regu_variable (parser, node->info.expr.arg2, unbox) : NULL;
8961  domain = pt_xasl_node_to_domain (parser, node);
8962  if (domain == NULL)
8963  {
8964  break;
8965  }
8966  regu = pt_make_regu_arith (r1, r2, NULL, T_TRIM, domain);
8967 
8968  pt_to_misc_operand (regu, node->info.expr.qualifier);
8969  break;
8970 
8971  case PT_INST_NUM:
8972  case PT_ROWNUM:
8973  case PT_ORDERBY_NUM:
8974  regu = pt_make_regu_numbering (parser, node);
8975  break;
8976 
8977  case PT_LEVEL:
8978  regu = pt_make_regu_level (parser, node);
8979  break;
8980 
8981  case PT_CONNECT_BY_ISLEAF:
8982  regu = pt_make_regu_isleaf (parser, node);
8983  break;
8984 
8985  case PT_CONNECT_BY_ISCYCLE:
8986  regu = pt_make_regu_iscycle (parser, node);
8987  break;
8988 
8989  case PT_LEAST:
8990  regu = pt_make_regu_arith (r1, r2, NULL, T_LEAST, domain);
8991  break;
8992 
8993  case PT_GREATEST:
8994  regu = pt_make_regu_arith (r1, r2, NULL, T_GREATEST, domain);
8995  break;
8996 
8997  case PT_CAST:
8998  {
8999  OPERATOR_TYPE op;
9000 
9001  assert (node->node_type == PT_EXPR);
9003  {
9004  op = T_CAST_NOFAIL;
9005  }
9006  else
9007  {
9009  {
9010  op = T_CAST_WRAP;
9011  }
9012  else
9013  {
9014  op = T_CAST;
9015  }
9016  }
9017 
9019  {
9020  PT_NODE *arg = node->info.expr.arg1;
9021 
9022  domain = pt_xasl_data_type_to_domain (parser, node->info.expr.cast_type);
9023  assert (domain->collation_id == PT_GET_COLLATION_MODIFIER (node));
9024  /* COLLATE modifier eliminates extra T_CAST operator with some exceptions: 1. argument is
9025  * PT_NAME; attributes may be fetched from shared DB_VALUEs, and we may end up overwriting
9026  * collation of the same attribute used in another context; 2. argument is a normal CAST
9027  * (without COLLATE modifier) : normal CAST should be executed normally if that CAST is
9028  * changing the charset of its argument */
9029  if (arg != NULL
9030  && (arg->node_type == PT_NAME
9031  || (arg->node_type == PT_EXPR && arg->info.expr.op == PT_CAST
9033  {
9034  regu = pt_make_regu_arith (r1, r2, NULL, op, domain);
9035  }
9036  else
9037  {
9038  regu = r2;
9039  }
9040  regu->domain = domain;
9041  if (!(arg != NULL && arg->node_type == PT_NAME && arg->type_enum == PT_TYPE_ENUMERATION))
9042  {
9044  }
9045  }
9046  else
9047  {
9048  domain = pt_xasl_data_type_to_domain (parser, node->info.expr.cast_type);
9049  regu = pt_make_regu_arith (r1, r2, NULL, op, domain);
9050  }
9051  }
9052  break;
9053 
9054  case PT_CASE:
9055  regu = pt_make_regu_arith (r1, r2, NULL, T_CASE, domain);
9056  if (regu == NULL)
9057  {
9058  break;
9059  }
9060  regu->value.arithptr->pred = pt_to_pred_expr (parser, node->info.expr.arg3);
9061  break;
9062 
9063  case PT_NULLIF:
9064  regu = pt_make_regu_arith (r1, r2, NULL, T_NULLIF, domain);
9065  break;
9066 
9067  case PT_COALESCE:
9068  regu = pt_make_regu_arith (r1, r2, NULL, T_COALESCE, domain);
9069  break;
9070 
9071  case PT_NVL:
9072  regu = pt_make_regu_arith (r1, r2, NULL, T_NVL, domain);
9073  break;
9074 
9075  case PT_NVL2:
9076  regu = pt_make_regu_arith (r1, r2, r3, T_NVL2, domain);
9077  break;
9078 
9079  case PT_DECODE:
9080  regu = pt_make_regu_arith (r1, r2, NULL, T_DECODE, domain);
9081  if (regu == NULL)
9082  {
9083  break;
9084  }
9085  regu->value.arithptr->pred = pt_to_pred_expr (parser, node->info.expr.arg3);
9086  break;
9087 
9088  case PT_EXTRACT:
9089  regu = pt_make_regu_arith (r1, r2, NULL, T_EXTRACT, domain);
9090  pt_to_misc_operand (regu, node->info.expr.qualifier);
9091  break;
9092 
9093  case PT_STRCAT:
9094  regu = pt_make_regu_arith (r1, r2, NULL, T_STRCAT, domain);
9095  break;
9096 
9098  regu = pt_make_regu_arith (r1, r2, r3, T_SYS_CONNECT_BY_PATH, domain);
9099  break;
9100 
9101  case PT_LIST_DBS:
9102  regu = pt_make_regu_arith (NULL, NULL, NULL, T_LIST_DBS, domain);
9103  break;
9104 
9105  case PT_SYS_GUID:
9106  regu = pt_make_regu_arith (NULL, NULL, NULL, T_SYS_GUID, domain);
9107  break;
9108 
9109  case PT_BIT_TO_BLOB:
9110  case PT_CHAR_TO_BLOB:
9111  data_type = pt_make_prim_data_type (parser, PT_TYPE_BLOB);
9112  domain = pt_xasl_data_type_to_domain (parser, data_type);
9113 
9114  regu = pt_make_regu_arith (r1, NULL, NULL, T_BIT_TO_BLOB, domain);
9115  parser_free_tree (parser, data_type);
9116  break;
9117 
9118  case PT_BLOB_TO_BIT:
9119  data_type = pt_make_prim_data_type (parser, PT_TYPE_VARBIT);
9120  domain = pt_xasl_data_type_to_domain (parser, data_type);
9121 
9122  regu = pt_make_regu_arith (r1, r2, NULL, T_BLOB_TO_BIT, domain);
9123  parser_free_tree (parser, data_type);
9124  break;
9125 
9126  case PT_CHAR_TO_CLOB:
9127  data_type = pt_make_prim_data_type (parser, PT_TYPE_CLOB);
9128  domain = pt_xasl_data_type_to_domain (parser, data_type);
9129 
9130  regu = pt_make_regu_arith (r1, NULL, NULL, T_CHAR_TO_CLOB, domain);
9131  parser_free_tree (parser, data_type);
9132  break;
9133 
9134  case PT_CLOB_TO_CHAR:
9135  if (node->data_type == NULL)
9136  {
9137  data_type = pt_make_prim_data_type (parser, PT_TYPE_VARCHAR);
9138  }
9139  else
9140  {
9141  data_type = node->data_type;
9142  }
9143 
9144  domain = pt_xasl_data_type_to_domain (parser, data_type);
9145 
9146  regu = pt_make_regu_arith (r1, r2, NULL, T_CLOB_TO_CHAR, domain);
9147  break;
9148 
9149  case PT_BLOB_LENGTH:
9150  case PT_CLOB_LENGTH:
9151  data_type = pt_make_prim_data_type (parser, PT_TYPE_BIGINT);
9152  domain = pt_xasl_data_type_to_domain (parser, data_type);
9153 
9154  regu = pt_make_regu_arith (r1, NULL, NULL, T_LOB_LENGTH, domain);
9155  parser_free_tree (parser, data_type);
9156  break;
9157 
9158  case PT_TYPEOF:
9159  regu = pt_make_regu_arith (NULL, r2, NULL, T_TYPEOF, domain);
9160  break;
9161 
9162  case PT_INDEX_CARDINALITY:
9163  regu = pt_make_regu_arith (r1, r2, r3, T_INDEX_CARDINALITY, domain);
9164  if (parser->parent_proc_xasl != NULL)
9165  {
9167  }
9168  else
9169  {
9170  /* should not happen */
9171  assert (false);
9172  }
9173  break;
9174 
9175  case PT_EXEC_STATS:
9176  regu = pt_make_regu_arith (r1, r2, r3, T_EXEC_STATS, domain);
9177  break;
9178 
9180  regu = pt_make_regu_arith (NULL, r2, NULL, T_TO_ENUMERATION_VALUE, domain);
9181  break;
9182 
9183  case PT_INET_ATON:
9184  regu = pt_make_regu_arith (r1, r2, NULL, T_INET_ATON, domain);
9185  break;
9186 
9187  case PT_INET_NTOA:
9188  regu = pt_make_regu_arith (r1, r2, NULL, T_INET_NTOA, domain);
9189  break;
9190 
9191  case PT_CHARSET:
9192  regu = pt_make_regu_arith (r1, r2, NULL, T_CHARSET, domain);
9193  break;
9194 
9195  case PT_COLLATION:
9196  regu = pt_make_regu_arith (r1, r2, NULL, T_COLLATION, domain);
9197  break;
9198 
9199  case PT_WIDTH_BUCKET:
9200  regu = pt_make_regu_arith (r1, r2, r3, T_WIDTH_BUCKET, domain);
9201  break;
9202 
9203  case PT_TZ_OFFSET:
9204  regu = pt_make_regu_arith (r1, r2, NULL, T_TZ_OFFSET, domain);
9205  break;
9206 
9207  case PT_CONV_TZ:
9208  regu = pt_make_regu_arith (r1, r2, NULL, T_CONV_TZ, domain);
9209  break;
9210 
9211  case PT_TRACE_STATS:
9212  regu = pt_make_regu_arith (r1, r2, r3, T_TRACE_STATS, domain);
9213  break;
9214 
9215  case PT_INDEX_PREFIX:
9216  regu = pt_make_regu_arith (r1, r2, r3, T_INDEX_PREFIX, domain);
9217  break;
9218 
9219  case PT_SLEEP:
9220  regu = pt_make_regu_arith (r1, r2, r3, T_SLEEP, domain);
9221  break;
9222 
9223  case PT_TO_DATETIME_TZ:
9224  data_type = pt_make_prim_data_type (parser, PT_TYPE_DATETIMETZ);
9225  domain = pt_xasl_data_type_to_domain (parser, data_type);
9226 
9227  regu = pt_make_regu_arith (r1, r2, r3, T_TO_DATETIME_TZ, domain);
9228  parser_free_tree (parser, data_type);
9229  break;
9230 
9231  case PT_TO_TIMESTAMP_TZ:
9232  data_type = pt_make_prim_data_type (parser, PT_TYPE_TIMESTAMPTZ);
9233  domain = pt_xasl_data_type_to_domain (parser, data_type);
9234 
9235  regu = pt_make_regu_arith (r1, r2, r3, T_TO_TIMESTAMP_TZ, domain);
9236  parser_free_tree (parser, data_type);
9237  break;
9238 
9239  case PT_UTC_TIMESTAMP:
9240  regu = pt_make_regu_arith (NULL, NULL, NULL, T_UTC_TIMESTAMP, domain);
9241  break;
9242 
9243  case PT_CRC32:
9244  regu = pt_make_regu_arith (r1, r2, NULL, T_CRC32, domain);
9245  break;
9246 
9247  default:
9248  break;
9249  }
9250 
9251  end_expr_op_switch:
9252 
9253  if (regu && domain)
9254  {
9255  regu->domain = domain;
9256  }
9257  break;
9258 
9259  case PT_HOST_VAR:
9260  regu = pt_make_regu_hostvar (parser, node);
9261  break;
9262 
9263  case PT_NODE_LIST:
9264  regu = pt_make_regu_reguvalues_list (parser, node, unbox);
9265  break;
9266 
9267  case PT_VALUE:
9268  value = pt_value_to_db (parser, node);
9269  if (value)
9270  {
9271  regu = pt_make_regu_constant (parser, value, pt_node_to_db_type (node), node);
9272  }
9273  break;
9274 
9275  case PT_INSERT_VALUE:
9276  /* Create a constant regu variable using the evaluated value */
9277  if (!node->info.insert_value.is_evaluated)
9278  {
9279  assert (false);
9280  break;
9281  }
9282  value = &node->info.insert_value.value;
9283  regu =
9286  break;
9287 
9288  case PT_NAME:
9289  if (node->info.name.meta_class == PT_PARAMETER)
9290  {
9291  value = pt_find_value_of_label (node->info.name.original);
9292  if (value)
9293  {
9294  /* Note that the value in the label table will be destroyed if another assignment is made with
9295  * the same name ! be sure that the lifetime of this regu node will not overlap the processing of
9296  * another statement that may result in label assignment. If this can happen, we'll have to copy
9297  * the value and remember to free it when the regu node goes away */
9298  regu = pt_make_regu_constant (parser, value, pt_node_to_db_type (node), node);
9299  }
9300  else
9301  {
9303  parser_print_tree (parser, node));
9304  }
9305  }
9306  else if (node->info.name.db_object && node->info.name.meta_class != PT_SHARED
9309  {
9310  regu_alloc (val);
9311  pt_evaluate_tree (parser, node, val, 1);
9312  if (!pt_has_error (parser))
9313  {
9314  regu = pt_make_regu_constant (parser, val, pt_node_to_db_type (node), node);
9315  }
9316  }
9317  else
9318  {
9319  regu = pt_attribute_to_regu (parser, node);
9320  }
9321 
9322  if (regu && node->info.name.hidden_column)
9323  {
9325  }
9326 
9327  break;
9328 
9329  case PT_FUNCTION:
9330  regu = pt_function_to_regu (parser, node);
9331  break;
9332 
9333  case PT_SELECT:
9334  case PT_UNION:
9335  case PT_DIFFERENCE:
9336  case PT_INTERSECTION:
9337  xasl = (XASL_NODE *) node->info.query.xasl;
9338 
9339  if (xasl == NULL && !pt_has_error (parser))
9340  {
9341  xasl = parser_generate_xasl (parser, node);
9342  }
9343 
9344  if (xasl)
9345  {
9346  PT_NODE *select_list = pt_get_select_list (parser, node);
9347  if (unbox != UNBOX_AS_TABLE && pt_length_of_select_list (select_list, EXCLUDE_HIDDEN_COLUMNS) != 1)
9348  {
9350  parser_print_tree (parser, node));
9351  }
9352 
9353  regu = pt_make_regu_subquery (parser, xasl, unbox, node);
9354  }
9355  break;
9356 
9357  case PT_INSERT:
9358  regu = pt_make_regu_insert (parser, node);
9359  break;
9360 
9361  default:
9362  /* force error */
9363  regu = NULL;
9364  }
9365 
9366  node->next = save_next;
9367  }
9368 
9369  node = save_node; /* restore */
9370  }
9371 
9372  if (regu == NULL)
9373  {
9374  if (!pt_has_error (parser))
9375  {
9376  PT_INTERNAL_ERROR (parser, "generate var");
9377  }
9378  }
9379 
9380  if (val != NULL)
9381  {
9382  pr_clear_value (val);
9383  }
9384 
9385  return regu;
9386 }
9387 
9388 /*
9389  * pt_make_reserved_value_list () - Allocate an array of dbvalue pointers to
9390  * use as a cache for reserved attribute
9391  * values.
9392  *
9393  * return : Pointer to dbvalue array.
9394  * parser (in) : Parser context.
9395  * type (in) : Reserved name type.
9396  */
9397 static DB_VALUE **
9399 {
9400  DB_VALUE **value_list = NULL;
9401  int start = 0, end = 0, size = 0;
9402 
9403  PT_GET_RESERVED_NAME_FIRST_AND_LAST (type, start, end);
9404  size = end - start + 1;
9405 
9406  // *INDENT-OFF*
9407  regu_array_alloc<DB_VALUE *> (&value_list, size);
9408  // *INDENT-ON*
9409 
9410  if (value_list)
9411  {
9412  /* initialize values */
9413  for (int i = 0; i < size; ++i)
9414  {
9415  regu_alloc (value_list[i]);
9416  if (value_list[i] == NULL)
9417  {
9418  /* memory will be freed later */
9419  return NULL;
9420  }
9421  }
9422  }
9423  return value_list;
9424 }
9425 
9426 
9427 /*
9428  * pt_to_regu_variable_list () - converts a parse expression tree list
9429  * to regu_variable_list
9430  * return: A NULL return indicates an error occurred
9431  * parser(in):
9432  * node_list(in):
9433  * unbox(in):
9434  * value_list(in):
9435  * attr_offsets(in):
9436  */
9437 static REGU_VARIABLE_LIST
9439  int *attr_offsets)
9440 {
9441  REGU_VARIABLE_LIST regu_list = NULL;
9442  REGU_VARIABLE_LIST *tail = NULL;
9443  REGU_VARIABLE *regu;
9444  PT_NODE *node;
9445  int i = 0;
9446 
9447  tail = &regu_list;
9448 
9449  for (node = node_list; node != NULL; node = node->next)
9450  {
9451  regu_alloc (*tail);
9452  regu = pt_to_regu_variable (parser, node, unbox);
9453 
9454  if (attr_offsets && value_list && regu)
9455  {
9456  regu->vfetch_to = pt_index_value (value_list, attr_offsets[i]);
9457  }
9458  i++;
9459 
9460  if (regu && *tail)
9461  {
9462  (*tail)->value = *regu;
9463  tail = &(*tail)->next;
9464  }
9465  else
9466  {
9467  regu_list = NULL;
9468  break;
9469  }
9470  }
9471 
9472  return regu_list;
9473 }
9474 
9475 
9476 /*
9477  * pt_regu_to_dbvalue () -
9478  * return:
9479  * parser(in):
9480  * regu(in):
9481  */
9482 static DB_VALUE *
9484 {
9485  DB_VALUE *val = NULL;
9486 
9487  if (regu->type == TYPE_CONSTANT)
9488  {
9489  val = regu->value.dbvalptr;
9490  }
9491  else if (regu->type == TYPE_DBVAL)
9492  {
9493  val = &regu->value.dbval;
9494  }
9495  else
9496  {
9497  if (!pt_has_error (parser))
9498  {
9499  PT_INTERNAL_ERROR (parser, "generate val");
9500  }
9501  }
9502 
9503  return val;
9504 }
9505 
9506 
9507 /*
9508  * pt_make_position_regu_variable () - converts a parse expression tree list
9509  * to regu_variable_list
9510  * return:
9511  * parser(in):
9512  * node(in):
9513  * i(in):
9514  */
9515 static REGU_VARIABLE *
9517 {
9518  REGU_VARIABLE *regu = NULL;
9519  TP_DOMAIN *domain;
9520 
9521  domain = pt_xasl_node_to_domain (parser, node);
9522 
9523  regu_alloc (regu);
9524 
9525  if (regu)
9526  {
9527  regu->type = TYPE_POSITION;
9528  regu->domain = domain;
9529  regu->value.pos_descr.pos_no = i;
9530  regu->value.pos_descr.dom = domain;
9531  }
9532 
9533  return regu;
9534 }
9535 
9536 
9537 /*
9538  * pt_make_pos_regu_var_from_scratch () - makes a position regu var from scratch
9539  * return:
9540  * dom(in): domain
9541  * fetch_to(in): pointer to the DB_VALUE that will hold the value
9542  * pos_no(in): position
9543  */
9544 static REGU_VARIABLE *
9546 {
9547  REGU_VARIABLE *regu = NULL;
9548 
9549  regu_alloc (regu);
9550  if (regu)
9551  {
9552  regu->type = TYPE_POSITION;
9553  regu->domain = dom;
9554  regu->vfetch_to = fetch_to;
9555  regu->value.pos_descr.pos_no = pos_no;
9556  regu->value.pos_descr.dom = dom;
9557  }
9558 
9559  return regu;
9560 }
9561 
9562 
9563 /*
9564  * pt_to_position_regu_variable_list () - converts a parse expression tree
9565  * list to regu_variable_list
9566  * return:
9567  * parser(in):
9568  * node_list(in):
9569  * value_list(in):
9570  * attr_offsets(in):
9571  */
9572 static REGU_VARIABLE_LIST
9574  int *attr_offsets)
9575 {
9576  REGU_VARIABLE_LIST regu_list = NULL;
9577  REGU_VARIABLE_LIST *tail = NULL;
9578  PT_NODE *node;
9579  int i = 0;
9580 
9581  tail = &regu_list;
9582 
9583  for (node = node_list; node != NULL; node = node->next)
9584  {
9585  regu_alloc (*tail);
9586 
9587  /* it would be better form to call pt_make_position_regu_variable, but this avoids additional allocation do to
9588  * regu variable and regu_variable_list bizarreness. */
9589  if (*tail)
9590  {
9591  TP_DOMAIN *domain = pt_xasl_node_to_domain (parser, node);
9592 
9593  (*tail)->value.type = TYPE_POSITION;
9594  (*tail)->value.domain = domain;
9595 
9596  if (attr_offsets)
9597  {
9598  (*tail)->value.value.pos_descr.pos_no = attr_offsets[i];
9599  }
9600  else
9601  {
9602  (*tail)->value.value.pos_descr.pos_no = i;
9603  }
9604 
9605  (*tail)->value.value.pos_descr.dom = domain;
9606 
9607  if (value_list)
9608  {
9609  if (attr_offsets)
9610  {
9611  (*tail)->value.vfetch_to = pt_index_value (value_list, attr_offsets[i]);
9612  }
9613  else
9614  {
9615  (*tail)->value.vfetch_to = pt_index_value (value_list, i);
9616  }
9617  }
9618 
9619  tail = &(*tail)->next;
9620  i++;
9621  }
9622  else
9623  {
9625  regu_list = NULL;
9626  break;
9627  }
9628  }
9629 
9630  return regu_list;
9631 }
9632 
9633 /*
9634  * pt_to_regu_attr_descr () -
9635  * return: int
9636  * attr_descr(in): pointer to an attribute descriptor
9637  * attr_id(in): attribute id
9638  * type(in): attribute type
9639  */
9640 
9641 static REGU_VARIABLE *
9643  PT_NODE * attr)
9644 {
9645  const char *attr_name = attr->info.name.original;
9646  int attr_id;
9647  SM_DOMAIN *smdomain = NULL;
9648  int sharedp;
9649  REGU_VARIABLE *regu;
9650  ATTR_DESCR *attr_descr;
9651 
9652 
9653  if (sm_att_info (class_object, attr_name, &attr_id, &smdomain, &sharedp, attr->info.name.meta_class == PT_META_ATTR)
9654  != NO_ERROR)
9655  {
9656  return NULL;
9657  }
9658  if (smdomain == NULL)
9659  {
9660  return NULL;
9661  }
9662  regu_alloc (regu);
9663  if (regu == NULL)
9664  {
9665  return NULL;
9666  }
9667 
9668  attr_descr = &regu->value.attr_descr;
9669  attr_descr->reset ();
9670 
9671  regu->type =
9673 
9674  regu->domain = (TP_DOMAIN *) smdomain;
9675  attr_descr->id = attr_id;
9676  attr_descr->cache_attrinfo = cache_attrinfo;
9677 
9678  if (smdomain)
9679  {
9680  attr_descr->type = smdomain->type->id;
9681  }
9682 
9683  return regu;
9684 }
9685 
9686 /*
9687  * pt_to_regu_reserved_name () - Creates a regu variable for a reserved
9688  * attribute.
9689  *
9690  * return : REGU VARIABLE.
9691  * parser (in) : Parser Context.
9692  * attr (in) : Parse tree node for a reserved attribute.
9693  *
9694  * NOTE: parser->symbols must include current_valuelist, and this regu
9695  * variable will point to one of the values in that list.
9696  */
9697 static REGU_VARIABLE *
9699 {
9700  REGU_VARIABLE *regu = NULL;
9701  SYMBOL_INFO *symbols = NULL;
9702  int reserved_id, index;
9703  DB_VALUE **reserved_values = NULL;
9704 
9705  symbols = parser->symbols;
9706  assert (symbols != NULL && symbols->reserved_values != NULL);
9707  reserved_values = symbols->reserved_values;
9708 
9709  CAST_POINTER_TO_NODE (attr);
9710  assert (attr != NULL && attr->node_type == PT_NAME && attr->info.name.meta_class == PT_RESERVED);
9711 
9712  regu_alloc (regu);
9713  if (regu == NULL)
9714  {
9715  return NULL;
9716  }
9717  reserved_id = attr->info.name.reserved_id;
9718  index = pt_reserved_id_to_valuelist_index (parser, (PT_RESERVED_NAME_ID) reserved_id);
9719  if (index == RESERVED_NAME_INVALID)
9720  {
9721  return NULL;
9722  }
9723 
9724  /* set regu variable type */
9725  regu->type = TYPE_CONSTANT;
9726 
9727  /* set regu variable value */
9728  regu->value.dbvalptr = reserved_values[index];
9729 
9730  /* set domain */
9731  regu->domain = pt_xasl_node_to_domain (parser, attr);
9732 
9733  return regu;
9734 }
9735 
9736 /*
9737  * pt_attribute_to_regu () - Convert an attribute spec into a REGU_VARIABLE
9738  * return:
9739  * parser(in):
9740  * attr(in):
9741  *
9742  * Note :
9743  * If "current_class" is non-null, use it to create a TYPE_ATTRID REGU_VARIABLE
9744  * Otherwise, create a TYPE_CONSTANT REGU_VARIABLE pointing to the symbol
9745  * table's value_list DB_VALUE, in the position matching where attr is
9746  * found in attribute_list.
9747  */
9748 static REGU_VARIABLE *
9750 {
9751  REGU_VARIABLE *regu = NULL;
9752  SYMBOL_INFO *symbols;
9753  DB_VALUE *dbval = NULL;
9755  int list_index;
9756 
9757  CAST_POINTER_TO_NODE (attr);
9758 
9759  if (attr && attr->node_type == PT_NAME)
9760  {
9761  symbols = parser->symbols;
9762  }
9763  else
9764  {
9765  symbols = NULL; /* error */
9766  }
9767 
9768  if (symbols && attr)
9769  {
9770  /* check the current scope first */
9771  table_info = pt_find_table_info (attr->info.name.spec_id, symbols->table_info);
9772 
9773  if (table_info)
9774  {
9775  /* We have found the attribute at this scope. If we had not, the attribute must have been a correlated
9776  * reference to an attribute at an outer scope. The correlated case is handled below in this "if" statement's
9777  * "else" clause. Determine if this is relative to a particular class or if the attribute should be relative
9778  * to the placeholder. */
9779 
9780  if (symbols->current_class && (table_info->spec_id == symbols->current_class->info.name.spec_id))
9781  {
9782  /* determine if this is an attribute, or an oid identifier */
9783  if (PT_IS_OID_NAME (attr))
9784  {
9785  regu_alloc (regu);
9786  if (regu)
9787  {
9788  regu->type = TYPE_OID;
9789  regu->domain = pt_xasl_node_to_domain (parser, attr);
9790  }
9791  }
9792  else if (attr->info.name.meta_class == PT_META_CLASS)
9793  {
9794  regu_alloc (regu);
9795  if (regu)
9796  {
9797  regu->type = TYPE_CLASSOID;
9798  regu->domain = pt_xasl_node_to_domain (parser, attr);
9799  }
9800  }
9801  else if (attr->info.name.meta_class == PT_RESERVED)
9802  {
9803  regu = pt_to_regu_reserved_name (parser, attr);
9804  }
9805  else
9806  {
9807  /* this is an attribute reference */
9808  if (symbols->current_class->info.name.db_object)
9809  {
9810  regu =
9812  symbols->cache_attrinfo, attr);
9813  }
9814  else
9815  {
9816  /* system error, we should have understood this name. */
9817  if (!pt_has_error (parser))
9818  {
9819  PT_INTERNAL_ERROR (parser, "generate attr");
9820  }
9821  regu = NULL;
9822  }
9823  }
9824 
9825  if (DB_TYPE_VOBJ == pt_node_to_db_type (attr))
9826  {
9827  regu = pt_make_vid (parser, attr->data_type, regu);
9828  }
9829  }
9830  else if (symbols->current_listfile
9831  && (list_index = pt_find_attribute (parser, attr, symbols->current_listfile)) >= 0)
9832  {
9833  /* add in the listfile attribute offset. This is used primarily for server update and insert constraint
9834  * predicates because the server update prepends two columns onto the select list of the listfile. */
9835  list_index += symbols->listfile_attr_offset;
9836 
9837  if (symbols->listfile_value_list)
9838  {
9839  regu_alloc (regu);
9840  if (regu)
9841  {
9842  regu->domain = pt_xasl_node_to_domain (parser, attr);
9843  regu->type = TYPE_CONSTANT;
9844  dbval = pt_index_value (symbols->listfile_value_list, list_index);
9845 
9846  if (dbval)
9847  {
9848  regu->value.dbvalptr = dbval;
9849  }
9850  else
9851  {
9852  regu = NULL;
9853  }
9854  }
9855  }
9856  else
9857  {
9858  /* here we need the position regu variable to access the list file directly, as in list access spec
9859  * predicate evaluation. */
9860  regu = pt_make_position_regu_variable (parser, attr, list_index);
9861  }
9862  }
9863  else
9864  {
9865  /* Here, we are determining attribute reference information relative to the list of attribute
9866  * placeholders which will be fetched from the class(es). The "type" of the attribute no longer affects
9867  * how the placeholder is referenced. */
9868  regu_alloc (regu);
9869  if (regu)
9870  {
9871  regu->type = TYPE_CONSTANT;
9872  regu->domain = pt_xasl_node_to_domain (parser, attr);
9873  dbval =
9874  pt_index_value (table_info->value_list,
9875  pt_find_attribute (parser, attr, table_info->attribute_list));
9876  if (dbval)
9877  {
9878  regu->value.dbvalptr = dbval;
9879  }
9880  else
9881  {
9882  if (PT_IS_OID_NAME (attr))
9883  {
9884  if (regu)
9885  {
9886  regu->type = TYPE_OID;
9887  regu->domain = pt_xasl_node_to_domain (parser, attr);
9888  }
9889  }
9890  else
9891  {
9892  regu = NULL;
9893  }
9894  }
9895  }
9896  }
9897  }
9898  else
9899  {
9900  regu_alloc (regu);
9901  if (regu != NULL)
9902  {
9903  /* The attribute is correlated variable. Find it in an enclosing scope(s). Note that this subquery has
9904  * also just been determined to be a correlated subquery. */
9905  if (symbols->stack == NULL)
9906  {
9907  if (!pt_has_error (parser))
9908  {
9909  PT_INTERNAL_ERROR (parser, "generate attr");
9910  }
9911 
9912  regu = NULL;
9913  }
9914  else
9915  {
9916  while (symbols->stack && !table_info)
9917  {
9918  symbols = symbols->stack;
9919  /* mark successive enclosing scopes correlated, until the attribute's "home" is found. */
9920  table_info = pt_find_table_info (attr->info.name.spec_id, symbols->table_info);
9921  }
9922 
9923  if (table_info)
9924  {
9925  regu->type = TYPE_CONSTANT;
9926  regu->domain = pt_xasl_node_to_domain (parser, attr);
9927  dbval =
9928  pt_index_value (table_info->value_list,
9929  pt_find_attribute (parser, attr, table_info->attribute_list));
9930  if (dbval)
9931  {
9932  regu->value.dbvalptr = dbval;
9933  }
9934  else
9935  {
9936  if (PT_IS_OID_NAME (attr))
9937  {
9938  if (regu)
9939  {
9940  regu->type = TYPE_OID;
9941  regu->domain = pt_xasl_node_to_domain (parser, attr);
9942  }
9943  }
9944  else
9945  {
9946  regu = NULL;
9947  }
9948  }
9949  }
9950  else
9951  {
9952  if (!pt_has_error (parser))
9953  {
9954  PT_INTERNAL_ERROR (parser, "generate attr");
9955  }
9956 
9957  regu = NULL;
9958  }
9959  }
9960  }
9961  }
9962  }
9963  else
9964  {
9965  regu = NULL;
9966  }
9967 
9968  if (regu == NULL && !pt_has_error (parser))
9969  {
9970  const char *p = "unknown";
9971 
9972  if (attr)
9973  {
9974  p = attr->info.name.original;
9975  }
9976 
9977  PT_INTERNAL_ERROR (parser, "generate attr");
9978  }
9979 
9980  return regu;
9981 }
9982 
9983 /*
9984  * pt_join_term_to_regu_variable () - Translate a PT_NODE path join term
9985  * to the regu_variable to follow from (left hand side of path)
9986  * return:
9987  * parser(in):
9988  * join_term(in):
9989  */
9990 static REGU_VARIABLE *
9992 {
9993  REGU_VARIABLE *regu = NULL;
9994 
9995  if (join_term && join_term->node_type == PT_EXPR && join_term->info.expr.op == PT_EQ)
9996  {
9997  regu = pt_to_regu_variable (parser, join_term->info.expr.arg1, UNBOX_AS_VALUE);
9998  }
9999 
10000  return regu;
10001 }
10002 
10003 
10004 /*
10005  * op_type_to_range () -
10006  * return:
10007  * op_type(in):
10008  * nterms(in):
10009  */
10010 static RANGE
10011 op_type_to_range (const PT_OP_TYPE op_type, const int nterms)
10012 {
10013  switch (op_type)
10014  {
10015  case PT_EQ:
10016  return EQ_NA;
10017  case PT_GT:
10018  return (nterms > 1) ? GT_LE : GT_INF;
10019  case PT_GE:
10020  return (nterms > 1) ? GE_LE : GE_INF;
10021  case PT_LT:
10022  return (nterms > 1) ? GE_LT : INF_LT;
10023  case PT_LE:
10024  return (nterms > 1) ? GE_LE : INF_LE;
10025  case PT_BETWEEN:
10026  return GE_LE;
10027  case PT_EQ_SOME:
10028  case PT_IS_IN:
10029  return EQ_NA;
10030  case PT_BETWEEN_AND:
10031  case PT_BETWEEN_GE_LE:
10032  return GE_LE;
10033  case PT_BETWEEN_GE_LT:
10034  return GE_LT;
10035  case PT_BETWEEN_GT_LE:
10036  return GT_LE;
10037  case PT_BETWEEN_GT_LT:
10038  return GT_LT;
10039  case PT_BETWEEN_EQ_NA:
10040  return EQ_NA;
10041  case PT_BETWEEN_INF_LE:
10042  return (nterms > 1) ? GE_LE : INF_LE;
10043  case PT_BETWEEN_INF_LT:
10044  return (nterms > 1) ? GE_LT : INF_LT;
10045  case PT_BETWEEN_GE_INF:
10046  return (nterms > 1) ? GE_LE : GE_INF;
10047  case PT_BETWEEN_GT_INF:
10048  return (nterms > 1) ? GT_LE : GT_INF;
10049  default:
10050  return NA_NA; /* error */
10051  }
10052 }
10053 
10054 /*
10055  * pt_create_iss_range () - Create a range to be used by Index Skip Scan
10056  * return: NO_ERROR or error code
10057  * indx_infop(in,out): the index info structure that holds the special
10058  * range used by Index Skip Scan
10059  * domain(in): domain of the first range element
10060  *
10061  * Note :
10062  * Index Skip Scan (ISS) uses an alternative range to scan the btree for
10063  * the next suitable value of the first column. It looks similar to
10064  * "col1 > cur_col1_value". Although it is used on the server side, it must
10065  * be created on the broker and serialized via XASL, because the server
10066  * cannot create regu variables.
10067  * The actual range (INF_INF, GT_INF, INF_LE) will be changed dynamically
10068  * at runtime, as well as the comparison value (left to NULL for now),
10069  * but we must create the basic regu var scaffolding here.
10070  */
10071 static int
10072 pt_create_iss_range (INDX_INFO * indx_infop, TP_DOMAIN * domain)
10073 {
10074  KEY_RANGE *kr = NULL;
10075  REGU_VARIABLE *key1 = NULL, *v1 = NULL;
10076 
10077  if (indx_infop == NULL)
10078  {
10079  assert (false);
10081 
10082  return ER_FAILED;
10083  }
10084 
10085  if (!indx_infop->use_iss)
10086  {
10087  /* nothing to do if not using iss */
10088  return NO_ERROR;
10089  }
10090 
10091  /* set up default range */
10092  kr = &indx_infop->iss_range;
10093  kr->range = INF_INF;
10094 
10095  /* allocate range lower bound as regu var (will be used on server) */
10096  regu_alloc (kr->key1);
10097  key1 = kr->key1;
10098  if (key1 == NULL)
10099  {
10100  return ER_FAILED;
10101  }
10102 
10103  key1->type = TYPE_FUNC;
10104  key1->domain = tp_domain_resolve_default (DB_TYPE_MIDXKEY);
10105  key1->xasl = NULL;
10106  key1->flags = 0;
10107 
10108  regu_alloc (key1->value.funcp);
10109  if (key1->value.funcp == NULL)
10110  {
10111  return ER_FAILED;
10112  }
10113 
10114  key1->value.funcp->ftype = F_MIDXKEY;
10115 
10116  regu_alloc (key1->value.funcp->operand);
10117  if (key1->value.funcp->operand == NULL)
10118  {
10119  return ER_FAILED;
10120  }
10121 
10122  key1->value.funcp->operand->next = NULL;
10123 
10124  v1 = &(key1->value.funcp->operand->value);
10125 
10126  v1->type = TYPE_DBVAL;
10127 
10128  v1->domain = domain;
10129  v1->flags = 0;
10130  db_make_null (&v1->value.dbval);
10131 
10132  v1->vfetch_to = NULL;
10133 
10134  /* upper bound is not needed */
10135  kr->key2 = NULL;
10136 
10137  return NO_ERROR;
10138 }
10139 
10140 /*
10141  * pt_to_single_key () - Create an key information(KEY_INFO) in INDX_INFO
10142  * structure for index scan with range spec of R_ON, R_FROM and R_TO.
10143  * return: 0 on success
10144  * parser(in):
10145  * term_exprs(in):
10146  * nterms(in):
10147  * multi_col(in):
10148  * key_infop(out):
10149  */
10150 static int
10151 pt_to_single_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col, KEY_INFO * key_infop,
10152  int *multi_col_pos)
10153 {
10154  PT_NODE *lhs, *rhs, *tmp, *midx_key;
10155  PT_OP_TYPE op_type;
10156  REGU_VARIABLE *regu_var;
10157  int i, pos;
10158 
10159  midx_key = NULL;
10160  regu_var = NULL;
10161  key_infop->key_cnt = 0;
10162  key_infop->key_ranges = NULL;
10163  key_infop->is_constant = true;
10164 
10165  for (i = 0; i < nterms; i++)
10166  {
10167  /* If nterms > 1, then it should be multi-column index and all term_exprs[0 .. nterms - 1] are equality
10168  * expression. (Even though nterms == 1, it can be multi-column index.) */
10169 
10170  /* op type, LHS side and RHS side of this term expression */
10171  op_type = term_exprs[i]->info.expr.op;
10172  lhs = term_exprs[i]->info.expr.arg1;
10173  rhs = term_exprs[i]->info.expr.arg2;
10174 
10175  /* incidentally we may have a term with only one range left out by pt_to_index_info(), which semantically is the
10176  * same as PT_EQ */
10177  if (op_type == PT_RANGE)
10178  {
10180  assert (rhs->or_next == NULL);
10181 
10182  /* has only one range */
10183  rhs = rhs->info.expr.arg1;
10184  }
10185 
10186  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10187  if (regu_var == NULL)
10188  {
10189  goto error;
10190  }
10191  if (!VALIDATE_REGU_KEY (regu_var))
10192  {
10193  /* correlated join index case swap LHS and RHS */
10194  tmp = rhs;
10195  rhs = lhs;
10196  lhs = tmp;
10197 
10198  /* try on RHS */
10199  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10200  if (regu_var == NULL || !VALIDATE_REGU_KEY (regu_var))
10201  {
10202  goto error;
10203  }
10204  }
10205 
10206  if (multi_col_pos[i] != -1)
10207  {
10208  /* case of multi column term. case1 : value type, case2 : function type */
10209  if (pt_is_set_type (rhs) && PT_IS_VALUE_NODE (rhs))
10210  {
10211  rhs = rhs->info.value.data_value.set;
10212  }
10213  else if (pt_is_set_type (rhs) && PT_IS_FUNCTION (rhs) && rhs->info.function.function_type == F_SEQUENCE)
10214  {
10215  rhs = rhs->info.function.arg_list;
10216  }
10217  else
10218  {
10219  /* rhs must be set type and (value or function type) */
10220  goto error;
10221  }
10222  for (pos = 0; pos < multi_col_pos[i]; pos++)
10223  {
10224  if (!rhs || (rhs && pt_is_set_type (rhs)))
10225  {
10226  /* must be NOT set of set */
10227  goto error;
10228  }
10229  rhs = rhs->next;
10230  }
10231  }
10232  else if (pt_is_set_type (rhs))
10233  {
10234  /* if lhs is not multi_col_term then rhs can't set type */
10235  goto error;
10236  }
10237 
10238  /* is the key value constant(value or host variable)? */
10239  key_infop->is_constant &= (rhs->node_type == PT_VALUE || rhs->node_type == PT_HOST_VAR);
10240 
10241  /* if it is multi-column index, make one PT_NODE for midx key value by concatenating all RHS of the terms */
10242  if (multi_col)
10243  {
10244  midx_key = parser_append_node (pt_point (parser, rhs), midx_key);
10245  }
10246  } /* for (i = 0; i < nterms; i++) */
10247 
10248  if (midx_key)
10249  {
10250  /* make a midxkey regu variable for multi-column index */
10251  tmp = parser_new_node (parser, PT_FUNCTION);
10252  if (tmp == NULL)
10253  {
10254  PT_INTERNAL_ERROR (parser, "allocate new node");
10255  goto error;
10256  }
10257  tmp->type_enum = PT_TYPE_MIDXKEY;
10259  tmp->info.function.arg_list = midx_key;
10260  regu_var = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
10261  parser_free_tree (parser, tmp);
10262  midx_key = NULL; /* already free */
10263  }
10264 
10265  /* set KEY_INFO structure */
10266  key_infop->key_cnt = 1; /* single range */
10267  regu_array_alloc (&key_infop->key_ranges, 1);
10268  if (!key_infop->key_ranges)
10269  {
10270  goto error;
10271  }
10272  key_infop->key_ranges[0].range = EQ_NA;
10273  key_infop->key_ranges[0].key1 = regu_var;
10274  key_infop->key_ranges[0].key2 = NULL;
10275 
10276  return 0;
10277 
10278 /* error handling */
10279 error:
10280  if (midx_key)
10281  {
10282  parser_free_tree (parser, midx_key);
10283  }
10284 
10285  return -1;
10286 }
10287 
10288 
10289 /*
10290  * pt_to_range_key () - Create an key information(KEY_INFO) in INDX_INFO
10291  * structure for index scan with range spec of R_RANGE.
10292  * return: 0 on success
10293  * parser(in):
10294  * term_exprs(in):
10295  * nterms(in):
10296  * multi_col(in):
10297  * key_infop(out): Construct two key values
10298  */
10299 static int
10300 pt_to_range_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col, KEY_INFO * key_infop)
10301 {
10302  PT_NODE *lhs, *rhs, *llim, *ulim, *tmp, *midxkey1, *midxkey2;
10303  PT_OP_TYPE op_type = (PT_OP_TYPE) 0;
10304  REGU_VARIABLE *regu_var1, *regu_var2;
10305  int i;
10306 
10307  midxkey1 = midxkey2 = NULL;
10308  regu_var1 = regu_var2 = NULL;
10309  key_infop->key_cnt = 0;
10310  key_infop->key_ranges = NULL;
10311  key_infop->is_constant = true;
10312 
10313  for (i = 0; i < nterms; i++)
10314  {
10315  /* If nterms > 1, then it should be multi-column index and all term_exprs[0 .. nterms - 1] are equality
10316  * expression. (Even though nterms == 1, it can be multi-column index.) */
10317 
10318  /* op type, LHS side and RHS side of this term expression */
10319  op_type = term_exprs[i]->info.expr.op;
10320  lhs = term_exprs[i]->info.expr.arg1;
10321  rhs = term_exprs[i]->info.expr.arg2;
10322 
10323  if (op_type != PT_BETWEEN)
10324  {
10325  /* PT_EQ, PT_LT, PT_LE, PT_GT, or PT_GE */
10326 
10327  regu_var1 = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10328  if (regu_var1 == NULL)
10329  {
10330  goto error;
10331  }
10332  if (!VALIDATE_REGU_KEY (regu_var1))
10333  {
10334  /* correlated join index case swap LHS and RHS */
10335  tmp = rhs;
10336  rhs = lhs;
10337  lhs = tmp;
10338 
10339  /* try on RHS */
10340  regu_var1 = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10341  if (regu_var1 == NULL || !VALIDATE_REGU_KEY (regu_var1))
10342  {
10343  goto error;
10344  }
10345  /* converse op type for the case of PT_LE, ... */
10346  op_type = pt_converse_op (op_type);
10347  }
10348  /* according to the 'op_type', adjust 'regu_var1' and 'regu_var2' */
10349  if (op_type == PT_LT || op_type == PT_LE)
10350  {
10351  /* but, 'regu_var1' and 'regu_var2' will be replaced with sequence values if it is multi-column index */
10352  regu_var2 = regu_var1;
10353  regu_var1 = NULL;
10354  }
10355  else
10356  {
10357  regu_var2 = NULL;
10358  }
10359 
10360  /* is the key value constant(value or host variable)? */
10361  key_infop->is_constant &= (rhs->node_type == PT_VALUE || rhs->node_type == PT_HOST_VAR);
10362 
10363  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of the terms
10364  */
10365  if (multi_col)
10366  {
10367  if (op_type == PT_EQ || op_type == PT_GT || op_type == PT_GE)
10368  midxkey1 = parser_append_node (pt_point (parser, rhs), midxkey1);
10369  if (op_type == PT_EQ || op_type == PT_LT || op_type == PT_LE)
10370  midxkey2 = parser_append_node (pt_point (parser, rhs), midxkey2);
10371  }
10372  }
10373  else
10374  {
10375  /* PT_BETWEEN */
10376  op_type = rhs->info.expr.op;
10377 
10378  /* range spec(lower limit and upper limit) from operands of BETWEEN expression */
10379  llim = rhs->info.expr.arg1;
10380  ulim = rhs->info.expr.arg2;
10381 
10382  regu_var1 = pt_to_regu_variable (parser, llim, UNBOX_AS_VALUE);
10383  regu_var2 = pt_to_regu_variable (parser, ulim, UNBOX_AS_VALUE);
10384  if (regu_var1 == NULL || !VALIDATE_REGU_KEY (regu_var1) || regu_var2 == NULL
10385  || !VALIDATE_REGU_KEY (regu_var2))
10386  {
10387  goto error;
10388  }
10389 
10390  /* is the key value constant(value or host variable)? */
10391  key_infop->is_constant &= ((llim->node_type == PT_VALUE || llim->node_type == PT_HOST_VAR)
10392  && (ulim->node_type == PT_VALUE || ulim->node_type == PT_HOST_VAR));
10393 
10394  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of the terms
10395  */
10396  if (multi_col)
10397  {
10398  midxkey1 = parser_append_node (pt_point (parser, llim), midxkey1);
10399  midxkey2 = parser_append_node (pt_point (parser, ulim), midxkey2);
10400  }
10401  }
10402  }
10403 
10404  if (midxkey1)
10405  {
10406  /* make a midxkey regu variable for multi-column index */
10407  tmp = parser_new_node (parser, PT_FUNCTION);
10408  if (tmp == NULL)
10409  {
10410  PT_INTERNAL_ERROR (parser, "allocate new node");
10411  goto error;
10412  }
10413  tmp->type_enum = PT_TYPE_MIDXKEY;
10415  tmp->info.function.arg_list = midxkey1;
10416  regu_var1 = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
10417  parser_free_tree (parser, tmp);
10418  midxkey1 = NULL; /* already free */
10419  }
10420 
10421  if (midxkey2)
10422  {
10423  /* make a midxkey regu variable for multi-column index */
10424  tmp = parser_new_node (parser, PT_FUNCTION);
10425  if (tmp == NULL)
10426  {
10427  PT_INTERNAL_ERROR (parser, "allocate new node");
10428  return -1;
10429  }
10430  tmp->type_enum = PT_TYPE_MIDXKEY;
10432  tmp->info.function.arg_list = midxkey2;
10433  regu_var2 = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
10434  parser_free_tree (parser, tmp);
10435  midxkey2 = NULL; /* already free */
10436  }
10437 
10438  /* set KEY_INFO structure */
10439  key_infop->key_cnt = 1; /* single range */
10440  regu_array_alloc (&key_infop->key_ranges, 1);
10441  if (!key_infop->key_ranges)
10442  {
10443  goto error;
10444  }
10445  key_infop->key_ranges[0].range = op_type_to_range (op_type, nterms);
10446  key_infop->key_ranges[0].key1 = regu_var1;
10447  key_infop->key_ranges[0].key2 = regu_var2;
10448 
10449  return 0;
10450 
10451 /* error handling */
10452 error:
10453 
10454  if (midxkey1)
10455  {
10456  parser_free_tree (parser, midxkey1);
10457  }
10458  if (midxkey2)
10459  {
10460  parser_free_tree (parser, midxkey2);
10461  }
10462 
10463  return -1;
10464 }
10465 
10466 /*
10467  * pt_to_list_key () - Create an key information(KEY_INFO) in INDX_INFO
10468  * structure for index scan with range spec of R_LIST
10469  * return: 0 on success
10470  * parser(in):
10471  * term_exprs(in):
10472  * nterms(in):
10473  * multi_col(in):
10474  * key_infop(out): Construct a list of key values
10475  */
10476 static int
10477 pt_to_list_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col, KEY_INFO * key_infop)
10478 {
10479  PT_NODE *lhs, *rhs, *elem, *tmp, **midxkey_list;
10480  PT_OP_TYPE op_type;
10481  REGU_VARIABLE **regu_var_list, *regu_var;
10482  int i, j, n_elem;
10483  DB_VALUE db_value, *p;
10484  DB_COLLECTION *db_collectionp = NULL;
10485 
10486  midxkey_list = NULL;
10487  regu_var_list = NULL;
10488  key_infop->key_cnt = 0;
10489  key_infop->key_ranges = NULL;
10490  key_infop->is_constant = true;
10491  n_elem = 0;
10492 
10493  /* get number of elements of the IN predicate */
10494  rhs = term_exprs[nterms - 1]->info.expr.arg2;
10495 
10496  if (rhs->node_type == PT_EXPR && rhs->info.expr.op == PT_CAST)
10497  {
10498  /* strip CAST operator off */
10499  rhs = rhs->info.expr.arg1;
10500  }
10501 
10502  switch (rhs->node_type)
10503  {
10504  case PT_FUNCTION:
10505  switch (rhs->info.function.function_type)
10506  {
10507  case F_SET:
10508  case F_MULTISET:
10509  case F_SEQUENCE:
10510  break;
10511  default:
10512  goto error;
10513  }
10514 
10515  for (elem = rhs->info.function.arg_list, n_elem = 0; elem; elem = elem->next, n_elem++)
10516  {
10517  ;
10518  }
10519  break;
10520 
10521  case PT_NAME:
10522  if (rhs->info.name.meta_class != PT_PARAMETER)
10523  {
10524  goto error;
10525  }
10526  /* FALLTHRU */
10527 
10528  case PT_VALUE:
10529  p = (rhs->node_type == PT_NAME) ? pt_find_value_of_label (rhs->info.name.original) : &rhs->info.value.db_value;
10530 
10531  if (p == NULL)
10532  {
10533  goto error;
10534  }
10535 
10536  switch (DB_VALUE_TYPE (p))
10537  {
10538  case DB_TYPE_SET:
10539  case DB_TYPE_MULTISET:
10540  case DB_TYPE_SEQUENCE:
10541  break;
10542  default:
10543  goto error;
10544  }
10545 
10546  db_collectionp = db_get_collection (p);
10547  n_elem = db_col_size (db_collectionp);
10548  break;
10549 
10550  case PT_HOST_VAR:
10551  p = pt_value_to_db (parser, rhs);
10552  if (p == NULL)
10553  {
10554  goto error;
10555  }
10556 
10557  switch (DB_VALUE_TYPE (p))
10558  {
10559  case DB_TYPE_SET:
10560  case DB_TYPE_MULTISET:
10561  case DB_TYPE_SEQUENCE:
10562  break;
10563  default:
10564  goto error;
10565  }
10566 
10567  db_collectionp = db_get_collection (p);
10568  n_elem = db_col_size (db_collectionp);
10569  break;
10570 
10571  default:
10572  goto error;
10573  }
10574 
10575  if (n_elem <= 0)
10576  {
10577  goto error;
10578  }
10579 
10580  /* allocate regu variable list and sequence value list */
10581  regu_array_alloc (&regu_var_list, n_elem);
10582  if (!regu_var_list)
10583  {
10584  goto error;
10585  }
10586 
10587  if (multi_col)
10588  {
10589  midxkey_list = (PT_NODE **) malloc (sizeof (PT_NODE *) * n_elem);
10590  if (!midxkey_list)
10591  {
10592  goto error;
10593  }
10594  memset (midxkey_list, 0, sizeof (PT_NODE *) * n_elem);
10595  }
10596 
10597  for (i = 0; i < nterms; i++)
10598  {
10599  /* If nterms > 1, then it should be multi-column index and all term_exprs[0 .. nterms - 1] are equality
10600  * expression. (Even though nterms == 1, it can be multi-column index.) */
10601 
10602  /* op type, LHS side and RHS side of this term expression */
10603  op_type = term_exprs[i]->info.expr.op;
10604  lhs = term_exprs[i]->info.expr.arg1;
10605  rhs = term_exprs[i]->info.expr.arg2;
10606 
10607  if (op_type != PT_IS_IN && op_type != PT_EQ_SOME)
10608  {
10609  /* PT_EQ */
10610 
10611  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10612  if (regu_var == NULL)
10613  {
10614  goto error;
10615  }
10616  if (!VALIDATE_REGU_KEY (regu_var))
10617  {
10618  /* correlated join index case swap LHS and RHS */
10619  tmp = rhs;
10620  rhs = lhs;
10621  lhs = tmp;
10622 
10623  /* try on RHS */
10624  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10625  if (regu_var == NULL || !VALIDATE_REGU_KEY (regu_var))
10626  {
10627  goto error;
10628  }
10629  }
10630 
10631  /* is the key value constant(value or host variable)? */
10632  key_infop->is_constant &= (rhs->node_type == PT_VALUE || rhs->node_type == PT_HOST_VAR);
10633 
10634  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of the terms
10635  */
10636  if (multi_col)
10637  {
10638  for (j = 0; j < n_elem; j++)
10639  {
10640  midxkey_list[j] = parser_append_node (pt_point (parser, rhs), midxkey_list[j]);
10641  }
10642  }
10643 
10644  }
10645  else
10646  {
10647  /* PT_IS_IN or PT_EQ_SOME */
10648 
10649  if (rhs->node_type == PT_FUNCTION)
10650  {
10651  /* PT_FUNCTION */
10652 
10653  for (j = 0, elem = rhs->info.function.arg_list; j < n_elem && elem; j++, elem = elem->next)
10654  {
10655 
10656  regu_var_list[j] = pt_to_regu_variable (parser, elem, UNBOX_AS_VALUE);
10657  if (regu_var_list[j] == NULL || !VALIDATE_REGU_KEY (regu_var_list[j]))
10658  {
10659  goto error;
10660  }
10661 
10662  /* is the key value constant(value or host variable)? */
10663  key_infop->is_constant &= (elem->node_type == PT_VALUE || elem->node_type == PT_HOST_VAR);
10664 
10665  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of
10666  * the terms */
10667  if (multi_col)
10668  {
10669  midxkey_list[j] = parser_append_node (pt_point (parser, elem), midxkey_list[j]);
10670  }
10671  } /* for (j = 0, = ...) */
10672  }
10673  else
10674  {
10675  /* PT_NAME or PT_VALUE */
10676  for (j = 0; j < n_elem; j++)
10677  {
10678  if (db_col_get (db_collectionp, j, &db_value) < 0)
10679  {
10680  goto error;
10681  }
10682  elem = pt_dbval_to_value (parser, &db_value);
10683  if (elem == NULL)
10684  {
10685  goto error;
10686  }
10687  pr_clear_value (&db_value);
10688 
10689  regu_var_list[j] = pt_to_regu_variable (parser, elem, UNBOX_AS_VALUE);
10690  if (regu_var_list[j] == NULL || !VALIDATE_REGU_KEY (regu_var_list[j]))
10691  {
10692  parser_free_tree (parser, elem);
10693  goto error;
10694  }
10695 
10696  /* if it is multi-column index, make one PT_NODE for midxkey value by concatenating all RHS of the
10697  * terms */
10698  if (multi_col)
10699  {
10700  midxkey_list[j] = parser_append_node (elem, midxkey_list[j]);
10701  }
10702  }
10703  }
10704  }
10705  }
10706 
10707  if (multi_col)
10708  {
10709  /* make a midxkey regu variable for multi-column index */
10710  for (i = 0; i < n_elem; i++)
10711  {
10712  if (!midxkey_list[i])
10713  {
10714  goto error;
10715  }
10716 
10717  tmp = parser_new_node (parser, PT_FUNCTION);
10718  if (tmp == NULL)
10719  {
10720  PT_INTERNAL_ERROR (parser, "allocate new node");
10721  goto error;
10722  }
10723  tmp->type_enum = PT_TYPE_MIDXKEY;
10725  tmp->info.function.arg_list = midxkey_list[i];
10726  regu_var_list[i] = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
10727  parser_free_tree (parser, tmp);
10728  midxkey_list[i] = NULL; /* already free */
10729  }
10730  }
10731 
10732  /* set KEY_INFO structure */
10733  key_infop->key_cnt = n_elem; /* n_elem ranges */
10734  regu_array_alloc (&key_infop->key_ranges, n_elem);
10735  if (!key_infop->key_ranges)
10736  {
10737  goto error;
10738  }
10739  for (i = 0; i < n_elem; i++)
10740  {
10741  key_infop->key_ranges[i].range = EQ_NA;
10742  key_infop->key_ranges[i].key1 = regu_var_list[i];
10743  key_infop->key_ranges[i].key2 = NULL;
10744  }
10745 
10746  if (midxkey_list)
10747  {
10748  free_and_init (midxkey_list);
10749  }
10750 
10751  return 0;
10752 
10753 /* error handling */
10754 error:
10755 
10756  if (midxkey_list)
10757  {
10758  for (i = 0; i < n_elem; i++)
10759  {
10760  if (midxkey_list[i])
10761  {
10762  parser_free_tree (parser, midxkey_list[i]);
10763  }
10764  }
10765  free_and_init (midxkey_list);
10766  }
10767 
10768  return -1;
10769 }
10770 
10771 
10772 /*
10773  * pt_to_rangelist_key () - Create an key information(KEY_INFO) in INDX_INFO
10774  * structure for index scan with range spec of R_RANGELIST
10775  * return:
10776  * parser(in):
10777  * term_exprs(in):
10778  * nterms(in):
10779  * multi_col(in):
10780  * key_infop(out): Construct a list of search range values
10781  * rangelist_idx(in):
10782  */
10783 static int
10784 pt_to_rangelist_key (PARSER_CONTEXT * parser, PT_NODE ** term_exprs, int nterms, bool multi_col, KEY_INFO * key_infop,
10785  int rangelist_idx, int *multi_col_pos)
10786 {
10787  PT_NODE *lhs, *rhs, *llim, *ulim, *elem, *tmp, *elem2;
10788  PT_NODE **midxkey_list1 = NULL, **midxkey_list2 = NULL;
10789  PT_OP_TYPE op_type;
10790  REGU_VARIABLE **regu_var_list1, **regu_var_list2, *regu_var;
10791  RANGE *range_list = NULL;
10792  int i, j, n_elem, pos;
10793  int list_count1, list_count2;
10794  int num_index_term;
10795 
10796  midxkey_list1 = midxkey_list2 = NULL;
10797  regu_var_list1 = regu_var_list2 = NULL;
10798  key_infop->key_cnt = 0;
10799  key_infop->key_ranges = NULL;
10800  key_infop->is_constant = true;
10801  n_elem = 0;
10802 
10803  /* get number of elements of the RANGE predicate */
10804  rhs = term_exprs[rangelist_idx]->info.expr.arg2;
10805  for (elem = rhs, n_elem = 0; elem; elem = elem->or_next, n_elem++)
10806  {
10807  ;
10808  }
10809  if (n_elem <= 0)
10810  {
10811  goto error;
10812  }
10813 
10814  /* allocate regu variable list and sequence value list */
10815  regu_array_alloc (&regu_var_list1, n_elem);
10816  regu_array_alloc (&regu_var_list2, n_elem);
10817  range_list = (RANGE *) malloc (sizeof (RANGE) * n_elem);
10818  if (!regu_var_list1 || !regu_var_list2 || !range_list)
10819  {
10820  goto error;
10821  }
10822 
10823  memset (range_list, 0, sizeof (RANGE) * n_elem);
10824 
10825  if (multi_col)
10826  {
10827  midxkey_list1 = (PT_NODE **) malloc (sizeof (PT_NODE *) * n_elem);
10828  if (midxkey_list1 == NULL)
10829  {
10830  goto error;
10831  }
10832  memset (midxkey_list1, 0, sizeof (PT_NODE *) * n_elem);
10833 
10834  midxkey_list2 = (PT_NODE **) malloc (sizeof (PT_NODE *) * n_elem);
10835  if (midxkey_list2 == NULL)
10836  {
10837  goto error;
10838  }
10839  memset (midxkey_list2, 0, sizeof (PT_NODE *) * n_elem);
10840  }
10841 
10842  /* for each term */
10843  for (i = 0; i < nterms; i++)
10844  {
10845  /* If nterms > 1, then it should be multi-column index and all term_expr[0 .. nterms - 1] are equality
10846  * expression. (Even though nterms == 1, it can be multi-column index.) */
10847 
10848  /* op type, LHS side and RHS side of this term expression */
10849  op_type = term_exprs[i]->info.expr.op;
10850  lhs = term_exprs[i]->info.expr.arg1;
10851  rhs = term_exprs[i]->info.expr.arg2;
10852 
10853  llim = ulim = NULL; /* init */
10854 
10855  if (op_type != PT_RANGE)
10856  {
10857  assert (i != rangelist_idx);
10858 
10859  /* PT_EQ */
10860 
10861  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10862  if (regu_var == NULL)
10863  {
10864  goto error;
10865  }
10866  if (!VALIDATE_REGU_KEY (regu_var))
10867  {
10868  /* correlated join index case swap LHS and RHS */
10869  tmp = rhs;
10870  rhs = lhs;
10871  lhs = tmp;
10872 
10873  /* try on RHS */
10874  regu_var = pt_to_regu_variable (parser, rhs, UNBOX_AS_VALUE);
10875  if (regu_var == NULL || !VALIDATE_REGU_KEY (regu_var))
10876  {
10877  goto error;
10878  }
10879  }
10880 
10881  /* is the key value constant(value or host variable)? */
10882  key_infop->is_constant &= (rhs->node_type == PT_VALUE || rhs->node_type == PT_HOST_VAR);
10883 
10884  for (j = 0; j < n_elem; j++)
10885  {
10886  if (i == nterms - 1)
10887  { /* the last term */
10888  range_list[j] = op_type_to_range (op_type, nterms);
10889  }
10890 
10891  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of the
10892  * terms */
10893  if (multi_col)
10894  {
10895  midxkey_list1[j] = parser_append_node (pt_point (parser, rhs), midxkey_list1[j]);
10896  midxkey_list2[j] = parser_append_node (pt_point (parser, rhs), midxkey_list2[j]);
10897  }
10898  }
10899  }
10900  else
10901  {
10902  assert ((i == rangelist_idx) || (i != rangelist_idx && rhs->or_next == NULL) || multi_col_pos[i] != -1);
10903 
10904  /* PT_RANGE */
10905  for (j = 0, elem = rhs; j < n_elem && elem; j++, elem = elem->or_next)
10906  {
10907  /* range type and spec(lower limit and upper limit) from operands of RANGE expression */
10908  op_type = elem->info.expr.op;
10909  switch (op_type)
10910  {
10911  case PT_BETWEEN_EQ_NA:
10912  llim = elem->info.expr.arg1;
10913  ulim = llim;
10914  break;
10915  case PT_BETWEEN_INF_LE:
10916  case PT_BETWEEN_INF_LT:
10917  llim = NULL;
10918  ulim = elem->info.expr.arg1;
10919  break;
10920  case PT_BETWEEN_GE_INF:
10921  case PT_BETWEEN_GT_INF:
10922  llim = elem->info.expr.arg1;
10923  ulim = NULL;
10924  break;
10925  default:
10926  llim = elem->info.expr.arg1;
10927  ulim = elem->info.expr.arg2;
10928  break;
10929  }
10930 
10931  if (multi_col_pos[i] != -1)
10932  {
10933  /* case of multi column term. case1 : value type, case2 : function type */
10934  if (pt_is_set_type (llim) && pt_is_value_node (llim))
10935  {
10936  llim = llim->info.value.data_value.set;
10937  }
10938  else if (pt_is_set_type (llim) && pt_is_function (llim)
10939  && llim->info.function.function_type == F_SEQUENCE)
10940  {
10941  llim = llim->info.function.arg_list;
10942  }
10943  else
10944  {
10945  /* rhs must be set type and (value or function type) */
10946  goto error;
10947  }
10948  ulim = llim;
10949  for (pos = 0; pos < multi_col_pos[i]; pos++)
10950  {
10951  if (!llim || (llim && pt_is_set_type (llim)))
10952  {
10953  /* must be NOT set of set */
10954  goto error;
10955  }
10956  llim = llim->next;
10957  ulim = ulim->next;
10958  }
10959  }
10960  else if (pt_is_set_type (llim))
10961  {
10962  /* if lhs is not multi_col_term then rhs can't set type */
10963  goto error;
10964  }
10965 
10966  if (llim)
10967  {
10968  regu_var_list1[j] = pt_to_regu_variable (parser, llim, UNBOX_AS_VALUE);
10969  if (regu_var_list1[j] == NULL || !VALIDATE_REGU_KEY (regu_var_list1[j]))
10970  {
10971  goto error;
10972  }
10973 
10974  /* is the key value constant(value or host variable)? */
10975  key_infop->is_constant &= (llim->node_type == PT_VALUE || llim->node_type == PT_HOST_VAR);
10976  }
10977  else
10978  {
10979  regu_var_list1[j] = NULL;
10980  } /* if (llim) */
10981 
10982  if (ulim)
10983  {
10984  regu_var_list2[j] = pt_to_regu_variable (parser, ulim, UNBOX_AS_VALUE);
10985  if (regu_var_list2[j] == NULL || !VALIDATE_REGU_KEY (regu_var_list2[j]))
10986  {
10987  goto error;
10988  }
10989 
10990  /* is the key value constant(value or host variable)? */
10991  key_infop->is_constant &= (ulim->node_type == PT_VALUE || ulim->node_type == PT_HOST_VAR);
10992  }
10993  else
10994  {
10995  regu_var_list2[j] = NULL;
10996  } /* if (ulim) */
10997 
10998  if (i == nterms - 1)
10999  { /* the last term */
11000  range_list[j] = op_type_to_range (op_type, nterms);
11001  }
11002 
11003  /* if it is multi-column index, make one PT_NODE for sequence key value by concatenating all RHS of the
11004  * terms */
11005  if (multi_col)
11006  {
11007  if (llim)
11008  {
11009  midxkey_list1[j] = parser_append_node (pt_point (parser, llim), midxkey_list1[j]);
11010  }
11011  if (ulim)
11012  {
11013  midxkey_list2[j] = parser_append_node (pt_point (parser, ulim), midxkey_list2[j]);
11014  }
11015  }
11016  } /* for (j = 0, elem = rhs; ... ) */
11017 
11018  if (multi_col_pos[i] != -1 || i == rangelist_idx)
11019  {
11020  assert (j == n_elem);
11021  /* OK; nop */
11022  }
11023  else
11024  {
11025  int k;
11026 
11027  assert (j == 1);
11028 
11029  for (k = j; k < n_elem; k++)
11030  {
11031  if (i == nterms - 1)
11032  { /* the last term */
11033  range_list[k] = op_type_to_range (op_type, nterms);
11034  }
11035 
11036  if (multi_col)
11037  {
11038  if (llim)
11039  {
11040  midxkey_list1[k] = parser_append_node (pt_point (parser, llim), midxkey_list1[k]);
11041  }
11042  if (ulim)
11043  {
11044  midxkey_list2[k] = parser_append_node (pt_point (parser, ulim), midxkey_list2[k]);
11045  }
11046  }
11047  } /* for */
11048  }
11049  } /* else (op_type != PT_RANGE) */
11050  } /* for (i = 0; i < nterms; i++) */
11051 
11052  if (multi_col)
11053  {
11054  /* make a midxkey regu variable for multi-column index */
11055  for (i = 0; i < n_elem; i++)
11056  {
11057  if (midxkey_list1[i])
11058  {
11059  tmp = parser_new_node (parser, PT_FUNCTION);
11060  if (tmp == NULL)
11061  {
11062  PT_INTERNAL_ERROR (parser, "allocate new node");
11063  goto error;
11064  }
11065 
11066  tmp->type_enum = PT_TYPE_MIDXKEY;
11068  tmp->info.function.arg_list = midxkey_list1[i];
11069  regu_var_list1[i] = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
11070  parser_free_tree (parser, tmp);
11071  midxkey_list1[i] = NULL; /* already free */
11072  }
11073  }
11074  free_and_init (midxkey_list1);
11075 
11076  /* make a midxkey regu variable for multi-column index */
11077  for (i = 0; i < n_elem; i++)
11078  {
11079  if (midxkey_list2[i])
11080  {
11081  tmp = parser_new_node (parser, PT_FUNCTION);
11082  if (tmp == NULL)
11083  {
11084  PT_INTERNAL_ERROR (parser, "allocate new node");
11085  goto error;
11086  }
11087  tmp->type_enum = PT_TYPE_MIDXKEY;
11089  tmp->info.function.arg_list = midxkey_list2[i];
11090  regu_var_list2[i] = pt_to_regu_variable (parser, tmp, UNBOX_AS_VALUE);
11091  parser_free_tree (parser, tmp);
11092  midxkey_list2[i] = NULL; /* already free */
11093  }
11094  }
11095  free_and_init (midxkey_list2);
11096  }
11097 
11098  /* assertion block */
11099  if (multi_col == true)
11100  {
11101  REGU_VARIABLE_LIST requ_list;
11102 
11103  num_index_term = 0; /* to make compiler be silent */
11104  for (i = 0; i < n_elem; i++)
11105  {
11106  list_count1 = list_count2 = 0;
11107 
11108  if (regu_var_list1[i] != NULL)
11109  {
11110  for (requ_list = regu_var_list1[i]->value.funcp->operand; requ_list; requ_list = requ_list->next)
11111  {
11112  list_count1++;
11113  }
11114  }
11115 
11116  if (regu_var_list2[i] != NULL)
11117  {
11118  for (requ_list = regu_var_list2[i]->value.funcp->operand; requ_list; requ_list = requ_list->next)
11119  {
11120  list_count2++;
11121  }
11122  }
11123 
11124  if (i == 0)
11125  {
11126  num_index_term = MAX (list_count1, list_count2);
11127  }
11128  else
11129  {
11130  if (num_index_term != MAX (list_count1, list_count2))
11131  {
11132  assert_release (0);
11133  goto error;
11134  }
11135  }
11136  }
11137  }
11138 
11139  /* set KEY_INFO structure */
11140  key_infop->key_cnt = n_elem; /* n_elem ranges */
11141  regu_array_alloc (&key_infop->key_ranges, n_elem);
11142  if (!key_infop->key_ranges)
11143  {
11144  goto error;
11145  }
11146 
11147  for (i = 0; i < n_elem; i++)
11148  {
11149  key_infop->key_ranges[i].range = range_list[i];
11150  key_infop->key_ranges[i].key1 = regu_var_list1[i];
11151  key_infop->key_ranges[i].key2 = regu_var_list2[i];
11152  }
11153 
11154  if (range_list)
11155  {
11156  free_and_init (range_list);
11157  }
11158 
11159  return 0;
11160 
11161 /* error handling */
11162 error:
11163 
11164  if (midxkey_list1)
11165  {
11166  for (i = 0; i < n_elem; i++)
11167  {
11168  if (midxkey_list1[i])
11169  {
11170  parser_free_tree (parser, midxkey_list1[i]);
11171  }
11172  }
11173  free_and_init (midxkey_list1);
11174  }
11175  if (midxkey_list2)
11176  {
11177  for (i = 0; i < n_elem; i++)
11178  {
11179  if (midxkey_list2[i])
11180  {
11181  parser_free_tree (parser, midxkey_list2[i]);
11182  }
11183  }
11184  free_and_init (midxkey_list2);
11185  }
11186 
11187  if (range_list)
11188  {
11189  free_and_init (range_list);
11190  }
11191 
11192  return -1;
11193 }
11194 
11195 
11196 /*
11197  * pt_to_key_limit () - Create index key limit regu variables
11198  * return:
11199  * parser(in):
11200  * key_limit(in):
11201  * key_infop(in):
11202  * key_limit_reset(in);
11203  */
11204 static int
11205 pt_to_key_limit (PARSER_CONTEXT * parser, PT_NODE * key_limit, QO_LIMIT_INFO * limit_infop, KEY_INFO * key_infop,
11206  bool key_limit_reset)
11207 {
11208  REGU_VARIABLE *regu_var_u = NULL, *regu_var_l = NULL;
11209  PT_NODE *limit_u, *limit_l;
11211 
11212  /* at least one of them should be NULL, although they both can */
11213  assert (key_limit == NULL || limit_infop == NULL);
11214 
11215  limit_u = key_limit;
11216  if (limit_u != NULL)
11217  {
11218  /* user explicitly specifies keylimit */
11219  key_infop->is_user_given_keylimit = true;
11220 
11221  if (limit_u->type_enum == PT_TYPE_MAYBE)
11222  {
11223  limit_u->expected_domain = dom_bigint;
11224  }
11225  regu_var_u = pt_to_regu_variable (parser, limit_u, UNBOX_AS_VALUE);
11226  if (regu_var_u == NULL)
11227  {
11228  goto error;
11229  }
11230 
11231  limit_l = limit_u->next;
11232  if (limit_l != NULL)
11233  {
11234  if (limit_l->type_enum == PT_TYPE_MAYBE)
11235  {
11236  limit_l->expected_domain = dom_bigint;
11237  }
11238  regu_var_l = pt_to_regu_variable (parser, limit_l, UNBOX_AS_VALUE);
11239  if (regu_var_l == NULL)
11240  {
11241  goto error;
11242  }
11243  }
11244  }
11245 
11246  if (limit_infop != NULL)
11247  {
11248  regu_var_u = limit_infop->upper;
11249  regu_var_l = limit_infop->lower;
11250  }
11251 
11252  if (key_infop->key_limit_u != NULL)
11253  {
11254  if (regu_var_u != NULL)
11255  {
11256  key_infop->key_limit_u = pt_make_regu_arith (key_infop->key_limit_u, regu_var_u, NULL, T_LEAST, dom_bigint);
11257  if (key_infop->key_limit_u == NULL)
11258  {
11259  goto error;
11260  }
11261  key_infop->key_limit_u->domain = dom_bigint;
11262  }
11263  }
11264  else
11265  {
11266  key_infop->key_limit_u = regu_var_u;
11267  }
11268 
11269  if (key_infop->key_limit_l != NULL)
11270  {
11271  if (regu_var_l != NULL)
11272  {
11273  key_infop->key_limit_l =
11274  pt_make_regu_arith (key_infop->key_limit_l, regu_var_l, NULL, T_GREATEST, dom_bigint);
11275  if (key_infop->key_limit_l == NULL)
11276  {
11277  goto error;
11278  }
11279  key_infop->key_limit_l->domain = dom_bigint;
11280  }
11281  }
11282  else
11283  {
11284  key_infop->key_limit_l = regu_var_l;
11285  }
11286 
11287  key_infop->key_limit_reset = key_limit_reset;
11288 
11289  return NO_ERROR;
11290 
11291 error:
11292 
11293  return ER_FAILED;
11294 }
11295 
11296 
11297 /*
11298  * pt_instnum_to_key_limit () - try to convert instnum to keylimit
11299  * return:
11300  * parser(in):
11301  * plan(in):
11302  * xasl(in):
11303  */
11304 static int
11306 {
11307  XASL_NODE *xptr;
11308  ACCESS_SPEC_TYPE *spec_list;
11309  QO_LIMIT_INFO *limit_infop;
11310  int ret = NO_ERROR;
11311 
11312  /* If ANY of the spec lists has a data filter, we cannot convert instnum to keylimit, because in the worst case
11313  * scenario the data filter could require all the records in a join operation and chose only the last Cartesian
11314  * tuple, and any keylimit on the joined tables would be wrong. */
11315  for (xptr = xasl; xptr; xptr = xptr->scan_ptr)
11316  {
11317  for (spec_list = xptr->spec_list; spec_list; spec_list = spec_list->next)
11318  {
11319  if (spec_list->where_pred)
11320  {
11321  /* this is not an error, just halt the optimization tentative */
11322  return NO_ERROR;
11323  }
11324  }
11325  }
11326 
11327  /* if there is an orderby_num pred, meaning order by was not skipped */
11328  if (xasl->ordbynum_pred || xasl->if_pred || xasl->after_join_pred)
11329  {
11330  /* can't optimize */
11331  return NO_ERROR;
11332  }
11333 
11334  /* halt if there is connect by */
11335  if (xasl->connect_by_ptr)
11336  {
11337  return NO_ERROR;
11338  }
11339 
11340  /* if there are analytic function and instnum, can't optimize */
11342  {
11343  return NO_ERROR;
11344  }
11345 
11346  limit_infop = qo_get_key_limit_from_instnum (parser, plan, xasl);
11347  if (!limit_infop)
11348  {
11349  return NO_ERROR;
11350  }
11351  if (!limit_infop->upper)
11352  {
11353  db_private_free (NULL, limit_infop);
11354  return NO_ERROR;
11355  }
11356 
11357 
11358  /* there is at least an upper limit, but we need to take some decisions depending on the presence of a lower limit
11359  * and the query complexity */
11360 
11361  /* do we have a join or other non-trivial select? */
11362  if (xasl->scan_ptr)
11363  {
11364  /* If we are joining multiple tables, we cannot afford to use the lower limit: it should be applied only at the
11365  * higher, join level and not at lower table scan levels. Discard the lower limit. */
11366  limit_infop->lower = NULL;
11367  }
11368  else if (QO_NODE_IS_CLASS_HIERARCHY (plan->plan_un.scan.node))
11369  {
11370  /* We cannot use the lower limit in a hierarchy */
11371  limit_infop->lower = NULL;
11372  }
11373  else
11374  {
11375  /* a trivial select: we can keep the lower limit, but we must adjust the upper limit.
11376  * qo_get_key_limit_from_instnum gets a lower and an upper limit, but keylimit requires a min and a count (i.e.
11377  * how many should we skip, and then how many should we fetch) */
11378  if (limit_infop->lower)
11379  {
11381 
11382  limit_infop->upper = pt_make_regu_arith (limit_infop->upper, limit_infop->lower, NULL, T_SUB, dom_bigint);
11383  if (limit_infop->upper == NULL)
11384  {
11385  goto exit_on_error;
11386  }
11387 
11388  limit_infop->upper->domain = dom_bigint;
11389  }
11390 
11391  /* we must also delete the instnum predicate, because we don't want two sets of lower limits for the same data */
11392  assert (xasl->instnum_pred);
11393  xasl->instnum_pred = NULL;
11394  }
11395 
11396  /* cannot handle for join; skip and go ahead */
11397  if (xasl->scan_ptr == NULL)
11398  {
11399  /* set the key limit to all the eligible spec lists (the ones that have index scans.) */
11400  for (xptr = xasl; xptr; xptr = xptr->scan_ptr)
11401  {
11402  for (spec_list = xptr->spec_list; spec_list; spec_list = spec_list->next)
11403  {
11404  if (!spec_list->indexptr)
11405  {
11406  continue;
11407  }
11408 
11409  ret = pt_to_key_limit (parser, NULL, limit_infop, &(spec_list->indexptr->key_info), false);
11410  if (ret != NO_ERROR)
11411  {
11412  goto exit_on_error;
11413  }
11414  }
11415  }
11416  }
11417 
11418  /* we're done with the generated key limit tree */
11419  db_private_free (NULL, limit_infop);
11420 
11421  return NO_ERROR;
11422 
11423 exit_on_error:
11424  if (limit_infop)
11425  {
11426  db_private_free (NULL, limit_infop);
11427  }
11428  return ER_FAILED;
11429 }
11430 
11431 
11432 /*
11433  * pt_fix_first_term_expr_for_iss () - allocates needed first term for the
11434  * index skip scan optimization (ISS)
11435  * return:
11436  * parser(in):
11437  * index_entryp(in):
11438  * term_exprs(in):
11439  *
11440  * Notes:
11441  * ISS involves using the index when there is no condition (term) on the first
11442  * column of the index, by performing multiple btree_range_search() calls, one
11443  * for each value of the first column that exists in the database.
11444  * For instance for an index on c1,c2,c3 and the condition
11445  * ... WHERE C2 = 5 and C3 > 10, we will have to generate a range similar to
11446  * [C1=?, C2=5, C3 > 10] and fill up the "?" at each successive run with a
11447  * new value for C1. This is taken care of on the server, in
11448  * obtain_next_iss_value() & co. However, the code that generates the range,
11449  * here in XASL generation, assumes that there ARE terms for all of C1,C2, C3.
11450  *
11451  * Therefore, we must generate a "fake" term [C1=?], and just allow the range
11452  * generation code to do its job, knowing that once it gets to the server
11453  * side, we will replace the "?" with proper values for C1.
11454  * The term that is added is harmless (i.e. it does not show up when printing
11455  * the tree etc).
11456  */
11457 static int
11459 {
11460  PT_NODE *expr = NULL;
11461  PT_NODE *arg = NULL;
11462  PT_NODE *val = NULL;
11463  PT_NODE *spec;
11464  QO_SEGMENT *seg;
11465  QO_NODE *head;
11466  DB_VALUE temp_null;
11467 
11468  /* better than leaving it uninitialized */
11469  term_exprs[0] = NULL;
11470 
11471  if (index_entryp->nsegs <= 1 || index_entryp->seg_idxs[1] == -1)
11472  {
11473  assert (index_entryp->nsegs > 1 && index_entryp->seg_idxs[1] != -1);
11474  goto exit_error;
11475  }
11476 
11477  if (index_entryp->constraints->func_index_info && index_entryp->constraints->func_index_info->col_id == 0)
11478  {
11479  if (pt_fix_first_term_func_index_for_iss (parser, index_entryp, term_exprs) != NO_ERROR)
11480  {
11481  goto exit_error;
11482  }
11483  return NO_ERROR;
11484  }
11485 
11486  arg = pt_name (parser, index_entryp->constraints->attributes[0]->header.name);
11487  if (arg == NULL)
11488  {
11489  goto exit_error;
11490  }
11491 
11492  /* SEG IDXS [1] is the SECOND column of the index */
11493  seg = QO_ENV_SEG (index_entryp->terms.env, index_entryp->seg_idxs[1]);
11494  head = QO_SEG_HEAD (seg);
11495  spec = head->entity_spec;
11496 
11497  arg->info.name.spec_id = spec->info.spec.id;
11498  arg->info.name.meta_class = PT_NORMAL;
11500 
11501  arg->data_type = pt_domain_to_data_type (parser, index_entryp->constraints->attributes[0]->domain);
11502  if (arg->data_type == NULL)
11503  {
11504  goto exit_error;
11505  }
11506 
11507  arg->type_enum = arg->data_type->type_enum;
11508 
11509  db_make_null (&temp_null);
11510  val = pt_dbval_to_value (parser, &temp_null);
11511  if (val == NULL)
11512  {
11513  goto exit_error;
11514  }
11515 
11516  expr = pt_expression_2 (parser, PT_EQ, arg, val);
11517  if (expr == NULL)
11518  {
11519  goto exit_error;
11520  }
11521 
11522  term_exprs[0] = expr;
11523 
11524  return NO_ERROR;
11525 
11526 exit_error:
11527  if (arg)
11528  {
11529  parser_free_tree (parser, arg);
11530  }
11531  if (val)
11532  {
11533  parser_free_tree (parser, val);
11534  }
11535  if (expr)
11536  {
11537  parser_free_tree (parser, expr);
11538  }
11539 
11540  return ER_FAILED;
11541 }
11542 
11543 /*
11544  * pt_fix_first_term_func_index_for_iss () - allocates needed first term for
11545  * the index skip scan optimization (ISS) when a
11546  * function index is used
11547  * return:
11548  * parser(in):
11549  * index_entryp(in):
11550  * term_exprs(in):
11551  */
11552 static int
11554 {
11555  int error = NO_ERROR;
11556  int query_str_len = 0;
11557  char *query_str = NULL;
11558  SM_FUNCTION_INFO *func_index = NULL;
11559  PT_NODE **stmt = NULL;
11560  PT_NODE *expr = NULL;
11561  PT_NODE *val = NULL;
11562  PT_NODE *new_term = NULL;
11563  DB_VALUE temp_null;
11564  PT_NODE *spec = NULL;
11565  QO_SEGMENT *seg = NULL;
11566  QO_NODE *head = NULL;
11567  char *class_name = NULL;
11568  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
11569 
11570  assert (index_entryp->constraints->func_index_info);
11571  func_index = index_entryp->constraints->func_index_info;
11572 
11573  seg = QO_ENV_SEG (index_entryp->terms.env, index_entryp->seg_idxs[1]);
11574  head = QO_SEG_HEAD (seg);
11575  spec = head->entity_spec;
11576  class_name = (char *) spec->info.spec.range_var->info.name.original;
11577 
11578  query_str_len = (int) strlen (func_index->expr_str) + (int) strlen (class_name) + 7 /* strlen("SELECT ") */ +
11579  6 /* strlen(" FROM ") */ +
11580  2 /* [] */ +
11581  1 /* terminating null */ ;
11582  query_str = (char *) malloc (query_str_len);
11583  if (query_str == NULL)
11584  {
11585  return ER_OUT_OF_VIRTUAL_MEMORY;
11586  }
11587 
11588  snprintf (query_str, query_str_len, "SELECT %s FROM [%s]", func_index->expr_str, class_name);
11589  stmt = parser_parse_string_use_sys_charset (parser, query_str);
11590  if (stmt == NULL || *stmt == NULL || pt_has_error (parser))
11591  {
11592  error = ER_FAILED;
11593  goto error;
11594  }
11595  *stmt = pt_resolve_names (parser, *stmt, &sc_info);
11596  if (*stmt != NULL && !pt_has_error (parser))
11597  {
11598  *stmt = pt_semantic_type (parser, *stmt, &sc_info);
11599  }
11600  else
11601  {
11602  error = ER_FAILED;
11603  goto error;
11604  }
11605  expr = (*stmt)->info.query.q.select.list;
11606 
11607  db_make_null (&temp_null);
11608  val = pt_dbval_to_value (parser, &temp_null);
11609  if (val == NULL)
11610  {
11611  error = ER_FAILED;
11612  goto error;
11613  }
11614 
11615  new_term = pt_expression_2 (parser, PT_EQ, expr, val);
11616  if (expr == NULL)
11617  {
11618  error = ER_FAILED;
11619  goto error;
11620  }
11621 
11622  term_exprs[0] = new_term;
11623  free_and_init (query_str);
11624 
11625  return NO_ERROR;
11626 
11627 error:
11628  if (query_str)
11629  {
11630  free_and_init (query_str);
11631  }
11632  if (expr)
11633  {
11634  parser_free_tree (parser, expr);
11635  }
11636  if (val)
11637  {
11638  parser_free_tree (parser, val);
11639  }
11640  if (new_term)
11641  {
11642  parser_free_tree (parser, new_term);
11643  }
11644  return error;
11645 }
11646 
11647 /*
11648  * pt_to_index_info () - Create an INDX_INFO structure for communication
11649  * to a class access spec for eventual incorporation into an index scan
11650  * return:
11651  * parser(in):
11652  * class(in):
11653  * where_pred(in):
11654  * plan(in):
11655  * qo_index_infop(in):
11656  */
11657 static INDX_INFO *
11659  QO_XASL_INDEX_INFO * qo_index_infop)
11660 {
11661  int nterms;
11662  int rangelist_idx = -1;
11663  PT_NODE **term_exprs;
11664  PT_NODE *pt_expr;
11665  PT_OP_TYPE op_type = PT_LAST_OPCODE;
11666  INDX_INFO *indx_infop;
11667  QO_NODE_INDEX_ENTRY *ni_entryp;
11668  QO_INDEX_ENTRY *index_entryp;
11669 #if !defined(NDEBUG)
11670  QO_INDEX_ENTRY *head_idxp;
11671 #endif
11672  KEY_INFO *key_infop;
11673  int rc;
11674  int i;
11675  bool is_prefix_index;
11676  SM_FUNCTION_INFO *fi_info = NULL;
11677 
11678  assert (parser != NULL);
11679  assert (class_ != NULL);
11680  assert (plan != NULL);
11681  assert (qo_index_infop->ni_entry != NULL && qo_index_infop->ni_entry->head != NULL);
11682 
11683  if (!qo_is_interesting_order_scan (plan))
11684  {
11685  assert (false);
11686  PT_INTERNAL_ERROR (parser, "index plan generation - invalid plan");
11687  return NULL;
11688  }
11689 
11690  ni_entryp = qo_index_infop->ni_entry;
11691 
11692  for (i = 0, index_entryp = ni_entryp->head; i < ni_entryp->n; i++, index_entryp = index_entryp->next)
11693  {
11694  if (class_ == index_entryp->class_->mop)
11695  {
11696  break; /* found */
11697  }
11698  }
11699  assert (index_entryp != NULL);
11700 
11701 #if !defined(NDEBUG)
11702  head_idxp = ni_entryp->head;
11703 
11704  if (index_entryp != head_idxp)
11705  {
11706  assert (qo_is_prefix_index (index_entryp) == qo_is_prefix_index (head_idxp));
11707  assert (index_entryp->is_iss_candidate == head_idxp->is_iss_candidate);
11708  assert (index_entryp->cover_segments == head_idxp->cover_segments);
11709  assert (index_entryp->use_descending == head_idxp->use_descending);
11710  assert (index_entryp->orderby_skip == head_idxp->orderby_skip);
11711  assert (index_entryp->groupby_skip == head_idxp->groupby_skip);
11712 
11713  assert (QO_ENTRY_MULTI_COL (index_entryp) == QO_ENTRY_MULTI_COL (head_idxp));
11714 
11715  assert (index_entryp->ils_prefix_len == head_idxp->ils_prefix_len);
11716  assert (index_entryp->key_limit == head_idxp->key_limit);
11717 
11718  assert ((index_entryp->constraints->filter_predicate == NULL && head_idxp->constraints->filter_predicate == NULL)
11719  || (index_entryp->constraints->filter_predicate != NULL
11720  && head_idxp->constraints->filter_predicate != NULL));
11721  assert ((index_entryp->constraints->func_index_info == NULL && head_idxp->constraints->func_index_info == NULL)
11722  || (index_entryp->constraints->func_index_info != NULL
11723  && head_idxp->constraints->func_index_info != NULL));
11724  }
11725 #endif
11726 
11727  /* get array of term expressions and number of them which are associated with this index */
11728  nterms = qo_xasl_get_num_terms (qo_index_infop);
11729  term_exprs = qo_xasl_get_terms (qo_index_infop);
11730 
11731  is_prefix_index = qo_is_prefix_index (index_entryp);
11732 
11733  if (class_ == NULL || nterms < 0 || index_entryp == NULL)
11734  {
11735  PT_INTERNAL_ERROR (parser, "index plan generation - invalid arg");
11736  return NULL;
11737  }
11738 
11739  /* fabricate the first term_expr, to complete the proper range search expression */
11740  if (qo_is_index_iss_scan (plan))
11741  {
11742  assert (index_entryp->is_iss_candidate);
11743 
11744  pt_fix_first_term_expr_for_iss (parser, index_entryp, term_exprs);
11745  }
11746 
11747  if (nterms > 0)
11748  {
11749  int start_column = qo_is_index_iss_scan (plan) ? 1 : 0;
11750  rangelist_idx = -1; /* init */
11751  for (i = start_column; i < nterms; i++)
11752  {
11753  pt_expr = term_exprs[i];
11754  assert (pt_expr != NULL);
11755  if (pt_expr->info.expr.op == PT_RANGE)
11756  {
11757  assert (pt_expr->info.expr.arg2 != NULL);
11758 
11759  if (pt_expr->info.expr.arg2)
11760  {
11761  PT_NODE *between_and;
11762 
11763  between_and = pt_expr->info.expr.arg2;
11764  if (between_and->or_next)
11765  {
11766  /* is RANGE (r1, r2, ...) */
11767  rangelist_idx = i;
11768  break;
11769  }
11770  }
11771  }
11772  }
11773 
11774  if (rangelist_idx == -1)
11775  {
11776  /* The last term expression in the array(that is, [nterms - 1]) is interesting because the multi-column index
11777  * scan depends on it. For example: a = ? AND b = ? AND c = ? a = ? AND b = ? AND c RANGE (r1) a = ? AND b =
11778  * ? AND c RANGE (r1, r2, ...) */
11779  rangelist_idx = nterms - 1;
11780  op_type = term_exprs[rangelist_idx]->info.expr.op;
11781  }
11782  else
11783  {
11784  /* Have non-last EQUAL range term and is only one. For example: a = ? AND b RANGE (r1=, r2=, ...) AND c = ? a
11785  * = ? AND b RANGE (r1=, r2=, ...) AND c RANGE (r1)
11786  *
11787  * but, the following is not permitted. a = ? AND b RANGE (r1=, r2=, ...) AND c RANGE (r1, r2, ...) */
11788  op_type = PT_RANGE;
11789  }
11790  }
11791 
11792  /* make INDX_INFO structure and fill it up using information in QO_XASL_INDEX_INFO structure */
11793  regu_alloc (indx_infop);
11794  if (indx_infop == NULL)
11795  {
11796  PT_INTERNAL_ERROR (parser, "index plan generation - memory alloc");
11797  return NULL;
11798  }
11799 
11800  /* BTID */
11801  BTID_COPY (&indx_infop->btid, &index_entryp->constraints->index_btid);
11802 
11803  /* check for covered index scan */
11804  indx_infop->coverage = 0; /* init */
11805  if (qo_is_index_covering_scan (plan))
11806  {
11807  assert (index_entryp->cover_segments == true);
11808  assert (where_pred == NULL); /* no data-filter */
11809  assert (is_prefix_index == false);
11810 
11811  if (index_entryp->cover_segments == true && where_pred == NULL && is_prefix_index == false)
11812  {
11813  indx_infop->coverage = 1;
11814  }
11815  }
11816 
11817  if (indx_infop->coverage)
11818  {
11819  COLL_OPT collation_opt;
11820 
11821  if (qo_check_type_index_covering (index_entryp) == false)
11822  {
11823  indx_infop->coverage = false;
11824  }
11825 
11826  if (indx_infop->coverage)
11827  {
11828  qo_check_coll_optimization (index_entryp, &collation_opt);
11829 
11830  indx_infop->coverage = collation_opt.allow_index_opt;
11831  }
11832  }
11833 
11834  indx_infop->class_oid = class_->oid_info.oid;
11835  indx_infop->use_desc_index = index_entryp->use_descending;
11836  indx_infop->orderby_skip = index_entryp->orderby_skip;
11837  indx_infop->groupby_skip = index_entryp->groupby_skip;
11838 
11839  /* 0 for now, see gen optimized plan for its computation */
11840  indx_infop->orderby_desc = 0;
11841  indx_infop->groupby_desc = 0;
11842 
11843  indx_infop->use_iss = 0; /* init */
11844  if (qo_is_index_iss_scan (plan))
11845  {
11846  assert (QO_ENTRY_MULTI_COL (index_entryp));
11847  assert (!qo_is_index_loose_scan (plan));
11848  assert (!qo_plan_multi_range_opt (plan));
11849  assert (!qo_is_filter_index (index_entryp));
11850 
11851  indx_infop->use_iss = 1;
11852  }
11853 
11854  /* check for loose index scan */
11855  indx_infop->ils_prefix_len = 0; /* init */
11856  if (qo_is_index_loose_scan (plan))
11857  {
11858  assert (QO_ENTRY_MULTI_COL (index_entryp));
11860  assert (is_prefix_index == false);
11861  assert (!qo_is_index_iss_scan (plan));
11862  assert (!qo_plan_multi_range_opt (plan));
11863 
11864  assert (where_pred == NULL); /* no data-filter */
11865 
11866  indx_infop->ils_prefix_len = index_entryp->ils_prefix_len;
11867  assert (indx_infop->ils_prefix_len > 0);
11868  }
11869 
11870  fi_info = index_entryp->constraints->func_index_info;
11871  if (fi_info)
11872  {
11873  indx_infop->func_idx_col_id = fi_info->col_id;
11874  assert (indx_infop->func_idx_col_id != -1);
11875 
11876  rc =
11877  pt_create_iss_range (indx_infop,
11878  tp_domain_resolve (fi_info->fi_domain->type->id, class_, fi_info->fi_domain->precision,
11879  fi_info->fi_domain->scale, NULL, fi_info->fi_domain->collation_id));
11880  }
11881  else
11882  {
11883  indx_infop->func_idx_col_id = -1;
11884 
11885  rc = pt_create_iss_range (indx_infop, index_entryp->constraints->attributes[0]->domain);
11886  }
11887  if (rc != NO_ERROR)
11888  {
11889  PT_INTERNAL_ERROR (parser, "index plan generation - create iss range fail");
11890  return NULL;
11891  }
11892 
11893  /* key limits */
11894  key_infop = &indx_infop->key_info;
11895  if (pt_to_key_limit (parser, index_entryp->key_limit, NULL, key_infop, false) != NO_ERROR)
11896  {
11897  PT_INTERNAL_ERROR (parser, "index plan generation - invalid key limit");
11898  return NULL;
11899  }
11900 
11901  if (nterms == 0)
11902  {
11903  key_infop->key_cnt = 1;
11904  key_infop->is_constant = false;
11905  regu_array_alloc (&key_infop->key_ranges, 1);
11906  if (key_infop->key_ranges == NULL)
11907  {
11908  PT_INTERNAL_ERROR (parser, "index plan generation - memory alloc");
11909  return NULL;
11910  }
11911 
11912  key_infop->key_ranges[0].key1 = NULL;
11913  key_infop->key_ranges[0].key2 = NULL;
11914  key_infop->key_ranges[0].range = INF_INF;
11915 
11916  indx_infop->range_type = R_RANGE;
11917 
11918  return indx_infop;
11919  }
11920 
11921  /* scan range spec and index key information */
11922  switch (op_type)
11923  {
11924  case PT_EQ:
11925  rc = pt_to_single_key (parser, term_exprs, nterms, QO_ENTRY_MULTI_COL (index_entryp), key_infop,
11926  qo_index_infop->multi_col_pos);
11927  indx_infop->range_type = R_KEY;
11928  break;
11929  case PT_GT:
11930  case PT_GE:
11931  case PT_LT:
11932  case PT_LE:
11933  case PT_BETWEEN:
11934  rc = pt_to_range_key (parser, term_exprs, nterms, QO_ENTRY_MULTI_COL (index_entryp), key_infop);
11935  indx_infop->range_type = R_RANGE;
11936  break;
11937  case PT_IS_IN:
11938  case PT_EQ_SOME:
11939  rc = pt_to_list_key (parser, term_exprs, nterms, QO_ENTRY_MULTI_COL (index_entryp), key_infop);
11940  indx_infop->range_type = R_KEYLIST;
11941  break;
11942  case PT_RANGE:
11943  rc = pt_to_rangelist_key (parser, term_exprs, nterms, QO_ENTRY_MULTI_COL (index_entryp), key_infop, rangelist_idx,
11944  qo_index_infop->multi_col_pos);
11945  for (i = 0; i < key_infop->key_cnt; i++)
11946  {
11947  if (key_infop->key_ranges[i].range != EQ_NA)
11948  {
11949  break;
11950  }
11951  }
11952  if (i < key_infop->key_cnt)
11953  {
11954  indx_infop->range_type = R_RANGELIST;
11955  }
11956  else
11957  {
11958  indx_infop->range_type = R_KEYLIST; /* attr IN (?, ?) */
11959  }
11960  break;
11961  default:
11962  /* the other operators are not applicable to index scan */
11963  rc = -1;
11964  }
11965 
11966  if (rc < 0)
11967  {
11968  PT_INTERNAL_ERROR (parser, "index plan generation - invalid key value");
11969  return NULL;
11970  }
11971 
11972  if (is_prefix_index)
11973  {
11974  for (i = 0; i < key_infop->key_cnt; i++)
11975  {
11976  if (key_infop->key_ranges[i].range == GT_INF)
11977  {
11978  key_infop->key_ranges[i].range = GE_INF;
11979  }
11980  if (key_infop->key_ranges[i].range == GT_LT)
11981  {
11982  key_infop->key_ranges[i].range = GE_LT;
11983  }
11984  if (key_infop->key_ranges[i].range == GT_LE)
11985  {
11986  key_infop->key_ranges[i].range = GE_LE;
11987  }
11988  }
11989  }
11990 
11991  return indx_infop;
11992 }
11993 
11994 /*
11995  * pt_get_mvcc_reev_range_data () - creates predicates for range filter
11996  * return:
11997  * table_info(in):
11998  * where_key_part(in):
11999  * index_pred(in):
12000  * where_range(in/out):
12001  * regu_attributes_range(in/out):
12002  * cache_range(in/out):
12003  */
12004 int
12006  QO_XASL_INDEX_INFO * index_pred, PRED_EXPR ** where_range,
12007  REGU_VARIABLE_LIST * regu_attributes_range, HEAP_CACHE_ATTRINFO ** cache_range)
12008 {
12009  int idx, *range_offsets = NULL, *range_rest_offsets = NULL;
12010  PT_NODE *where_range_part = NULL;
12011  PT_NODE *range_attrs = NULL, *range_rest_attrs = NULL;
12012 
12013  if (parser->symbols == NULL)
12014  {
12015  return ER_FAILED;
12016  }
12017  if (where_key_part != NULL)
12018  {
12019  PT_NODE *diff1 = NULL, *diff2 = NULL;
12020 
12021  for (idx = 0; idx < index_pred->nterms; idx++)
12022  {
12023  diff1 = parser_get_tree_list_diff (parser, index_pred->term_exprs[idx], where_key_part);
12024  if (diff1 != NULL)
12025  {
12026  diff2 = parser_get_tree_list_diff (parser, diff1, where_range_part);
12027  parser_free_tree (parser, diff1);
12028  where_range_part = parser_append_node (diff2, where_range_part);
12029  }
12030  }
12031  }
12032  else
12033  {
12034  for (idx = 0; idx < index_pred->nterms; idx++)
12035  {
12036  where_range_part =
12037  parser_append_node (parser_copy_tree (parser, index_pred->term_exprs[idx]), where_range_part);
12038  }
12039  }
12040  if (pt_split_attrs (parser, table_info, where_range_part, &range_attrs, &range_rest_attrs, NULL, &range_offsets,
12041  &range_rest_offsets, NULL) != NO_ERROR)
12042  {
12043  parser_free_tree (parser, where_range_part);
12044  return ER_FAILED;
12045  }
12046 
12047  regu_alloc (*cache_range);
12048  parser->symbols->cache_attrinfo = *cache_range;
12049 
12050  *where_range = pt_to_pred_expr (parser, where_range_part);
12051 
12052  *regu_attributes_range =
12053  pt_to_regu_variable_list (parser, range_attrs, UNBOX_AS_VALUE, table_info->value_list, range_offsets);
12054 
12055  parser_free_tree (parser, where_range_part);
12056  parser_free_tree (parser, range_attrs);
12057  free_and_init (range_offsets);
12058  free_and_init (range_rest_offsets);
12059 
12060  return NO_ERROR;
12061 }
12062 
12063 /*
12064  * pt_to_class_spec_list () - Convert a PT_NODE flat class list to
12065  * an ACCESS_SPEC_LIST list of representing the classes to be selected from
12066  * return:
12067  * parser(in):
12068  * spec(in):
12069  * where_key_part(in):
12070  * where_part(in):
12071  * plan(in):
12072  * index_pred(in):
12073  */
12074 static ACCESS_SPEC_TYPE *
12075 pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_key_part, PT_NODE * where_part,
12076  QO_PLAN * plan, QO_XASL_INDEX_INFO * index_pred)
12077 {
12078  SYMBOL_INFO *symbols = NULL;
12079  ACCESS_SPEC_TYPE *access = NULL;
12081  PT_NODE *flat;
12082  PT_NODE *class_;
12083  PRED_EXPR *where_key = NULL;
12084  REGU_VARIABLE_LIST regu_attributes_key;
12085  HEAP_CACHE_ATTRINFO *cache_key = NULL;
12086  PT_NODE *key_attrs = NULL;
12087  int *key_offsets = NULL;
12088  PRED_EXPR *where = NULL, *where_range = NULL;
12089  REGU_VARIABLE_LIST regu_attributes_pred, regu_attributes_rest;
12090  REGU_VARIABLE_LIST regu_attributes_reserved;
12091  REGU_VARIABLE_LIST regu_attributes_range = NULL;
12093  INDX_INFO *index_info = NULL;
12094  HEAP_CACHE_ATTRINFO *cache_pred = NULL, *cache_rest = NULL;
12095  HEAP_CACHE_ATTRINFO *cache_range = NULL;
12096  PT_NODE *pred_attrs = NULL, *rest_attrs = NULL, *reserved_attrs = NULL;
12097  int *pred_offsets = NULL, *rest_offsets = NULL, *reserved_offsets = NULL;
12098  OUTPTR_LIST *output_val_list = NULL;
12099  REGU_VARIABLE_LIST regu_var_list = NULL;
12100  DB_VALUE **db_values_array_p = NULL;
12101 
12102  assert (parser != NULL);
12103 
12104  if (spec == NULL)
12105  {
12106  return NULL;
12107  }
12108 
12109  flat = spec->info.spec.flat_entity_list;
12110  if (flat == NULL)
12111  {
12112  return NULL;
12113  }
12114 
12115  symbols = parser->symbols;
12116  if (symbols == NULL)
12117  {
12118  return NULL;
12119  }
12120 
12121  table_info = pt_find_table_info (flat->info.name.spec_id, symbols->table_info);
12122 
12123  if (table_info)
12124  {
12125  for (class_ = flat; class_ != NULL; class_ = class_->next)
12126  {
12127  /* The scans have changed to grab the val list before predicate evaluation since evaluation now does
12128  * comparisons using DB_VALUES instead of disk rep. Thus, the where predicate does NOT want to generate
12129  * TYPE_ATTR_ID regu variables, but rather TYPE_CONSTANT regu variables. This is driven off the
12130  * symbols->current class variable so we need to generate the where pred first. */
12131 
12132  if (index_pred == NULL)
12133  {
12134  /* Heap scan */
12135  TARGET_TYPE scan_type;
12136  ACCESS_METHOD access_method = ACCESS_METHOD_SEQUENTIAL;
12137 
12138  /* determine access_method */
12140  {
12141  access_method = ACCESS_METHOD_SEQUENTIAL_RECORD_INFO;
12142  }
12144  {
12145  access_method = ACCESS_METHOD_SEQUENTIAL_PAGE_SCAN;
12146  }
12147 
12148  /* for VALUES query, a new scan type is set */
12149  if (PT_IS_VALUE_QUERY (spec))
12150  {
12151  scan_type = TARGET_REGUVAL_LIST;
12152  }
12153  else if (spec->info.spec.meta_class == PT_META_CLASS)
12154  {
12155  scan_type = TARGET_CLASS_ATTR;
12156  }
12157  else
12158  {
12159  scan_type = TARGET_CLASS;
12160  }
12161 
12162  if (pt_split_attrs (parser, table_info, where_part, &pred_attrs, &rest_attrs, &reserved_attrs,
12163  &pred_offsets, &rest_offsets, &reserved_offsets) != NO_ERROR)
12164  {
12165  return NULL;
12166  }
12167 
12168  if (access_method == ACCESS_METHOD_SEQUENTIAL_PAGE_SCAN)
12169  {
12170  cache_pred = NULL;
12171  cache_rest = NULL;
12172 
12173  db_values_array_p = pt_make_reserved_value_list (parser, RESERVED_NAME_PAGE_INFO);
12174  }
12175  else
12176  {
12177  regu_alloc (cache_pred);
12178  regu_alloc (cache_rest);
12179  if (access_method == ACCESS_METHOD_SEQUENTIAL_RECORD_INFO)
12180  {
12181  db_values_array_p = pt_make_reserved_value_list (parser, RESERVED_NAME_RECORD_INFO);
12182  }
12183  }
12184 
12185  symbols->current_class = (scan_type == TARGET_CLASS_ATTR) ? NULL : class_;
12186  symbols->cache_attrinfo = cache_pred;
12187  symbols->reserved_values = db_values_array_p;
12188 
12189  where = pt_to_pred_expr (parser, where_part);
12190 
12191  if (scan_type == TARGET_CLASS_ATTR)
12192  {
12193  symbols->current_class = class_;
12194  }
12195 
12196  regu_attributes_pred =
12197  pt_to_regu_variable_list (parser, pred_attrs, UNBOX_AS_VALUE, table_info->value_list, pred_offsets);
12198 
12199  symbols->cache_attrinfo = cache_rest;
12200 
12201  regu_attributes_rest =
12202  pt_to_regu_variable_list (parser, rest_attrs, UNBOX_AS_VALUE, table_info->value_list, rest_offsets);
12203 
12204  regu_attributes_reserved =
12205  pt_to_regu_variable_list (parser, reserved_attrs, UNBOX_AS_VALUE, table_info->value_list,
12206  reserved_offsets);
12207 
12208  output_val_list = NULL;
12209  regu_var_list = NULL;
12210 
12211  parser_free_tree (parser, pred_attrs);
12212  parser_free_tree (parser, rest_attrs);
12213  parser_free_tree (parser, reserved_attrs);
12214  if (pred_offsets != NULL)
12215  {
12216  free_and_init (pred_offsets);
12217  }
12218  if (rest_offsets != NULL)
12219  {
12220  free_and_init (rest_offsets);
12221  }
12222  if (reserved_offsets != NULL)
12223  {
12224  free_and_init (reserved_offsets);
12225  }
12226 
12227  access =
12228  pt_make_class_access_spec (parser, flat, class_->info.name.db_object, scan_type, access_method, NULL,
12229  NULL, where, NULL, NULL, regu_attributes_pred, regu_attributes_rest, NULL,
12230  output_val_list, regu_var_list, NULL, cache_pred, cache_rest,
12231  NULL, NO_SCHEMA, db_values_array_p, regu_attributes_reserved);
12232  }
12233  else if (PT_SPEC_SPECIAL_INDEX_SCAN (spec))
12234  {
12235  /* Index scan for key info */
12237  ACCESS_METHOD access_method = ACCESS_METHOD_SEQUENTIAL;
12238 
12239  if (pt_split_attrs (parser, table_info, where_part, &pred_attrs, &rest_attrs, &reserved_attrs,
12240  &pred_offsets, &rest_offsets, &reserved_offsets) != NO_ERROR)
12241  {
12242  return NULL;
12243  }
12244  /* pred_attrs and rest_attrs should have only class attributes. key info scan only allows selecting
12245  * reserved key info names. */
12246  assert (pred_attrs == NULL && rest_attrs == NULL && reserved_attrs != NULL);
12247 
12249  {
12250  reserved_type = RESERVED_NAME_KEY_INFO;
12251  access_method = ACCESS_METHOD_INDEX_KEY_INFO;
12252  }
12254  {
12255  reserved_type = RESERVED_NAME_BTREE_NODE_INFO;
12256  access_method = ACCESS_METHOD_INDEX_NODE_INFO;
12257  }
12258  else
12259  {
12260  /* Should never happen */
12261  assert (0);
12262  }
12263  db_values_array_p = pt_make_reserved_value_list (parser, reserved_type);
12264 
12265  symbols->current_class = class_;
12266  symbols->reserved_values = db_values_array_p;
12267 
12268  where = pt_to_pred_expr (parser, where_part);
12269 
12270  output_val_list = pt_make_outlist_from_vallist (parser, table_info->value_list);
12271 
12272  regu_attributes_pred = NULL;
12273  regu_attributes_rest = NULL;
12274  regu_attributes_reserved =
12275  pt_to_regu_variable_list (parser, reserved_attrs, UNBOX_AS_VALUE, table_info->value_list,
12276  reserved_offsets);
12277 
12278  parser_free_tree (parser, pred_attrs);
12279  parser_free_tree (parser, rest_attrs);
12280  parser_free_tree (parser, reserved_attrs);
12281  if (pred_offsets != NULL)
12282  {
12283  free_and_init (pred_offsets);
12284  }
12285  if (rest_offsets != NULL)
12286  {
12287  free_and_init (rest_offsets);
12288  }
12289  if (reserved_offsets != NULL)
12290  {
12291  free_and_init (reserved_offsets);
12292  }
12293 
12294  index_info = pt_to_index_info (parser, class_->info.name.db_object, where, plan, index_pred);
12295  access =
12296  pt_make_class_access_spec (parser, flat, class_->info.name.db_object, TARGET_CLASS, access_method,
12297  index_info, NULL, where, NULL, NULL, NULL, NULL, NULL, output_val_list, NULL,
12298  NULL, NULL, NULL, NULL, NO_SCHEMA, db_values_array_p,
12299  regu_attributes_reserved);
12300  }
12301  else
12302  {
12303  /* Index scan */
12304  /* for index with prefix length */
12305  PT_NODE *where_part_save = NULL, *where_key_part_save = NULL;
12306  PT_NODE *ipl_where_part = NULL;
12307 
12308  if (index_pred->ni_entry && index_pred->ni_entry->head && qo_is_prefix_index (index_pred->ni_entry->head))
12309  {
12310  if (index_pred->nterms > 0 || where_key_part)
12311  {
12312  ipl_where_part =
12313  pt_make_prefix_index_data_filter (parser, where_key_part, where_part, index_pred);
12314  }
12315 
12316  if (ipl_where_part)
12317  {
12318  where_part_save = where_part;
12319  where_part = ipl_where_part;
12320  where_key_part_save = where_key_part;
12321  where_key_part = NULL;
12322  }
12323  }
12324 
12325  if (!pt_to_index_attrs (parser, table_info, index_pred, where_key_part, &key_attrs, &key_offsets))
12326  {
12327  if (ipl_where_part)
12328  {
12329  parser_free_tree (parser, where_part);
12330  where_part = where_part_save;
12331  where_key_part = where_key_part_save;
12332  }
12333  return NULL;
12334  }
12335  if (pt_split_attrs (parser, table_info, where_part, &pred_attrs, &rest_attrs, NULL, &pred_offsets,
12336  &rest_offsets, NULL) != NO_ERROR)
12337  {
12338  if (ipl_where_part)
12339  {
12340  parser_free_tree (parser, where_part);
12341  where_part = where_part_save;
12342  where_key_part = where_key_part_save;
12343  }
12344  parser_free_tree (parser, key_attrs);
12345  if (key_offsets != NULL)
12346  {
12347  free_and_init (key_offsets);
12348  }
12349  return NULL;
12350  }
12351 
12352  symbols->current_class = class_;
12353 
12354  if (pt_get_mvcc_reev_range_data (parser, table_info, where_key_part, index_pred, &where_range,
12355  &regu_attributes_range, &cache_range) != NO_ERROR)
12356  {
12357  parser_free_tree (parser, key_attrs);
12358  if (key_offsets != NULL)
12359  {
12360  free_and_init (key_offsets);
12361  }
12362  parser_free_tree (parser, pred_attrs);
12363  if (pred_offsets != NULL)
12364  {
12365  free_and_init (pred_offsets);
12366  }
12367  parser_free_tree (parser, rest_attrs);
12368  if (rest_offsets != NULL)
12369  {
12370  free_and_init (rest_offsets);
12371  }
12372  return NULL;
12373  }
12374 
12375  regu_alloc (cache_key);
12376  regu_alloc (cache_pred);
12377  regu_alloc (cache_rest);
12378 
12379  symbols->cache_attrinfo = cache_key;
12380 
12381  where_key = pt_to_pred_expr (parser, where_key_part);
12382 
12383  regu_attributes_key =
12384  pt_to_regu_variable_list (parser, key_attrs, UNBOX_AS_VALUE, table_info->value_list, key_offsets);
12385 
12386  symbols->cache_attrinfo = cache_pred;
12387 
12388  where = pt_to_pred_expr (parser, where_part);
12389 
12390  regu_attributes_pred =
12391  pt_to_regu_variable_list (parser, pred_attrs, UNBOX_AS_VALUE, table_info->value_list, pred_offsets);
12392 
12393  symbols->cache_attrinfo = cache_rest;
12394 
12395  regu_attributes_rest =
12396  pt_to_regu_variable_list (parser, rest_attrs, UNBOX_AS_VALUE, table_info->value_list, rest_offsets);
12397 
12398  output_val_list = pt_make_outlist_from_vallist (parser, table_info->value_list);
12399 
12400  regu_var_list =
12401  pt_to_position_regu_variable_list (parser, rest_attrs, table_info->value_list, rest_offsets);
12402 
12403  parser_free_tree (parser, key_attrs);
12404  parser_free_tree (parser, pred_attrs);
12405  parser_free_tree (parser, rest_attrs);
12406  if (key_offsets != NULL)
12407  {
12408  free_and_init (key_offsets);
12409  }
12410  if (pred_offsets != NULL)
12411  {
12412  free_and_init (pred_offsets);
12413  }
12414  if (rest_offsets != NULL)
12415  {
12416  free_and_init (rest_offsets);
12417  }
12418 
12419  /*
12420  * pt_make_class_spec() will return NULL if passed a
12421  * NULL INDX_INFO *, so there isn't any need to check
12422  * return values here.
12423  */
12424  index_info = pt_to_index_info (parser, class_->info.name.db_object, where, plan, index_pred);
12425 
12426  if (pt_has_error (parser))
12427  {
12428  return NULL;
12429  }
12430 
12431  assert (index_info != NULL);
12432  access =
12434  index_info, where_key, where, where_range, regu_attributes_key,
12435  regu_attributes_pred, regu_attributes_rest, regu_attributes_range,
12436  output_val_list, regu_var_list, cache_key, cache_pred, cache_rest,
12437  cache_range, NO_SCHEMA, NULL, NULL);
12438 
12439  if (ipl_where_part)
12440  {
12441  parser_free_tree (parser, where_part);
12442  where_part = where_part_save;
12443  where_key_part = where_key_part_save;
12444  }
12445  }
12446 
12447  if (access == NULL
12448  || (regu_attributes_pred == NULL && regu_attributes_rest == NULL && table_info->attribute_list != NULL
12449  && access->access == ACCESS_METHOD_SEQUENTIAL) || pt_has_error (parser))
12450  {
12451  /* an error condition */
12452  access = NULL;
12453  }
12454 
12455  if (access)
12456  {
12458  {
12459  access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_FOR_UPDATE);
12460  }
12461 
12462  access->next = access_list;
12463  access_list = access;
12464  }
12465  else
12466  {
12467  /* an error condition */
12468  access_list = NULL;
12469  break;
12470  }
12471  }
12472 
12473  symbols->current_class = NULL;
12474  symbols->cache_attrinfo = NULL;
12475 
12476  }
12477 
12478  return access_list;
12479 }
12480 
12481 /*
12482  * pt_to_showstmt_spec_list () - Convert a QUERY PT_NODE
12483  * an showstmt query
12484  * return:
12485  * parser(in):
12486  * spec(in):
12487  * where_part(in):
12488  */
12489 static ACCESS_SPEC_TYPE *
12491 {
12492  PT_NODE *saved_current_class;
12493  PT_NODE *derived_table;
12494  SHOWSTMT_TYPE show_type;
12495  PT_NODE *show_args;
12496  REGU_VARIABLE_LIST arg_list;
12497  ACCESS_SPEC_TYPE *access;
12498  PRED_EXPR *where = NULL;
12499 
12500  if (spec->info.spec.derived_table_type != PT_IS_SHOWSTMT || (derived_table = spec->info.spec.derived_table) == NULL
12501  || derived_table->node_type != PT_SHOWSTMT)
12502  {
12503  return NULL;
12504  }
12505 
12506  saved_current_class = parser->symbols->current_class;
12507  parser->symbols->current_class = NULL;
12508  where = pt_to_pred_expr (parser, where_part);
12509  parser->symbols->current_class = saved_current_class;
12510  if (where_part != NULL && where == NULL)
12511  {
12512  return NULL;
12513  }
12514 
12515  show_type = derived_table->info.showstmt.show_type;
12516  show_args = derived_table->info.showstmt.show_args;
12517  arg_list = pt_to_regu_variable_list (parser, show_args, UNBOX_AS_VALUE, NULL, NULL);
12518  if (show_args != NULL && arg_list == NULL)
12519  {
12520  return NULL;
12521  }
12522 
12523  access = pt_make_showstmt_access_spec (where, show_type, arg_list);
12524 
12525  return access;
12526 }
12527 
12528 /*
12529  * pt_to_subquery_table_spec_list () - Convert a QUERY PT_NODE
12530  * an ACCESS_SPEC_LIST list for its list file
12531  * return:
12532  * parser(in):
12533  * spec(in):
12534  * subquery(in):
12535  * where_part(in):
12536  */
12537 static ACCESS_SPEC_TYPE *
12539  PT_NODE * where_hash_part)
12540 {
12541  XASL_NODE *subquery_proc;
12542  PT_NODE *saved_current_class;
12543  REGU_VARIABLE_LIST regu_attributes_pred, regu_attributes_rest, regu_attributes_build, regu_attributes_probe;
12544  ACCESS_SPEC_TYPE *access;
12545  PRED_EXPR *where = NULL;
12546  TABLE_INFO *tbl_info;
12547  PT_NODE *pred_attrs = NULL, *rest_attrs = NULL, *build_attrs = NULL, *probe_attrs = NULL;
12548  int *pred_offsets = NULL, *rest_offsets = NULL;
12549 
12550  subquery_proc = (XASL_NODE *) subquery->info.query.xasl;
12551 
12552  tbl_info = pt_find_table_info (spec->info.spec.id, parser->symbols->table_info);
12553 
12554  if (pt_split_attrs (parser, tbl_info, where_part, &pred_attrs, &rest_attrs, NULL, &pred_offsets, &rest_offsets, NULL)
12555  != NO_ERROR)
12556  {
12557  return NULL;
12558  }
12559 
12560  /* This generates a list of TYPE_POSITION regu_variables There information is stored in a QFILE_TUPLE_VALUE_POSITION,
12561  * which describes a type and index into a list file. */
12562  regu_attributes_pred = pt_to_position_regu_variable_list (parser, pred_attrs, tbl_info->value_list, pred_offsets);
12563  regu_attributes_rest = pt_to_position_regu_variable_list (parser, rest_attrs, tbl_info->value_list, rest_offsets);
12564 
12565  parser_free_tree (parser, pred_attrs);
12566  parser_free_tree (parser, rest_attrs);
12567  free_and_init (pred_offsets);
12568  free_and_init (rest_offsets);
12569 
12570  if (pt_split_hash_attrs (parser, tbl_info, where_hash_part, &build_attrs, &probe_attrs) != NO_ERROR)
12571  {
12572  return NULL;
12573  }
12574  regu_attributes_build = pt_to_regu_variable_list (parser, build_attrs, UNBOX_AS_VALUE, tbl_info->value_list, NULL);
12575  regu_attributes_probe = pt_to_regu_variable_list (parser, probe_attrs, UNBOX_AS_VALUE, tbl_info->value_list, NULL);
12576 
12577  parser_free_tree (parser, build_attrs);
12578  parser_free_tree (parser, probe_attrs);
12579 
12581  parser->symbols->current_listfile = NULL;
12582 
12583  /* The where predicate is now evaluated after the val list has been fetched. This means that we want to generate
12584  * "CONSTANT" regu variables instead of "POSITION" regu variables which would happen if
12585  * parser->symbols->current_listfile != NULL. pred should never user the current instance for fetches either, so we
12586  * turn off the current_class, if there is one. */
12587  saved_current_class = parser->symbols->current_class;
12588  parser->symbols->current_class = NULL;
12589  where = pt_to_pred_expr (parser, where_part);
12590  parser->symbols->current_class = saved_current_class;
12591 
12592  access =
12593  pt_make_list_access_spec (subquery_proc, ACCESS_METHOD_SEQUENTIAL, NULL, where, regu_attributes_pred,
12594  regu_attributes_rest, regu_attributes_build, regu_attributes_probe);
12595 
12596  if (access && subquery_proc && (regu_attributes_pred || regu_attributes_rest || !spec->info.spec.as_attr_list))
12597  {
12598  return access;
12599  }
12600 
12601  return NULL;
12602 }
12603 
12604 /*
12605  * pt_to_set_expr_table_spec_list () - Convert a PT_NODE flat class list
12606  * to an ACCESS_SPEC_LIST list of representing the classes
12607  * to be selected from
12608  * return:
12609  * parser(in):
12610  * spec(in):
12611  * set_expr(in):
12612  * where_part(in):
12613  */
12614 static ACCESS_SPEC_TYPE *
12616 {
12617  REGU_VARIABLE_LIST regu_attributes;
12618  REGU_VARIABLE *regu_set_expr;
12619  PRED_EXPR *where = NULL;
12620 
12621  ACCESS_SPEC_TYPE *access;
12622 
12623  regu_set_expr = pt_to_regu_variable (parser, set_expr, UNBOX_AS_VALUE);
12624 
12625  /* This generates a list of TYPE_POSITION regu_variables There information is stored in a QFILE_TUPLE_VALUE_POSITION,
12626  * which describes a type and index into a list file. */
12627  regu_attributes = pt_to_position_regu_variable_list (parser, spec->info.spec.as_attr_list, NULL, NULL);
12628 
12629  where = pt_to_pred_expr (parser, where_part);
12630 
12631  access = pt_make_set_access_spec (regu_set_expr, ACCESS_METHOD_SEQUENTIAL, NULL, where, regu_attributes);
12632 
12633  if (access && regu_set_expr && (regu_attributes || !spec->info.spec.as_attr_list))
12634  {
12635  return access;
12636  }
12637 
12638  return NULL;
12639 }
12640 
12641 /*
12642  * pt_to_cselect_table_spec_list () - Convert a PT_NODE flat class list to
12643  * an ACCESS_SPEC_LIST list of representing the classes to be selected from
12644  * return:
12645  * parser(in):
12646  * spec(in):
12647  * cselect(in):
12648  * src_derived_tbl(in):
12649  */
12650 static ACCESS_SPEC_TYPE *
12652 {
12653  XASL_NODE *subquery_proc;
12654  REGU_VARIABLE_LIST regu_attributes;
12655  ACCESS_SPEC_TYPE *access;
12657 
12658  /* every cselect must have a subquery for its source list file, this is pointed to by the methods of the cselect */
12659  if (!cselect || !(cselect->node_type == PT_METHOD_CALL) || !src_derived_tbl || !PT_SPEC_IS_DERIVED (src_derived_tbl))
12660  {
12661  return NULL;
12662  }
12663 
12664  subquery_proc = (XASL_NODE *) src_derived_tbl->info.spec.derived_table->info.query.xasl;
12665 
12666  method_sig_list = pt_to_method_sig_list (parser, cselect, src_derived_tbl->info.spec.as_attr_list);
12667 
12668  /* This generates a list of TYPE_POSITION regu_variables There information is stored in a QFILE_TUPLE_VALUE_POSITION,
12669  * which describes a type and index into a list file. */
12670 
12671  regu_attributes = pt_to_position_regu_variable_list (parser, spec->info.spec.as_attr_list, NULL, NULL);
12672 
12673  access =
12674  pt_make_cselect_access_spec (subquery_proc, method_sig_list, ACCESS_METHOD_SEQUENTIAL, NULL, NULL, regu_attributes);
12675 
12676  if (access && subquery_proc && method_sig_list && (regu_attributes || !spec->info.spec.as_attr_list))
12677  {
12678  return access;
12679  }
12680 
12681  return NULL;
12682 }
12683 
12684 static ACCESS_SPEC_TYPE *
12686  PT_NODE * src_derived_tbl, PT_NODE * where_p)
12687 {
12688  ACCESS_SPEC_TYPE *access;
12689 
12690  PRED_EXPR *where = pt_to_pred_expr (parser, where_p);
12691 
12692  TABLE_INFO *tbl_info = pt_find_table_info (spec->info.spec.id, parser->symbols->table_info);
12693  assert (tbl_info != NULL);
12694 
12695  REGU_VARIABLE *regu_var = pt_to_regu_variable (parser, json_table->info.json_table_info.expr, UNBOX_AS_VALUE);
12696 
12697  access = pt_make_json_table_access_spec (parser, regu_var, where, &json_table->info.json_table_info, tbl_info);
12698 
12699  return access;
12700 }
12701 
12702 /*
12703  * pt_to_cte_table_spec_list () - Convert a PT_NODE CTE to an ACCESS_SPEC_LIST of representations
12704  of the classes to be selected from
12705  * return:
12706  * parser(in):
12707  * spec(in):
12708  * cte_def(in):
12709  * where_part(in):
12710  */
12711 static ACCESS_SPEC_TYPE *
12713 {
12714  XASL_NODE *cte_proc;
12715  PT_NODE *saved_current_class;
12716  TABLE_INFO *tbl_info;
12717  REGU_VARIABLE_LIST regu_attributes_pred, regu_attributes_rest;
12718  ACCESS_SPEC_TYPE *access;
12719  PT_NODE *pred_attrs = NULL, *rest_attrs = NULL;
12720  int *pred_offsets = NULL, *rest_offsets = NULL;
12721  PRED_EXPR *where = NULL;
12722 
12723  if (spec == NULL || cte_def == NULL || spec->info.spec.cte_pointer == NULL)
12724  {
12725  return NULL;
12726  }
12727 
12728  if (cte_def->info.cte.xasl)
12729  {
12730  cte_proc = (XASL_NODE *) cte_def->info.cte.xasl;
12731  }
12732  else
12733  {
12734  /* The CTE xasl is null because the recursive part xasl has not been generated yet, but this is not a problem
12735  * because the recursive part should have access only to the non recursive part.
12736  * This may also happen with a CTE referenced by another one. If CTE1 is referenced by CTE2, the XASL of CTE1
12737  * is not completed when reaching this function from CTE2. CTE2 is reached following *next* link of CTE1 before
12738  * CTE1 post function of xasl generation is executed.
12739  */
12740  PT_NODE *non_recursive_part = cte_def->info.cte.non_recursive_part;
12741 
12742  if (non_recursive_part->info.query.xasl)
12743  {
12744  cte_proc = (XASL_NODE *) non_recursive_part->info.query.xasl;
12745  }
12746  else
12747  {
12748  assert (false);
12749  return NULL;
12750  }
12751  }
12752 
12753  tbl_info = pt_find_table_info (spec->info.spec.id, parser->symbols->table_info);
12754 
12755  if (pt_split_attrs (parser, tbl_info, where_part, &pred_attrs, &rest_attrs, NULL, &pred_offsets, &rest_offsets, NULL)
12756  != NO_ERROR)
12757  {
12758  return NULL;
12759  }
12760 
12761  /* This generates a list of TYPE_POSITION regu_variables
12762  * There information is stored in a QFILE_TUPLE_VALUE_POSITION, which
12763  * describes a type and index into a list file.
12764  */
12765  regu_attributes_pred = pt_to_position_regu_variable_list (parser, pred_attrs, tbl_info->value_list, pred_offsets);
12766  regu_attributes_rest = pt_to_position_regu_variable_list (parser, rest_attrs, tbl_info->value_list, rest_offsets);
12767 
12768  parser_free_tree (parser, pred_attrs);
12769  parser_free_tree (parser, rest_attrs);
12770  free_and_init (pred_offsets);
12771  free_and_init (rest_offsets);
12772 
12774  parser->symbols->current_listfile = NULL;
12775 
12776  /* The where predicate is now evaluated after the val list has been fetched.
12777  * This means that we want to generate "CONSTANT" regu variables instead of "POSITION" regu variables which would
12778  * happen if parser->symbols->current_listfile != NULL.
12779  * pred should never use the current instance for fetches either, so we turn off the current_class, if there is one.
12780  */
12781  saved_current_class = parser->symbols->current_class;
12782  parser->symbols->current_class = NULL;
12783  where = pt_to_pred_expr (parser, where_part);
12784  parser->symbols->current_class = saved_current_class;
12785 
12786  access =
12787  pt_make_list_access_spec (cte_proc, ACCESS_METHOD_SEQUENTIAL, NULL, where, regu_attributes_pred,
12788  regu_attributes_rest, NULL, NULL);
12789 
12790  if (access && cte_proc && (regu_attributes_pred || regu_attributes_rest || !spec->info.spec.as_attr_list))
12791  {
12792  return access;
12793  }
12794 
12795  return NULL;
12796 }
12797 
12798 /*
12799  * pt_to_spec_list () - Convert a PT_NODE spec to an ACCESS_SPEC_LIST list of
12800  * representing the classes to be selected from
12801  * return:
12802  * parser(in):
12803  * spec(in):
12804  * where_key_part(in):
12805  * where_part(in):
12806  * plan(in):
12807  * index_part(in):
12808  * src_derived_tbl(in):
12809  */
12811 pt_to_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_key_part, PT_NODE * where_part,
12812  QO_PLAN * plan, QO_XASL_INDEX_INFO * index_part, PT_NODE * src_derived_tbl, PT_NODE * where_hash_part)
12813 {
12814  ACCESS_SPEC_TYPE *access = NULL;
12815 
12816  if (spec->info.spec.flat_entity_list != NULL && !PT_SPEC_IS_CTE (spec) && !PT_SPEC_IS_DERIVED (spec))
12817  {
12818  access = pt_to_class_spec_list (parser, spec, where_key_part, where_part, plan, index_part);
12819  }
12820  else if (PT_SPEC_IS_DERIVED (spec))
12821  {
12822  /* derived table index_part better be NULL here! */
12824  {
12825  access =
12826  pt_to_subquery_table_spec_list (parser, spec, spec->info.spec.derived_table, where_part, where_hash_part);
12827  }
12828  else if (spec->info.spec.derived_table_type == PT_IS_SET_EXPR)
12829  {
12830  /* a set expression derived table */
12831  access = pt_to_set_expr_table_spec_list (parser, spec, spec->info.spec.derived_table, where_part);
12832  }
12833  else if (spec->info.spec.derived_table_type == PT_IS_SHOWSTMT)
12834  {
12835  access = pt_to_showstmt_spec_list (parser, spec, where_part);
12836  }
12837  else if (spec->info.spec.derived_table_type == PT_IS_CSELECT)
12838  {
12839  /* a CSELECT derived table */
12840  access = pt_to_cselect_table_spec_list (parser, spec, spec->info.spec.derived_table, src_derived_tbl);
12841  }
12843  {
12844  /* PT_JSON_DERIVED_TABLE derived table */
12845  access =
12846  pt_to_json_table_spec_list (parser, spec, spec->info.spec.derived_table, src_derived_tbl, where_part);
12847  }
12848  else
12849  {
12850  // unrecognized derived table type
12851  assert (false);
12853  return NULL;
12854  }
12855  }
12856  else
12857  {
12858  /* there is a cte_pointer inside spec */
12859  assert (PT_SPEC_IS_CTE (spec));
12860 
12861  /* the subquery should be in non_recursive_part of the cte */
12862  access = pt_to_cte_table_spec_list (parser, spec, spec->info.spec.cte_pointer->info.pointer.node, where_part);
12863  }
12864 
12865  return access;
12866 }
12867 
12868 /*
12869  * pt_to_val_list () -
12870  * return: val_list corresponding to the entity spec
12871  * parser(in):
12872  * id(in):
12873  */
12874 VAL_LIST *
12876 {
12877  SYMBOL_INFO *symbols;
12878  VAL_LIST *val_list = NULL;
12880 
12881  if (parser)
12882  {
12883  symbols = parser->symbols;
12884  table_info = pt_find_table_info (id, symbols->table_info);
12885 
12886  if (table_info)
12887  {
12888  val_list = table_info->value_list;
12889  }
12890  }
12891 
12892  return val_list;
12893 }
12894 
12895 /*
12896  * pt_find_xasl () - appends the from list to the end of the to list
12897  * return:
12898  * list(in):
12899  * match(in):
12900  */
12901 static XASL_NODE *
12903 {
12904  XASL_NODE *xasl = list;
12905 
12906  while (xasl && xasl != match)
12907  {
12908  xasl = xasl->next;
12909  }
12910 
12911  return xasl;
12912 }
12913 
12914 /*
12915  * pt_append_xasl () - appends the from list to the end of the to list
12916  * return:
12917  * to(in):
12918  * from_list(in):
12919  */
12920 XASL_NODE *
12922 {
12923  XASL_NODE *xasl = to;
12924  XASL_NODE *next;
12925  XASL_NODE *from = from_list;
12926 
12927  if (!xasl)
12928  {
12929  return from_list;
12930  }
12931 
12932  while (xasl->next)
12933  {
12934  xasl = xasl->next;
12935  }
12936 
12937  while (from)
12938  {
12939  next = from->next;
12940 
12941  if (pt_find_xasl (to, from))
12942  {
12943  /* already on list, do nothing necessarily, the rest of the nodes are on the list, since they are linked to
12944  * from. */
12945  from = NULL;
12946  }
12947  else
12948  {
12949  xasl->next = from;
12950  xasl = from;
12951  from->next = NULL;
12952  from = next;
12953  }
12954  }
12955 
12956  return to;
12957 }
12958 
12959 
12960 /*
12961  * pt_remove_xasl () - removes an xasl node from an xasl list
12962  * return:
12963  * xasl_list(in):
12964  * remove(in):
12965  */
12966 XASL_NODE *
12967 pt_remove_xasl (XASL_NODE * xasl_list, XASL_NODE * remove)
12968 {
12969  XASL_NODE *list = xasl_list;
12970 
12971  if (!list)
12972  {
12973  return list;
12974  }
12975 
12976  if (list == remove)
12977  {
12978  xasl_list = remove->next;
12979  remove->next = NULL;
12980  }
12981  else
12982  {
12983  while (list->next && list->next != remove)
12984  {
12985  list = list->next;
12986  }
12987 
12988  if (list->next == remove)
12989  {
12990  list->next = remove->next;
12991  remove->next = NULL;
12992  }
12993  }
12994 
12995  return xasl_list;
12996 }
12997 
12998 /*
12999  * pt_set_dptr () - If this xasl node should have a dptr list from
13000  * "correlated == 1" queries, they will be set
13001  * return:
13002  * parser(in):
13003  * node(in):
13004  * xasl(in):
13005  * id(in):
13006  */
13007 void
13008 pt_set_dptr (PARSER_CONTEXT * parser, PT_NODE * node, XASL_NODE * xasl, UINTPTR id)
13009 {
13010  if (xasl)
13011  {
13012  xasl->dptr_list =
13013  pt_remove_xasl (pt_append_xasl (xasl->dptr_list, pt_to_corr_subquery_list (parser, node, id)), xasl);
13014  }
13015 }
13016 
13017 /*
13018  * pt_set_aptr () - If this xasl node should have an aptr list from
13019  * "correlated > 1" queries, they will be set
13020  * return:
13021  * parser(in):
13022  * select_node(in):
13023  * xasl(in):
13024  */
13025 static void
13027 {
13028  if (xasl)
13029  {
13030  xasl->aptr_list =
13031  pt_remove_xasl (pt_append_xasl (xasl->aptr_list, pt_to_uncorr_subquery_list (parser, select_node)), xasl);
13032  }
13033 }
13034 
13035 /*
13036  * pt_set_connect_by_xasl() - set the CONNECT BY xasl node,
13037  * and make the pseudo-columns regu vars
13038  * parser(in):
13039  * select_node(in):
13040  * xasl(in):
13041  */
13042 static XASL_NODE *
13044 {
13045  int n;
13046  XASL_NODE *connect_by_xasl;
13047 
13048  if (!xasl)
13049  {
13050  return NULL;
13051  }
13052 
13053  connect_by_xasl = pt_make_connect_by_proc (parser, select_node, xasl);
13054  if (!connect_by_xasl)
13055  {
13056  return xasl;
13057  }
13058 
13059  /* set the CONNECT BY pointer and flag */
13060  xasl->connect_by_ptr = connect_by_xasl;
13062 
13063  /* make regu vars for use for pseudo-columns values fetching */
13064 
13065  n = connect_by_xasl->outptr_list->valptr_cnt;
13066 
13067  /* LEVEL pseudo-column */
13068  if (xasl->level_val)
13069  {
13070  if (!xasl->level_regu)
13071  {
13072  xasl->level_regu =
13074  if (!xasl->level_regu)
13075  {
13076  return NULL;
13077  }
13078  }
13079  }
13080 
13081  /* CONNECT_BY_ISLEAF pseudo-column */
13082  if (xasl->isleaf_val)
13083  {
13084  if (!xasl->isleaf_regu)
13085  {
13086  xasl->isleaf_regu =
13088  if (!xasl->isleaf_regu)
13089  {
13090  return NULL;
13091  }
13092  }
13093  }
13094 
13095  /* CONNECT_BY_ISCYCLE pseudo-column */
13096  if (xasl->iscycle_val)
13097  {
13098  if (!xasl->iscycle_regu)
13099  {
13100  xasl->iscycle_regu =
13102  if (!xasl->iscycle_regu)
13103  {
13104  return NULL;
13105  }
13106  }
13107  }
13108 
13109  /* move ORDER SIBLINGS BY column list in the CONNECT BY xasl if order_by was not cut out because of aggregates */
13110  if (xasl->orderby_list != NULL && select_node->info.query.flag.order_siblings == 1)
13111  {
13112  connect_by_xasl->orderby_list = pt_to_order_siblings_by (parser, xasl, connect_by_xasl);
13113  if (!connect_by_xasl->orderby_list)
13114  {
13115  return NULL;
13116  }
13117  xasl->orderby_list = NULL;
13118  }
13119 
13120  return xasl;
13121 }
13122 
13123 /*
13124  * pt_append_scan () - appends the from list to the end of the to list
13125  * return:
13126  * to(in):
13127  * from(in):
13128  */
13129 static XASL_NODE *
13130 pt_append_scan (const XASL_NODE * to, const XASL_NODE * from)
13131 {
13132  XASL_NODE *xasl = (XASL_NODE *) to;
13133 
13134  if (!xasl)
13135  {
13136  return (XASL_NODE *) from;
13137  }
13138 
13139  while (xasl->scan_ptr)
13140  {
13141  xasl = xasl->scan_ptr;
13142  }
13143  xasl->scan_ptr = (XASL_NODE *) from;
13144 
13145  return (XASL_NODE *) to;
13146 }
13147 
13148 /*
13149  * pt_uncorr_pre () - builds xasl list of locally correlated (level 1) queries
13150  * return:
13151  * parser(in):
13152  * node(in):
13153  * arg(in/out):
13154  * continue_walk(in/out):
13155  */
13156 static PT_NODE *
13157 pt_uncorr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13158 {
13159  UNCORR_INFO *info = (UNCORR_INFO *) arg;
13160 
13161  *continue_walk = PT_CONTINUE_WALK;
13162 
13163  if (!PT_IS_QUERY_NODE_TYPE (node->node_type) && node->node_type != PT_CTE)
13164  {
13165  return node;
13166  }
13167 
13168  /* Can not increment level for list portion of walk. Since those queries are not sub-queries of this query.
13169  * Consequently, we recurse separately for the list leading from a query. Can't just call
13170  * pt_to_uncorr_subquery_list() directly since it needs to do a leaf walk and we want to do a full walk on the next
13171  * list. */
13172  if (node->next)
13173  {
13174  node->next = parser_walk_tree (parser, node->next, pt_uncorr_pre, info, pt_uncorr_post, info);
13175  }
13176 
13177  *continue_walk = PT_LEAF_WALK;
13178 
13179  if (node->node_type == PT_CTE)
13180  {
13181  /* don't want to include the subqueries from the PT_CTE */
13182  *continue_walk = PT_STOP_WALK;
13183  }
13184  /* increment level as we dive into subqueries */
13185  info->level++;
13186 
13187  return node;
13188 }
13189 
13190 /*
13191  * pt_uncorr_post () - decrement level of correlation after passing selects
13192  * return:
13193  * parser(in):
13194  * node(in):
13195  * arg(in/out):
13196  * continue_walk(in/out):
13197  */
13198 static PT_NODE *
13199 pt_uncorr_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13200 {
13201  UNCORR_INFO *info = (UNCORR_INFO *) arg;
13202  XASL_NODE *xasl;
13203 
13204  switch (node->node_type)
13205  {
13206  case PT_SELECT:
13207  case PT_UNION:
13208  case PT_DIFFERENCE:
13209  case PT_INTERSECTION:
13210  info->level--;
13211  xasl = (XASL_NODE *) node->info.query.xasl;
13212 
13213  if (xasl && pt_is_subquery (node))
13214  {
13215  if (node->info.query.correlation_level == 0)
13216  {
13217  /* add to this level */
13218  node->info.query.correlation_level = info->level;
13219  }
13220 
13221  if (node->info.query.correlation_level == info->level)
13222  {
13223  /* order is important. we are on the way up, so putting things at the tail of the list will end up deeper
13224  * nested queries being first, which is required. */
13225  info->xasl = pt_append_xasl (info->xasl, xasl);
13226  }
13227  }
13228 
13229  break;
13230 
13231  case PT_CTE:
13232  info->level--;
13233  xasl = (XASL_NODE *) node->info.cte.xasl;
13234 
13235  if (xasl)
13236  {
13237  /* The CTE correlation level is kept in the non_recursive_part query and it is handled here since
13238  * the CTE subqueries are not accessed for correlation check;
13239  * After validation, the CTE XASL is added to the list */
13240 
13241  PT_NODE *non_recursive_part = node->info.cte.non_recursive_part;
13242  // non_recursive_part can become PT_VALUE during constant folding
13243  assert (PT_IS_QUERY (non_recursive_part) || PT_IS_VALUE_NODE (non_recursive_part));
13244  if (PT_IS_VALUE_NODE (non_recursive_part))
13245  {
13246  info->xasl = pt_append_xasl (xasl, info->xasl);
13247  break;
13248  }
13249 
13250  if (non_recursive_part->info.query.correlation_level == 0)
13251  {
13252  /* add non_recursive_part to this level */
13253  non_recursive_part->info.query.correlation_level = info->level;
13254  }
13255 
13256  if (non_recursive_part->info.query.correlation_level == info->level)
13257  {
13258  /* append the CTE xasl at the beginning of the list */
13259  info->xasl = pt_append_xasl (xasl, info->xasl);
13260  }
13261  }
13262 
13263  break;
13264 
13265  default:
13266  break;
13267  }
13268 
13269  return node;
13270 }
13271 
13272 /*
13273  * pt_to_uncorr_subquery_list () - Gather the correlated level > 1 subqueries
13274  * include nested queries, such that nest level + 2 = correlation level
13275  * exclude the node being passed in
13276  * return:
13277  * parser(in):
13278  * node(in):
13279  */
13280 static XASL_NODE *
13282 {
13283  UNCORR_INFO info;
13284 
13285  info.xasl = NULL;
13286  info.level = 2;
13287 
13288  node = parser_walk_leaves (parser, node, pt_uncorr_pre, &info, pt_uncorr_post, &info);
13289 
13290  return info.xasl;
13291 }
13292 
13293 /*
13294  * pt_corr_pre () - builds xasl list of locally correlated (level 1) queries
13295  * directly reachable. (no nested queries, which are already handled)
13296  * return:
13297  * parser(in):
13298  * node(in):
13299  * arg(in):
13300  * continue_walk(in):
13301  */
13302 static PT_NODE *
13303 pt_corr_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13304 {
13305  XASL_NODE *xasl;
13306  CORR_INFO *info = (CORR_INFO *) arg;
13307 
13308  *continue_walk = PT_CONTINUE_WALK;
13309 
13310  switch (node->node_type)
13311  {
13312  case PT_SELECT:
13313  case PT_UNION:
13314  case PT_DIFFERENCE:
13315  case PT_INTERSECTION:
13316  *continue_walk = PT_LIST_WALK;
13317  xasl = (XASL_NODE *) node->info.query.xasl;
13318 
13319  if (xasl && node->info.query.correlation_level == 1 && (info->id == MATCH_ALL || node->spec_ident == info->id))
13320  {
13321  info->xasl_head = pt_append_xasl (xasl, info->xasl_head);
13322  }
13323 
13324  default:
13325  break;
13326  }
13327 
13328  return node;
13329 }
13330 
13331 /*
13332  * pt_to_corr_subquery_list () - Gather the correlated level == 1 subqueries.
13333  * exclude nested queries. including the node being passed in
13334  * return:
13335  * parser(in):
13336  * node(in):
13337  * id(in):
13338  */
13339 static XASL_NODE *
13341 {
13342  CORR_INFO info;
13343 
13344  info.xasl_head = NULL;
13345  info.id = id;
13346 
13347  node = parser_walk_tree (parser, node, pt_corr_pre, &info, pt_continue_walk, NULL);
13348 
13349  return info.xasl_head;
13350 }
13351 
13352 /*
13353  * pt_link_regu_to_selupd_list () - Link update related regu list from outlist
13354  * into selupd list of XASL tree
13355  * return:
13356  * parser(in):
13357  * regulist(in):
13358  * selupd_list(in):
13359  * target_class(in):
13360  */
13361 static SELUPD_LIST *
13363  DB_OBJECT * target_class)
13364 {
13365  SELUPD_LIST *node;
13366  REGU_VARLIST_LIST l_regulist;
13367  OID *oid_ptr;
13368  HFID *hfid_ptr;
13369  int is_partition = 0;
13370 
13371  oid_ptr = ws_identifier (target_class);
13372  hfid_ptr = sm_get_ch_heap (target_class);
13373 
13374  if (oid_ptr == NULL || hfid_ptr == NULL)
13375  {
13376  return NULL;
13377  }
13378 
13379  /* find a related info node for the target class */
13380  for (node = selupd_list; node != NULL; node = node->next)
13381  {
13382  if (OID_EQ (&node->class_oid, oid_ptr))
13383  break;
13384  }
13385  if (node == NULL)
13386  {
13387  regu_alloc (node);
13388  if (node == NULL)
13389  {
13390  return NULL;
13391  }
13392  if (sm_partitioned_class_type (target_class, &is_partition, NULL, NULL) != NO_ERROR)
13393  {
13394  return NULL;
13395  }
13396  if (is_partition != DB_NOT_PARTITIONED_CLASS)
13397  {
13398  /* if target class is a partitioned class, the class to access will be determimed at execution time. so do
13399  * not set class oid and hfid */
13400  OID_SET_NULL (&node->class_oid);
13401  HFID_SET_NULL (&node->class_hfid);
13402  }
13403  else
13404  {
13405  /* setup class info */
13406  COPY_OID (&node->class_oid, oid_ptr);
13407  HFID_COPY (&node->class_hfid, hfid_ptr);
13408  }
13409 
13410  /* insert the node into the selupd list */
13411  if (selupd_list == NULL)
13412  {
13413  selupd_list = node;
13414  }
13415  else
13416  {
13417  node->next = selupd_list;
13418  selupd_list = node;
13419  }
13420  }
13421 
13422  regu_alloc (l_regulist);
13423  if (l_regulist == NULL)
13424  {
13425  return NULL;
13426  }
13427 
13428  /* link the regulist of outlist to the node */
13429  l_regulist->list = regulist;
13430 
13431  /* add the regulist pointer to the current node */
13432  l_regulist->next = node->select_list;
13433  node->select_list = l_regulist;
13434  node->select_list_size++;
13435 
13436  return selupd_list;
13437 }
13438 
13439 /*
13440  * pt_to_outlist () - Convert a pt_node list to an outlist (of regu_variables)
13441  * return:
13442  * parser(in):
13443  * node_list(in):
13444  * selupd_list_ptr(in):
13445  * unbox(in):
13446  */
13447 static OUTPTR_LIST *
13448 pt_to_outlist (PARSER_CONTEXT * parser, PT_NODE * node_list, SELUPD_LIST ** selupd_list_ptr, UNBOX unbox)
13449 {
13450  OUTPTR_LIST *outlist;
13451  PT_NODE *node = NULL, *node_next, *col;
13452  int count = 0;
13453  REGU_VARIABLE *regu;
13454  REGU_VARIABLE_LIST *regulist;
13455  PT_NODE *save_node = NULL, *save_next = NULL;
13456  XASL_NODE *xasl = NULL;
13457  QFILE_SORTED_LIST_ID *srlist_id;
13458  QPROC_DB_VALUE_LIST value_list = NULL;
13459  int i;
13460  bool skip_hidden;
13461  PT_NODE *new_node_list = NULL;
13462  int list_len = 0;
13463  PT_NODE *cur;
13464 
13465  regu_alloc (outlist);
13466  if (outlist == NULL)
13467  {
13469  goto exit_on_error;
13470  }
13471 
13472  regulist = &outlist->valptrp;
13473 
13474  /* link next_row for PT_VALUE,PT_NAME,PT_EXPR... in PT_NODE_LIST */
13475  if (node_list && node_list->node_type == PT_NODE_LIST)
13476  {
13477  node = node_list->info.node_list.list;
13478  while (node)
13479  {
13480 #if 0 /* TODO - */
13481  assert (node->type_enum != PT_TYPE_NULL);
13482 #endif
13483  ++list_len;
13484  node = node->next;
13485  }
13486 
13487  /* new list head_nodes */
13488  new_node_list = (PT_NODE *) pt_alloc_packing_buf (list_len * sizeof (PT_NODE));
13489  if (new_node_list == NULL)
13490  {
13492  goto exit_on_error;
13493  }
13494 
13495  for (i = 0, node = node_list->info.node_list.list; i < list_len && node; ++i, node = node->next)
13496  {
13497  new_node_list[i].node_type = PT_NODE_LIST;
13498  parser_reinit_node (&new_node_list[i]); /* type must be set before init */
13499 
13500  new_node_list[i].info.node_list.list = node;
13501  PT_SET_VALUE_QUERY (&new_node_list[i]);
13502 
13503  if (i == list_len - 1)
13504  {
13505  new_node_list[i].next = NULL;
13506  }
13507  else
13508  {
13509  new_node_list[i].next = &new_node_list[i + 1];
13510  }
13511  }
13512 
13513  /* link next_row pointer */
13514  for (node = node_list; node && node->next; node = node->next)
13515  {
13516  /* column count of rows are checked in semantic_check.c */
13517  for (cur = node->info.node_list.list, node_next = node->next->info.node_list.list; cur && node_next;
13518  cur = cur->next, node_next = node_next->next)
13519  {
13520  cur->next_row = node_next;
13521  }
13522  }
13523 
13524  assert (node);
13525 
13526  /* Now node points to the last row of node_list set the last row's next_row pointer to NULL */
13527  for (cur = node->info.node_list.list; cur != NULL; cur = cur->next)
13528  {
13529  cur->next_row = NULL;
13530  }
13531 
13532  node_list = new_node_list;
13533  }
13534 
13535  for (node = node_list, node_next = node ? node->next : NULL; node != NULL;
13536  node = node_next, node_next = node ? node->next : NULL)
13537  {
13538  save_node = node; /* save */
13539 
13540  CAST_POINTER_TO_NODE (node);
13541  if (node)
13542  {
13543 #if 0 /* TODO - */
13544  assert (node->type_enum != PT_TYPE_NULL);
13545 #endif
13546 
13547  /* reset flag for new node */
13548  skip_hidden = false;
13549 
13550  /* save and cut-off node link */
13551  save_next = node->next;
13552  node->next = NULL;
13553 
13554  /* get column list */
13555  col = node;
13556  if (PT_IS_QUERY_NODE_TYPE (node->node_type))
13557  {
13558  /* hidden columns from subquery should not get referenced in select list */
13559  skip_hidden = true;
13560 
13561  xasl = (XASL_NODE *) node->info.query.xasl;
13562  if (xasl == NULL)
13563  {
13564  goto exit_on_error;
13565  }
13566 
13567  xasl->is_single_tuple = (unbox != UNBOX_AS_TABLE);
13568  if (xasl->is_single_tuple)
13569  {
13570  col = pt_get_select_list (parser, node);
13571  if (!xasl->single_tuple)
13572  {
13573  xasl->single_tuple = pt_make_val_list (parser, col);
13574  if (xasl->single_tuple == NULL)
13575  {
13577  goto exit_on_error;
13578  }
13579  }
13580 
13581  value_list = xasl->single_tuple->valp;
13582  }
13583  }
13584 
13585  /* make outlist */
13586  for (i = 0; col; col = col->next, i++)
13587  {
13588 #if 0 /* TODO - */
13589  assert (col->type_enum != PT_TYPE_NULL);
13590 #endif
13591 
13592  if (skip_hidden && col->flag.is_hidden_column && i > 0)
13593  {
13594  /* we don't need this node; also, we assume the first column of the subquery is NOT hidden */
13595  continue;
13596  }
13597 
13598  regu_alloc (*regulist);
13599  if (*regulist == NULL)
13600  {
13601  goto exit_on_error;
13602  }
13603 
13604  if (PT_IS_QUERY_NODE_TYPE (node->node_type))
13605  {
13606  regu_alloc (regu);
13607  if (regu == NULL)
13608  {
13609  goto exit_on_error;
13610  }
13611 
13612  if (i == 0)
13613  {
13614  /* set as linked to regu var */
13616  regu->xasl = xasl;
13617  }
13618 
13619  if (xasl->is_single_tuple)
13620  {
13621  regu->type = TYPE_CONSTANT;
13622  regu->domain = pt_xasl_node_to_domain (parser, col);
13623  regu->value.dbvalptr = value_list->val;
13624  /* move to next db_value holder */
13625  value_list = value_list->next;
13626  }
13627  else
13628  {
13629  regu_alloc (srlist_id);
13630  if (srlist_id == NULL)
13631  {
13632  goto exit_on_error;
13633  }
13634 
13635  regu->type = TYPE_LIST_ID;
13636  regu->value.srlist_id = srlist_id;
13637  srlist_id->list_id = xasl->list_id;
13638  }
13639  }
13640  else if (col->node_type == PT_EXPR && col->info.expr.op == PT_ORDERBY_NUM)
13641  {
13642  regu_alloc (regu);
13643  if (regu == NULL)
13644  {
13645  goto exit_on_error;
13646  }
13647 
13648  regu->type = TYPE_ORDERBY_NUM;
13649  regu->domain = pt_xasl_node_to_domain (parser, col);
13650  regu->value.dbvalptr = (DB_VALUE *) col->etc;
13651  }
13652  else
13653  {
13654  regu = pt_to_regu_variable (parser, col, unbox);
13655  }
13656 
13657  if (regu == NULL)
13658  {
13659  goto exit_on_error;
13660  }
13661 
13662 #if 0 /* TODO - */
13663  assert (TP_DOMAIN_TYPE (regu->domain) != DB_TYPE_NULL);
13664 #endif
13665 
13666  /* append to outlist */
13667  (*regulist)->value = *regu;
13668 
13669  /* in case of increment expr, find a target class to do the expr, and link the regulist to a node which
13670  * contains update info for the target class */
13671  if (selupd_list_ptr != NULL && col->node_type == PT_EXPR
13672  && (col->info.expr.op == PT_INCR || col->info.expr.op == PT_DECR))
13673  {
13674  PT_NODE *upd_obj;
13675  PT_NODE *upd_dom;
13676  PT_NODE *upd_dom_nm;
13677  DB_OBJECT *upd_dom_cls;
13678  OID nulloid;
13679 
13680  upd_obj = col->info.expr.arg2;
13681  if (upd_obj == NULL)
13682  {
13683  goto exit_on_error;
13684  }
13685 
13686  upd_dom = (upd_obj->node_type == PT_DOT_) ? upd_obj->info.dot.arg2->data_type : upd_obj->data_type;
13687  if (upd_dom == NULL)
13688  {
13689  goto exit_on_error;
13690  }
13691 
13692  if (upd_obj->type_enum != PT_TYPE_OBJECT || upd_dom->info.data_type.virt_type_enum != PT_TYPE_OBJECT)
13693  {
13694  goto exit_on_error;
13695  }
13696 
13697  upd_dom_nm = upd_dom->info.data_type.entity;
13698  if (upd_dom_nm == NULL)
13699  {
13700  goto exit_on_error;
13701  }
13702 
13703  upd_dom_cls = upd_dom_nm->info.name.db_object;
13704 
13705  /* initialize result of regu expr */
13706  OID_SET_NULL (&nulloid);
13707  db_make_oid (regu->value.arithptr->value, &nulloid);
13708 
13709  (*selupd_list_ptr) = pt_link_regu_to_selupd_list (parser, *regulist, (*selupd_list_ptr), upd_dom_cls);
13710  if ((*selupd_list_ptr) == NULL)
13711  {
13712  goto exit_on_error;
13713  }
13714  }
13715  regulist = &(*regulist)->next;
13716 
13717  count++;
13718  } /* for (i = 0; ...) */
13719 
13720  /* restore node link */
13721  node->next = save_next;
13722  }
13723 
13724  node = save_node; /* restore */
13725  }
13726 
13727  outlist->valptr_cnt = count;
13728 
13729  return outlist;
13730 
13731 exit_on_error:
13732 
13733  /* restore node link */
13734  if (node)
13735  {
13736  node->next = save_next;
13737  }
13738 
13739  node = save_node; /* restore */
13740 
13741  return NULL;
13742 }
13743 
13744 
13745 /*
13746  * pt_to_fetch_as_scan_proc () - Translate a PT_NODE path entity spec to an
13747  * a left outer scan proc on a list file from an xasl proc
13748  * return:
13749  * parser(in):
13750  * spec(in):
13751  * pred(in):
13752  * join_term(in):
13753  * xasl_to_scan(in):
13754  */
13755 static XASL_NODE *
13756 pt_to_fetch_as_scan_proc (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * join_term, XASL_NODE * xasl_to_scan)
13757 {
13758  XASL_NODE *xasl;
13759  PT_NODE *saved_current_class;
13760  REGU_VARIABLE *regu;
13761  REGU_VARIABLE_LIST regu_attributes_pred, regu_attributes_rest;
13762  ACCESS_SPEC_TYPE *access;
13763  UNBOX unbox;
13764  TABLE_INFO *tbl_info;
13765  PRED_EXPR *where = NULL;
13766  PT_NODE *pred_attrs = NULL, *rest_attrs = NULL;
13767  int *pred_offsets = NULL, *rest_offsets = NULL;
13768 
13770  if (!xasl)
13771  {
13772  PT_ERROR (parser, spec,
13774  return NULL;
13775  }
13776 
13777  unbox = UNBOX_AS_VALUE;
13778 
13779  xasl->val_list = pt_to_val_list (parser, spec->info.spec.id);
13780 
13781  tbl_info = pt_find_table_info (spec->info.spec.id, parser->symbols->table_info);
13782 
13783  if (pt_split_attrs (parser, tbl_info, join_term, &pred_attrs, &rest_attrs, NULL, &pred_offsets, &rest_offsets, NULL)
13784  != NO_ERROR)
13785  {
13786  return NULL;
13787  }
13788 
13789  /* This generates a list of TYPE_POSITION regu_variables There information is stored in a QFILE_TUPLE_VALUE_POSITION,
13790  * which describes a type and index into a list file. */
13791  regu_attributes_pred = pt_to_position_regu_variable_list (parser, pred_attrs, tbl_info->value_list, pred_offsets);
13792  regu_attributes_rest = pt_to_position_regu_variable_list (parser, rest_attrs, tbl_info->value_list, rest_offsets);
13793 
13794  parser_free_tree (parser, pred_attrs);
13795  parser_free_tree (parser, rest_attrs);
13796  free_and_init (pred_offsets);
13797  free_and_init (rest_offsets);
13798 
13799  parser->symbols->listfile_unbox = unbox;
13800  parser->symbols->current_listfile = NULL;
13801 
13802  /* The where predicate is now evaluated after the val list has been fetched. This means that we want to generate
13803  * "CONSTANT" regu variables instead of "POSITION" regu variables which would happen if
13804  * parser->symbols->current_listfile != NULL. pred should never user the current instance for fetches either, so we
13805  * turn off the current_class, if there is one. */
13806  saved_current_class = parser->symbols->current_class;
13807  parser->symbols->current_class = NULL;
13808  where = pt_to_pred_expr (parser, join_term);
13809  parser->symbols->current_class = saved_current_class;
13810 
13811  access =
13812  pt_make_list_access_spec (xasl_to_scan, ACCESS_METHOD_SEQUENTIAL, NULL, where, regu_attributes_pred,
13813  regu_attributes_rest, NULL, NULL);
13814 
13815  if (access)
13816  {
13817  xasl->spec_list = access;
13818 
13819  access->single_fetch = QPROC_SINGLE_OUTER;
13820 
13821  regu = pt_join_term_to_regu_variable (parser, join_term);
13822 
13823  if (regu)
13824  {
13825  if (regu->type == TYPE_CONSTANT || regu->type == TYPE_DBVAL)
13826  access->s_dbval = pt_regu_to_dbvalue (parser, regu);
13827  }
13828  }
13830 
13831  return xasl;
13832 }
13833 
13834 
13835 /*
13836  * pt_to_fetch_proc () - Translate a PT_NODE path entity spec to
13837  * an OBJFETCH_PROC
13838  * return:
13839  * parser(in):
13840  * spec(in):
13841  * pred(in):
13842  */
13843 XASL_NODE *
13845 {
13846  XASL_NODE *xasl = NULL;
13847  PT_NODE *oid_name = NULL;
13848  REGU_VARIABLE *regu;
13849  PT_NODE *flat;
13850  PT_NODE *conjunct;
13851  PT_NODE *derived;
13852 
13853  if (!spec)
13854  {
13855  return NULL; /* no error */
13856  }
13857 
13858  if (spec->node_type == PT_SPEC && (conjunct = spec->info.spec.path_conjuncts) && (conjunct->node_type == PT_EXPR)
13859  && (oid_name = conjunct->info.expr.arg1))
13860  {
13861  flat = spec->info.spec.flat_entity_list;
13862  if (flat)
13863  {
13865 
13866  if (xasl)
13867  {
13868  FETCH_PROC_NODE *fetch = &xasl->proc.fetch;
13869 
13870  xasl->next = NULL;
13871 
13873 
13874  if (xasl->outptr_list == NULL)
13875  {
13876  goto exit_on_error;
13877  }
13878 
13879  xasl->spec_list = pt_to_class_spec_list (parser, spec, NULL, pred, NULL, NULL);
13880 
13881  if (xasl->spec_list == NULL)
13882  {
13883  goto exit_on_error;
13884  }
13885 
13886  xasl->val_list = pt_to_val_list (parser, spec->info.spec.id);
13887 
13888  /* done in last if_pred, for now */
13889  fetch->set_pred = NULL;
13890 
13891  /* set flag for INNER path fetches */
13892  fetch->ql_flag = (QL_FLAG) (spec->info.spec.meta_class == PT_PATH_INNER);
13893 
13894  /* fill in xasl->proc.fetch set oid argument to DB_VALUE of left side of dot expression */
13895  regu = pt_attribute_to_regu (parser, oid_name);
13896  fetch->arg = NULL;
13897  if (regu)
13898  {
13899  fetch->arg = pt_regu_to_dbvalue (parser, regu);
13900  }
13901  }
13902  else
13903  {
13904  PT_ERROR (parser, spec,
13907  return NULL;
13908  }
13909  }
13910  else if ((derived = spec->info.spec.derived_table))
13911  {
13912  /* this is a derived table path spec */
13913  xasl = pt_to_fetch_as_scan_proc (parser, spec, conjunct, (XASL_NODE *) derived->info.query.xasl);
13914  }
13915  }
13916 
13917  return xasl;
13918 
13919 exit_on_error:
13920 
13921  return NULL;
13922 }
13923 
13924 
13925 /*
13926  * pt_to_fetch_proc_list_recurse () - Translate a PT_NODE path (dot) expression
13927  * to a XASL OBJFETCH or SETFETCH proc
13928  * return:
13929  * parser(in):
13930  * spec(in):
13931  * root(in):
13932  */
13933 static void
13935 {
13936  XASL_NODE *xasl = NULL;
13937 
13938  xasl = pt_to_fetch_proc (parser, spec, NULL);
13939 
13940  if (!xasl)
13941  {
13942  return;
13943  }
13944 
13945  if (xasl->type == SCAN_PROC)
13946  {
13947  APPEND_TO_XASL (root, scan_ptr, xasl);
13948  }
13949  else
13950  {
13951  APPEND_TO_XASL (root, bptr_list, xasl);
13952  }
13953 
13954  /* get the rest of the fetch procs at this level */
13955  if (spec->next)
13956  {
13957  pt_to_fetch_proc_list_recurse (parser, spec->next, root);
13958  }
13959 
13960  if (xasl && spec->info.spec.path_entities)
13961  {
13962  pt_to_fetch_proc_list_recurse (parser, spec->info.spec.path_entities, root);
13963  }
13964 
13965  return;
13966 }
13967 
13968 /*
13969  * pt_to_fetch_proc_list () - Translate a PT_NODE path (dot) expression to
13970  * a XASL OBJFETCH or SETFETCH proc
13971  * return: none
13972  * parser(in):
13973  * spec(in):
13974  * root(in):
13975  */
13976 static void
13978 {
13979  XASL_NODE *xasl = NULL;
13980 
13981  pt_to_fetch_proc_list_recurse (parser, spec, root);
13982 
13983  xasl = root->scan_ptr;
13984  if (xasl)
13985  {
13986  while (xasl->scan_ptr)
13987  {
13988  xasl = xasl->scan_ptr;
13989  }
13990 
13991  /* we must promote the if_pred to the fetch as scan proc Only do this once, not recursively */
13992  xasl->if_pred = root->if_pred;
13993  root->if_pred = NULL;
13994  xasl->dptr_list = root->dptr_list;
13995  root->dptr_list = NULL;
13996  }
13997 
13998  return;
13999 }
14000 
14001 
14002 /*
14003  * ptqo_to_scan_proc () - Convert a spec pt_node to a SCAN_PROC
14004  * return:
14005  * parser(in):
14006  * plan(in):
14007  * xasl(in):
14008  * spec(in):
14009  * where_key_part(in):
14010  * where_part(in):
14011  * info(in):
14012  */
14013 XASL_NODE *
14014 ptqo_to_scan_proc (PARSER_CONTEXT * parser, QO_PLAN * plan, XASL_NODE * xasl, PT_NODE * spec, PT_NODE * where_key_part,
14015  PT_NODE * where_part, QO_XASL_INDEX_INFO * info, PT_NODE * where_hash_part)
14016 {
14017  if (xasl == NULL)
14018  {
14020  }
14021 
14022  if (!xasl)
14023  {
14024  PT_ERROR (parser, spec,
14026  return NULL;
14027  }
14028 
14029  if (spec != NULL)
14030  {
14031  xasl->spec_list = pt_to_spec_list (parser, spec, where_key_part, where_part, plan, info, NULL, where_hash_part);
14032  if (xasl->spec_list == NULL)
14033  {
14034  goto exit_on_error;
14035  }
14036 
14037  xasl->val_list = pt_to_val_list (parser, spec->info.spec.id);
14038  }
14039 
14040  return xasl;
14041 
14042 exit_on_error:
14043 
14044  return NULL;
14045 }
14046 
14047 
14048 /*
14049  * pt_skeleton_buildlist_proc () - Construct a partly
14050  * initialized BUILDLIST_PROC
14051  * return:
14052  * parser(in):
14053  * namelist(in):
14054  */
14055 XASL_NODE *
14057 {
14058  XASL_NODE *xasl;
14059 
14060  assert (parser != NULL);
14061 
14063  if (xasl == NULL)
14064  {
14065  goto exit_on_error;
14066  }
14067 
14068  xasl->outptr_list = pt_to_outlist (parser, namelist, NULL, UNBOX_AS_VALUE);
14069  if (xasl->outptr_list == NULL)
14070  {
14071  goto exit_on_error;
14072  }
14073 
14074  return xasl;
14075 
14076 exit_on_error:
14077 
14078  return NULL;
14079 }
14080 
14081 
14082 /*
14083  * ptqo_to_list_scan_proc () - Convert an spec pt_node to a SCAN_PROC
14084  * return:
14085  * parser(in):
14086  * xasl(in):
14087  * proc_type(in):
14088  * listfile(in):
14089  * namelist(in):
14090  * pred(in):
14091  * poslist(in):
14092  */
14093 XASL_NODE *
14095  PT_NODE * namelist, PT_NODE * pred, int *poslist)
14096 {
14097  if (xasl == NULL)
14098  {
14099  xasl = regu_xasl_node_alloc (proc_type);
14100  }
14101 
14102  if (xasl && listfile)
14103  {
14104  PRED_EXPR *pred_expr = NULL;
14105  REGU_VARIABLE_LIST regu_attributes = NULL;
14106  PT_NODE *saved_current_class;
14107  int *attr_offsets;
14108 
14110  parser->symbols->current_listfile = NULL;
14111 
14112  /* The where predicate is now evaluated after the val list has been fetched. This means that we want to generate
14113  * "CONSTANT" regu variables instead of "POSITION" regu variables which would happen if
14114  * parser->symbols->current_listfile != NULL. pred should never user the current instance for fetches either, so
14115  * we turn off the current_class, if there is one. */
14116  saved_current_class = parser->symbols->current_class;
14117  parser->symbols->current_class = NULL;
14118  pred_expr = pt_to_pred_expr (parser, pred);
14119  parser->symbols->current_class = saved_current_class;
14120 
14121  /* Need to create a value list using the already allocated DB_VALUE data buckets on some other XASL_PROC's val
14122  * list. Actually, these should be simply global, but aren't. */
14123  xasl->val_list = pt_clone_val_list (parser, namelist);
14124 
14125  /* handle the buildlist case. append regu to the out_list, and create a new value to append to the value_list */
14126  attr_offsets = pt_make_identity_offsets (namelist);
14127  regu_attributes = pt_to_position_regu_variable_list (parser, namelist, xasl->val_list, attr_offsets);
14128 
14129  /* hack for the case of list scan in merge join */
14130  if (poslist)
14131  {
14133  int i;
14134 
14135  for (p = regu_attributes, i = 0; p; p = p->next, i++)
14136  {
14137  p->value.value.pos_descr.pos_no = poslist[i];
14138  }
14139  }
14140  free_and_init (attr_offsets);
14141 
14142  xasl->spec_list =
14143  pt_make_list_access_spec (listfile, ACCESS_METHOD_SEQUENTIAL, NULL, pred_expr, regu_attributes, NULL, NULL,
14144  NULL);
14145 
14146  if (xasl->spec_list == NULL || xasl->val_list == NULL)
14147  {
14148  xasl = NULL;
14149  }
14150  }
14151  else
14152  {
14153  xasl = NULL;
14154  }
14155 
14156  return xasl;
14157 }
14158 
14159 
14160 /*
14161  * ptqo_to_merge_list_proc () - Make a MERGELIST_PROC to merge an inner
14162  * and outer list
14163  * return:
14164  * parser(in):
14165  * left(in):
14166  * right(in):
14167  * join_type(in):
14168  */
14169 XASL_NODE *
14171 {
14172  XASL_NODE *xasl;
14173 
14174  assert (parser != NULL);
14175 
14176  if (left == NULL || right == NULL)
14177  {
14178  return NULL;
14179  }
14180 
14182 
14183  if (!xasl)
14184  {
14185  PT_NODE dummy;
14186 
14187  memset (&dummy, 0, sizeof (dummy));
14188  PT_ERROR (parser, &dummy,
14190  return NULL;
14191  }
14192 
14193  xasl->proc.mergelist.outer_xasl = left;
14194  xasl->proc.mergelist.inner_xasl = right;
14195 
14196  if (join_type == JOIN_RIGHT)
14197  {
14198  right->next = left;
14199  xasl->aptr_list = right;
14200  }
14201  else
14202  {
14203  left->next = right;
14204  xasl->aptr_list = left;
14205  }
14206 
14207  return xasl;
14208 }
14209 
14210 
14211 /*
14212  * ptqo_single_orderby () - Make a SORT_LIST that will sort the given column
14213  * according to the type of the given name
14214  * return:
14215  * parser(in):
14216  */
14217 SORT_LIST *
14219 {
14220  SORT_LIST *list;
14221 
14222  regu_alloc (list);
14223  if (list)
14224  {
14225  list->next = NULL;
14226  }
14227 
14228  return list;
14229 }
14230 
14231 
14232 /*
14233  * pt_to_scan_proc_list () - Convert a SELECT pt_node to an XASL_NODE
14234  * list of SCAN_PROCs
14235  * return:
14236  * parser(in):
14237  * node(in):
14238  * root(in):
14239  */
14240 static XASL_NODE *
14242 {
14243  XASL_NODE *xasl = NULL;
14244  XASL_NODE *list = NULL;
14245  XASL_NODE *last = root;
14246  PT_NODE *from;
14247 
14248  from = node->info.query.q.select.from->next;
14249 
14250  while (from)
14251  {
14252  xasl = ptqo_to_scan_proc (parser, NULL, NULL, from, NULL, NULL, NULL, NULL);
14253 
14254  pt_to_pred_terms (parser, node->info.query.q.select.where, from->info.spec.id, &xasl->if_pred);
14255 
14256  pt_set_dptr (parser, node->info.query.q.select.where, xasl, from->info.spec.id);
14257  pt_set_dptr (parser, node->info.query.q.select.list, xasl, from->info.spec.id);
14258 
14259  if (!xasl)
14260  {
14261  return NULL;
14262  }
14263 
14264  if (from->info.spec.path_entities)
14265  {
14266  pt_to_fetch_proc_list (parser, from->info.spec.path_entities, xasl);
14267  }
14268 
14269  pt_set_dptr (parser, from->info.spec.derived_table, last, MATCH_ALL);
14270 
14271  last = xasl;
14272 
14273  from = from->next;
14274 
14275  /* preserve order for maintenance & sanity */
14276  list = pt_append_scan (list, xasl);
14277  }
14278 
14279  return list;
14280 }
14281 
14282 /*
14283  * pt_gen_optimized_plan () - Translate a PT_SELECT node to a XASL plan
14284  * return:
14285  * parser(in):
14286  * select_node(in):
14287  * plan(in):
14288  * xasl(in):
14289  */
14290 static XASL_NODE *
14292 {
14293  XASL_NODE *ret = NULL;
14294 
14295  assert (parser != NULL);
14296 
14297  if (xasl && select_node && !pt_has_error (parser))
14298  {
14299  ret = qo_to_xasl (plan, xasl);
14300 
14301  if (ret == NULL)
14302  {
14303  xasl->spec_list = NULL;
14304  xasl->scan_ptr = NULL;
14305  }
14306  else
14307  {
14308  /* if the user asked for a descending scan, force it on all iscans */
14309  if (select_node->info.query.q.select.hint & PT_HINT_USE_IDX_DESC)
14310  {
14311  XASL_NODE *ptr;
14312  for (ptr = xasl; ptr; ptr = ptr->scan_ptr)
14313  {
14314  if (ptr->spec_list && ptr->spec_list->indexptr)
14315  {
14316  ptr->spec_list->indexptr->use_desc_index = 1;
14317  }
14318  }
14319  }
14320 
14321  if (select_node->info.query.q.select.hint & PT_HINT_NO_IDX_DESC)
14322  {
14323  XASL_NODE *ptr;
14324  for (ptr = xasl; ptr; ptr = ptr->scan_ptr)
14325  {
14326  if (ptr->spec_list && ptr->spec_list->indexptr)
14327  {
14328  ptr->spec_list->indexptr->use_desc_index = 0;
14329  }
14330  }
14331  }
14332 
14333  /* check direction of the first order by column. see also scan_get_index_oidset() in scan_manager.c */
14334  if (xasl->spec_list && select_node->info.query.order_by && xasl->spec_list->indexptr)
14335  {
14336  PT_NODE *ob = select_node->info.query.order_by;
14337 
14338  if (ob->info.sort_spec.asc_or_desc == PT_DESC)
14339  {
14340  xasl->spec_list->indexptr->orderby_desc = 1;
14341  }
14342  }
14343 
14344  /* check direction of the first group by column. see also scan_get_index_oidset() in scan_manager.c */
14345  if (xasl->spec_list && select_node->info.query.q.select.group_by && xasl->spec_list->indexptr)
14346  {
14347  PT_NODE *gb = select_node->info.query.q.select.group_by;
14348 
14349  if (gb->info.sort_spec.asc_or_desc == PT_DESC)
14350  {
14351  xasl->spec_list->indexptr->groupby_desc = 1;
14352  }
14353  }
14354 
14355  /* if the user asked for NO_HASH_LIST_SCAN, force it on all list scan */
14356  if (select_node->info.query.q.select.hint & PT_HINT_NO_HASH_LIST_SCAN)
14357  {
14358  XASL_NODE *ptr;
14359  for (ptr = xasl; ptr; ptr = ptr->scan_ptr)
14360  {
14361  if (ptr->spec_list && ptr->spec_list->type == TARGET_LIST)
14362  {
14364  }
14365  }
14366  }
14367  }
14368  }
14369 
14370  return ret;
14371 }
14372 
14373 /*
14374  * pt_gen_simple_plan () - Translate a PT_SELECT node to a XASL plan
14375  * return:
14376  * parser(in):
14377  * select_node(in):
14378  * plan(in):
14379  * xasl(in):
14380  */
14381 static XASL_NODE *
14383 {
14384  PT_NODE *from, *where;
14385  PT_NODE *access_part, *if_part, *instnum_part;
14386  XASL_NODE *lastxasl;
14387  int flag;
14388 
14389  assert (parser != NULL);
14390 
14391  if (xasl && select_node && !pt_has_error (parser))
14392  {
14393  from = select_node->info.query.q.select.from;
14394 
14395  /* copy so as to preserve parse tree */
14396  where = parser_copy_tree_list (parser, select_node->info.query.q.select.where);
14397 
14398  /* set 'etc' field for pseudocolumn nodes in WHERE pred */
14399  if (select_node->info.query.q.select.connect_by)
14400  {
14401  pt_set_level_node_etc (parser, where, &xasl->level_val);
14402  pt_set_isleaf_node_etc (parser, where, &xasl->isleaf_val);
14403  pt_set_iscycle_node_etc (parser, where, &xasl->iscycle_val);
14404  pt_set_connect_by_operator_node_etc (parser, where, xasl);
14405  pt_set_qprior_node_etc (parser, where, xasl);
14406  }
14407 
14408  pt_split_access_if_instnum (parser, from, where, &access_part, &if_part, &instnum_part);
14409 
14410  xasl->spec_list = pt_to_spec_list (parser, from, NULL, access_part, NULL, NULL, NULL, NULL);
14411  if (xasl->spec_list == NULL)
14412  {
14413  goto exit_on_error;
14414  }
14415 
14416  /* save where part to restore tree later */
14417  where = select_node->info.query.q.select.where;
14418  select_node->info.query.q.select.where = if_part;
14419 
14420  pt_to_pred_terms (parser, if_part, from->info.spec.id, &xasl->if_pred);
14421 
14422  /* and pick up any uncorrelated terms */
14423  pt_to_pred_terms (parser, if_part, 0, &xasl->if_pred);
14424 
14425  xasl = pt_to_instnum_pred (parser, xasl, instnum_part);
14426 
14427  if (from->info.spec.path_entities)
14428  {
14429  pt_to_fetch_proc_list (parser, from->info.spec.path_entities, xasl);
14430  }
14431 
14432  /* Find the last scan proc. Some pseudo-fetch procs may be on this list */
14433  lastxasl = xasl;
14434  while (lastxasl && lastxasl->scan_ptr)
14435  {
14436  lastxasl = lastxasl->scan_ptr;
14437  }
14438 
14439  /* if pseudo fetch procs are there, the dptr must be attached to the last xasl scan proc. */
14440  pt_set_dptr (parser, select_node->info.query.q.select.where, lastxasl, from->info.spec.id);
14441 
14442  /* this also correctly places correlated subqueries for derived tables */
14443  lastxasl->scan_ptr = pt_to_scan_proc_list (parser, select_node, lastxasl);
14444 
14445  while (lastxasl && lastxasl->scan_ptr)
14446  {
14447  lastxasl = lastxasl->scan_ptr;
14448  }
14449 
14450  /* make sure all scan_ptrs are found before putting correlated subqueries from the select list on the last
14451  * (inner) scan_ptr. because they may be correlated to specs later in the from list. */
14452  pt_set_dptr (parser, select_node->info.query.q.select.list, lastxasl, 0);
14453 
14454  xasl->val_list = pt_to_val_list (parser, from->info.spec.id);
14455 
14456  parser_free_tree (parser, access_part);
14457  parser_free_tree (parser, if_part);
14458  parser_free_tree (parser, instnum_part);
14459  select_node->info.query.q.select.where = where;
14460  }
14461 
14462  return xasl;
14463 
14464 exit_on_error:
14465 
14466  return NULL;
14467 }
14468 
14469 
14470 /*
14471  * pt_gen_simple_merge_plan () - Translate a PT_SELECT node to a XASL plan
14472  * return:
14473  * parser(in):
14474  * select_node(in):
14475  * plan(in):
14476  * xasl(in):
14477  */
14478 XASL_NODE *
14480 {
14481  PT_NODE *table1, *table2;
14482  PT_NODE *where;
14483  PT_NODE *if_part, *instnum_part;
14484  int flag;
14485 
14486  assert (parser != NULL);
14487 
14488  if (xasl && select_node && !pt_has_error (parser) && (table1 = select_node->info.query.q.select.from)
14489  && (table2 = select_node->info.query.q.select.from->next) && !select_node->info.query.q.select.from->next->next)
14490  {
14491  xasl->spec_list = pt_to_spec_list (parser, table1, NULL, NULL, plan, NULL, NULL, NULL);
14492  if (xasl->spec_list == NULL)
14493  {
14494  goto exit_on_error;
14495  }
14496 
14497  xasl->merge_spec = pt_to_spec_list (parser, table2, NULL, NULL, plan, NULL, table1, NULL);
14498  if (xasl->merge_spec == NULL)
14499  {
14500  goto exit_on_error;
14501  }
14502 
14503  if (table1->info.spec.path_entities)
14504  {
14505  pt_to_fetch_proc_list (parser, table1->info.spec.path_entities, xasl);
14506  }
14507 
14508  if (table2->info.spec.path_entities)
14509  {
14510  pt_to_fetch_proc_list (parser, table2->info.spec.path_entities, xasl);
14511  }
14512 
14513  /* Correctly place correlated subqueries for derived tables. */
14514  if (table1->info.spec.derived_table)
14515  {
14516  pt_set_dptr (parser, table1->info.spec.derived_table, xasl, table1->info.spec.id);
14517  }
14518 
14519  /* There are two cases for table2: 1) if table1 is a derived table, then if table2 is correlated then it is
14520  * correlated to table1. 2) if table1 is not derived then if table2 is correlated, then it correlates to the
14521  * merge block. Case 2 should never happen for rewritten queries that contain method calls, but we include it
14522  * here for completeness. */
14523  if (table1->info.spec.derived_table && table1->info.spec.derived_table_type == PT_IS_SUBQUERY)
14524  {
14525  XASL_NODE *t_xasl;
14526 
14527  if (!(t_xasl = (XASL_NODE *) table1->info.spec.derived_table->info.query.xasl))
14528  {
14529  PT_INTERNAL_ERROR (parser, "generate plan");
14530  goto exit_on_error;
14531  }
14532 
14533  pt_set_dptr (parser, table2->info.spec.derived_table, t_xasl, table2->info.spec.id);
14534  }
14535  else
14536  {
14537  pt_set_dptr (parser, table2->info.spec.derived_table, xasl, table2->info.spec.id);
14538  }
14539 
14540  xasl->val_list = pt_to_val_list (parser, table1->info.spec.id);
14541  xasl->merge_val_list = pt_to_val_list (parser, table2->info.spec.id);
14542 
14543  /* copy so as to preserve parse tree */
14544  where = parser_copy_tree_list (parser, select_node->info.query.q.select.where);
14545 
14546  /* set 'etc' field for pseudocolumn nodes */
14547  pt_set_level_node_etc (parser, where, &xasl->level_val);
14548  pt_set_isleaf_node_etc (parser, where, &xasl->isleaf_val);
14549  pt_set_iscycle_node_etc (parser, where, &xasl->iscycle_val);
14550  pt_set_connect_by_operator_node_etc (parser, where, xasl);
14551  pt_set_qprior_node_etc (parser, where, xasl);
14552 
14553  pt_split_if_instnum (parser, where, &if_part, &instnum_part);
14554 
14555  /* This is NOT temporary till where clauses get sorted out!!! We never want predicates on the scans of the tables
14556  * because merge depend on both tables having the same cardinality which would get screwed up if we pushed
14557  * predicates down into the table scans. */
14558  pt_to_pred_terms (parser, if_part, table1->info.spec.id, &xasl->if_pred);
14559  pt_to_pred_terms (parser, if_part, table2->info.spec.id, &xasl->if_pred);
14560 
14561  xasl = pt_to_instnum_pred (parser, xasl, instnum_part);
14562  pt_set_dptr (parser, if_part, xasl, MATCH_ALL);
14563 
14564  pt_set_dptr (parser, select_node->info.query.q.select.list, xasl, MATCH_ALL);
14565 
14566  parser_free_tree (parser, if_part);
14567  parser_free_tree (parser, instnum_part);
14568  }
14569 
14570  return xasl;
14571 
14572 exit_on_error:
14573 
14574  return NULL;
14575 }
14576 
14577 /*
14578  * pt_to_buildschema_proc () - Translate a schema PT_SELECT node to
14579  * a XASL buildschema proc
14580  * return:
14581  * parser(in):
14582  * select_node(in): the query node
14583  */
14584 static XASL_NODE *
14586 {
14587  XASL_NODE *xasl = NULL;
14588  SYMBOL_INFO *symbols = NULL;
14589  UNBOX unbox;
14590  PT_NODE *flat = NULL, *from = NULL;
14591  ACCESS_SCHEMA_TYPE acces_schema_type;
14592 
14593  symbols = parser->symbols;
14594  if (symbols == NULL)
14595  {
14596  return NULL;
14597  }
14598 
14599  if (select_node == NULL || select_node->node_type != PT_SELECT)
14600  {
14601  return NULL;
14602  }
14603 
14604  from = select_node->info.query.q.select.from;
14605  if (from == NULL)
14606  {
14607  return NULL;
14608  }
14609 
14610  flat = from->info.spec.flat_entity_list;
14611  if (flat == NULL)
14612  {
14613  return NULL;
14614  }
14615 
14617  if (xasl == NULL)
14618  {
14620  return NULL;
14621  }
14622 
14623  xasl->next = NULL;
14624  xasl->option = Q_ALL;
14625  unbox = UNBOX_AS_VALUE;
14626 
14627  xasl->flag = 0;
14628  xasl->after_iscan_list = NULL;
14629 
14631  {
14632  xasl->orderby_list = pt_to_orderby (parser, select_node->info.query.order_by, select_node);
14633  if (xasl->orderby_list == NULL)
14634  {
14635  goto error_exit;
14636  }
14638  }
14639 
14640  xasl->ordbynum_pred = NULL;
14641  xasl->ordbynum_val = NULL;
14642  xasl->orderby_limit = NULL;
14643  xasl->orderby_limit = NULL;
14644 
14645  xasl->single_tuple = NULL;
14646  xasl->is_single_tuple = 0;
14647  xasl->outptr_list = pt_to_outlist (parser, select_node->info.query.q.select.list, &xasl->selected_upd_list, unbox);
14648 
14650  {
14651  acces_schema_type = COLUMNS_SCHEMA;
14652  }
14654  {
14655  acces_schema_type = FULL_COLUMNS_SCHEMA;
14656  }
14657  else
14658  {
14659  acces_schema_type = INDEX_SCHEMA;
14660  }
14661 
14662  xasl->spec_list =
14665  acces_schema_type, NULL, NULL);
14666 
14667  if (xasl->spec_list == NULL)
14668  {
14669  goto error_exit;
14670  }
14671 
14672  xasl->merge_spec = NULL;
14673  xasl->val_list = NULL;
14674  xasl->merge_val_list = NULL;
14675  xasl->aptr_list = NULL;
14676  xasl->bptr_list = NULL;
14677  xasl->dptr_list = NULL;
14678  xasl->after_join_pred = NULL;
14679  xasl->if_pred = NULL;
14680  xasl->instnum_pred = NULL;
14681  xasl->instnum_val = NULL;
14682  xasl->save_instnum_val = NULL;
14683  xasl->fptr_list = NULL;
14684  xasl->scan_ptr = NULL;
14685  xasl->connect_by_ptr = NULL;
14686  xasl->level_val = NULL;
14687  xasl->level_regu = NULL;
14688  xasl->isleaf_val = NULL;
14689  xasl->isleaf_regu = NULL;
14690  xasl->iscycle_val = NULL;
14691  xasl->iscycle_regu = NULL;
14692  xasl->curr_spec = NULL;
14693  xasl->instnum_flag = 0;
14694 
14695  return xasl;
14696 
14697 error_exit:
14698 
14699  return NULL;
14700 }
14701 
14702 /*
14703  * pt_analytic_to_metadomain () - initialize metadomain for analytic function
14704  * and index the sort list elements
14705  * returns: true if successful, false if sort spec index overflows
14706  * func_p(in): analytic function
14707  * sort_list(in): sort list of analytic function
14708  * func_meta(in): metadomain to be initialized
14709  * index(in/out): sort spec index
14710  * index_size(in/out): sort spec index size
14711  */
14712 static bool
14714  PT_NODE ** index, int *index_size)
14715 {
14716  PT_NODE *list;
14717  int i, idx;
14718 
14719  assert (func_p != NULL && func_meta != NULL && index != NULL);
14720 
14721  /* structure initialization */
14722  func_meta->level = 0;
14723  func_meta->key_size = 0;
14724  func_meta->links_count = 0;
14725  func_meta->demoted = false;
14726  func_meta->children[0] = NULL;
14727  func_meta->children[1] = NULL;
14728  func_meta->source = func_p;
14729  func_meta->part_size = func_p->sort_prefix_size;
14730 
14731  /* build index and structure */
14732  for (list = sort_list; list != NULL; list = list->next)
14733  {
14734  /* search for sort list in index */
14735  idx = -1;
14736  for (i = 0; i < (*index_size); i++)
14737  {
14738  if (SORT_SPEC_EQ (index[i], list))
14739  {
14740  /* found */
14741  idx = i;
14742  break;
14743  }
14744  }
14745 
14746  /* add to index if not present */
14747  if (idx == -1)
14748  {
14749  if ((*index_size) >= ANALYTIC_OPT_MAX_SORT_LIST_COLUMNS)
14750  {
14751  /* no more space in index */
14752  return false;
14753  }
14754 
14755  idx = (*index_size);
14756  index[idx] = list;
14757  (*index_size)++;
14758  }
14759 
14760  /* register */
14761  func_meta->key[func_meta->key_size] = idx;
14762  func_meta->key_size++;
14763  func_meta->level++;
14764  }
14765 
14766  /* all ok */
14767  return true;
14768 }
14769 
14770 /*
14771  * pt_metadomains_compatible () - determine if two metadomains are compatible
14772  * (i.e. can be evaluated together)
14773  * returns: compatibility as boolean
14774  * f1/f2(in): the two metadomains
14775  * out(in): output (common) metadomain to be populated
14776  * lost_link_count(out): the number of compatibility links that are lost by
14777  * combining the two metadomains
14778  * level(in): maximum sort list size to consider in compatibility checking
14779  *
14780  * NOTE: Given two window definitions like the following (* denotes a partition
14781  * by column, # denotes an order by column):
14782  *
14783  * f1: * * * * # # # # #
14784  * f2: * * # # # # #
14785  * out: * * # # # # # # #
14786  * ^-^--------------------------- common partition prefix (CPP)
14787  * ^-^----------------------- forced partition suffix (FPS)
14788  * ^-^-^----------------- common sort list (CSL)
14789  * ^-^------------- sort list suffix (SLS)
14790  *
14791  * The two windows can share a sort list iff:
14792  * a. CSL(f1) == CSL(f2)
14793  * b. {CPP(f2)} + {FPS(f2)} is a subset of {FPS(f1)} + {CPP(f1)}
14794  *
14795  * The resulting window (out) will have the structure:
14796  * out = CPP(f2) + FPS(f2) + CSL(f1) + SLS(f1) i.e.
14797  * out = f2 + SLS(f1)
14798  */
14799 static bool
14801  int *lost_link_count, int level)
14802 {
14803  unsigned int f1_fps_cpp = 0, f2_fps_cpp = 0;
14804  int i, j;
14805  bool found;
14806  ANALYTIC_TYPE *analytic1 = NULL, *analytic2 = NULL;
14807 
14808  assert (f1 != NULL && f2 != NULL);
14809 
14810  if (lost_link_count != NULL)
14811  {
14812  /* initialize to default value in case of failure */
14813  (*lost_link_count) = -1;
14814  }
14815 
14816  /* determine larger key */
14817  if (f1->part_size < f2->part_size)
14818  {
14819  ANALYTIC_KEY_METADOMAIN *aux = f1;
14820  f1 = f2;
14821  f2 = aux;
14822  }
14823 
14824  analytic1 = f1->source;
14825  analytic2 = f2->source;
14826 
14827  /* step (a): compare common sort lists */
14828  for (i = f1->part_size; i < MIN (level, MIN (f1->key_size, f2->key_size)); i++)
14829  {
14830  if (f1->key[i] != f2->key[i])
14831  {
14832  return false;
14833  }
14834  }
14835 
14836  /* step (b) */
14837  for (i = 0; i < MIN (level, f1->part_size); i++)
14838  {
14839  f1_fps_cpp |= 1 << f1->key[i];
14840  }
14841  for (i = 0; i < MIN (level, MIN (f1->part_size, f2->key_size)); i++)
14842  {
14843  f2_fps_cpp |= 1 << f2->key[i];
14844  }
14845  if ((f2_fps_cpp & f1_fps_cpp) != f2_fps_cpp)
14846  {
14847  /* f2_fps_cpp is not a subset of f1_fps_cpp */
14848  return false;
14849  }
14850 
14851  /* interpolation function with string arg type is not compatible with other functions */
14852  if (analytic1 != NULL && analytic2 != NULL)
14853  {
14854  if (QPROC_IS_INTERPOLATION_FUNC (analytic1) && QPROC_IS_INTERPOLATION_FUNC (analytic2)
14855  && (f1->part_size != f2->part_size
14856  || (TP_IS_STRING_TYPE (analytic1->opr_dbtype) ^ TP_IS_STRING_TYPE (analytic2->opr_dbtype))))
14857  {
14858  return false;
14859  }
14860  else if (QPROC_IS_INTERPOLATION_FUNC (analytic1) && !QPROC_IS_INTERPOLATION_FUNC (analytic2)
14861  && TP_IS_STRING_TYPE (analytic1->opr_dbtype))
14862  {
14863  return false;
14864  }
14865  else if (QPROC_IS_INTERPOLATION_FUNC (analytic2) && !QPROC_IS_INTERPOLATION_FUNC (analytic1)
14866  && TP_IS_STRING_TYPE (analytic2->opr_dbtype))
14867  {
14868  return false;
14869  }
14870  }
14871 
14872  if (out == NULL || lost_link_count == NULL)
14873  {
14874  /* no need to compute common metadomain */
14875  return true;
14876  }
14877 
14878  /* build common metadomain */
14879  out->source = NULL;
14880  out->links_count = 0;
14881  out->level = level;
14882  out->demoted = false;
14883  out->children[0] = f1;
14884  out->children[1] = f2;
14885  out->part_size = MIN (f2->part_size, level);
14886  out->key_size = MIN (MAX (f1->key_size, f2->key_size), level);
14887 
14888  for (i = 0; i < out->key_size; i++)
14889  {
14890  if (i < f2->key_size)
14891  {
14892  /* get from f2 */
14893  out->key[i] = f2->key[i];
14894  if (i < f1->part_size)
14895  {
14896  /* current key element cannot be used further */
14897  f1_fps_cpp &= ~(1 << f2->key[i]);
14898  }
14899  }
14900  else
14901  {
14902  if (i >= f1->part_size)
14903  {
14904  /* original order (SLS) */
14905  out->key[i] = f1->key[i];
14906  }
14907  else
14908  {
14909  bool found = false;
14910 
14911  /* whatever order from what's left in {CPP(f1)} + {FPS(f1)} */
14912  for (j = 0; j < ANALYTIC_OPT_MAX_SORT_LIST_COLUMNS; j++)
14913  {
14914  if (f1_fps_cpp & (1 << j))
14915  {
14916  out->key[i] = j;
14917  f1_fps_cpp &= ~(1 << j);
14918  found = true;
14919  break;
14920  }
14921  }
14922  if (!found)
14923  {
14924  assert (false);
14925  /* make sure corrupted struct is not used */
14926  return false;
14927  }
14928  }
14929  }
14930  }
14931 
14932  /* build links */
14933  (*lost_link_count) = 0;
14934 
14935  for (i = 0; i < f1->links_count; i++)
14936  {
14937  if (f1->links[i] == f2)
14938  {
14939  continue;
14940  }
14941  else if (pt_metadomains_compatible (out, f1->links[i], NULL, NULL, level))
14942  {
14943  out->links[out->links_count++] = f1->links[i];
14944  }
14945  else
14946  {
14947  (*lost_link_count)++;
14948  }
14949  }
14950  for (i = 0; i < f2->links_count; i++)
14951  {
14952  found = false;
14953  for (j = 0; j < f1->links_count; j++)
14954  {
14955  if (f1->links[j] == f2->links[i])
14956  {
14957  found = true;
14958  break;
14959  }
14960  }
14961 
14962  if ((f2->links[i] == f1) || found)
14963  {
14964  continue;
14965  }
14966  else
14967  {
14968  if (pt_metadomains_compatible (out, f2->links[i], NULL, NULL, level))
14969  {
14970  out->links[out->links_count++] = f2->links[i];
14971  }
14972  else
14973  {
14974  (*lost_link_count)++;
14975  }
14976  }
14977  }
14978 
14979  /* all ok */
14980  return true;
14981 }
14982 
14983 /*
14984  * pt_metadomain_build_comp_graph () - build metadomain compatibility graph of
14985  * all analytic functions
14986  * af_meta(in): analytic function meta domain list
14987  * af_count(in): analytic function count
14988  * level(in): maximum size of considered sort list
14989  */
14990 static void
14991 pt_metadomain_build_comp_graph (ANALYTIC_KEY_METADOMAIN * af_meta, int af_count, int level)
14992 {
14993  int i, j;
14994 
14995  assert (af_meta != NULL);
14996 
14997  /* reset link count */
14998  for (i = 0; i < af_count; i++)
14999  {
15000  af_meta[i].links_count = 0;
15001  }
15002 
15003  /* check compatibility */
15004  for (i = 0; i < af_count; i++)
15005  {
15006  if (af_meta[i].demoted)
15007  {
15008  continue;
15009  }
15010 
15011  for (j = i + 1; j < af_count; j++)
15012  {
15013  if (af_meta[j].demoted)
15014  {
15015  continue;
15016  }
15017 
15018  if (pt_metadomains_compatible (&af_meta[i], &af_meta[j], NULL, NULL, level))
15019  {
15020  /* now kiss */
15021  af_meta[i].links[af_meta[i].links_count] = &af_meta[j];
15022  af_meta[j].links[af_meta[j].links_count] = &af_meta[i];
15023  af_meta[i].links_count++;
15024  af_meta[j].links_count++;
15025  }
15026  }
15027  }
15028 }
15029 
15030 /*
15031  * pt_sort_list_from_metadomain () - build sort list for metadomain
15032  * returns: sort list or NULL on error
15033  * parser(in): parser context
15034  * sort_list_index(in): index of sort specs
15035  * select_list(in): select list of query
15036  */
15037 static SORT_LIST *
15039  PT_NODE * select_list)
15040 {
15041  PT_NODE *sort_list_pt = NULL;
15043  int i;
15044 
15045  assert (meta != NULL && sort_list_index != NULL);
15046 
15047  /* build PT_NODE list */
15048  for (i = 0; i < meta->key_size; i++)
15049  {
15050  PT_NODE *copy = parser_copy_tree (parser, sort_list_index[meta->key[i]]);
15051  if (copy == NULL)
15052  {
15053  PT_INTERNAL_ERROR (parser, "copy tree");
15054  (void) parser_free_tree (parser, sort_list_pt);
15055  return NULL;
15056  }
15057  else
15058  {
15059  copy->next = NULL;
15060  sort_list_pt = parser_append_node (copy, sort_list_pt);
15061  }
15062  }
15063 
15064  if (sort_list_pt != NULL)
15065  {
15066  sort_list = pt_to_sort_list (parser, sort_list_pt, select_list, SORT_LIST_ANALYTIC_WINDOW);
15067  parser_free_tree (parser, sort_list_pt);
15068 
15069  if (sort_list == NULL)
15070  {
15071  PT_INTERNAL_ERROR (parser, "sort list generation");
15072  }
15073 
15074  return sort_list;
15075  }
15076  else
15077  {
15078  return NULL;
15079  }
15080 }
15081 
15082 /*
15083  * pt_metadomain_adjust_key_prefix () - adjust children's sort key using parent's sort key
15084  * meta(in): metadomain
15085  */
15086 static void
15088 {
15089  int i, child;
15090 
15091  assert (meta != NULL);
15092 
15093  for (child = 0; child < 2; child++)
15094  {
15095  if (meta->children[child])
15096  {
15097  for (i = 0; i < meta->level; i++)
15098  {
15099  if (i < meta->children[child]->key_size)
15100  {
15101  meta->children[child]->key[i] = meta->key[i];
15102  }
15103  }
15104 
15106  }
15107  }
15108 }
15109 
15110 /*
15111  * pt_build_analytic_eval_list () - build evaluation sequence based on computed
15112  * metadomains
15113  * returns: (partial) evaluation sequence
15114  * parser(in): parser context
15115  * meta(in): metadomain
15116  * eval(in): eval structure (i.e. sequence component)
15117  * sort_list_index(in): index of sort specs
15118  * info(in): analytic info structure
15119  */
15120 static ANALYTIC_EVAL_TYPE *
15122  PT_NODE ** sort_list_index, ANALYTIC_INFO * info)
15123 {
15124  ANALYTIC_EVAL_TYPE *newa = NULL, *new2 = NULL, *tail;
15125  ANALYTIC_TYPE *func_p;
15126 
15127  assert (meta != NULL && info != NULL);
15128 
15129  if (meta->children[0] && meta->children[1])
15130  {
15131  if (meta->level >= meta->children[0]->level && meta->level >= meta->children[1]->level)
15132  {
15133  if (eval == NULL)
15134  {
15135  regu_alloc (eval);
15136  if (eval == NULL)
15137  {
15138  PT_INTERNAL_ERROR (parser, "regu alloc");
15139  return NULL;
15140  }
15141 
15142  eval->sort_list = pt_sort_list_from_metadomain (parser, meta, sort_list_index, info->select_list);
15143  if (meta->key_size > 0 && eval->sort_list == NULL)
15144  {
15145  /* error was already set */
15146  return NULL;
15147  }
15148  }
15149 
15150  /* this is the case of a perfect match where both children can be evaluated together */
15151  eval = pt_build_analytic_eval_list (parser, meta->children[0], eval, sort_list_index, info);
15152  if (eval == NULL)
15153  {
15154  /* error was already set */
15155  return NULL;
15156  }
15157 
15158  eval = pt_build_analytic_eval_list (parser, meta->children[1], eval, sort_list_index, info);
15159  if (eval == NULL)
15160  {
15161  /* error was already set */
15162  return NULL;
15163  }
15164  }
15165  else
15166  {
15167  if (meta->level >= meta->children[0]->level)
15168  {
15169  eval = pt_build_analytic_eval_list (parser, meta->children[0], eval, sort_list_index, info);
15170  if (eval == NULL)
15171  {
15172  /* error was already set */
15173  return NULL;
15174  }
15175 
15176  newa = pt_build_analytic_eval_list (parser, meta->children[1], NULL, sort_list_index, info);
15177  if (newa == NULL)
15178  {
15179  /* error was already set */
15180  return NULL;
15181  }
15182  }
15183  else if (meta->level >= meta->children[1]->level)
15184  {
15185  eval = pt_build_analytic_eval_list (parser, meta->children[1], eval, sort_list_index, info);
15186  if (eval == NULL)
15187  {
15188  /* error was already set */
15189  return NULL;
15190  }
15191 
15192  newa = pt_build_analytic_eval_list (parser, meta->children[0], NULL, sort_list_index, info);
15193  if (newa == NULL)
15194  {
15195  /* error was already set */
15196  return NULL;
15197  }
15198  }
15199  else
15200  {
15201  newa = pt_build_analytic_eval_list (parser, meta->children[0], NULL, sort_list_index, info);
15202  if (newa == NULL)
15203  {
15204  /* error was already set */
15205  return NULL;
15206  }
15207 
15208  new2 = pt_build_analytic_eval_list (parser, meta->children[1], NULL, sort_list_index, info);
15209  if (new2 == NULL)
15210  {
15211  /* error was already set */
15212  return NULL;
15213  }
15214  }
15215 
15216  if (newa != NULL && new2 != NULL)
15217  {
15218  /* link new to new2 */
15219  tail = newa;
15220  while (tail->next != NULL)
15221  {
15222  tail = tail->next;
15223  }
15224  tail->next = new2;
15225  }
15226 
15227  if (eval == NULL)
15228  {
15229  eval = newa;
15230  }
15231  else
15232  {
15233  /* link eval to new */
15234  tail = eval;
15235  while (tail->next != NULL)
15236  {
15237  tail = tail->next;
15238  }
15239  tail->next = newa;
15240  }
15241  }
15242  }
15243  else
15244  {
15245  /* this is a leaf node; create eval structure if necessary */
15246  if (eval == NULL)
15247  {
15248  regu_alloc (eval);
15249  if (eval == NULL)
15250  {
15251  PT_INTERNAL_ERROR (parser, "regu alloc");
15252  return NULL;
15253  }
15254 
15255  /* check for top level here, write sort list */
15256  eval->sort_list = pt_sort_list_from_metadomain (parser, meta, sort_list_index, info->select_list);
15257  if (meta->key_size > 0 && eval->sort_list == NULL)
15258  {
15259  /* error was already set */
15260  return NULL;
15261  }
15262  }
15263 
15264  meta->source->next = NULL;
15265  if (eval->head != NULL)
15266  {
15267  for (func_p = eval->head; func_p->next != NULL; func_p = func_p->next);
15268  func_p->next = meta->source;
15269  }
15270  else
15271  {
15272  eval->head = meta->source;
15273  }
15274  }
15275 
15276  return eval;
15277 }
15278 
15279 /*
15280  * pt_initialize_analytic_info () - initialize analytic_info
15281  * parser(in):
15282  * analytic_info(out):
15283  * select_node(in):
15284  * select_node_ex(in):
15285  * buidlist(in):
15286  */
15287 static int
15289  PT_NODE * select_list_ex, BUILDLIST_PROC_NODE * buildlist)
15290 {
15291  PT_NODE *node;
15292  int idx;
15293  QPROC_DB_VALUE_LIST vallist_p;
15294 
15295  assert (analytic_info != NULL);
15296 
15297  analytic_info->head_list = NULL;
15298  analytic_info->sort_lists = NULL;
15299  analytic_info->select_node = select_node;
15300  analytic_info->select_list = select_list_ex;
15301  analytic_info->val_list = buildlist->a_val_list;
15302 
15303  for (node = select_list_ex, vallist_p = buildlist->a_val_list->valp, idx = 0; node;
15304  node = node->next, vallist_p = vallist_p->next, idx++)
15305  {
15306  assert (vallist_p != NULL);
15307 
15308  if (PT_IS_ANALYTIC_NODE (node))
15309  {
15310  /* process analytic node */
15311  if (pt_to_analytic_node (parser, node, analytic_info) == NULL)
15312  {
15313  return ER_FAILED;
15314  }
15315 
15316  /* register vallist dbval for further use */
15317  analytic_info->head_list->out_value = vallist_p->val;
15318  }
15319  }
15320 
15321  return NO_ERROR;
15322 }
15323 
15324 /*
15325  * pt_is_analytic_eval_list_valid () - check the generated eval list
15326  * eval_list(in):
15327  *
15328  * NOTE: This function checks the generated list whether it includes an invalid node.
15329  * This is just a quick fix and should be removed when we fix pt_optimize_analytic_list.
15330  */
15331 static bool
15333 {
15335 
15336  assert (eval_list != NULL);
15337 
15338  for (p = eval_list; p != NULL; p = p->next)
15339  {
15340  if (p->head == NULL)
15341  {
15342  /* This is badly generated. We give up optimization for this invalid case. */
15343  return false;
15344  }
15345  }
15346 
15347  return true;
15348 }
15349 
15350 /*
15351  * pt_generate_simple_analytic_eval_type () - generate simple when optimization fails
15352  * info(in/out): analytic info
15353  *
15354  * NOTE: This function generates one evaluation structure for an analytic function.
15355  */
15356 static ANALYTIC_EVAL_TYPE *
15358 {
15359  ANALYTIC_EVAL_TYPE *ret = NULL;
15360  ANALYTIC_TYPE *func_p, *save_next;
15361  PT_NODE *sort_list;
15362 
15363  /* build one eval group for each analytic function */
15364  func_p = info->head_list;
15365  sort_list = info->sort_lists;
15366  while (func_p)
15367  {
15368  ANALYTIC_EVAL_TYPE *newa = NULL;
15369 
15370  /* new eval structure */
15371  regu_alloc (newa);
15372  if (newa == NULL)
15373  {
15374  PT_INTERNAL_ERROR (parser, "regu alloc");
15375  return NULL;
15376  }
15377  else if (ret == NULL)
15378  {
15379  ret = newa;
15380  }
15381  else
15382  {
15383  newa->next = ret;
15384  ret = newa;
15385  }
15386 
15387  /* set up sort list */
15388  if (sort_list->info.pointer.node != NULL)
15389  {
15390  ret->sort_list =
15392  if (ret->sort_list == NULL)
15393  {
15394  /* error has already been set */
15395  return NULL;
15396  }
15397  }
15398  else
15399  {
15400  ret->sort_list = NULL;
15401  }
15402 
15403  /* one function */
15404  ret->head = func_p;
15405 
15406  /* unlink and advance */
15407  save_next = func_p->next;
15408  func_p->next = NULL;
15409  func_p = save_next;
15410  sort_list = sort_list->next;
15411  }
15412 
15413  return ret;
15414 }
15415 
15416 /*
15417  * pt_optimize_analytic_list () - optimize analytic exectution
15418  * info(in/out): analytic info
15419  * no_optimization(out):
15420  *
15421  * NOTE: This function groups together the evaluation of analytic functions
15422  * that share the same window.
15423  */
15424 static ANALYTIC_EVAL_TYPE *
15426 {
15427  ANALYTIC_EVAL_TYPE *ret = NULL;
15428  ANALYTIC_TYPE *func_p;
15429  PT_NODE *sort_list;
15430  bool found;
15431  int i, j, level = 0;
15432 
15433  /* sort list index */
15435  int sc_count = 0;
15436 
15437  /* meta domains */
15439  int af_count = 0;
15440 
15441  assert (info != NULL);
15442 
15443  *no_optimization = false;
15444 
15445  /* find unique sort columns and index them; build analytic meta structures */
15446  for (func_p = info->head_list, sort_list = info->sort_lists; func_p != NULL && sort_list != NULL;
15447  func_p = func_p->next, sort_list = sort_list->next, af_count++)
15448  {
15449  if (!pt_analytic_to_metadomain (func_p, sort_list->info.pointer.node, &af_meta[af_count], sc_index, &sc_count))
15450  {
15451  /* sort spec index overflow, we'll do it the old fashioned way */
15452  *no_optimization = true;
15453  return NULL;
15454  }
15455 
15456  /* first level is maximum key size */
15457  if (level < af_meta[af_count].key_size)
15458  {
15459  level = af_meta[af_count].key_size;
15460  }
15461  }
15462 
15463  /* group metadomains with zero-length sort keys */
15464  do
15465  {
15466  found = false;
15467  for (i = 0; i < af_count - 1; i++)
15468  {
15469  if (!af_meta[i].demoted && af_meta[i].key_size == 0)
15470  {
15471  for (j = i + 1; j < af_count; j++)
15472  {
15473  if (!af_meta[j].demoted && af_meta[j].key_size == 0)
15474  {
15475  found = true;
15476 
15477  if (af_count >= ANALYTIC_OPT_MAX_FUNCTIONS)
15478  {
15479  *no_optimization = true;
15480  return NULL;
15481  }
15482 
15483  /* demote and register children */
15484  af_meta[i].demoted = true;
15485  af_meta[j].demoted = true;
15486  af_meta[af_count].children[0] = &af_meta[i];
15487  af_meta[af_count].children[1] = &af_meta[j];
15488 
15489  /* populate new metadomain */
15490  af_meta[af_count].demoted = false;
15491  af_meta[af_count].part_size = 0;
15492  af_meta[af_count].key_size = 0;
15493  af_meta[af_count].level = level; /* maximum level */
15494  af_meta[af_count].links_count = 0;
15495  af_meta[af_count].source = NULL;
15496 
15497  /* repeat */
15498  af_count++;
15499  break;
15500  }
15501  }
15502 
15503  if (found)
15504  {
15505  break;
15506  }
15507  }
15508  }
15509  }
15510  while (found);
15511 
15512  /* build initial compatibility graph */
15513  pt_metadomain_build_comp_graph (af_meta, af_count, level);
15514 
15515  /* compose every compatible metadomains from each possible prefix length */
15516  while (level > 0)
15517  {
15520  int new_destroyed = -1, best_destroyed = -1;
15521 
15522  /* compose best two compatible metadomains */
15523  for (i = 0; i < af_count; i++)
15524  {
15525  if (af_meta[i].links_count <= 0 || af_meta[i].demoted)
15526  {
15527  /* nothing to do for unlinked or demoted metadomain */
15528  continue;
15529  }
15530 
15531  for (j = 0; j < af_meta[i].links_count; j++)
15532  {
15533  /* build composite metadomain */
15534  pt_metadomains_compatible (&af_meta[i], af_meta[i].links[j], &newa, &new_destroyed, level);
15535 
15536  /* see if it's better than current best */
15537  if (new_destroyed < best_destroyed || best_destroyed == -1)
15538  {
15539  best_destroyed = new_destroyed;
15540  best = newa;
15541  }
15542 
15543  if (best_destroyed == 0)
15544  {
15545  /* early exit, perfect match */
15546  break;
15547  }
15548  }
15549 
15550  if (best_destroyed == 0)
15551  {
15552  /* early exit, perfect match */
15553  break;
15554  }
15555  }
15556 
15557  if (best_destroyed == -1)
15558  {
15559  /* no more optimizations on this level */
15560  level--;
15561 
15562  /* rebuild compatibility graph */
15563  pt_metadomain_build_comp_graph (af_meta, af_count, level);
15564  }
15565  else
15566  {
15568 
15569  /* add new composed metadomain */
15570  af_meta[af_count++] = best;
15571 
15572  /* unlink child metadomains */
15573  for (i = 0; i < best.children[0]->links_count; i++)
15574  {
15575  link = best.children[0]->links[i];
15576  for (j = 0; j < link->links_count; j++)
15577  {
15578  if (link->links[j] == best.children[0])
15579  {
15580  link->links[j] = link->links[link->links_count - 1];
15581  link->links_count--;
15582  break;
15583  }
15584  }
15585  }
15586  for (i = 0; i < best.children[1]->links_count; i++)
15587  {
15588  link = best.children[1]->links[i];
15589  for (j = 0; j < link->links_count; j++)
15590  {
15591  if (link->links[j] == best.children[1])
15592  {
15593  link->links[j] = link->links[link->links_count - 1];
15594  link->links_count--;
15595  break;
15596  }
15597  }
15598  }
15599 
15600  /* demote and unlink child metadomains */
15601  best.children[0]->demoted = true;
15602  best.children[1]->demoted = true;
15603  best.children[0]->links_count = 0;
15604  best.children[1]->links_count = 0;
15605 
15606  /* relink new composite metadomain */
15607  for (i = 0; i < best.links_count; i++)
15608  {
15609  link = best.links[i];
15610  link->links[link->links_count++] = &af_meta[af_count - 1];
15611  }
15612 
15613  /* adjust key prefix on tree */
15615  }
15616  }
15617 
15618  /* rebuild analytic type list */
15619  ret = NULL;
15620  for (i = 0; i < af_count; i++)
15621  {
15622  ANALYTIC_EVAL_TYPE *newa, *tail;
15623 
15624  if (af_meta[i].demoted)
15625  {
15626  /* demoted metadomains have already been composed; we're interested only in top level metadomains */
15627  continue;
15628  }
15629 
15630  /* build new list */
15631  newa = pt_build_analytic_eval_list (parser, &af_meta[i], NULL, sc_index, info);
15632  if (newa == NULL)
15633  {
15634  /* error has already been set */
15635  return NULL;
15636  }
15637 
15638  /* attach to current list */
15639  if (ret == NULL)
15640  {
15641  /* first top level metadomain */
15642  ret = newa;
15643  }
15644  else
15645  {
15646  /* locate list tail */
15647  tail = ret;
15648  while (tail->next != NULL)
15649  {
15650  tail = tail->next;
15651  }
15652 
15653  /* link */
15654  tail->next = newa;
15655  }
15656  }
15657 
15658  /*
15659  * FIXME: This is a quick fix. Remove this when we fix pt_build_analytic_eval_list ().
15660  */
15661  if (!pt_is_analytic_eval_list_valid (ret))
15662  {
15663  /* give up optimization for the case */
15664  *no_optimization = true;
15665  return NULL;
15666  }
15667 
15668  return ret;
15669 }
15670 
15671 
15672 /*
15673  * pt_to_buildlist_proc () - Translate a PT_SELECT node to
15674  * a XASL buildlist proc
15675  * return:
15676  * parser(in):
15677  * select_node(in):
15678  * qo_plan(in):
15679  */
15680 static XASL_NODE *
15682 {
15683  XASL_NODE *xasl, *save_parent_proc_xasl;
15684  PT_NODE *saved_current_class;
15685  int groupby_ok = 1;
15686  AGGREGATE_TYPE *aggregate = NULL, *agg_list = NULL;
15687  SYMBOL_INFO *symbols;
15688  PT_NODE *from, *limit;
15689  UNBOX unbox;
15690  PT_NODE *having_part, *grbynum_part;
15691  int grbynum_flag, ordbynum_flag;
15692  bool orderby_skip = false, orderby_ok = true;
15693  bool groupby_skip = false;
15694  BUILDLIST_PROC_NODE *buildlist;
15695  int i;
15696  REGU_VARIABLE_LIST regu_var_p;
15697 
15698  assert (parser != NULL);
15699 
15700  symbols = parser->symbols;
15701  if (symbols == NULL)
15702  {
15703  return NULL;
15704  }
15705 
15706  if (select_node == NULL || select_node->node_type != PT_SELECT)
15707  {
15708  assert (false);
15709  return NULL;
15710  }
15711 
15712  from = select_node->info.query.q.select.from;
15713  if (from == NULL)
15714  {
15715  return NULL;
15716  }
15717 
15719  if (xasl == NULL)
15720  {
15721  return NULL;
15722  }
15723 
15724  /* save this XASL node for children to access */
15725  save_parent_proc_xasl = parser->parent_proc_xasl;
15726  parser->parent_proc_xasl = xasl;
15727 
15728  buildlist = &xasl->proc.buildlist;
15729  xasl->next = NULL;
15730 
15731  xasl->limit_row_count = NULL;
15732  xasl->limit_offset = NULL;
15733 
15734  limit = select_node->info.query.limit;
15735  if (limit)
15736  {
15737  if (limit->next)
15738  {
15739  xasl->limit_offset = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
15740  limit = limit->next;
15741  }
15742  xasl->limit_row_count = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
15743  }
15744 
15745  /* set references of INST_NUM and ORDERBY_NUM values in parse tree */
15746  pt_set_numbering_node_etc (parser, select_node->info.query.q.select.list, &xasl->instnum_val, &xasl->ordbynum_val);
15747  pt_set_numbering_node_etc (parser, select_node->info.query.q.select.where, &xasl->instnum_val, &xasl->ordbynum_val);
15748  pt_set_numbering_node_etc (parser, select_node->info.query.orderby_for, &xasl->instnum_val, &xasl->ordbynum_val);
15749 
15750  /* assume parse tree correct, and PT_DISTINCT only other possibility */
15751  if (select_node->info.query.all_distinct == PT_ALL)
15752  {
15753  xasl->option = Q_ALL;
15754  }
15755  else
15756  {
15757  xasl->option = Q_DISTINCT;
15758  }
15759 
15760  unbox = UNBOX_AS_VALUE;
15761 
15762  if (pt_has_aggregate (parser, select_node))
15763  {
15764  int *attr_offsets;
15765  PT_NODE *group_out_list, *group;
15766 
15767  /* set 'etc' field for pseudocolumns nodes */
15768  pt_set_level_node_etc (parser, select_node->info.query.q.select.group_by, &xasl->level_val);
15769  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.group_by, &xasl->isleaf_val);
15770  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.group_by, &xasl->iscycle_val);
15771  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.group_by, xasl);
15772  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.group_by, xasl);
15773  pt_set_level_node_etc (parser, select_node->info.query.q.select.having, &xasl->level_val);
15774  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.having, &xasl->isleaf_val);
15775  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.having, &xasl->iscycle_val);
15776  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.having, xasl);
15777  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.having, xasl);
15778 
15779  group_out_list = NULL;
15780  for (group = select_node->info.query.q.select.group_by; group; group = group->next)
15781  {
15782  /* safe guard: invalid parse tree */
15783  if (group->node_type != PT_SORT_SPEC)
15784  {
15785  if (group_out_list)
15786  {
15787  parser_free_tree (parser, group_out_list);
15788  }
15789  goto exit_on_error;
15790  }
15791 
15792  group_out_list = parser_append_node (pt_point (parser, group->info.sort_spec.expr), group_out_list);
15793  }
15794 
15795  /* determine if query is eligible for hash aggregate evaluation */
15796  if (select_node->info.query.q.select.hint & PT_HINT_NO_HASH_AGGREGATE)
15797  {
15798  /* forced not applicable */
15799  buildlist->g_hash_eligible = false;
15800  }
15801  else
15802  {
15803  buildlist->g_hash_eligible = true;
15804 
15805  (void) parser_walk_tree (parser, select_node->info.query.q.select.list, pt_is_hash_agg_eligible,
15806  (void *) &buildlist->g_hash_eligible, NULL, NULL);
15807  (void) parser_walk_tree (parser, select_node->info.query.q.select.having, pt_is_hash_agg_eligible,
15808  (void *) &buildlist->g_hash_eligible, NULL, NULL);
15809 
15810  /* determine where we're storing the first tuple of each group */
15811  if (buildlist->g_hash_eligible)
15812  {
15813  if (select_node->info.query.q.select.group_by->flag.with_rollup)
15814  {
15815  /* if using rollup groups, we must output the first tuple of each group so rollup will be correctly
15816  * handled during sort */
15817  buildlist->g_output_first_tuple = true;
15818  }
15819  else
15820  {
15821  /* in other cases just store everyting in hash table */
15822  buildlist->g_output_first_tuple = false;
15823  }
15824  }
15825  }
15826 
15827  /* this one will be altered further on and it's the actual output of the initial scan; will contain group key and
15828  * aggregate expressions */
15829  xasl->outptr_list = pt_to_outlist (parser, group_out_list, NULL, UNBOX_AS_VALUE);
15830 
15831  if (xasl->outptr_list == NULL)
15832  {
15833  if (group_out_list)
15834  {
15835  parser_free_tree (parser, group_out_list);
15836  }
15837  goto exit_on_error;
15838  }
15839 
15840  buildlist->g_val_list = pt_make_val_list (parser, group_out_list);
15841 
15842  if (buildlist->g_val_list == NULL)
15843  {
15845  if (group_out_list)
15846  {
15847  parser_free_tree (parser, group_out_list);
15848  }
15849  goto exit_on_error;
15850  }
15851 
15852  attr_offsets = pt_make_identity_offsets (group_out_list);
15853 
15854  /* set up hash aggregate lists */
15855  if (buildlist->g_hash_eligible)
15856  {
15857  /* regulist for hash key during initial scan */
15858  buildlist->g_hk_scan_regu_list =
15859  pt_to_regu_variable_list (parser, group_out_list, UNBOX_AS_VALUE, buildlist->g_val_list, attr_offsets);
15860 
15861  /* regulist for hash key during sort operation */
15862  buildlist->g_hk_sort_regu_list =
15863  pt_to_position_regu_variable_list (parser, group_out_list, buildlist->g_val_list, attr_offsets);
15864  }
15865  else
15866  {
15867  buildlist->g_hk_sort_regu_list = NULL;
15868  buildlist->g_hk_scan_regu_list = NULL;
15869  }
15870 
15871  /* this will load values from initial scan into g_val_list, a bypass of outptr_list => (listfile) => g_regu_list
15872  * => g_vallist; this will be modified when building aggregate nodes */
15873  buildlist->g_scan_regu_list =
15874  pt_to_regu_variable_list (parser, group_out_list, UNBOX_AS_VALUE, buildlist->g_val_list, attr_offsets);
15875 
15876  /* regulist for loading from listfile */
15877  buildlist->g_regu_list =
15878  pt_to_position_regu_variable_list (parser, group_out_list, buildlist->g_val_list, attr_offsets);
15879 
15880  pt_fix_pseudocolumns_pos_regu_list (parser, group_out_list, buildlist->g_regu_list);
15881 
15882  free_and_init (attr_offsets);
15883 
15884  /* set 'etc' field for pseudocolumns nodes */
15885  pt_set_level_node_etc (parser, select_node->info.query.q.select.list, &xasl->level_val);
15886  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.list, &xasl->isleaf_val);
15887  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.list, &xasl->iscycle_val);
15888  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.list, xasl);
15889  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.list, xasl);
15890 
15891  aggregate =
15892  pt_to_aggregate (parser, select_node, xasl->outptr_list, buildlist->g_val_list, buildlist->g_regu_list,
15893  buildlist->g_scan_regu_list, group_out_list, &buildlist->g_grbynum_val);
15894 
15895  /* compute function count */
15896  buildlist->g_func_count = 0;
15897  agg_list = aggregate;
15898  while (agg_list != NULL)
15899  {
15900  buildlist->g_func_count++;
15901  agg_list = agg_list->next;
15902  }
15903 
15904  /* compute hash key size */
15905  buildlist->g_hkey_size = 0;
15906  if (buildlist->g_hash_eligible)
15907  {
15908  REGU_VARIABLE_LIST regu_list = buildlist->g_hk_scan_regu_list;
15909  while (regu_list != NULL)
15910  {
15911  buildlist->g_hkey_size++;
15912  regu_list = regu_list->next;
15913  }
15914  }
15915 
15916  /* set current_listfile only around call to make g_outptr_list and havein_pred */
15917  symbols->current_listfile = group_out_list;
15918  symbols->listfile_value_list = buildlist->g_val_list;
15919 
15920  buildlist->g_outptr_list = pt_to_outlist (parser, select_node->info.query.q.select.list, NULL, unbox);
15921 
15922  if (buildlist->g_outptr_list == NULL)
15923  {
15924  if (group_out_list)
15925  {
15926  parser_free_tree (parser, group_out_list);
15927  }
15928  goto exit_on_error;
15929  }
15930 
15931  /* pred should never user the current instance for fetches either, so we turn off the current_class, if there is
15932  * one. */
15933  saved_current_class = parser->symbols->current_class;
15934  parser->symbols->current_class = NULL;
15935  pt_split_having_grbynum (parser, select_node->info.query.q.select.having, &having_part, &grbynum_part);
15936  buildlist->g_having_pred = pt_to_pred_expr (parser, having_part);
15937  grbynum_flag = 0;
15938  buildlist->g_grbynum_pred = pt_to_pred_expr_with_arg (parser, grbynum_part, &grbynum_flag);
15939  if (grbynum_flag & PT_PRED_ARG_GRBYNUM_CONTINUE)
15940  {
15942  }
15943  if (grbynum_part != NULL && PT_EXPR_INFO_IS_FLAGED (grbynum_part, PT_EXPR_INFO_GROUPBYNUM_LIMIT))
15944  {
15945  if (grbynum_part->next != NULL)
15946  {
15948  }
15949  else
15950  {
15952  }
15953  }
15954 
15955  select_node->info.query.q.select.having = parser_append_node (having_part, grbynum_part);
15956 
15957  parser->symbols->current_class = saved_current_class;
15958  symbols->current_listfile = NULL;
15959  symbols->listfile_value_list = NULL;
15960  if (group_out_list)
15961  {
15962  parser_free_tree (parser, group_out_list);
15963  }
15964 
15965  buildlist->g_agg_list = aggregate;
15966 
15967  buildlist->g_with_rollup = select_node->info.query.q.select.group_by->flag.with_rollup;
15968  }
15969  else
15970  {
15971  /* set 'etc' field for pseudocolumns nodes */
15972  pt_set_level_node_etc (parser, select_node->info.query.q.select.list, &xasl->level_val);
15973  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.list, &xasl->isleaf_val);
15974  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.list, &xasl->iscycle_val);
15975  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.list, xasl);
15976  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.list, xasl);
15977 
15978  if (!pt_has_analytic (parser, select_node))
15979  {
15980  xasl->outptr_list =
15981  pt_to_outlist (parser, select_node->info.query.q.select.list, &xasl->selected_upd_list, unbox);
15982  }
15983  else
15984  {
15985  /* the select list will be altered a lot in the following code block, make sure you understand what's
15986  * happening before making adjustments */
15987 
15988  ANALYTIC_INFO analytic_info, analytic_info_clone;
15989  PT_NODE *select_list_ex = NULL, *select_list_final = NULL, *node;
15990  int idx, final_idx, final_count, *sort_adjust = NULL;
15991  bool no_optimization_done = false;
15992 
15993  /* prepare sort adjustment array */
15994  final_idx = 0;
15995  final_count = pt_length_of_list (select_node->info.query.q.select.list);
15996  sort_adjust = (int *) db_private_alloc (NULL, final_count * sizeof (int));
15997  if (sort_adjust == NULL)
15998  {
16000  goto analytic_exit_on_error;
16001  }
16002 
16003  /* break up expressions with analytic functions */
16004  select_list_ex = NULL;
16005  select_list_final = NULL;
16006 
16007  node = select_node->info.query.q.select.list;
16008  select_node->info.query.q.select.list = NULL;
16009 
16010  while (node != NULL)
16011  {
16012  PT_NODE *final_node, *to_ex_list = NULL, *save_next;
16013 
16014  /* save next and unlink node */
16015  save_next = node->next;
16016  node->next = NULL;
16017 
16018  /* get final select list node */
16019  final_node = pt_to_analytic_final_node (parser, node, &to_ex_list, &xasl->instnum_flag);
16020  if (final_node == NULL)
16021  {
16022  /* error was set somewhere - clean up */
16023  parser_free_tree (parser, node);
16024  parser_free_tree (parser, save_next);
16025  parser_free_tree (parser, to_ex_list);
16026 
16027  goto analytic_exit_on_error;
16028  }
16029 
16030  /* append nodes to list */
16031  select_list_ex = parser_append_node (to_ex_list, select_list_ex);
16032  select_list_final = parser_append_node (final_node, select_list_final);
16033 
16034  /* modify sort spec adjustment counter to account for new nodes */
16035  assert (final_idx < final_count);
16036  sort_adjust[final_idx] = -1; /* subtracted 1 for original node */
16037  for (; to_ex_list != NULL; to_ex_list = to_ex_list->next)
16038  {
16039  /* add one for each node that goes in extended list */
16040  sort_adjust[final_idx] += 1;
16041  }
16042 
16043  /* advance */
16044  node = save_next;
16045  final_idx++;
16046  }
16047 
16048  /* adjust sort specs of analytics in select_list_ex */
16049  for (node = select_list_final, idx = 0, final_idx = 0; node != NULL && final_idx < final_count;
16050  node = node->next, final_idx++)
16051  {
16052  PT_NODE *list;
16053 
16054  /* walk list and adjust */
16055  for (list = select_list_ex; list; list = list->next)
16056  {
16057  pt_adjust_analytic_sort_specs (parser, list, idx, sort_adjust[final_idx]);
16058  }
16059 
16060  /* increment and adjust index too */
16061  idx += sort_adjust[final_idx] + 1;
16062  }
16063 
16064  /* we now have all analytics as top-level nodes in select_list_ex; allocate DB_VALUEs for them and push sort
16065  * cols and parameters in select_list_ex */
16066  for (node = select_list_ex; node; node = node->next)
16067  {
16068  if (PT_IS_ANALYTIC_NODE (node))
16069  {
16070  /* allocate a DB_VALUE in node's etc */
16071  if (pt_set_analytic_node_etc (parser, node) == NULL)
16072  {
16073  goto analytic_exit_on_error;
16074  }
16075 
16076  /* expand node; the select list will be modified, but that is acceptable; query sort specs must not
16077  * be modified as they reference positions in the final outptr list */
16078  if (pt_expand_analytic_node (parser, node, select_list_ex) == NULL)
16079  {
16080  goto analytic_exit_on_error;
16081  }
16082  }
16083  }
16084 
16085  /* generate buffer value list */
16086  buildlist->a_val_list = pt_make_val_list (parser, select_list_ex);
16087  if (buildlist->a_val_list == NULL)
16088  {
16090  goto analytic_exit_on_error;
16091  }
16092 
16093  /* resolve regu pointers in final outlist to vallist */
16094  for (node = select_list_final; node; node = node->next)
16095  {
16096  if (pt_resolve_analytic_references (parser, node, select_list_ex, buildlist->a_val_list) == NULL)
16097  {
16098  goto analytic_exit_on_error;
16099  }
16100  }
16101 
16102  /* generate analytic nodes */
16103  if (pt_initialize_analytic_info (parser, &analytic_info, select_node, select_list_ex, buildlist) != NO_ERROR)
16104  {
16105  goto analytic_exit_on_error;
16106  }
16107 
16108  /* FIXME
16109  *
16110  * The cloned list will be used when optimization of analytic functions fails.
16111  * Cloning is not necessary for oridinary cases, however I just want to make the lists are same.
16112  * It will be removed when we fix pt_build_analytic_eval_list ().
16113  */
16114  if (pt_initialize_analytic_info (parser, &analytic_info_clone, select_node, select_list_ex, buildlist) !=
16115  NO_ERROR)
16116  {
16117  goto analytic_exit_on_error;
16118  }
16119 
16120  /* generate regu list (identity fetching from temp tuple) */
16121  buildlist->a_regu_list =
16122  pt_to_position_regu_variable_list (parser, select_list_ex, buildlist->a_val_list, NULL);
16123 
16124  if (buildlist->a_regu_list == NULL)
16125  {
16126  goto analytic_exit_on_error;
16127  }
16128 
16129  /* generate intermediate output list (identity writing) */
16130  buildlist->a_outptr_list_interm = pt_make_outlist_from_vallist (parser, buildlist->a_val_list);
16131 
16132  if (buildlist->a_outptr_list_interm == NULL)
16133  {
16134  goto analytic_exit_on_error;
16135  }
16136 
16137  /* set to intermediate analytic window regu_vars */
16138  for (i = 0, regu_var_p = buildlist->a_outptr_list_interm->valptrp;
16139  i < buildlist->a_outptr_list_interm->valptr_cnt && regu_var_p; i++, regu_var_p = regu_var_p->next)
16140  {
16142  }
16143  assert (i == buildlist->a_outptr_list_interm->valptr_cnt);
16144  assert (regu_var_p == NULL);
16145 
16146  /* generate initial outlist (for data fetching) */
16147  buildlist->a_outptr_list_ex = pt_to_outlist (parser, select_list_ex, &xasl->selected_upd_list, unbox);
16148 
16149  if (buildlist->a_regu_list == NULL)
16150  {
16151  goto analytic_exit_on_error;
16152  }
16153 
16154  /* generate final outlist */
16155  buildlist->a_outptr_list = pt_to_outlist (parser, select_list_final, NULL, unbox);
16156 
16157  if (buildlist->a_outptr_list == NULL)
16158  {
16159  goto analytic_exit_on_error;
16160  }
16161 
16162  /* optimize analytic function list */
16163  xasl->proc.buildlist.a_eval_list = pt_optimize_analytic_list (parser, &analytic_info, &no_optimization_done);
16164 
16165  /* FIXME - Fix it with pt_build_analytic_eval_list (). */
16166  if (no_optimization_done == true)
16167  {
16168  /* generate one per analytic function */
16169  xasl->proc.buildlist.a_eval_list = pt_generate_simple_analytic_eval_type (parser, &analytic_info_clone);
16170  }
16171 
16172  if (xasl->proc.buildlist.a_eval_list == NULL && analytic_info.head_list != NULL)
16173  {
16174  /* input functions were provided but optimizer messed up */
16175  goto analytic_exit_on_error;
16176  }
16177  else
16178  {
16179  /* register the eval list in the plan for printing purposes */
16180  qo_plan->analytic_eval_list = xasl->proc.buildlist.a_eval_list;
16181  }
16182 
16183  /* substitute references of analytic arguments */
16184  for (node = select_list_ex; node; node = node->next)
16185  {
16186  if (PT_IS_ANALYTIC_NODE (node))
16187  {
16188  if (node->info.function.arg_list != NULL)
16189  {
16190  node->info.function.arg_list =
16191  pt_substitute_analytic_references (parser, node->info.function.arg_list, &select_list_ex);
16192  if (node->info.function.arg_list == NULL)
16193  {
16194  goto analytic_exit_on_error;
16195  }
16196  }
16197 
16198  if (node->info.function.analytic.offset != NULL)
16199  {
16200  node->info.function.analytic.offset =
16201  pt_substitute_analytic_references (parser, node->info.function.analytic.offset,
16202  &select_list_ex);
16203  if (node->info.function.analytic.offset == NULL)
16204  {
16205  goto analytic_exit_on_error;
16206  }
16207  }
16208 
16209  if (node->info.function.analytic.default_value != NULL)
16210  {
16211  node->info.function.analytic.default_value =
16212  pt_substitute_analytic_references (parser, node->info.function.analytic.default_value,
16213  &select_list_ex);
16214  if (node->info.function.analytic.default_value == NULL)
16215  {
16216  goto analytic_exit_on_error;
16217  }
16218  }
16219  }
16220  }
16221 
16222  /* substitute references in final select list and register it as query's select list; this is done mostly for
16223  * printing purposes */
16224  node = select_list_final;
16225  select_list_final = NULL;
16226  while (node != NULL)
16227  {
16228  PT_NODE *save_next = node->next, *resolved;
16229  node->next = NULL;
16230 
16231  resolved = pt_substitute_analytic_references (parser, node, &select_list_ex);
16232  if (resolved == NULL)
16233  {
16234  /* error has been set */
16235  parser_free_tree (parser, save_next);
16236  parser_free_tree (parser, node);
16237 
16238  goto analytic_exit_on_error;
16239  }
16240 
16241  /* append to select list */
16242  select_node->info.query.q.select.list =
16243  parser_append_node (resolved, select_node->info.query.q.select.list);
16244 
16245  /* advance */
16246  node = save_next;
16247  }
16248 
16249  /* whatever we're left with in select_list_ex are sort columns of analytic functions; there might be
16250  * subqueries, generate aptr and dptr lists for them */
16251  node = select_node->info.query.q.select.list;
16252  select_node->info.query.q.select.list = select_list_ex;
16253 
16254  pt_set_aptr (parser, select_node, xasl);
16255  pt_set_dptr (parser, select_list_ex, xasl, MATCH_ALL);
16256 
16257  select_node->info.query.q.select.list = node;
16258 
16259  /* we can dispose of the sort columns now as they no longer serve a purpose */
16260  parser_free_tree (parser, select_list_ex);
16261  select_list_ex = NULL;
16262 
16263  /* register initial outlist */
16264  xasl->outptr_list = buildlist->a_outptr_list_ex;
16265 
16266  /* all done */
16267  goto analytic_exit;
16268 
16269  analytic_exit_on_error:
16270  /* cleanup and goto error */
16271  if (select_list_ex != NULL)
16272  {
16273  parser_free_tree (parser, select_list_ex);
16274  }
16275  if (select_list_final != NULL)
16276  {
16277  parser_free_tree (parser, select_list_final);
16278  }
16279  if (sort_adjust != NULL)
16280  {
16281  db_private_free (NULL, sort_adjust);
16282  }
16283  goto exit_on_error;
16284 
16285  analytic_exit:
16286  if (sort_adjust != NULL)
16287  {
16288  db_private_free (NULL, sort_adjust);
16289  }
16290  /* finalized correctly */
16291  }
16292 
16293  /* check if this select statement has click counter */
16294  if (xasl->selected_upd_list != NULL)
16295  {
16296  /* set lock timeout hint if specified */
16297  PT_NODE *hint_arg;
16298  float hint_wait_secs;
16299 
16301  hint_arg = select_node->info.query.q.select.waitsecs_hint;
16302  if (select_node->info.query.q.select.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
16303  {
16304  hint_wait_secs = (float) atof (hint_arg->info.name.original);
16305  if (hint_wait_secs > 0)
16306  {
16307  xasl->selected_upd_list->wait_msecs = (int) (hint_wait_secs * 1000);
16308  }
16309  else
16310  {
16311  xasl->selected_upd_list->wait_msecs = (int) hint_wait_secs;
16312  }
16313  }
16314  }
16315 
16316  if (xasl->outptr_list == NULL)
16317  {
16318  goto exit_on_error;
16319  }
16320  }
16321 
16322  /* the calls pt_to_out_list and pt_to_spec_list record information in the "symbol_info" structure used by subsequent
16323  * calls, and must be done first, before calculating subquery lists, etc. */
16324 
16325  pt_set_aptr (parser, select_node, xasl);
16326 
16327  if (qo_plan == NULL || !pt_gen_optimized_plan (parser, select_node, qo_plan, xasl))
16328  {
16329  while (from)
16330  {
16331  if (from->info.spec.join_type != PT_JOIN_NONE)
16332  {
16334  goto exit_on_error;
16335  }
16336  from = from->next;
16337  }
16338 
16339  if (select_node->info.query.q.select.flavor == PT_MERGE_SELECT)
16340  {
16341  xasl = pt_gen_simple_merge_plan (parser, select_node, qo_plan, xasl);
16342  }
16343  else
16344  {
16345  xasl = pt_gen_simple_plan (parser, select_node, qo_plan, xasl);
16346  }
16347 
16348  if (xasl == NULL)
16349  {
16350  goto exit_on_error;
16351  }
16352 
16353  buildlist = &xasl->proc.buildlist;
16354 
16355  /* mark as simple plan generation */
16356  qo_plan = NULL;
16357  }
16358 
16359  if (xasl->outptr_list)
16360  {
16361  if (qo_plan)
16362  { /* is optimized plan */
16363  xasl->after_iscan_list = pt_to_after_iscan (parser, qo_plan_iscan_sort_list (qo_plan), select_node);
16364  }
16365  else
16366  {
16367  xasl->after_iscan_list = NULL;
16368  }
16369 
16370  if (select_node->info.query.order_by)
16371  {
16372  /* set 'etc' field for pseudocolumns nodes */
16373  pt_set_level_node_etc (parser, select_node->info.query.orderby_for, &xasl->level_val);
16374  pt_set_isleaf_node_etc (parser, select_node->info.query.orderby_for, &xasl->isleaf_val);
16375  pt_set_iscycle_node_etc (parser, select_node->info.query.orderby_for, &xasl->iscycle_val);
16376  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.orderby_for, xasl);
16377  pt_set_qprior_node_etc (parser, select_node->info.query.orderby_for, xasl);
16378 
16379  ordbynum_flag = 0;
16380  xasl->ordbynum_pred = pt_to_pred_expr_with_arg (parser, select_node->info.query.orderby_for, &ordbynum_flag);
16381  if (ordbynum_flag & PT_PRED_ARG_ORDBYNUM_CONTINUE)
16382  {
16384  }
16385 
16386  /* check order by opt */
16387  if (qo_plan && qo_plan_skip_orderby (qo_plan) && !qo_plan_multi_range_opt (qo_plan))
16388  {
16389  orderby_skip = true;
16390 
16391  /* move orderby_num() to inst_num() */
16392  if (xasl->ordbynum_val)
16393  {
16394  if (xasl->instnum_pred)
16395  {
16397  xasl->ordbynum_pred, B_AND);
16398  if (!pred)
16399  {
16400  goto exit_on_error;
16401  }
16402  xasl->instnum_pred = pred;
16403  }
16404  else
16405  {
16406  xasl->instnum_pred = xasl->ordbynum_pred;
16407  }
16408 
16409  /* When we set instnum_val to point to the DBVALUE referenced by ordbynum_val, we lose track the
16410  * DBVALUE originally stored in instnum_val. This is an important value because it is referenced by
16411  * any regu var that was converted from ROWNUM in the select list (before we knew we were going to
16412  * optimize away the ORDER BY clause). We will save the dbval in save_instnum_val and update it
16413  * whenever we update the new instnum_val. */
16414  xasl->save_instnum_val = xasl->instnum_val;
16415  xasl->instnum_val = xasl->ordbynum_val;
16416  xasl->instnum_flag = xasl->ordbynum_flag;
16417 
16418  xasl->ordbynum_pred = NULL;
16419  xasl->ordbynum_val = NULL;
16420  xasl->ordbynum_flag = 0;
16421  }
16422  }
16423  else
16424  {
16425  xasl->orderby_list = pt_to_orderby (parser, select_node->info.query.order_by, select_node);
16426  /* clear flag */
16428  }
16429 
16430  /* sanity check */
16431  orderby_ok = ((xasl->orderby_list != NULL) || orderby_skip);
16432  }
16433  else if (select_node->info.query.order_by == NULL && select_node->info.query.orderby_for != NULL
16434  && xasl->option == Q_DISTINCT)
16435  {
16436  ordbynum_flag = 0;
16437  xasl->ordbynum_pred = pt_to_pred_expr_with_arg (parser, select_node->info.query.orderby_for, &ordbynum_flag);
16438  if (ordbynum_flag & PT_PRED_ARG_ORDBYNUM_CONTINUE)
16439  {
16441  }
16442  }
16443 
16445  && pt_has_analytic (parser, select_node))
16446  {
16447  /* we have an inst_num() which should not get evaluated in the initial fetch(processing stage)
16448  * qexec_execute_analytic(post-processing stage) will use it in the final sort */
16450  }
16451 
16452  /* union fields for BUILDLIST_PROC_NODE - BUILDLIST_PROC */
16453  if (select_node->info.query.q.select.group_by)
16454  {
16455  if (qo_plan && qo_plan_skip_groupby (qo_plan))
16456  {
16457  groupby_skip = true;
16458  }
16459 
16460  /* finish group by processing */
16461  buildlist->groupby_list = pt_to_groupby (parser, select_node->info.query.q.select.group_by, select_node);
16462 
16463  /* Build SORT_LIST of the list file created by GROUP BY */
16464  buildlist->after_groupby_list =
16465  pt_to_after_groupby (parser, select_node->info.query.q.select.group_by, select_node);
16466 
16467  /* This is a having subquery list. If it has correlated subqueries, they must be run each group */
16468  buildlist->eptr_list = pt_to_corr_subquery_list (parser, select_node->info.query.q.select.having, 0);
16469 
16470  /* otherwise should be run once, at beginning. these have already been put on the aptr list above */
16471  groupby_ok = (buildlist->groupby_list && buildlist->g_outptr_list
16472  && (buildlist->g_having_pred || buildlist->g_grbynum_pred
16473  || !select_node->info.query.q.select.having));
16474 
16475  if (groupby_skip)
16476  {
16477  groupby_ok = 1;
16478  }
16479 
16480  buildlist->a_eval_list = NULL;
16481  buildlist->a_outptr_list = NULL;
16482  buildlist->a_outptr_list_ex = NULL;
16483  buildlist->a_regu_list = NULL;
16484  buildlist->a_val_list = NULL;
16485  }
16486  else
16487  {
16488  /* with no group by, a build-list proc should not be built a build-value proc should be built instead */
16489  buildlist->groupby_list = NULL;
16490  buildlist->g_regu_list = NULL;
16491  buildlist->g_val_list = NULL;
16492  buildlist->g_having_pred = NULL;
16493  buildlist->g_grbynum_pred = NULL;
16494  buildlist->g_grbynum_val = NULL;
16495  buildlist->g_grbynum_flag = 0;
16496  buildlist->g_agg_list = NULL;
16497  buildlist->eptr_list = NULL;
16498  buildlist->g_with_rollup = 0;
16499  }
16500 
16501  /* set index scan order */
16502  xasl->iscan_oid_order = ((orderby_skip) ? false : prm_get_bool_value (PRM_ID_BT_INDEX_SCAN_OID_ORDER));
16503 
16504  /* save single tuple info */
16505  if (select_node->info.query.flag.single_tuple == 1)
16506  {
16507  xasl->is_single_tuple = true;
16508  }
16509  } /* end xasl->outptr_list */
16510 
16511  /* verify everything worked */
16512  if (!xasl->outptr_list || !xasl->spec_list || !xasl->val_list || !groupby_ok || !orderby_ok || pt_has_error (parser))
16513  {
16514  goto exit_on_error;
16515  }
16516 
16517  /* set CONNECT BY xasl */
16518  xasl = pt_set_connect_by_xasl (parser, select_node, xasl);
16519  if (!xasl)
16520  {
16521  goto exit_on_error;
16522  }
16523 
16524  /* convert instnum to key limit (optimization) */
16525  if (pt_instnum_to_key_limit (parser, qo_plan, xasl) != NO_ERROR)
16526  {
16527  goto exit_on_error;
16528  }
16529 
16530  xasl->orderby_limit = NULL;
16531  if (xasl->ordbynum_pred)
16532  {
16533  QO_LIMIT_INFO *limit_infop = qo_get_key_limit_from_ordbynum (parser, qo_plan, xasl, false);
16534  if (limit_infop)
16535  {
16536  xasl->orderby_limit = limit_infop->upper;
16537  db_private_free (NULL, limit_infop);
16538  }
16539  }
16540 
16541  if (pt_set_limit_optimization_flags (parser, qo_plan, xasl) != NO_ERROR)
16542  {
16543  goto exit_on_error;
16544  }
16545 
16546  /* set list file descriptor for dummy pusher */
16548  {
16549  buildlist->push_list_id = select_node->info.query.q.select.push_list;
16550  }
16551 
16552  /* set flag for multi-update subquery */
16554  {
16556  }
16557 
16558  /* set flag for merge query */
16560  {
16562  /* set flag to ignore class oid in object fetch */
16563  if (xasl->fptr_list)
16564  {
16566  }
16567  }
16568 
16569  /* restore old parent xasl */
16570  parser->parent_proc_xasl = save_parent_proc_xasl;
16571 
16572  return xasl;
16573 
16574 exit_on_error:
16575 
16576  /* restore old parent xasl */
16577  parser->parent_proc_xasl = save_parent_proc_xasl;
16578 
16579  return NULL;
16580 }
16581 
16582 /*
16583  * pt_to_buildvalue_proc () - Make a buildvalue xasl proc
16584  * return:
16585  * parser(in):
16586  * select_node(in):
16587  * qo_plan(in):
16588  */
16589 static XASL_NODE *
16591 {
16592  XASL_NODE *xasl, *save_parent_proc_xasl;
16593  BUILDVALUE_PROC_NODE *buildvalue;
16594  AGGREGATE_TYPE *aggregate;
16595  PT_NODE *saved_current_class;
16596  XASL_NODE *dptr_head;
16597 
16598  if (!select_node || select_node->node_type != PT_SELECT || !select_node->info.query.q.select.from)
16599  {
16600  return NULL;
16601  }
16602 
16604  if (!xasl)
16605  {
16606  return NULL;
16607  }
16608 
16609  /* save parent xasl */
16610  save_parent_proc_xasl = parser->parent_proc_xasl;
16611  parser->parent_proc_xasl = xasl;
16612 
16613  buildvalue = &xasl->proc.buildvalue;
16614  xasl->next = NULL;
16615 
16616  /* set references of INST_NUM and ORDERBY_NUM values in parse tree */
16617  pt_set_numbering_node_etc (parser, select_node->info.query.q.select.list, &xasl->instnum_val, &xasl->ordbynum_val);
16618  pt_set_numbering_node_etc (parser, select_node->info.query.q.select.where, &xasl->instnum_val, &xasl->ordbynum_val);
16619  pt_set_numbering_node_etc (parser, select_node->info.query.orderby_for, &xasl->instnum_val, &xasl->ordbynum_val);
16620 
16621  /* assume parse tree correct, and PT_DISTINCT only other possibility */
16622  xasl->option = ((select_node->info.query.all_distinct == PT_ALL) ? Q_ALL : Q_DISTINCT);
16623 
16624  /* set 'etc' field for pseudocolumn nodes */
16625  pt_set_level_node_etc (parser, select_node->info.query.q.select.list, &xasl->level_val);
16626  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.list, &xasl->isleaf_val);
16627  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.list, &xasl->iscycle_val);
16628  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.list, xasl);
16629  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.list, xasl);
16630  pt_set_level_node_etc (parser, select_node->info.query.q.select.having, &xasl->level_val);
16631  pt_set_isleaf_node_etc (parser, select_node->info.query.q.select.having, &xasl->isleaf_val);
16632  pt_set_iscycle_node_etc (parser, select_node->info.query.q.select.having, &xasl->iscycle_val);
16633  pt_set_connect_by_operator_node_etc (parser, select_node->info.query.q.select.having, xasl);
16634  pt_set_qprior_node_etc (parser, select_node->info.query.q.select.having, xasl);
16635 
16636  aggregate = pt_to_aggregate (parser, select_node, NULL, NULL, NULL, NULL, NULL, &buildvalue->grbynum_val);
16637 
16638  /* the calls pt_to_out_list, pt_to_spec_list, and pt_to_if_pred, record information in the "symbol_info" structure
16639  * used by subsequent calls, and must be done first, before calculating subquery lists, etc. */
16640  xasl->outptr_list =
16641  pt_to_outlist (parser, select_node->info.query.q.select.list, &xasl->selected_upd_list, UNBOX_AS_VALUE);
16642 
16643  /* check if this select statement has click counter */
16644  if (xasl->selected_upd_list != NULL)
16645  {
16646  /* set lock timeout hint if specified */
16647  PT_NODE *hint_arg;
16648  float hint_wait_secs;
16649 
16651  hint_arg = select_node->info.query.q.select.waitsecs_hint;
16652  if (select_node->info.query.q.select.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
16653  {
16654  hint_wait_secs = (float) atof (hint_arg->info.name.original);
16655  if (hint_wait_secs > 0)
16656  {
16657  xasl->selected_upd_list->wait_msecs = (int) (hint_wait_secs * 1000);
16658  }
16659  else
16660  {
16661  xasl->selected_upd_list->wait_msecs = (int) hint_wait_secs;
16662  }
16663  }
16664  }
16665 
16666  if (xasl->outptr_list == NULL)
16667  {
16668  goto exit_on_error;
16669  }
16670 
16671  pt_set_aptr (parser, select_node, xasl);
16672 
16673  if (!qo_plan || !pt_gen_optimized_plan (parser, select_node, qo_plan, xasl))
16674  {
16675  PT_NODE *from;
16676 
16677  from = select_node->info.query.q.select.from;
16678  while (from)
16679  {
16680  if (from->info.spec.join_type != PT_JOIN_NONE)
16681  {
16683  goto exit_on_error;
16684  }
16685  from = from->next;
16686  }
16687 
16688  if (select_node->info.query.q.select.flavor == PT_MERGE_SELECT)
16689  {
16690  xasl = pt_gen_simple_merge_plan (parser, select_node, qo_plan, xasl);
16691  }
16692  else
16693  {
16694  xasl = pt_gen_simple_plan (parser, select_node, qo_plan, xasl);
16695  }
16696 
16697  if (xasl == NULL)
16698  {
16699  goto exit_on_error;
16700  }
16701  buildvalue = &xasl->proc.buildvalue;
16702  }
16703 
16704  /* save info for derived table size estimation */
16705  xasl->projected_size = 1;
16706  xasl->cardinality = 1.0;
16707 
16708  /* pred should never user the current instance for fetches either, so we turn off the current_class, if there is one. */
16709  saved_current_class = parser->symbols->current_class;
16710  parser->symbols->current_class = NULL;
16711  buildvalue->having_pred = pt_to_pred_expr (parser, select_node->info.query.q.select.having);
16712  parser->symbols->current_class = saved_current_class;
16713 
16714  if (xasl->scan_ptr)
16715  {
16716  dptr_head = xasl->scan_ptr;
16717  while (dptr_head->scan_ptr)
16718  {
16719  dptr_head = dptr_head->scan_ptr;
16720  }
16721  }
16722  else
16723  {
16724  dptr_head = xasl;
16725  }
16726  pt_set_dptr (parser, select_node->info.query.q.select.having, dptr_head, MATCH_ALL);
16727 
16728  /* union fields from BUILDVALUE_PROC_NODE - BUILDVALUE_PROC */
16729  buildvalue->agg_list = aggregate;
16730 
16731  /* this is not useful, set it to NULL. it was set by the old parser, and apparently used, but the use was apparently
16732  * redundant. */
16733  buildvalue->outarith_list = NULL;
16734 
16735  if (pt_false_search_condition (parser, select_node->info.query.q.select.where))
16736  {
16737  buildvalue->is_always_false = true;
16738  }
16739  else
16740  {
16741  buildvalue->is_always_false = false;
16742  }
16743 
16744  /* verify everything worked */
16745  if (!xasl->outptr_list || !xasl->spec_list || !xasl->val_list || pt_has_error (parser))
16746  {
16747  goto exit_on_error;
16748  }
16749 
16750  /* set CONNECT BY xasl */
16751  xasl = pt_set_connect_by_xasl (parser, select_node, xasl);
16752  if (!xasl)
16753  {
16754  goto exit_on_error;
16755  }
16756 
16757  /* convert instnum to key limit (optimization) */
16758  if (pt_instnum_to_key_limit (parser, qo_plan, xasl) != NO_ERROR)
16759  {
16760  goto exit_on_error;
16761  }
16762 
16763  /* convert ordbynum to key limit if we have iscan with multiple key ranges */
16764  if (qo_plan && qo_plan_multi_range_opt (qo_plan))
16765  {
16766  if (pt_ordbynum_to_key_limit_multiple_ranges (parser, qo_plan, xasl) != NO_ERROR)
16767  {
16768  goto exit_on_error;
16769  }
16770  }
16771 
16772  /* restore old parent xasl */
16773  parser->parent_proc_xasl = save_parent_proc_xasl;
16774 
16775  return xasl;
16776 
16777 exit_on_error:
16778 
16779  /* restore old parent xasl */
16780  parser->parent_proc_xasl = save_parent_proc_xasl;
16781 
16782  return NULL;
16783 }
16784 
16785 
16786 /*
16787  * pt_to_union_proc () - converts a PT_NODE tree of a query
16788  * union/intersection/difference to an XASL tree
16789  * return: XASL_NODE, NULL indicates error
16790  * parser(in): context
16791  * node(in): a query union/difference/intersection
16792  * type(in): xasl PROC type
16793  */
16794 static XASL_NODE *
16796 {
16797  XASL_NODE *xasl = NULL;
16798  XASL_NODE *left, *right = NULL;
16799  SORT_LIST *orderby = NULL;
16800  int ordbynum_flag;
16801 
16802  /* note that PT_UNION, PT_DIFFERENCE, and PT_INTERSECTION node types share the same node structure */
16803  left = (XASL_NODE *) node->info.query.q.union_.arg1->info.query.xasl;
16804  right = (XASL_NODE *) node->info.query.q.union_.arg2->info.query.xasl;
16805 
16806  /* orderby can legitimately be null */
16807  orderby = pt_to_orderby (parser, node->info.query.order_by, node);
16808 
16809  if (left && right && (orderby || !node->info.query.order_by))
16810  {
16811  /* don't allocate till everything looks ok. */
16812  xasl = regu_xasl_node_alloc (type);
16813  }
16814 
16815  if (xasl)
16816  {
16817  xasl->proc.union_.left = left;
16818  xasl->proc.union_.right = right;
16819 
16820  /* assume parse tree correct, and PT_DISTINCT only other possibility */
16821  xasl->option = (node->info.query.all_distinct == PT_ALL) ? Q_ALL : Q_DISTINCT;
16822 
16823  xasl->orderby_list = orderby;
16824 
16825  /* clear flag */
16827 
16828  /* save single tuple info */
16829  if (node->info.query.flag.single_tuple == 1)
16830  {
16831  xasl->is_single_tuple = true;
16832  }
16833 
16834  /* set 'etc' field of PT_NODEs which belong to inst_num() and orderby_num() expression in order to use at
16835  * pt_make_regu_numbering() */
16837  ordbynum_flag = 0;
16838  xasl->ordbynum_pred = pt_to_pred_expr_with_arg (parser, node->info.query.orderby_for, &ordbynum_flag);
16839 
16840  if (ordbynum_flag & PT_PRED_ARG_ORDBYNUM_CONTINUE)
16841  {
16843  }
16844 
16845  pt_set_aptr (parser, node, xasl);
16846 
16847  /* save info for derived table size estimation */
16848  switch (type)
16849  {
16850  case UNION_PROC:
16851  xasl->projected_size = MAX (left->projected_size, right->projected_size);
16852  xasl->cardinality = left->cardinality + right->cardinality;
16853  break;
16854  case DIFFERENCE_PROC:
16855  xasl->projected_size = left->projected_size;
16856  xasl->cardinality = left->cardinality;
16857  break;
16858  case INTERSECTION_PROC:
16859  xasl->projected_size = MAX (left->projected_size, right->projected_size);
16860  xasl->cardinality = MIN (left->cardinality, right->cardinality);
16861  break;
16862  default:
16863  break;
16864  }
16865 
16866  if (node->info.query.limit)
16867  {
16868  PT_NODE *limit;
16869 
16870  limit = node->info.query.limit;
16871  if (limit->next)
16872  {
16873  xasl->limit_offset = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
16874  limit = limit->next;
16875  }
16876  xasl->limit_row_count = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
16877  }
16878  } /* end xasl */
16879  else
16880  {
16881  xasl = NULL;
16882  }
16883 
16884  return xasl;
16885 }
16886 
16887 
16888 /*
16889  * pt_plan_set_query () - converts a PT_NODE tree of
16890  * a query union to an XASL tree
16891  * return: XASL_NODE, NULL indicates error
16892  * parser(in): context
16893  * node(in): a query union/difference/intersection
16894  * proc_type(in): xasl PROC type
16895  */
16896 static XASL_NODE *
16898 {
16899  XASL_NODE *xasl;
16900 
16901  /* no optimization for now */
16902  xasl = pt_to_union_proc (parser, node, proc_type);
16903 
16904  return xasl;
16905 }
16906 
16907 /*
16908  * pt_plan_cte () - converts a PT_NODE tree of a CTE to an XASL tree
16909  * return: XASL_NODE, NULL indicates error
16910  * parser(in): context
16911  * node(in): a CTE
16912  * proc_type(in): xasl PROC type
16913  */
16914 static XASL_NODE *
16916 {
16917  XASL_NODE *xasl;
16918  XASL_NODE *non_recursive_part_xasl = NULL, *recursive_part_xasl = NULL;
16919  PT_NODE *non_recursive_part, *recursive_part;
16920 
16921  if (node == NULL)
16922  {
16923  return NULL;
16924  }
16925 
16926  non_recursive_part = node->info.cte.non_recursive_part;
16927  recursive_part = node->info.cte.recursive_part;
16928 
16929  if (non_recursive_part == NULL)
16930  {
16931  PT_INTERNAL_ERROR (parser, "Non recursive part should be not null");
16932  return NULL;
16933  }
16934  non_recursive_part_xasl = (XASL_NODE *) non_recursive_part->info.query.xasl;
16935 
16936  if (recursive_part)
16937  {
16938  recursive_part_xasl = (XASL_NODE *) recursive_part->info.query.xasl;
16939  }
16940 
16941  xasl = regu_xasl_node_alloc (proc_type);
16942 
16943  if (xasl != NULL)
16944  {
16945  xasl->proc.cte.non_recursive_part = non_recursive_part_xasl;
16946  xasl->proc.cte.recursive_part = recursive_part_xasl;
16947  }
16948 
16949  if (recursive_part_xasl == NULL && non_recursive_part_xasl != NULL)
16950  {
16951  /* save single tuple info, cardinality, limit... from non_recursive_part */
16952  if (non_recursive_part->info.query.flag.single_tuple == 1)
16953  {
16954  xasl->is_single_tuple = true;
16955  }
16956 
16957  xasl->projected_size = non_recursive_part_xasl->projected_size;
16958  xasl->cardinality = non_recursive_part_xasl->cardinality;
16959 
16960  if (non_recursive_part->info.query.limit)
16961  {
16962  PT_NODE *limit;
16963 
16964  limit = non_recursive_part->info.query.limit;
16965  if (limit->next)
16966  {
16967  xasl->limit_offset = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
16968  limit = limit->next;
16969  }
16970  xasl->limit_row_count = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
16971  }
16972  }
16973 
16974  return xasl;
16975 }
16976 
16977 /*
16978  * pt_plan_schema () - Translate a schema PT_SELECT node to
16979  * a XASL buildschema proc
16980  * return: XASL_NODE, NULL indicates error
16981  * parser(in): context
16982  * select_node(in): of PT_SELECT type
16983  */
16984 static XASL_NODE *
16986 {
16987  XASL_NODE *xasl = NULL;
16988  int level;
16989 
16992  {
16993  xasl = pt_to_buildschema_proc (parser, select_node);
16994  if (xasl == NULL)
16995  {
16996  return NULL;
16997  }
16998  }
16999  else if (PT_SELECT_INFO_IS_FLAGED (select_node, PT_SELECT_INFO_IDX_SCHEMA))
17000  {
17001  xasl = pt_to_buildschema_proc (parser, select_node);
17002  if (xasl == NULL)
17003  {
17004  return NULL;
17005  }
17006 
17008  if (level & 0x200)
17009  {
17010  unsigned int save_custom;
17011 
17012  if (query_Plan_dump_fp == NULL)
17013  {
17014  query_Plan_dump_fp = stdout;
17015  }
17016 
17017  save_custom = parser->custom_print;
17018  parser->custom_print |= PT_CONVERT_RANGE;
17019  fprintf (query_Plan_dump_fp, "\nQuery stmt:%s\n\n%s\n\n", "", parser_print_tree (parser, select_node));
17020 
17021  parser->custom_print = save_custom;
17022  }
17023  }
17024 
17025  return xasl;
17026 }
17027 
17028 
17029 /*
17030  * pt_plan_query () -
17031  * return: XASL_NODE, NULL indicates error
17032  * parser(in): context
17033  * select_node(in): of PT_SELECT type
17034  */
17035 static XASL_NODE *
17037 {
17038  XASL_NODE *xasl;
17039  QO_PLAN *plan = NULL;
17040  PT_NODE *spec;
17041  int level, trace_format;
17042  bool hint_ignored = false;
17043  bool dump_plan;
17044 
17045  if (select_node->node_type != PT_SELECT)
17046  {
17047  return NULL;
17048  }
17049 
17050  /* Check for join, path expr, and index optimizations */
17051  plan = qo_optimize_query (parser, select_node);
17052 
17053  /* optimization fails, ignore join hint and retry optimization */
17054  if (!plan && select_node->info.query.q.select.hint != PT_HINT_NONE)
17055  {
17056  hint_ignored = true;
17057 
17058  /* init hint */
17059  select_node->info.query.q.select.hint = PT_HINT_NONE;
17060  if (select_node->info.query.q.select.ordered)
17061  {
17062  parser_free_tree (parser, select_node->info.query.q.select.ordered);
17063  select_node->info.query.q.select.ordered = NULL;
17064  }
17065  if (select_node->info.query.q.select.use_nl)
17066  {
17067  parser_free_tree (parser, select_node->info.query.q.select.use_nl);
17068  select_node->info.query.q.select.use_nl = NULL;
17069  }
17070  if (select_node->info.query.q.select.use_idx)
17071  {
17072  parser_free_tree (parser, select_node->info.query.q.select.use_idx);
17073  select_node->info.query.q.select.use_idx = NULL;
17074  }
17075  if (select_node->info.query.q.select.index_ss)
17076  {
17077  parser_free_tree (parser, select_node->info.query.q.select.index_ss);
17078  select_node->info.query.q.select.index_ss = NULL;
17079  }
17080  if (select_node->info.query.q.select.index_ls)
17081  {
17082  parser_free_tree (parser, select_node->info.query.q.select.index_ls);
17083  select_node->info.query.q.select.index_ls = NULL;
17084  }
17085  if (select_node->info.query.q.select.use_merge)
17086  {
17087  parser_free_tree (parser, select_node->info.query.q.select.use_merge);
17088  select_node->info.query.q.select.use_merge = NULL;
17089  }
17090 
17091  select_node->alias_print = NULL;
17092 
17093 #if defined(CUBRID_DEBUG)
17094  PT_NODE_PRINT_TO_ALIAS (parser, select_node, PT_CONVERT_RANGE);
17095 #endif /* CUBRID_DEBUG */
17096 
17097  plan = qo_optimize_query (parser, select_node);
17098  }
17099 
17100  if (pt_is_single_tuple (parser, select_node))
17101  {
17102  xasl = pt_to_buildvalue_proc (parser, select_node, plan);
17103  }
17104  else
17105  {
17106  xasl = pt_to_buildlist_proc (parser, select_node, plan);
17107  }
17108 
17110  if (level >= 0x100 && !PT_SELECT_INFO_IS_FLAGED (select_node, PT_SELECT_INFO_COLS_SCHEMA)
17112  && !select_node->flag.is_system_generated_stmt
17113  && !((spec = select_node->info.query.q.select.from) != NULL
17115  {
17116  dump_plan = true;
17117  }
17118  else
17119  {
17120  dump_plan = false;
17121  }
17122 
17123  /* Print out any needed post-optimization info. Leave a way to find out about environment info if we aren't able to
17124  * produce a plan. If this happens in the field at least we'll be able to glean some info */
17125  if (plan != NULL && dump_plan == true)
17126  {
17127  if (query_Plan_dump_fp == NULL)
17128  {
17129  query_Plan_dump_fp = stdout;
17130  }
17131  fputs ("\nQuery plan:\n", query_Plan_dump_fp);
17133  }
17134 
17135  if (dump_plan == true)
17136  {
17137  unsigned int save_custom;
17138 
17139  if (query_Plan_dump_fp == NULL)
17140  {
17141  query_Plan_dump_fp = stdout;
17142  }
17143 
17144  if (DETAILED_DUMP (level))
17145  {
17146  save_custom = parser->custom_print;
17147  parser->custom_print |= PT_CONVERT_RANGE;
17148  fprintf (query_Plan_dump_fp, "\nQuery stmt:%s\n\n%s\n\n", ((hint_ignored) ? " [Warning: HINT ignored]" : ""),
17149  parser_print_tree (parser, select_node));
17150  parser->custom_print = save_custom;
17151  }
17152 
17153  if (select_node->info.query.order_by && xasl && xasl->spec_list && xasl->spec_list->indexptr
17154  && xasl->spec_list->indexptr->orderby_skip)
17155  {
17156  if (DETAILED_DUMP (level))
17157  {
17158  fprintf (query_Plan_dump_fp, "/* ---> skip ORDER BY */\n");
17159  }
17160  else if (SIMPLE_DUMP (level))
17161  {
17162  fprintf (query_Plan_dump_fp, " skip ORDER BY\n");
17163  }
17164  }
17165 
17166  if (select_node->info.query.q.select.group_by && xasl && xasl->spec_list && xasl->spec_list->indexptr
17167  && xasl->spec_list->indexptr->groupby_skip)
17168  {
17169  if (DETAILED_DUMP (level))
17170  {
17171  fprintf (query_Plan_dump_fp, "/* ---> skip GROUP BY */\n");
17172  }
17173  else if (SIMPLE_DUMP (level))
17174  {
17175  fprintf (query_Plan_dump_fp, " skip GROUP BY\n");
17176  }
17177  }
17178  }
17179 
17180  if (xasl != NULL && plan != NULL)
17181  {
17182  size_t plan_len, sizeloc;
17183  char *ptr;
17184  char sql_plan_empty[] = "";
17185  char *sql_plan = sql_plan_empty;
17186  COMPILE_CONTEXT *contextp = &parser->context;
17187 
17188  FILE *fp = port_open_memstream (&ptr, &sizeloc);
17189  if (fp)
17190  {
17191  qo_plan_lite_print (plan, fp, 0);
17192  if (select_node->info.query.order_by && xasl && xasl->spec_list && xasl->spec_list->indexptr
17193  && xasl->spec_list->indexptr->orderby_skip)
17194  {
17195  fprintf (fp, "\n skip ORDER BY\n");
17196  }
17197 
17198  if (select_node->info.query.q.select.group_by && xasl && xasl->spec_list && xasl->spec_list->indexptr
17199  && xasl->spec_list->indexptr->groupby_skip)
17200  {
17201  fprintf (fp, "\n skip GROUP BY\n");
17202  }
17203 
17204  port_close_memstream (fp, &ptr, &sizeloc);
17205 
17206  if (ptr)
17207  {
17208  sql_plan = pt_alloc_packing_buf ((int) sizeloc + 1);
17209  if (sql_plan == NULL)
17210  {
17211  goto exit;
17212  }
17213 
17214  strncpy (sql_plan, ptr, sizeloc);
17215  sql_plan[sizeloc] = '\0';
17216  free (ptr);
17217  }
17218  }
17219 
17220  if (sql_plan)
17221  {
17222  plan_len = strlen (sql_plan);
17223 
17224  if (contextp->sql_plan_alloc_size == 0)
17225  {
17226  int size = MAX (1024, (int) plan_len * 2);
17227  contextp->sql_plan_text = (char *) parser_alloc (parser, size);
17228  if (contextp->sql_plan_text == NULL)
17229  {
17230  goto exit;
17231  }
17232 
17233  contextp->sql_plan_alloc_size = size;
17234  contextp->sql_plan_text[0] = '\0';
17235  }
17236  else if (contextp->sql_plan_alloc_size - (int) strlen (contextp->sql_plan_text) < (long) plan_len)
17237  {
17238  char *ptr;
17239  int size = (contextp->sql_plan_alloc_size + (int) plan_len) * 2;
17240 
17241  ptr = (char *) parser_alloc (parser, size);
17242  if (ptr == NULL)
17243  {
17244  goto exit;
17245  }
17246 
17247  ptr[0] = '\0';
17248  strcpy (ptr, contextp->sql_plan_text);
17249 
17250  contextp->sql_plan_text = ptr;
17251  contextp->sql_plan_alloc_size = size;
17252  }
17253 
17254  strcat (contextp->sql_plan_text, sql_plan);
17255  }
17256  }
17257 
17258  if (parser->query_trace == true && !qo_need_skip_execution () && plan != NULL && xasl != NULL)
17259  {
17261 
17262  if (trace_format == QUERY_TRACE_TEXT)
17263  {
17264  qo_top_plan_print_text (parser, xasl, select_node, plan);
17265  }
17266  else if (trace_format == QUERY_TRACE_JSON)
17267  {
17268  qo_top_plan_print_json (parser, xasl, select_node, plan);
17269  }
17270  }
17271 
17272  if (level >= 0x100)
17273  {
17274  if (select_node->info.query.is_subquery == PT_IS_CTE_NON_REC_SUBQUERY)
17275  {
17276  fprintf (query_Plan_dump_fp, "\nend of non recursive part of CTE\n");
17277  }
17278  else if (select_node->info.query.is_subquery == PT_IS_CTE_REC_SUBQUERY)
17279  {
17280  fprintf (query_Plan_dump_fp, "\nend of CTE definition\n");
17281  }
17282  }
17283 
17284 
17285 exit:
17286  if (plan != NULL)
17287  {
17288  qo_plan_discard (plan);
17289  }
17290 
17291  return xasl;
17292 }
17293 
17294 
17295 /*
17296  * parser_generate_xasl_proc () - Creates xasl proc for parse tree.
17297  * Also used for direct recursion, not for subquery recursion
17298  * return:
17299  * parser(in):
17300  * node(in): pointer to a query structure
17301  * query_list(in): pointer to the generated xasl-tree
17302  */
17303 static XASL_NODE *
17305 {
17306  XASL_NODE *xasl = NULL;
17307  PT_NODE *query;
17308  bool query_Plan_dump_fp_open = false;
17309 
17310  /* we should propagate abort error from the server */
17311  if (!parser->flag.abort && (PT_IS_QUERY (node) || node->node_type == PT_CTE))
17312  {
17313  /* check for cached query xasl */
17314  for (query = query_list; query; query = query->next)
17315  {
17316  if (query->info.query.xasl && query->info.query.id == node->info.query.id)
17317  {
17318  /* found cached query xasl */
17319  node->info.query.xasl = query->info.query.xasl;
17321 
17322  return (XASL_NODE *) node->info.query.xasl;
17323  }
17324  } /* for (query = ... ) */
17325 
17326  /* not found cached query xasl */
17327  switch (node->node_type)
17328  {
17329  case PT_SELECT:
17330  /* This function is reenterable by pt_plan_query so, query_Plan_dump_fp should be open once at first call and
17331  * be closed at that call. */
17333  {
17334  if (query_Plan_dump_fp == NULL || query_Plan_dump_fp == stdout)
17335  {
17337  if (query_Plan_dump_fp != NULL)
17338  {
17339  query_Plan_dump_fp_open = true;
17340  }
17341  }
17342  }
17343 
17344  if (query_Plan_dump_fp == NULL)
17345  {
17346  query_Plan_dump_fp = stdout;
17347  }
17348 
17353  {
17354  xasl = pt_plan_schema (parser, node);
17355  }
17356  else
17357  {
17358  xasl = pt_plan_query (parser, node);
17359  }
17360  node->info.query.xasl = xasl;
17361 
17362  /* close file handle if this function open it */
17363  if (query_Plan_dump_fp_open == true)
17364  {
17366 
17367  fclose (query_Plan_dump_fp);
17368  query_Plan_dump_fp = stdout;
17369  }
17370  break;
17371 
17372  case PT_UNION:
17373  xasl = pt_plan_set_query (parser, node, UNION_PROC);
17374  node->info.query.xasl = xasl;
17375  break;
17376 
17377  case PT_DIFFERENCE:
17378  xasl = pt_plan_set_query (parser, node, DIFFERENCE_PROC);
17379  node->info.query.xasl = xasl;
17380  break;
17381 
17382  case PT_INTERSECTION:
17383  xasl = pt_plan_set_query (parser, node, INTERSECTION_PROC);
17384  node->info.query.xasl = xasl;
17385  break;
17386 
17387  case PT_CTE:
17388  xasl = pt_plan_cte (parser, node, CTE_PROC);
17389  node->info.cte.xasl = xasl;
17390  break;
17391 
17392  default:
17393  if (!pt_has_error (parser))
17394  {
17395  PT_INTERNAL_ERROR (parser, "generate xasl");
17396  }
17397  /* should never get here */
17398  break;
17399  }
17400  }
17401 
17402  if (pt_has_error (parser))
17403  {
17404  xasl = NULL; /* signal error occurred */
17405  }
17406 
17407  if (xasl)
17408  {
17409  PT_NODE *spec;
17410 
17411  /* Check to see if composite locking needs to be turned on. We do not do composite locking from proxies. */
17412  if (node->node_type == PT_SELECT && node->info.query.xasl && !READONLY_SCAN (node->info.query.scan_op_type))
17413  {
17414  spec = node->info.query.q.select.from;
17415  while (spec)
17416  {
17418  {
17419  PT_NODE *entity_list;
17420 
17421  if (spec->info.spec.flat_entity_list != NULL)
17422  {
17423  entity_list = spec->info.spec.flat_entity_list;
17424  }
17425  else if (spec->info.spec.derived_table_type == PT_IS_SET_EXPR && spec->info.spec.path_entities != NULL
17426  && spec->info.spec.path_entities->node_type == PT_SPEC
17428  {
17429  entity_list = spec->info.spec.path_entities->info.spec.flat_entity_list;
17430  }
17431  else
17432  {
17433  entity_list = NULL;
17434  }
17435 
17436  if (entity_list)
17437  {
17438  if ((node->info.query.upd_del_class_cnt > 1)
17439  || (node->info.query.upd_del_class_cnt == 1 && xasl->scan_ptr))
17440  {
17441  MOP mop = entity_list->info.name.db_object;
17442  if (mop && !WS_ISVID (mop))
17443  {
17444  XASL_NODE *scan = NULL;
17445  ACCESS_SPEC_TYPE *cs = NULL;
17446 
17447  for (scan = xasl; scan != NULL; scan = scan->scan_ptr)
17448  {
17449  for (cs = scan->spec_list; cs != NULL; cs = cs->next)
17450  {
17451  if ((cs->type == TARGET_CLASS)
17452  && (OID_EQ (&ACCESS_SPEC_CLS_OID (cs), WS_REAL_OID (mop))))
17453  {
17454  scan->scan_op_type = node->info.query.scan_op_type;
17455  break;
17456  }
17457  }
17458  if (cs)
17459  {
17460  break;
17461  }
17462  }
17463  }
17464  }
17465  else
17466  {
17467  xasl->scan_op_type = node->info.query.scan_op_type;
17468  break;
17469  }
17470  }
17471  }
17472 
17473  spec = spec->next;
17474  }
17475 
17478  }
17479 
17480  /* set as zero correlation-level; this uncorrelated subquery need to be executed at most one time */
17481  if ((PT_IS_QUERY (node) && node->info.query.correlation_level == 0) || node->node_type == PT_CTE)
17482  {
17484  }
17485 
17486 /* BUG FIX - COMMENT OUT: DO NOT REMOVE ME FOR USE IN THE FUTURE */
17487 #if 0
17488  /* cache query xasl */
17489  if (node->info.query.id)
17490  {
17491  query = parser_new_node (parser, node->node_type);
17492  query->info.query.id = node->info.query.id;
17493  query->info.query.xasl = node->info.query.xasl;
17495 
17496  query_list = parser_append_node (query, query_list);
17497  }
17498 #endif /* 0 */
17499  }
17500  else
17501  {
17502  /* if the previous request to get a driver caused a deadlock following message would make confuse */
17503  if (!parser->flag.abort && !pt_has_error (parser))
17504  {
17505  PT_INTERNAL_ERROR (parser, "generate xasl");
17506  }
17507  }
17508 
17509  return xasl;
17510 }
17511 
17512 /*
17513  * pt_spec_to_xasl_class_oid_list () - get class OID list
17514  * from the spec node list
17515  * return:
17516  * parser(in):
17517  * spec(in):
17518  * oid_listp(out):
17519  * lock_listp(out):
17520  * tcard_listp(out):
17521  * nump(out):
17522  * sizep(out):
17523  * includes_tde_class(out):
17524  */
17525 static int
17526 pt_spec_to_xasl_class_oid_list (PARSER_CONTEXT * parser, const PT_NODE * spec, OID ** oid_listp, int **lock_listp,
17527  int **tcard_listp, int *nump, int *sizep, int *includes_tde_class)
17528 {
17529  PT_NODE *flat = NULL;
17530  OID *oid = NULL, *v_oid = NULL, *o_list = NULL;
17531  int *lck_list = NULL;
17532  int *t_list = NULL;
17533  DB_OBJECT *class_obj = NULL;
17534  SM_CLASS *smclass = NULL;
17535  OID *oldptr = NULL;
17536  OID *oid_ptr = NULL;
17537  int index;
17538  int lock = (int) NULL_LOCK;
17539 #if defined(WINDOWS)
17540  unsigned int o_num, o_size, prev_o_num;
17541 #else
17542  size_t o_num, o_size, prev_o_num;
17543 #endif
17544 
17545  if (*oid_listp == NULL || *lock_listp == NULL || *tcard_listp == NULL)
17546  {
17547  *oid_listp = (OID *) malloc (sizeof (OID) * OID_LIST_GROWTH);
17548  *lock_listp = (int *) malloc (sizeof (int) * OID_LIST_GROWTH);
17549  *tcard_listp = (int *) malloc (sizeof (int) * OID_LIST_GROWTH);
17550  *sizep = OID_LIST_GROWTH;
17551  }
17552 
17553  if (*oid_listp == NULL || *lock_listp == NULL || *tcard_listp == NULL || *nump >= *sizep)
17554  {
17555  goto error;
17556  }
17557 
17558  o_num = *nump;
17559  o_size = *sizep;
17560  o_list = *oid_listp;
17561  lck_list = *lock_listp;
17562  t_list = *tcard_listp;
17563 
17564  /* traverse spec list which is a FROM clause */
17565  for (; spec; spec = spec->next)
17566  {
17567  /* traverse flat entity list which are resolved classes */
17569  {
17570  lock = (int) IX_LOCK;
17571  }
17572  else
17573  {
17574  lock = (int) IS_LOCK;
17575  }
17576  for (flat = spec->info.spec.flat_entity_list; flat; flat = flat->next)
17577  {
17578  /* get the OID of the class object which is fetched before */
17579  oid = ((flat->info.name.db_object != NULL) ? ws_identifier (flat->info.name.db_object) : NULL);
17580  v_oid = NULL;
17581  while (oid != NULL)
17582  {
17583  prev_o_num = o_num;
17584  oid_ptr = (OID *) lsearch (oid, o_list, &o_num, sizeof (OID), oid_compare);
17585 
17586  if (o_num > prev_o_num && (long) o_num > (*nump))
17587  {
17588  int is_class = 0;
17589 
17590  /* init #pages */
17591  *(t_list + o_num - 1) = XASL_CLASS_NO_TCARD;
17592 
17593  /* get #pages of the given class */
17594  class_obj = flat->info.name.db_object;
17595 
17596  assert (class_obj != NULL);
17597  assert (locator_is_class (class_obj, DB_FETCH_QUERY_READ) > 0);
17598  assert (!OID_ISTEMP (WS_OID (class_obj)));
17599 
17600  if (class_obj != NULL)
17601  {
17602  is_class = locator_is_class (class_obj, DB_FETCH_QUERY_READ);
17603  if (is_class < 0)
17604  {
17605  goto error;
17606  }
17607  }
17608  if (is_class && !OID_ISTEMP (WS_OID (class_obj)))
17609  {
17610  if (au_fetch_class (class_obj, &smclass, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
17611  {
17612  if (smclass)
17613  {
17614  if (smclass->tde_algorithm != TDE_ALGORITHM_NONE)
17615  {
17616  *includes_tde_class = 1;
17617  }
17618  if (smclass->stats)
17619  {
17620  assert (smclass->stats->heap_num_pages >= 0);
17621  *(t_list + o_num - 1) = smclass->stats->heap_num_pages;
17622  }
17623  }
17624  }
17625  else
17626  {
17627  /* avoid continue in loop with error */
17628  goto error;
17629  }
17630  }
17631 
17632  /* Lock for scans is IS_LOCK/IX_LOCK. */
17633  *(lck_list + o_num - 1) = lock;
17634  }
17635  else
17636  {
17637  /* Find index of existing object. */
17638  assert (oid_ptr != NULL);
17639  index = (int) (oid_ptr - o_list);
17640 
17641  /* Merge existing lock with IS_LOCK/IX_LOCK. */
17642  lck_list[index] = lock_Conv[lck_list[index]][lock];
17643  }
17644 
17645  if (o_num >= o_size)
17646  {
17647  o_size += OID_LIST_GROWTH;
17648  oldptr = (OID *) o_list;
17649  o_list = (OID *) realloc (o_list, o_size * sizeof (OID));
17650  if (o_list == NULL)
17651  {
17652  free_and_init (oldptr);
17653  *oid_listp = NULL;
17654  goto error;
17655  }
17656 
17657  oldptr = (OID *) lck_list;
17658  lck_list = (int *) realloc (lck_list, o_size * sizeof (int));
17659  if (lck_list == NULL)
17660  {
17661  free_and_init (oldptr);
17662  free_and_init (o_list);
17663  *oid_listp = NULL;
17664  *lock_listp = NULL;
17665  goto error;
17666  }
17667 
17668  oldptr = (OID *) t_list;
17669  t_list = (int *) realloc (t_list, o_size * sizeof (int));
17670  if (t_list == NULL)
17671  {
17672  free_and_init (oldptr);
17673  free_and_init (o_list);
17674  free_and_init (lck_list);
17675  *oid_listp = NULL;
17676  *lock_listp = NULL;
17677  *tcard_listp = NULL;
17678  goto error;
17679  }
17680  }
17681 
17682  if (v_oid == NULL)
17683  {
17684  /* get the OID of the view object */
17685  v_oid = ((flat->info.name.virt_object != NULL) ? ws_identifier (flat->info.name.virt_object) : NULL);
17686  oid = v_oid;
17687  }
17688  else
17689  {
17690  break;
17691  }
17692  }
17693  }
17694  }
17695 
17696  *nump = o_num;
17697  *sizep = o_size;
17698  *oid_listp = o_list;
17699  *lock_listp = lck_list;
17700  *tcard_listp = t_list;
17701 
17702  return o_num;
17703 
17704 error:
17705  if (*oid_listp)
17706  {
17707  free_and_init (*oid_listp);
17708  }
17709 
17710  if (*tcard_listp)
17711  {
17712  free_and_init (*tcard_listp);
17713  }
17714 
17715  *nump = *sizep = 0;
17716 
17717  return -1;
17718 }
17719 
17720 
17721 /*
17722  * pt_serial_to_xasl_class_oid_list () - get serial OID list
17723  * from the node
17724  * return:
17725  * parser(in):
17726  * serial(in):
17727  * oid_listp(out):
17728  * lock_listp(out):
17729  * tcard_listp(out):
17730  * nump(out):
17731  * sizep(out):
17732  */
17733 static int
17734 pt_serial_to_xasl_class_oid_list (PARSER_CONTEXT * parser, const PT_NODE * serial, OID ** oid_listp, int **lock_listp,
17735  int **tcard_listp, int *nump, int *sizep)
17736 {
17737  MOP serial_mop;
17738  OID *serial_oid_p;
17739  OID *o_list = NULL;
17740  int *lck_list = NULL;
17741  int *t_list = NULL;
17742  void *oldptr = NULL;
17743 #if defined(WINDOWS)
17744  unsigned int o_num, o_size, prev_o_num;
17745 #else
17746  size_t o_num, o_size, prev_o_num;
17747 #endif
17748 
17749  assert (PT_IS_EXPR_NODE (serial) && PT_IS_SERIAL (serial->info.expr.op));
17750 
17751  /* get the OID of the serial object which is fetched before */
17752  serial_mop = pt_resolve_serial (parser, serial->info.expr.arg1);
17753  if (serial_mop == NULL)
17754  {
17755  goto error;
17756  }
17757  serial_oid_p = db_identifier (serial_mop);
17758  if (serial_oid_p == NULL)
17759  {
17760  goto error;
17761  }
17762 
17763  if (*oid_listp == NULL || *tcard_listp == NULL)
17764  {
17765  *oid_listp = (OID *) malloc (sizeof (OID) * OID_LIST_GROWTH);
17766  if (*oid_listp == NULL)
17767  {
17769  goto error;
17770  }
17771 
17772  *lock_listp = (int *) malloc (sizeof (int) * OID_LIST_GROWTH);
17773  if (*lock_listp == NULL)
17774  {
17776  goto error;
17777  }
17778 
17779  *tcard_listp = (int *) malloc (sizeof (int) * OID_LIST_GROWTH);
17780  if (*tcard_listp == NULL)
17781  {
17783  goto error;
17784  }
17785  *sizep = OID_LIST_GROWTH;
17786  }
17787 
17788  if (*nump >= *sizep)
17789  {
17790  goto error;
17791  }
17792 
17793  o_num = *nump;
17794  o_size = *sizep;
17795  o_list = *oid_listp;
17796  lck_list = *lock_listp;
17797  t_list = *tcard_listp;
17798 
17799  prev_o_num = o_num;
17800  (void) lsearch (serial_oid_p, o_list, &o_num, sizeof (OID), oid_compare);
17801  if (o_num > prev_o_num && o_num > (size_t) * nump)
17802  {
17803  *(t_list + o_num - 1) = XASL_SERIAL_OID_TCARD; /* init #pages */
17804  *(lck_list + o_num - 1) = (int) NULL_LOCK;
17805  }
17806 
17807  if (o_num >= o_size)
17808  {
17809  o_size += OID_LIST_GROWTH;
17810  oldptr = (void *) o_list;
17811  o_list = (OID *) realloc (o_list, o_size * sizeof (OID));
17812  if (o_list == NULL)
17813  {
17815 
17816  free_and_init (oldptr);
17817  *oid_listp = NULL;
17818  goto error;
17819  }
17820 
17821  oldptr = (void *) lck_list;
17822  lck_list = (int *) realloc (lck_list, o_size * sizeof (int));
17823  if (lck_list == NULL)
17824  {
17825  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, o_size * sizeof (int));
17826 
17827  free_and_init (oldptr);
17828  free_and_init (o_list);
17829  *oid_listp = NULL;
17830  *lock_listp = NULL;
17831  goto error;
17832  }
17833 
17834  oldptr = (void *) t_list;
17835  t_list = (int *) realloc (t_list, o_size * sizeof (int));
17836  if (t_list == NULL)
17837  {
17838  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, o_size * sizeof (int));
17839 
17840  free_and_init (oldptr);
17841  free_and_init (o_list);
17842  free_and_init (lck_list);
17843  *oid_listp = NULL;
17844  *lock_listp = NULL;
17845  *tcard_listp = NULL;
17846  goto error;
17847  }
17848  }
17849 
17850  *nump = o_num;
17851  *sizep = o_size;
17852  *oid_listp = o_list;
17853  *tcard_listp = t_list;
17854 
17855  return o_num;
17856 
17857 error:
17858  if (*oid_listp)
17859  {
17860  free_and_init (*oid_listp);
17861  }
17862 
17863  if (*tcard_listp)
17864  {
17865  free_and_init (*tcard_listp);
17866  }
17867 
17868  *nump = *sizep = 0;
17869 
17870  return -1;
17871 }
17872 
17873 /*
17874  * pt_make_aptr_parent_node () - Builds a BUILDLIST proc for the query node and
17875  * attaches it as the aptr to the xasl node.
17876  * A list scan spec from the aptr's list file is
17877  * attached to the xasl node.
17878  *
17879  * return : XASL node.
17880  * parser (in) : Parser context.
17881  * node (in) : Parser node containing sub-query.
17882  * type (in) : XASL proc type.
17883  *
17884  * NOTE: This function should not be used in the INSERT ... VALUES case.
17885  */
17886 static XASL_NODE *
17888 {
17889  XASL_NODE *aptr = NULL;
17890  XASL_NODE *xasl = NULL;
17891  REGU_VARIABLE_LIST regu_attributes;
17892 
17893  xasl = regu_xasl_node_alloc (type);
17894 
17895  if (xasl != NULL && node != NULL)
17896  {
17897  if (PT_IS_QUERY_NODE_TYPE (node->node_type))
17898  {
17899  PT_NODE *namelist;
17900  REGU_VARIABLE_LIST regu_var_list;
17901 
17902  namelist = NULL;
17903 
17904  aptr = parser_generate_xasl (parser, node);
17905  if (aptr != NULL)
17906  {
17908 
17909  if (type == UPDATE_PROC)
17910  {
17911  PT_NODE *col;
17912 
17913  for (col = pt_get_select_list (parser, node); col != NULL; col = col->next)
17914  {
17915  if (PT_IS_QUERY_NODE_TYPE (col->node_type))
17916  {
17917  namelist =
17918  parser_append_node (pt_point_l (parser, pt_get_select_list (parser, col)), namelist);
17919  }
17920  else
17921  {
17922  namelist = parser_append_node (pt_point (parser, col), namelist);
17923  }
17924  }
17925  }
17926  else
17927  {
17928  namelist = pt_get_select_list (parser, node);
17929  }
17930 
17931  if ((type == UPDATE_PROC || type == INSERT_PROC) && aptr->outptr_list)
17932  {
17933  for (regu_var_list = aptr->outptr_list->valptrp; regu_var_list; regu_var_list = regu_var_list->next)
17934  {
17935  regu_var_list->value.flags |= REGU_VARIABLE_UPD_INS_LIST;
17936  }
17937  }
17938 
17939  aptr->next = NULL;
17940  xasl->aptr_list = aptr;
17941 
17942  xasl->val_list = pt_make_val_list (parser, namelist);
17943  if (xasl->val_list != NULL)
17944  {
17945  int *attr_offsets;
17946 
17947  attr_offsets = pt_make_identity_offsets (namelist);
17948  regu_attributes = pt_to_position_regu_variable_list (parser, namelist, xasl->val_list, attr_offsets);
17949  if (attr_offsets != NULL)
17950  {
17951  free_and_init (attr_offsets);
17952  }
17953 
17954  if (regu_attributes != NULL)
17955  {
17956  xasl->spec_list =
17957  pt_make_list_access_spec (aptr, ACCESS_METHOD_SEQUENTIAL, NULL, NULL, regu_attributes, NULL,
17958  NULL, NULL);
17959  }
17960  }
17961  else
17962  {
17964  }
17965 
17966  if (type == UPDATE_PROC && namelist != NULL)
17967  {
17968  parser_free_tree (parser, namelist);
17969  }
17970  }
17971 
17972  if (type == INSERT_PROC)
17973  {
17974  xasl->proc.insert.num_val_lists = 0;
17975  xasl->proc.insert.valptr_lists = NULL;
17976  }
17977  }
17978  else
17979  {
17980  /* Shouldn't be here */
17981  assert (0);
17982  return NULL;
17983  }
17984  }
17985 
17986  if (pt_has_error (parser))
17987  {
17988  pt_report_to_ersys (parser, PT_SEMANTIC);
17989  goto exit_on_error;
17990  }
17991 
17992  return xasl;
17993 
17994 exit_on_error:
17995 
17996  return NULL;
17997 }
17998 
17999 
18000 /*
18001  * pt_to_constraint_pred () - Builds predicate of NOT NULL conjuncts.
18002  * Then generates the corresponding filter predicate
18003  * return: NO_ERROR on success, non-zero for ERROR
18004  * parser(in):
18005  * xasl(in): value list contains the attributes the predicate must point to
18006  * spec(in): spec that generated the list file for the above value list
18007  * non_null_attrs(in): list of attributes to make into a constraint pred
18008  * attr_list(in): corresponds to the list file's value list positions
18009  * attr_offset(in): the additional offset into the value list. This is
18010  * necessary because the update prepends 2 columns for
18011  * each class that will be updated on the select list of
18012  * the aptr query
18013  *
18014  * NOTE: on outer joins, the OID of a node in not_null_attrs can be null.
18015  * In this case, constraint verification should be skipped, because there
18016  * will be nothing to update.
18017  */
18018 static int
18020  PT_NODE * attr_list, int attr_offset)
18021 {
18022  PT_NODE *pt_pred = NULL, *node, *conj, *next, *oid_is_null_expr, *constraint;
18023  PT_NODE *name, *spec_list;
18024  PRED_EXPR *pred = NULL;
18025  TABLE_INFO *ti = NULL;
18026 
18027  assert (xasl != NULL && spec != NULL && parser != NULL);
18028 
18029  node = non_null_attrs;
18030 
18031  parser->symbols = pt_symbol_info_alloc ();
18032  if (parser->symbols == NULL)
18033  {
18034  goto outofmem;
18035  }
18036 
18037  while (node != NULL)
18038  {
18039  /* we don't want a DAG so we need to NULL the next pointer as we create a conjunct for each of the
18040  * non_null_attrs. Thus we must save the next pointer for the loop. */
18041  next = node->next;
18042  node->next = NULL;
18043 
18044  constraint = parser_new_node (parser, PT_EXPR);
18045  if (constraint == NULL)
18046  {
18047  goto outofmem;
18048  }
18049 
18050  oid_is_null_expr = NULL;
18051 
18052  name = node;
18053  CAST_POINTER_TO_NODE (name);
18054  assert (PT_IS_NAME_NODE (name));
18055 
18056  /* look for spec in spec list */
18057  spec_list = spec;
18058  while (spec_list != NULL)
18059  {
18060  if (spec_list->info.spec.id == name->info.name.spec_id)
18061  {
18062  break;
18063  }
18064  spec_list = spec_list->next;
18065  }
18066 
18067  assert (spec_list != NULL);
18068 
18069  /* create not null constraint */
18070  constraint->next = NULL;
18071  constraint->line_number = node->line_number;
18072  constraint->column_number = node->column_number;
18073  constraint->type_enum = PT_TYPE_LOGICAL;
18074  constraint->info.expr.op = PT_IS_NOT_NULL;
18075  constraint->info.expr.arg1 = node;
18076 
18077  if (mq_is_outer_join_spec (parser, spec_list))
18078  {
18079  /* need rewrite */
18080  /* verify not null constraint only if OID is not null */
18081  /* create OID is NULL expression */
18082  oid_is_null_expr = parser_new_node (parser, PT_EXPR);
18083  if (oid_is_null_expr == NULL)
18084  {
18085  goto outofmem;
18086  }
18087  oid_is_null_expr->type_enum = PT_TYPE_LOGICAL;
18088  oid_is_null_expr->info.expr.op = PT_IS_NULL;
18089  oid_is_null_expr->info.expr.arg1 = pt_spec_to_oid_attr (parser, spec_list, OID_NAME);
18090  if (oid_is_null_expr->info.expr.arg1 == NULL)
18091  {
18092  goto outofmem;
18093  }
18094 
18095  /* create an OR expression, first argument OID is NULL, second argument the constraint. This way, constraint
18096  * check will be skipped if OID is NULL */
18097  conj = parser_new_node (parser, PT_EXPR);
18098  if (conj == NULL)
18099  {
18100  goto outofmem;
18101  }
18102  conj->type_enum = PT_TYPE_LOGICAL;
18103  conj->info.expr.op = PT_OR;
18104  conj->info.expr.arg1 = oid_is_null_expr;
18105  conj->info.expr.arg2 = constraint;
18106  }
18107  else
18108  {
18109  conj = constraint;
18110  }
18111  /* add spec to table info */
18112  ti = pt_make_table_info (parser, spec_list);
18113  if (ti != NULL)
18114  {
18115  ti->next = parser->symbols->table_info;
18116  parser->symbols->table_info = ti;
18117  }
18118 
18119  conj->next = pt_pred;
18120  pt_pred = conj;
18121  node = next; /* go to the next node */
18122  }
18123 
18124  parser->symbols->current_listfile = attr_list;
18125  parser->symbols->listfile_value_list = xasl->val_list;
18126  parser->symbols->listfile_attr_offset = attr_offset;
18127 
18128  pred = pt_to_pred_expr (parser, pt_pred);
18129 
18130  conj = pt_pred;
18131  while (conj != NULL)
18132  {
18133  conj->info.expr.arg1 = NULL;
18134  conj = conj->next;
18135  }
18136  if (pt_pred != NULL)
18137  {
18138  parser_free_tree (parser, pt_pred);
18139  }
18140 
18141  /* symbols are allocated with pt_alloc_packing_buf, and freed at end of xasl generation. */
18142  parser->symbols = NULL;
18143 
18144  if (xasl->type == INSERT_PROC)
18145  {
18146  xasl->proc.insert.cons_pred = pred;
18147  }
18148  else if (xasl->type == UPDATE_PROC)
18149  {
18150  xasl->proc.update.cons_pred = pred;
18151  }
18152  else
18153  {
18155  return ER_GENERIC_ERROR;
18156  }
18157 
18158  return NO_ERROR;
18159 
18160 outofmem:
18162  if (pt_pred != NULL)
18163  {
18164  parser_free_tree (parser, pt_pred);
18165  }
18166 
18168 
18169 }
18170 
18171 /*
18172  * pt_to_insert_xasl () - Converts an insert parse tree to an XASL tree for insert server execution.
18173  *
18174  * return : Xasl node.
18175  * parser (in) : Parser context.
18176  * statement (in) : Parse tree node for insert statement.
18177  */
18178 XASL_NODE *
18180 {
18181  XASL_NODE *xasl = NULL;
18182  INSERT_PROC_NODE *insert = NULL;
18183  PT_NODE *value_clauses = NULL, *query = NULL, *val_list = NULL;
18184  PT_NODE *attr = NULL, *attrs = NULL;
18185  PT_NODE *non_null_attrs = NULL, *default_expr_attrs = NULL;
18186  MOBJ class_;
18187  OID *class_oid = NULL;
18188  DB_OBJECT *class_obj = NULL;
18189  SM_CLASS *smclass = NULL;
18190  HFID *hfid = NULL;
18191  int num_vals, num_default_expr;
18192  int a, i, has_uniques;
18193  int error = NO_ERROR;
18194  PT_NODE *hint_arg = NULL;
18195  float hint_wait_secs;
18196 
18197  assert (parser != NULL && statement != NULL);
18198 
18199  if (statement->info.insert.odku_assignments != NULL || statement->info.insert.do_replace)
18200  {
18201  statement = parser_walk_tree (parser, statement, pt_null_xasl, NULL, NULL, NULL);
18202  }
18203 
18204  has_uniques = statement->info.insert.has_uniques;
18205  non_null_attrs = statement->info.insert.non_null_attrs;
18206 
18207  value_clauses = statement->info.insert.value_clauses;
18208  attrs = statement->info.insert.attr_list;
18209 
18210  class_obj = statement->info.insert.spec->info.spec.flat_entity_list->info.name.db_object;
18211 
18212  class_ = locator_create_heap_if_needed (class_obj, sm_is_reuse_oid_class (class_obj));
18213  if (class_ == NULL)
18214  {
18215  return NULL;
18216  }
18217 
18218  hfid = sm_ch_heap (class_);
18219  if (hfid == NULL)
18220  {
18221  return NULL;
18222  }
18223 
18224  if (locator_flush_class (class_obj) != NO_ERROR)
18225  {
18226  return NULL;
18227  }
18228 
18229  error = pt_find_omitted_default_expr (parser, class_obj, attrs, &default_expr_attrs);
18230  if (error != NO_ERROR)
18231  {
18232  return NULL;
18233  }
18234  num_default_expr = pt_length_of_list (default_expr_attrs);
18235 
18236  if (value_clauses->info.node_list.list_type == PT_IS_SUBQUERY)
18237  {
18238  query = value_clauses->info.node_list.list;
18239 
18240  assert (PT_IS_QUERY (query));
18241 
18243  /* also add columns referenced in assignments */
18244  if (PT_IS_SELECT (query) && statement->info.insert.odku_assignments != NULL)
18245  {
18246  PT_NODE *select_list = query->info.query.q.select.list;
18247  PT_NODE *select_from = query->info.query.q.select.from;
18248  PT_NODE *assigns = statement->info.insert.odku_assignments;
18249 
18250  select_list = pt_append_assignment_references (parser, assigns, select_from, select_list);
18251  if (select_list == NULL)
18252  {
18253  PT_INTERNAL_ERROR (parser, "Error appending odku references to select list");
18254  return NULL;
18255  }
18256  }
18257  }
18258  else
18259  {
18260  val_list = value_clauses->info.node_list.list;
18261  num_vals = pt_length_of_list (val_list);
18262  }
18263 
18264  if (value_clauses->info.node_list.list_type == PT_IS_SUBQUERY)
18265  {
18266  xasl = pt_make_aptr_parent_node (parser, value_clauses->info.node_list.list, INSERT_PROC);
18267  }
18268  else
18269  {
18270  /* INSERT VALUES */
18271  int n;
18272  TABLE_INFO *ti;
18273 
18275  if (xasl == NULL)
18276  {
18277  return NULL;
18278  }
18279 
18281 
18282  /* init parser->symbols */
18283  parser->symbols = pt_symbol_info_alloc ();
18284  ti = pt_make_table_info (parser, statement->info.insert.spec);
18285  if (ti == NULL)
18286  {
18287  PT_ERRORm (parser, statement->info.insert.spec, MSGCAT_SET_PARSER_RUNTIME,
18289  return NULL;
18290  }
18291  if (parser->symbols->table_info != NULL)
18292  {
18293  ti->next = parser->symbols->table_info;
18294  }
18295  parser->symbols->table_info = ti;
18296 
18297  value_clauses = parser_walk_tree (parser, value_clauses, parser_generate_xasl_pre, NULL,
18298  parser_generate_xasl_post, &xasl_Supp_info);
18299 
18300  if ((n = xasl_Supp_info.n_oid_list) > 0 && (xasl->class_oid_list = regu_oid_array_alloc (n))
18301  && (xasl->class_locks = regu_int_array_alloc (n)) && (xasl->tcard_list = regu_int_array_alloc (n)))
18302  {
18303  xasl->n_oid_list = n;
18304  (void) memcpy (xasl->class_oid_list, xasl_Supp_info.class_oid_list, sizeof (OID) * n);
18305  (void) memcpy (xasl->class_locks, xasl_Supp_info.class_locks, sizeof (int) * n);
18306  (void) memcpy (xasl->tcard_list, xasl_Supp_info.tcard_list, sizeof (int) * n);
18307  if (xasl_Supp_info.includes_tde_class == 1)
18308  {
18310  }
18311  }
18312 
18314 
18315  insert = &xasl->proc.insert;
18316 
18317  /* generate xasl->val_list */
18318  xasl->val_list = pt_make_val_list (parser, attrs);
18319  if (xasl->val_list == NULL)
18320  {
18321  return NULL;
18322  }
18323 
18324  parser->symbols->current_class = statement->info.insert.spec;
18325  parser->symbols->listfile_value_list = xasl->val_list;
18326  parser->symbols->current_listfile = statement->info.insert.attr_list;
18327  parser->symbols->listfile_attr_offset = 0;
18329 
18330  /* count the number of value lists in values clause */
18331  for (insert->num_val_lists = 0, val_list = value_clauses; val_list != NULL;
18332  insert->num_val_lists++, val_list = val_list->next)
18333  ;
18334 
18335  /* alloc valptr_lists for each list of values */
18336  regu_array_alloc (&insert->valptr_lists, insert->num_val_lists);
18337  if (insert->valptr_lists == NULL)
18338  {
18339  return NULL;
18340  }
18341 
18342  for (i = 0, val_list = value_clauses; val_list != NULL; i++, val_list = val_list->next)
18343  {
18344  assert (i < insert->num_val_lists);
18345 
18346  if (i >= insert->num_val_lists)
18347  {
18348  PT_INTERNAL_ERROR (parser, "Generated insert xasl is corrupted: incorrect number of value lists");
18349  }
18350 
18351  insert->valptr_lists[i] = pt_to_outlist (parser, val_list->info.node_list.list, &xasl->selected_upd_list,
18352  UNBOX_AS_VALUE);
18353  if (insert->valptr_lists[i] == NULL)
18354  {
18355  return NULL;
18356  }
18357  }
18358  }
18359 
18360  if (xasl)
18361  {
18362  if (parser->flag.return_generated_keys)
18363  {
18365  }
18366 
18367  insert = &xasl->proc.insert;
18368  insert->class_hfid = *hfid;
18369 
18370  class_oid = ws_identifier (class_obj);
18371  if (class_oid != NULL)
18372  {
18373  insert->class_oid = *class_oid;
18374  }
18375  else
18376  {
18377  error = ER_HEAP_UNKNOWN_OBJECT;
18378  }
18379 
18380  if (sm_partitioned_class_type (class_obj, &insert->pruning_type, NULL, NULL) != NO_ERROR)
18381  {
18382  PT_ERRORc (parser, statement, er_msg ());
18383  return NULL;
18384  }
18385 
18386  insert->has_uniques = has_uniques;
18388 
18389  hint_arg = statement->info.insert.waitsecs_hint;
18390  if (statement->info.insert.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
18391  {
18392  hint_wait_secs = (float) atof (hint_arg->info.name.original);
18393  if (hint_wait_secs > 0)
18394  {
18395  insert->wait_msecs = (int) (hint_wait_secs * 1000);
18396  }
18397  else
18398  {
18399  insert->wait_msecs = (int) hint_wait_secs;
18400  }
18401  }
18402 
18403  insert->no_logging = (statement->info.insert.hint & PT_HINT_NO_LOGGING);
18404  insert->do_replace = (statement->info.insert.do_replace ? 1 : 0);
18405 
18406  if (error >= NO_ERROR && (num_vals + num_default_expr > 0))
18407  {
18408  insert->att_id = regu_int_array_alloc (num_vals + num_default_expr);
18409  if (insert->att_id)
18410  {
18411  /* the identifiers of the attributes that have a default expression are placed first */
18412  int save_au;
18413 
18414  AU_DISABLE (save_au);
18415 
18416  for (attr = default_expr_attrs, a = 0; error >= NO_ERROR && a < num_default_expr; attr = attr->next, ++a)
18417  {
18418  insert->att_id[a] = sm_att_id (class_obj, attr->info.name.original);
18419  if (insert->att_id[a] < 0)
18420  {
18421  ASSERT_ERROR_AND_SET (error);
18422  }
18423  }
18424 
18425  for (attr = attrs, a = num_default_expr; error >= NO_ERROR && a < num_default_expr + num_vals;
18426  attr = attr->next, ++a)
18427  {
18428  insert->att_id[a] = sm_att_id (class_obj, attr->info.name.original);
18429  if (insert->att_id[a] < 0)
18430  {
18431  ASSERT_ERROR_AND_SET (error);
18432  }
18433  }
18434 
18435  AU_ENABLE (save_au);
18436 
18437  insert->vals = NULL;
18438  insert->num_vals = num_vals + num_default_expr;
18439  insert->num_default_expr = num_default_expr;
18440  }
18441  else
18442  {
18443  ASSERT_ERROR_AND_SET (error);
18444  }
18445  }
18446  }
18447  else
18448  {
18449  ASSERT_ERROR_AND_SET (error);
18450  }
18451 
18452  if (xasl != NULL && error >= NO_ERROR)
18453  {
18454  error = pt_to_constraint_pred (parser, xasl, statement->info.insert.spec, non_null_attrs, attrs, 0);
18455  }
18456 
18457  if (pt_has_error (parser))
18458  {
18459  pt_report_to_ersys (parser, PT_SEMANTIC);
18460  xasl = NULL;
18461  }
18462 
18463  /* fill in XASL cache related information */
18464  if (xasl)
18465  {
18466  OID *oid;
18467 
18468  /* OID of the user who is creating this XASL */
18469  oid = ws_identifier (db_get_user ());
18470  if (oid != NULL)
18471  {
18472  COPY_OID (&xasl->creator_oid, oid);
18473  }
18474  else
18475  {
18476  OID_SET_NULL (&xasl->creator_oid);
18477  }
18478 
18479  /* list of class OIDs used in this XASL */
18480  if (xasl->aptr_list != NULL)
18481  {
18482  XASL_NODE *aptr = xasl->aptr_list;
18483 
18484  /*
18485  * in case of 'insert into foo select a from b'
18486  * so there is no serial oid list from values list
18487  */
18488  assert (xasl->n_oid_list == 0);
18489 
18490  /* reserve spec oid space by 1+ */
18491  xasl->class_oid_list = regu_oid_array_alloc (1 + aptr->n_oid_list);
18492  xasl->class_locks = regu_int_array_alloc (1 + aptr->n_oid_list);
18493  xasl->tcard_list = regu_int_array_alloc (1 + aptr->n_oid_list);
18494  if (xasl->class_oid_list == NULL || xasl->class_locks == NULL || xasl->tcard_list == NULL)
18495  {
18496  return NULL;
18497  }
18498 
18499  xasl->n_oid_list = 1 + aptr->n_oid_list;
18500 
18501  /* copy aptr oids to xasl */
18502  (void) memcpy (xasl->class_oid_list + 1, aptr->class_oid_list, sizeof (OID) * aptr->n_oid_list);
18503  (void) memcpy (xasl->class_locks + 1, aptr->class_locks, sizeof (int) * aptr->n_oid_list);
18504  (void) memcpy (xasl->tcard_list + 1, aptr->tcard_list, sizeof (int) * aptr->n_oid_list);
18505  XASL_SET_FLAG (xasl, aptr->flag & XASL_INCLUDES_TDE_CLASS);
18506 
18507  /* set spec oid */
18508  xasl->class_oid_list[0] = insert->class_oid;
18509  xasl->class_locks[0] = (int) IX_LOCK;
18510  xasl->tcard_list[0] = XASL_CLASS_NO_TCARD; /* init #pages */
18511 
18512  xasl->dbval_cnt = aptr->dbval_cnt;
18513  }
18514  else
18515  {
18516  /* reserve spec oid space by 1+ */
18517  OID *o_list = regu_oid_array_alloc (1 + xasl->n_oid_list);
18518  int *lck_list = regu_int_array_alloc (1 + xasl->n_oid_list);
18519  int *t_list = regu_int_array_alloc (1 + xasl->n_oid_list);
18520 
18521  if (o_list == NULL || lck_list == NULL || t_list == NULL)
18522  {
18523  return NULL;
18524  }
18525 
18526  /* copy previous serial oids to new space */
18527  (void) memcpy (o_list + 1, xasl->class_oid_list, sizeof (OID) * xasl->n_oid_list);
18528  (void) memcpy (lck_list + 1, xasl->class_locks, sizeof (int) * xasl->n_oid_list);
18529  (void) memcpy (t_list + 1, xasl->tcard_list, sizeof (int) * xasl->n_oid_list);
18530 
18531  xasl->class_oid_list = o_list;
18532  xasl->class_locks = lck_list;
18533  xasl->tcard_list = t_list;
18534 
18535  /* set spec oid */
18536  xasl->n_oid_list += 1;
18537  xasl->class_oid_list[0] = insert->class_oid;
18538  xasl->class_locks[0] = (int) IX_LOCK;
18539  xasl->tcard_list[0] = XASL_CLASS_NO_TCARD; /* init #pages */
18540  }
18541 
18542  assert (locator_is_class (class_obj, DB_FETCH_QUERY_READ) > 0);
18543  (void) au_fetch_class (class_obj, &smclass, AU_FETCH_READ, AU_SELECT);
18544 
18545  if (smclass)
18546  {
18547  if (smclass->tde_algorithm != TDE_ALGORITHM_NONE)
18548  {
18550  }
18551  }
18552  }
18553 
18554  if (xasl && statement->info.insert.odku_assignments)
18555  {
18556  xasl->proc.insert.odku = pt_to_odku_info (parser, statement, xasl);
18557  if (xasl->proc.insert.odku == NULL)
18558  {
18559  if (pt_has_error (parser))
18560  {
18561  pt_report_to_ersys (parser, PT_SEMANTIC);
18562  }
18563  return NULL;
18564  }
18565  }
18566 
18567  if (xasl)
18568  {
18569  xasl->query_alias = statement->alias_print;
18570  }
18571 
18572  return xasl;
18573 }
18574 
18575 /*
18576  * pt_append_assignment_references () - append names referenced in right side of ON DUPLICATE KEY UPDATE to
18577  * SELECT list of an INSERT...SELECT statement
18578  * return : updated node or NULL
18579  * parser (in) : parser context
18580  * assignments (in) : assignments
18581  * from (in) : SELECT spec list
18582  * select_list (in/out) : SELECT list
18583  */
18584 static PT_NODE *
18586 {
18587  PT_NODE *spec;
18589  PT_NODE *ref_nodes;
18590  PT_NODE *save_next;
18591  PT_NODE *save_ref = NULL;
18592 
18593  if (assignments == NULL)
18594  {
18595  return select_list;
18596  }
18597 
18598  parser->symbols = pt_symbol_info_alloc ();
18599  if (parser->symbols == NULL)
18600  {
18602  return NULL;
18603  }
18604 
18605  for (spec = from; spec != NULL; spec = spec->next)
18606  {
18607  save_ref = spec->info.spec.referenced_attrs;
18608  spec->info.spec.referenced_attrs = NULL;
18609  table_info = pt_make_table_info (parser, spec);
18610  if (table_info == NULL)
18611  {
18612  spec->info.spec.referenced_attrs = save_ref;
18613  return NULL;
18614  }
18615 
18616  parser->symbols->table_info = table_info;
18617 
18618  /* make sure we only get references from assignments, not from the spec also: call mq_get_references_helper with
18619  * false for the last argument */
18620  ref_nodes = mq_get_references_helper (parser, assignments, spec, false);
18621 
18622  if (pt_has_error (parser))
18623  {
18624  spec->info.spec.referenced_attrs = save_ref;
18625  return NULL;
18626  }
18627 
18628  while (ref_nodes != NULL)
18629  {
18630  save_next = ref_nodes->next;
18631  ref_nodes->next = NULL;
18632  if (pt_find_name (parser, ref_nodes, select_list) == NULL)
18633  {
18634  parser_append_node (ref_nodes, select_list);
18635  }
18636  ref_nodes = save_next;
18637  }
18638  spec->info.spec.referenced_attrs = save_ref;
18639  }
18640 
18641  parser->symbols = NULL;
18642  return select_list;
18643 }
18644 
18645 /*
18646  * pt_to_odku_info () - build a ODKU_INFO for an INSERT ... ON DUPLICATE KEY UPDATE statement
18647  * return : ODKU info or NULL
18648  * parser (in) : parser context
18649  * insert (in) : insert statement
18650  * xasl (in) : INSERT XASL node
18651  */
18652 static ODKU_INFO *
18654 {
18655  PT_NODE *insert_spec = NULL;
18656  PT_NODE *select_specs = NULL;
18657  PT_NODE *select_list = NULL;
18658  PT_NODE *assignments = NULL;
18659  PT_NODE *prev = NULL, *node = NULL, *next = NULL, *tmp = NULL;
18660  PT_NODE *spec = NULL, *constraint = NULL, *save = NULL, *pt_pred = NULL;
18661  int insert_subquery;
18662  PT_ASSIGNMENTS_HELPER assignments_helper;
18663  DB_OBJECT *cls_obj = NULL;
18664  int i = 0, error = NO_ERROR;
18665  ODKU_INFO *odku = NULL;
18666  DB_VALUE *val = NULL;
18667  TABLE_INFO *ti = NULL;
18668  DB_ATTRIBUTE *attr = NULL;
18669  TP_DOMAIN *domain = NULL;
18670 
18671  assert (insert->node_type == PT_INSERT);
18672  assert (insert->info.insert.odku_assignments != NULL);
18673 
18674  parser->symbols = pt_symbol_info_alloc ();
18675  if (parser->symbols == NULL)
18676  {
18679  goto exit_on_error;
18680  }
18681 
18682  regu_alloc (odku);
18683  if (odku == NULL)
18684  {
18685  goto exit_on_error;
18686  }
18687 
18688  insert_spec = insert->info.insert.spec;
18689 
18690  insert_subquery = PT_IS_SELECT (insert->info.insert.value_clauses->info.node_list.list);
18691 
18692  if (insert_subquery)
18693  {
18694  select_specs = insert->info.insert.value_clauses->info.node_list.list->info.query.q.select.from;
18695  select_list = insert->info.insert.value_clauses->info.node_list.list->info.query.q.select.list;
18696  }
18697  else
18698  {
18699  select_list = NULL;
18700  select_specs = NULL;
18701  }
18702 
18703  assignments = insert->info.insert.odku_assignments;
18704  error = pt_append_omitted_on_update_expr_assignments (parser, assignments, insert_spec);
18705  if (error != NO_ERROR)
18706  {
18707  PT_INTERNAL_ERROR (parser, "odku on update insert error");
18708  goto exit_on_error;
18709  }
18710 
18711  /* init update attribute ids */
18712  odku->num_assigns = 0;
18713  pt_init_assignments_helper (parser, &assignments_helper, assignments);
18714  while (pt_get_next_assignment (&assignments_helper) != NULL)
18715  {
18716  odku->num_assigns++;
18717  }
18718 
18719  odku->attr_ids = regu_int_array_alloc (odku->num_assigns);
18720  if (odku->attr_ids == NULL)
18721  {
18722  goto exit_on_error;
18723  }
18724 
18725  regu_array_alloc (&odku->assignments, odku->num_assigns);
18726  if (odku->assignments == NULL)
18727  {
18728  goto exit_on_error;
18729  }
18730 
18731  regu_alloc (odku->attr_info);
18732  if (odku->attr_info == NULL)
18733  {
18734  goto exit_on_error;
18735  }
18736 
18737  /* build table info */
18738  ti = pt_make_table_info (parser, insert_spec);
18739  if (ti == NULL)
18740  {
18743  goto exit_on_error;
18744  }
18745 
18746  ti->next = parser->symbols->table_info;
18747  parser->symbols->table_info = ti;
18748 
18749  for (spec = select_specs; spec != NULL; spec = spec->next)
18750  {
18751  ti = pt_make_table_info (parser, spec);
18752  if (ti == NULL)
18753  {
18756  goto exit_on_error;
18757  }
18758 
18759  ti->next = parser->symbols->table_info;
18760  parser->symbols->table_info = ti;
18761  }
18762 
18763  /* init symbols */
18764  parser->symbols->current_class = insert_spec->info.spec.entity_name;
18765  parser->symbols->cache_attrinfo = odku->attr_info;
18766  parser->symbols->current_listfile = select_list;
18767  parser->symbols->listfile_value_list = xasl->val_list;
18768  parser->symbols->listfile_attr_offset = 0;
18769 
18770  cls_obj = insert_spec->info.spec.entity_name->info.name.db_object;
18771 
18772  pt_init_assignments_helper (parser, &assignments_helper, assignments);
18773  i = 0;
18774  while (pt_get_next_assignment (&assignments_helper))
18775  {
18776  attr = db_get_attribute (cls_obj, assignments_helper.lhs->info.name.original);
18777  if (attr == NULL)
18778  {
18780  goto exit_on_error;
18781  }
18782 
18783  odku->attr_ids[i] = attr->id;
18784  odku->assignments[i].att_idx = i;
18785  odku->assignments[i].cls_idx = -1;
18786  if (assignments_helper.is_rhs_const)
18787  {
18788  val = pt_value_to_db (parser, assignments_helper.rhs);
18789  if (val == NULL)
18790  {
18793  goto exit_on_error;
18794  }
18795 
18796  prev = NULL;
18797  for (node = insert->info.insert.odku_non_null_attrs; node != NULL; node = next)
18798  {
18799  /* Check to see if this is a NON NULL attr */
18800  next = node->next;
18801 
18802  if (!pt_name_equal (parser, node, assignments_helper.lhs))
18803  {
18804  prev = node;
18805  continue;
18806  }
18807  /* Found attribute in non null list. */
18808 
18809  if (DB_IS_NULL (val))
18810  {
18811  /* assignment of a NULL value to a non null attribute */
18813  assignments_helper.lhs->info.name.original);
18815  goto exit_on_error;
18816  }
18817  /* Break loop since we already found attribute. */
18818  break;
18819  }
18820 
18821  regu_alloc (odku->assignments[i].constant);
18822  if (odku->assignments[i].constant == NULL)
18823  {
18825  goto exit_on_error;
18826  }
18827 
18828  domain = db_attribute_domain (attr);
18829  error = tp_value_cast (val, odku->assignments[i].constant, domain, false);
18830  if (error != DOMAIN_COMPATIBLE)
18831  {
18834  goto exit_on_error;
18835  }
18836  }
18837  else
18838  {
18839  if (pt_is_query (assignments_helper.rhs))
18840  {
18841  XASL_NODE *rhs_xasl = NULL;
18842 
18843  rhs_xasl = parser_generate_xasl (parser, assignments_helper.rhs);
18844  if (rhs_xasl == NULL)
18845  {
18847  goto exit_on_error;
18848  }
18849  }
18850 
18851  odku->assignments[i].regu_var = pt_to_regu_variable (parser, assignments_helper.rhs, UNBOX_AS_VALUE);
18852  if (odku->assignments[i].regu_var == NULL)
18853  {
18854  goto exit_on_error;
18855  }
18856  }
18857 
18858  i++;
18859  }
18860 
18861  if (insert->info.insert.odku_non_null_attrs)
18862  {
18863  /* build constraint pred */
18864  pt_init_assignments_helper (parser, &assignments_helper, assignments);
18865 
18866  node = insert->info.insert.odku_non_null_attrs;
18867  while (node)
18868  {
18869  save = node->next;
18870  CAST_POINTER_TO_NODE (node);
18871  do
18872  {
18873  pt_get_next_assignment (&assignments_helper);
18874  }
18875  while (assignments_helper.lhs != NULL && !pt_name_equal (parser, assignments_helper.lhs, node));
18876 
18877  if (assignments_helper.lhs == NULL)
18878  {
18879  /* I don't think this should happen */
18880  assert (false);
18881  break;
18882  }
18883 
18884  constraint = parser_new_node (parser, PT_EXPR);
18885  if (constraint == NULL)
18886  {
18889  goto exit_on_error;
18890  }
18891 
18892  tmp = parser_copy_tree (parser, node);
18893  if (tmp == NULL)
18894  {
18895  parser_free_tree (parser, constraint);
18898  goto exit_on_error;
18899  }
18900 
18901  constraint->next = pt_pred;
18902  constraint->line_number = node->line_number;
18903  constraint->column_number = node->column_number;
18904  constraint->info.expr.op = PT_IS_NOT_NULL;
18905  constraint->info.expr.arg1 = tmp;
18906  pt_pred = constraint;
18907 
18908  node = save;
18909  }
18910 
18911  odku->cons_pred = pt_to_pred_expr (parser, pt_pred);
18912  if (odku->cons_pred == NULL)
18913  {
18914  goto exit_on_error;
18915  }
18916  }
18917 
18918  if (pt_pred != NULL)
18919  {
18920  parser_free_tree (parser, pt_pred);
18921  }
18922 
18923  return odku;
18924 
18925 exit_on_error:
18926  if (er_errid () == NO_ERROR && !pt_has_error (parser))
18927  {
18928  PT_INTERNAL_ERROR (parser, "ODKU Info generation failed");
18929  error = ER_FAILED;
18930  }
18931  if (pt_pred != NULL)
18932  {
18933  parser_free_tree (parser, pt_pred);
18934  }
18935  return NULL;
18936 }
18937 
18938 /*
18939  * pt_init_pred_expr_context () -
18940  * return: error code
18941  * parser(in): context
18942  * predicate(in) : predicate parse tree
18943  * spec(in): entity spec
18944  * pred_expr(out): PRED_EXPR_WITH_CONTEXT
18945  */
18946 static int
18948  PRED_EXPR_WITH_CONTEXT * pred_expr)
18949 {
18950  PRED_EXPR *pred = NULL;
18951  PT_NODE *node_list = NULL;
18952  int cnt_attrs = 0;
18953  ATTR_ID *attrids_pred = NULL;
18954  REGU_VARIABLE_LIST regu_attributes_pred = NULL;
18955  SYMBOL_INFO *symbols = NULL;
18957  int attr_num = 0;
18958 
18959  assert (pred_expr != NULL && spec != NULL && parser != NULL);
18960 
18961  parser->symbols = pt_symbol_info_alloc ();
18962  if (parser->symbols == NULL)
18963  {
18964  goto outofmem;
18965  }
18966 
18967  symbols = parser->symbols;
18968 
18969  symbols->table_info = pt_make_table_info (parser, spec);
18970  if (symbols->table_info == NULL)
18971  {
18972  goto outofmem;
18973  }
18974 
18975  table_info = symbols->table_info;
18976  /* should be only one node in flat_entity_list */
18977  symbols->current_class = spec->info.spec.flat_entity_list;
18978  regu_alloc (symbols->cache_attrinfo);
18979  if (symbols->cache_attrinfo == NULL)
18980  {
18981  goto outofmem;
18982  }
18983 
18984  table_info->class_spec = spec;
18985  table_info->exposed = spec->info.spec.range_var->info.name.original;
18986  table_info->spec_id = spec->info.spec.id;
18987  /* don't care about attribute_list and value_list */
18988  table_info->attribute_list = NULL;
18989  table_info->value_list = NULL;
18990 
18991  (void) pt_get_pred_attrs (parser, symbols->table_info, predicate, &node_list);
18992 
18993  regu_attributes_pred = pt_to_regu_variable_list (parser, node_list, UNBOX_AS_VALUE, NULL, NULL);
18994  cnt_attrs = pt_cnt_attrs (regu_attributes_pred);
18995  attrids_pred = regu_int_array_alloc (cnt_attrs);
18996  attr_num = 0;
18997  pt_fill_in_attrid_array (regu_attributes_pred, attrids_pred, &attr_num);
18998 
18999  pred = pt_to_pred_expr (parser, predicate);
19000 
19001  pred_expr->pred = pred;
19002  pred_expr->attrids_pred = attrids_pred;
19003  pred_expr->num_attrs_pred = cnt_attrs;
19004  pred_expr->cache_pred = symbols->cache_attrinfo;
19005 
19006  if (node_list)
19007  {
19008  parser_free_tree (parser, node_list);
19009  }
19010 
19011  /* symbols are allocated with pt_alloc_packing_buf, and freed at end of xasl generation. */
19012  parser->symbols = NULL;
19013  return NO_ERROR;
19014 
19015 outofmem:
19016 
19017  if (node_list)
19018  {
19019  parser_free_tree (parser, node_list);
19020  }
19021 
19023 
19025 }
19026 
19027 /*
19028  * pt_to_pred_with_context () - Create a PRED_EXPR_WITH_CONTEXT from filter
19029  * predicate parse tree
19030  * return: PRED_EXPR_WITH_CONTEXT *
19031  * parser(in):
19032  * predicate(in): predicate parse tree
19033  * spec(in): entity spec
19034  */
19037 {
19038  DB_OBJECT *class_obj = NULL;
19039  MOBJ class_ = NULL;
19040  HFID *hfid = NULL;
19041  PRED_EXPR_WITH_CONTEXT *pred_expr = NULL;
19042 
19043  if (parser == NULL || predicate == NULL || spec == NULL)
19044  {
19045  return NULL;
19046  }
19047 
19048  /* flush the class, just to be sure */
19049  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
19050  class_ = locator_create_heap_if_needed (class_obj, sm_is_reuse_oid_class (class_obj));
19051  if (class_ == NULL)
19052  {
19053  return NULL;
19054  }
19055 
19056  hfid = sm_ch_heap (class_);
19057  if (hfid == NULL)
19058  {
19059  return NULL;
19060  }
19061 
19062  regu_alloc (pred_expr);
19063  if (pred_expr)
19064  {
19065  (void) pt_init_pred_expr_context (parser, predicate, spec, pred_expr);
19066  }
19067 
19068  if (pt_has_error (parser))
19069  {
19070  pt_report_to_ersys (parser, PT_SEMANTIC);
19071  pred_expr = NULL;
19072  }
19073 
19074  return pred_expr;
19075 }
19076 
19077 /*
19078  * pt_copy_upddel_hints_to_select () - copy hints from delete/update statement
19079  * to select statement.
19080  * return: NO_ERROR or error code.
19081  * parser(in):
19082  * node(in): delete/update statement that provides the hints to be
19083  * copied to the select statement.
19084  * select_stmt(in): select statement that will receive hints.
19085  *
19086  * Note :
19087  * The hints that are copied from delete/update statement to SELECT statement
19088  * are: ORDERED, USE_DESC_IDX, NO_COVERING_INDEX, NO_DESC_IDX, USE_NL, USE_IDX,
19089  * USE_MERGE, NO_MULTI_RANGE_OPT, RECOMPILE.
19090  */
19091 int
19093 {
19094  int err = NO_ERROR;
19095  int hint_flags =
19098  PT_NODE *arg = NULL;
19099 
19100  switch (node->node_type)
19101  {
19102  case PT_DELETE:
19103  hint_flags &= node->info.delete_.hint;
19104  break;
19105  case PT_UPDATE:
19106  hint_flags &= node->info.update.hint;
19107  break;
19108  default:
19109  return NO_ERROR;
19110  }
19111 
19113 
19114  select_stmt->info.query.q.select.hint = (PT_HINT_ENUM) (select_stmt->info.query.q.select.hint | hint_flags);
19115  select_stmt->flag.recompile = node->flag.recompile;
19116 
19117  if (hint_flags & PT_HINT_ORDERED)
19118  {
19119  switch (node->node_type)
19120  {
19121  case PT_DELETE:
19122  arg = node->info.delete_.ordered_hint;
19123  break;
19124  case PT_UPDATE:
19125  arg = node->info.update.ordered_hint;
19126  break;
19127  default:
19128  break;
19129  }
19130  if (arg != NULL)
19131  {
19132  arg = parser_copy_tree_list (parser, arg);
19133  if (arg == NULL)
19134  {
19135  goto exit_on_error;
19136  }
19137  }
19138  select_stmt->info.query.q.select.ordered = arg;
19139  }
19140 
19141  if (hint_flags & PT_HINT_USE_NL)
19142  {
19143  switch (node->node_type)
19144  {
19145  case PT_DELETE:
19146  arg = node->info.delete_.use_nl_hint;
19147  break;
19148  case PT_UPDATE:
19149  arg = node->info.update.use_nl_hint;
19150  break;
19151  default:
19152  break;
19153  }
19154  if (arg != NULL)
19155  {
19156  arg = parser_copy_tree_list (parser, arg);
19157  if (arg == NULL)
19158  {
19159  goto exit_on_error;
19160  }
19161  }
19162  select_stmt->info.query.q.select.use_nl = arg;
19163  }
19164 
19165  if (hint_flags & PT_HINT_USE_IDX)
19166  {
19167  switch (node->node_type)
19168  {
19169  case PT_DELETE:
19170  arg = node->info.delete_.use_idx_hint;
19171  break;
19172  case PT_UPDATE:
19173  arg = node->info.update.use_idx_hint;
19174  break;
19175  default:
19176  break;
19177  }
19178  if (arg != NULL)
19179  {
19180  arg = parser_copy_tree_list (parser, arg);
19181  if (arg == NULL)
19182  {
19183  goto exit_on_error;
19184  }
19185  }
19186  select_stmt->info.query.q.select.use_idx = arg;
19187  }
19188 
19189  if (hint_flags & PT_HINT_USE_MERGE)
19190  {
19191  switch (node->node_type)
19192  {
19193  case PT_DELETE:
19194  arg = node->info.delete_.use_merge_hint;
19195  break;
19196  case PT_UPDATE:
19197  arg = node->info.update.use_merge_hint;
19198  break;
19199  default:
19200  break;
19201  }
19202  if (arg != NULL)
19203  {
19204  arg = parser_copy_tree_list (parser, arg);
19205  if (arg == NULL)
19206  {
19207  goto exit_on_error;
19208  }
19209  }
19210  select_stmt->info.query.q.select.use_merge = arg;
19211  }
19212 
19213  return NO_ERROR;
19214 
19215 exit_on_error:
19216  if (pt_has_error (parser))
19217  {
19218  assert (er_errid () != NO_ERROR);
19219  err = er_errid ();
19220  }
19221  else
19222  {
19223  err = ER_GENERIC_ERROR;
19225  }
19226 
19227  return err;
19228 }
19229 
19230 /*
19231  * pt_mvcc_flag_specs_cond_reev () - flag specs that are involved in condition
19232  * return: NO_ERROR or error code.
19233  * parser(in):
19234  * spec_list(in): List of specs that can be referenced in condition
19235  * cond(in): condition expression in which specs from spec_list can be
19236  * referenced
19237  *
19238  * Note :
19239  * The specs flagged in this function are used in MVCC condition reevaluation
19240  */
19241 static int
19243 {
19244  PT_NODE *node = NULL, *spec = NULL;
19245  PT_NODE *real_refs = NULL;
19246 
19247  if (spec_list == NULL || cond == NULL)
19248  {
19249  return NO_ERROR;
19250  }
19251 
19252  for (spec = spec_list; spec != NULL; spec = spec->next)
19253  {
19254  real_refs = spec->info.spec.referenced_attrs;
19255  spec->info.spec.referenced_attrs = NULL;
19256  node = mq_get_references (parser, cond, spec);
19257  if (node == NULL)
19258  {
19259  spec->info.spec.referenced_attrs = real_refs;
19260  continue;
19261  }
19262  spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_MVCC_COND_REEV);
19263 
19264  spec->info.spec.referenced_attrs = real_refs;
19265  parser_free_tree (parser, node);
19266  }
19267 
19268  return NO_ERROR;
19269 }
19270 
19271 /*
19272  * pt_mvcc_flag_specs_assign_reev () - flag specs that are involved in
19273  * assignments
19274  * return: NO_ERROR or error code.
19275  * parser(in):
19276  * spec_list(in): List of specs that can be involved in assignments
19277  * cond(in): condition expression in which specs from spec_list can be
19278  * referenced
19279  *
19280  * Note :
19281  * The specs flagged in this function are used in MVCC assignments reevaluation
19282  */
19283 static int
19285 {
19286  PT_NODE *node = NULL, *spec = NULL;
19287  PT_NODE *real_refs = NULL;
19289 
19290  if (spec_list == NULL || assign_list == NULL)
19291  {
19292  return NO_ERROR;
19293  }
19294 
19295  for (spec = spec_list; spec != NULL; spec = spec->next)
19296  {
19297  pt_init_assignments_helper (parser, &ah, assign_list);
19298 
19299  while (pt_get_next_assignment (&ah) != NULL)
19300  {
19301  real_refs = spec->info.spec.referenced_attrs;
19302  spec->info.spec.referenced_attrs = NULL;
19303  node = mq_get_references (parser, ah.rhs, spec);
19304  if (node != NULL)
19305  {
19306  spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_MVCC_ASSIGN_REEV);
19307  spec->info.spec.referenced_attrs = real_refs;
19308  parser_free_tree (parser, node);
19309  break;
19310  }
19311  spec->info.spec.referenced_attrs = real_refs;
19312  }
19313  }
19314 
19315  return NO_ERROR;
19316 }
19317 
19318 /*
19319  * pt_mvcc_set_spec_assign_reev_extra_indexes () - returns indexes of specs that
19320  * appear on the right side of
19321  * assignments (and not in
19322  * condition) and have a given
19323  * spec (spec_assign) on the left
19324  * side of assignments.
19325  * return: count of indexes.
19326  * parser(in):
19327  * spec_assign(in): spec that must be on the left side of assignments
19328  * spec_list(in): List of specs (FROM clause of UPDATE statement)
19329  * assign_list(in): assignments
19330  * indexes(in/out): a preallocated array to store indexes
19331  * indexes_alloc_size(in): the allocated size of indexes array. Used for
19332  * overflow checking.
19333  *
19334  * Note :
19335  * The indexes refers the positions of specs in the spec_list
19336  */
19337 static int
19339  PT_NODE * assign_list, int *indexes, int indexes_alloc_size)
19340 {
19341  PT_NODE *nodes_list = NULL, *spec = NULL;
19342  PT_NODE *real_refs = NULL;
19344  int idx, count = 0;
19345 
19346  if (spec_list == NULL || assign_list == NULL)
19347  {
19348  return 0;
19349  }
19350 
19351  for (spec = spec_list, idx = 0; spec != NULL; spec = spec->next, idx++)
19352  {
19353  if ((spec->info.spec.flag & (PT_SPEC_FLAG_MVCC_COND_REEV | PT_SPEC_FLAG_MVCC_ASSIGN_REEV)) !=
19355  {
19356  /* Skip specs that are not only on the right side of assignments */
19357  continue;
19358  }
19359 
19360  pt_init_assignments_helper (parser, &ah, assign_list);
19361  while (pt_get_next_assignment (&ah) != NULL)
19362  {
19363  if (ah.lhs->info.name.spec_id == spec_assign->info.spec.id)
19364  {
19365  /* we found our spec on the left side of assignment */
19366  real_refs = spec->info.spec.referenced_attrs;
19367  spec->info.spec.referenced_attrs = NULL;
19368 
19369  /* check whether the spec is referenced in the right side of assignment. */
19370  nodes_list = mq_get_references (parser, ah.rhs, spec);
19371  if (nodes_list != NULL)
19372  {
19373  spec->info.spec.referenced_attrs = real_refs;
19374  parser_free_tree (parser, nodes_list);
19375 
19376  assert (count < indexes_alloc_size);
19377  indexes[count++] = idx;
19378  break;
19379  }
19380  spec->info.spec.referenced_attrs = real_refs;
19381  }
19382  }
19383  }
19384 
19385  return count;
19386 }
19387 
19388 /*
19389  * pt_mvcc_prepare_upd_del_select () - prepare generated SELECT for MVCC
19390  * reevaluation
19391  * return: New statement or NULL on error.
19392  * parser(in):
19393  * select_stmt(in): The generated SELECT statement for UPDATE/DELETE that will
19394  * be prepared.
19395  *
19396  * Note :
19397  * The SELECT list must already contain the OID - CLASS OID pairs for classes
19398  * that will be updated.
19399  * The function adds OID - CLASS OID pairs into the SELECT statement's list for
19400  * classes that are referenced in conditions or asignments and aren't already
19401  * flagged for UPDATE/DELETE. These OIDs will be used at reevaluation stage to
19402  * load all values needed for conditions and assignments reevaluation.
19403  */
19404 static PT_NODE *
19406 {
19407  PT_NODE *node = NULL, *prev = NULL, *spec = NULL, *save_next = NULL;
19408  PT_NODE *from = NULL, *list = NULL;
19409  int idx = 0, upd_del_class_cnt = 0;
19410 
19411  if (select_stmt == NULL || select_stmt->node_type != PT_SELECT || select_stmt->info.query.upd_del_class_cnt == 0)
19412  {
19413  return select_stmt;
19414  }
19415 
19416  /* Find the insertion point in the SELECT list */
19417  upd_del_class_cnt = select_stmt->info.query.upd_del_class_cnt;
19418  assert (upd_del_class_cnt > 0);
19419 
19420  node = select_stmt->info.query.q.select.list;
19421  idx = 0;
19422  while (idx < upd_del_class_cnt && node != NULL)
19423  {
19424  node = node->next;
19425  if (node != NULL)
19426  {
19427  prev = node;
19428  node = node->next;
19429  idx++;
19430  }
19431  }
19432 
19433  if (idx < upd_del_class_cnt)
19434  {
19435  PT_INTERNAL_ERROR (parser, "Invalid SELECT list");
19436  return NULL;
19437  }
19438 
19439  from = select_stmt->info.query.q.select.from;
19440  list = select_stmt->info.query.q.select.list;
19441 
19442  /* Add pairs OID - CLASS OID to the SELECT list that are referenced in assignments and are not referenced in
19443  * condition */
19444  for (spec = from; spec != NULL; spec = spec->next)
19445  {
19446  /* Skip classes flagged for UPDATE/DELETE because they are already in SELECT list */
19447  if ((spec->info.spec.flag
19450  {
19451  save_next = spec->next;
19452  spec->next = NULL;
19453 
19454  select_stmt->info.query.q.select.from = spec;
19455  select_stmt->info.query.q.select.list = NULL;
19456 
19457  select_stmt = pt_add_row_classoid_name (parser, select_stmt, 1);
19458  assert (select_stmt != NULL);
19459 
19460  select_stmt = pt_add_row_oid_name (parser, select_stmt);
19461  assert (select_stmt != NULL);
19462 
19463  spec->next = save_next;
19464  select_stmt->info.query.q.select.list->next->next = prev->next;
19465  prev->next = select_stmt->info.query.q.select.list;
19466  prev = prev->next->next;
19467 
19468  select_stmt->info.query.mvcc_reev_extra_cls_cnt++;
19469  }
19470  }
19471 
19472  /* Add pairs OID - CLASS OID to the SELECT list that are referenced in condition */
19473  for (spec = from; spec != NULL; spec = spec->next)
19474  {
19475  /* Skip classes flagged for UPDATE/DELETE because they are already in SELECT list */
19476  if ((spec->info.spec.flag & (PT_SPEC_FLAG_UPDATE | PT_SPEC_FLAG_DELETE | PT_SPEC_FLAG_MVCC_COND_REEV)) ==
19478  {
19479  save_next = spec->next;
19480  spec->next = NULL;
19481 
19482  select_stmt->info.query.q.select.from = spec;
19483  select_stmt->info.query.q.select.list = NULL;
19484 
19485  select_stmt = pt_add_row_classoid_name (parser, select_stmt, 1);
19486  assert (select_stmt != NULL);
19487 
19488  select_stmt = pt_add_row_oid_name (parser, select_stmt);
19489  assert (select_stmt != NULL);
19490 
19491  spec->next = save_next;
19492  select_stmt->info.query.q.select.list->next->next = prev->next;
19493  prev->next = select_stmt->info.query.q.select.list;
19494  prev = prev->next->next;
19495 
19496  select_stmt->info.query.mvcc_reev_extra_cls_cnt++;
19497  }
19498  }
19499 
19500  select_stmt->info.query.q.select.from = from;
19501  select_stmt->info.query.q.select.list = list;
19502 
19503  return select_stmt;
19504 }
19505 
19506 /*
19507  * pt_mark_spec_list_for_update_clause -- mark the spec which need be
19508  * updated/deleted with PT_SPEC_FLAG_FOR_UPDATE_CLAUSE flag
19509  * return:
19510  * parser(in): context
19511  * statement(in): select parse tree
19512  * spec_flag(in): spec flag: PT_SPEC_FLAG_UPDATE or PT_SPEC_FLAG_DELETE
19513  */
19514 
19515 void
19517 {
19518  PT_NODE *spec;
19519 
19520  assert (statement->node_type == PT_SELECT);
19521 
19522  for (spec = statement->info.query.q.select.from; spec; spec = spec->next)
19523  {
19524  if (spec->info.spec.flag & spec_flag)
19525  {
19527  }
19528 
19529  if (spec->info.spec.derived_table != NULL && spec->info.spec.derived_table->node_type == PT_SELECT)
19530  {
19531  pt_mark_spec_list_for_update_clause (parser, spec->info.spec.derived_table, spec_flag);
19532  }
19533  }
19534 }
19535 
19536 /*
19537  * pt_to_upd_del_query () - Creates a query based on the given select list,
19538  * from list, and where clause
19539  * return: PT_NODE *, query statement or NULL if error
19540  * parser(in):
19541  * select_list(in):
19542  * from(in):
19543  * with(in):
19544  * class_specs(in):
19545  * where(in):
19546  * using_index(in):
19547  * order_by(in):
19548  * orderby_for(in):
19549  * server_op(in):
19550  * for_update(in): true if query is used in update operation
19551  *
19552  * Note :
19553  * Prepends the class oid and the instance oid onto the select list for use
19554  * during the update or delete operation.
19555  * If the operation is a server side update, the prepended class oid is
19556  * put in the list file otherwise the class oid is a hidden column and
19557  * not put in the list file
19558  */
19559 PT_NODE *
19560 pt_to_upd_del_query (PARSER_CONTEXT * parser, PT_NODE * select_names, PT_NODE * select_list, PT_NODE * from,
19561  PT_NODE * with, PT_NODE * class_specs, PT_NODE * where, PT_NODE * using_index, PT_NODE * order_by,
19562  PT_NODE * orderby_for, int server_op, SCAN_OPERATION_TYPE scan_op_type)
19563 {
19564  PT_NODE *statement = NULL, *from_temp = NULL, *node = NULL;
19565  PT_NODE *save_next = NULL, *spec = NULL;
19566 
19567  assert (parser != NULL);
19568 
19569  statement = parser_new_node (parser, PT_SELECT);
19570  if (statement != NULL)
19571  {
19572  statement->info.query.with = with;
19573 
19574  /* this is an internally built query */
19576 
19577  statement->info.query.q.select.list = parser_copy_tree_list (parser, select_list);
19578 
19579  if (scan_op_type == S_UPDATE)
19580  {
19581  /* The system generated select was "SELECT ..., rhs1, rhs2, ... FROM table ...".
19582  * When two different updates set different sets of attrs, generated select was lead to one XASL entry.
19583  * This causes unexpected issues of reusing an XASL entry, e.g, mismatched types.
19584  *
19585  * Uses lhs of an assignment as its column alias:
19586  * For example, "UPDATE t SET x = ?, y = ?;" will generate "SELECT ..., ? AS x, ? AS y FROM t;".
19587  *
19588  * pt_print_select will print aliases as well as values for the system generated select queries.
19589  */
19590 
19591  PT_NODE *lhs, *rhs;
19592 
19593  for (rhs = statement->info.query.q.select.list, lhs = select_names;
19594  rhs != NULL && lhs != NULL; rhs = rhs->next, lhs = lhs->next)
19595  {
19596  rhs->alias_print = parser_print_tree (parser, lhs);
19597  }
19598  }
19599 
19600  statement->info.query.q.select.from = parser_copy_tree_list (parser, from);
19601  statement->info.query.q.select.using_index = parser_copy_tree_list (parser, using_index);
19602 
19603  /* add in the class specs to the spec list */
19604  statement->info.query.q.select.from =
19605  parser_append_node (parser_copy_tree_list (parser, class_specs), statement->info.query.q.select.from);
19606 
19607  statement->info.query.q.select.where = parser_copy_tree_list (parser, where);
19608 
19609  if (scan_op_type == S_UPDATE && statement->info.query.q.select.from->next != NULL)
19610  {
19611  /* this is a multi-table update statement */
19612  for (spec = statement->info.query.q.select.from; spec; spec = spec->next)
19613  {
19614  PT_NODE *name = NULL, *val = NULL, *last_val = NULL;
19615 
19616  if ((spec->info.spec.flag & PT_SPEC_FLAG_UPDATE) == 0)
19617  {
19618  /* class will not be updated, nothing to do */
19619  continue;
19620  }
19621 
19622  if (!mq_is_outer_join_spec (parser, spec))
19623  {
19624  /* spec is not outer joined in list; no need to rewrite */
19625  continue;
19626  }
19627 
19628  /*
19629  * Class will be updated and is outer joined.
19630  *
19631  * We must rewrite all expressions that will be assigned to
19632  * attributes of this class as
19633  *
19634  * IF (class_oid IS NULL, NULL, expr)
19635  *
19636  * so that expr will evaluate and/or fail only if an assignment
19637  * will be done.
19638  */
19639 
19640  name = select_names;
19641  val = statement->info.query.q.select.list;
19642  for (; name && val; name = name->next, val = val->next)
19643  {
19644  PT_NODE *if_expr = NULL, *isnull_expr = NULL;
19645  PT_NODE *bool_expr = NULL;
19646  PT_NODE *nv = NULL, *class_oid = NULL;
19647  DB_TYPE dom_type;
19648  DB_VALUE nv_value, *nv_valp;
19649  TP_DOMAIN *dom;
19650 
19651  assert (name->type_enum != PT_TYPE_NULL);
19652 
19653  if (name->info.name.spec_id != spec->info.spec.id)
19654  {
19655  /* attribute does not belong to the class */
19656  last_val = val;
19657  continue;
19658  }
19659 
19660  /* build class oid node */
19661  class_oid = pt_spec_to_oid_attr (parser, spec, OID_NAME);
19662  if (class_oid == NULL)
19663  {
19664  assert (false);
19665  PT_INTERNAL_ERROR (parser, "error building oid attr");
19666  parser_free_tree (parser, statement);
19667  return NULL;
19668  }
19669 
19670  /* allocate new parser nodes */
19671  isnull_expr = parser_new_node (parser, PT_EXPR);
19672  if (isnull_expr == NULL)
19673  {
19674  assert (false);
19675  PT_INTERNAL_ERROR (parser, "out of memory");
19676  parser_free_tree (parser, statement);
19677  return NULL;
19678  }
19679 
19680  /* (class_oid IS NULL) logical expression */
19681  isnull_expr->info.expr.op = PT_ISNULL;
19682  isnull_expr->info.expr.arg1 = class_oid;
19683 
19684  bool_expr = pt_convert_to_logical_expr (parser, isnull_expr, 1, 1);
19685  /* NULL value node */
19686  dom_type = pt_type_enum_to_db (name->type_enum);
19687  dom = tp_domain_resolve_default (dom_type);
19688  if (dom == NULL)
19689  {
19690  assert (false);
19691  PT_INTERNAL_ERROR (parser, "error building domain");
19692  parser_free_tree (parser, statement);
19693  return NULL;
19694  }
19695 
19696  if (db_value_domain_default (&nv_value, dom_type, dom->precision, dom->scale, dom->codeset,
19697  dom->collation_id, &dom->enumeration) != NO_ERROR)
19698  {
19699  assert (false);
19700  PT_INTERNAL_ERROR (parser, "error building default val");
19701  parser_free_tree (parser, statement);
19702  return NULL;
19703  }
19704  nv = pt_dbval_to_value (parser, &nv_value);
19705 
19706  assert (nv->type_enum != PT_TYPE_NULL);
19707  assert (nv->type_enum != PT_TYPE_NONE);
19708 
19709  nv_valp = pt_value_to_db (parser, nv);
19710  if (nv_valp == NULL)
19711  {
19712  assert (false);
19713  PT_INTERNAL_ERROR (parser, "error building default val");
19714  parser_free_tree (parser, statement);
19715  return NULL;
19716  }
19717 
19718  /* set as NULL value */
19719  (void) pr_clear_value (nv_valp);
19720 
19721  assert (nv->type_enum != PT_TYPE_NULL);
19722  assert (nv->type_enum != PT_TYPE_NONE);
19723 
19724  /* IF expr node */
19725  if_expr = parser_new_node (parser, PT_EXPR);
19726  if (bool_expr == NULL || nv == NULL || if_expr == NULL)
19727  {
19728  /* free allocated nodes */
19729  if (bool_expr)
19730  {
19731  parser_free_tree (parser, bool_expr);
19732  }
19733 
19734  if (nv)
19735  {
19736  parser_free_node (parser, nv);
19737  }
19738 
19739  if (if_expr)
19740  {
19741  parser_free_node (parser, if_expr);
19742  }
19743 
19744  assert (false);
19745  PT_INTERNAL_ERROR (parser, "out of memory");
19746  parser_free_tree (parser, statement);
19747  return NULL;
19748  }
19749 
19750  /* IF (ISNULL(class_oid)<>0, NULL, val) expression */
19751  if_expr->info.expr.op = PT_IF;
19752  if_expr->info.expr.arg1 = bool_expr;
19753  if_expr->info.expr.arg2 = nv;
19754  if_expr->info.expr.arg3 = val;
19755  if_expr->type_enum = name->type_enum;
19756  if_expr->data_type = parser_copy_tree_list (parser, name->data_type);
19757 
19758  /* rebuild links */
19759  PT_NODE_MOVE_NUMBER_OUTERLINK (if_expr, val);
19760  val = if_expr;
19761 
19762  if (last_val != NULL)
19763  {
19764  last_val->next = val;
19765  }
19766  else
19767  {
19768  statement->info.query.q.select.list = val;
19769  }
19770 
19771 
19772  /* remember this node as previous assignment node */
19773  last_val = val;
19774  }
19775  }
19776  }
19777 
19778  /* add the class and instance OIDs to the select list */
19779  from_temp = statement->info.query.q.select.from;
19780  node = from;
19781  statement->info.query.upd_del_class_cnt = 0;
19782  while (node)
19783  {
19784  if (node->node_type != PT_SPEC)
19785  {
19786  assert (false);
19787  PT_INTERNAL_ERROR (parser, "Invalid node type");
19788  parser_free_tree (parser, statement);
19789  return NULL;
19790  }
19791  if (node->info.spec.flag & (PT_SPEC_FLAG_UPDATE | PT_SPEC_FLAG_DELETE))
19792  {
19793  save_next = node->next;
19794  node->next = NULL;
19795  statement->info.query.q.select.from = node;
19796  statement = pt_add_row_classoid_name (parser, statement, server_op);
19797  assert (statement != NULL);
19798  statement = pt_add_row_oid_name (parser, statement);
19799  assert (statement != NULL);
19800  node->next = save_next;
19801 
19802  statement->info.query.upd_del_class_cnt++;
19803  }
19804  node = node->next;
19805  }
19806  statement->info.query.q.select.from = from_temp;
19807 
19808  if (scan_op_type == S_UPDATE && statement->info.query.upd_del_class_cnt == 1
19809  && statement->info.query.q.select.from->next != NULL && !pt_has_analytic (parser, statement))
19810  {
19811 
19812  /* In case of an update of a single table joined with other tables group the result of the select by instance
19813  * oid of the table to be updated */
19814 
19815  PT_NODE *oid_node = statement->info.query.q.select.list, *group_by;
19816 
19817  group_by = parser_new_node (parser, PT_SORT_SPEC);
19818  if (group_by == NULL)
19819  {
19820  PT_INTERNAL_ERROR (parser, "allocate new node");
19821  /* leave the error code set by check_order_by, will be handled by the calling function */
19822  parser_free_tree (parser, statement);
19823  return NULL;
19824  }
19825  group_by->info.sort_spec.asc_or_desc = PT_ASC;
19826  save_next = oid_node->next;
19827  oid_node->next = NULL;
19828  group_by->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, oid_node);
19829  group_by->info.sort_spec.pos_descr.pos_no = 1;
19830  group_by->info.sort_spec.expr = parser_copy_tree_list (parser, oid_node);
19831  oid_node->next = save_next;
19832  statement->info.query.q.select.group_by = group_by;
19834 
19835  /* can't use hash aggregation for this, might mess up order */
19836  statement->info.query.q.select.hint =
19838  /* The locking at update/delete stage does not work with GROUP BY, so, we will lock at SELECT stage. */
19840  }
19841 
19842  /* don't allow orderby_for without order_by */
19843  assert (!((orderby_for != NULL) && (order_by == NULL)));
19844 
19845  statement->info.query.order_by = parser_copy_tree_list (parser, order_by);
19846 
19847  if (statement->info.query.order_by != NULL)
19848  {
19849  /* translate col names into col numbers */
19850  if (pt_check_order_by (parser, statement) != NO_ERROR)
19851  {
19852  /* leave the error code set by check_order_by, will be handled by the calling function */
19853  parser_free_tree (parser, statement);
19854  return NULL;
19855  }
19856  }
19857 
19858  statement->info.query.orderby_for = parser_copy_tree_list (parser, orderby_for);
19859 
19860  if (statement)
19861  {
19862  statement->info.query.scan_op_type = scan_op_type;
19863 
19864  /* no strict oid checking for generated subquery */
19866  if (!server_op)
19867  {
19868  /* When UPDATE/DELETE statement is broker-side executed we must perform locking at SELECT stage */
19870  }
19871  }
19872  }
19873 
19875  {
19877  }
19878 
19879  return statement;
19880 }
19881 
19882 
19883 /*
19884  * pt_to_delete_xasl () - Converts an delete parse tree to
19885  * an XASL graph for an delete
19886  * return:
19887  * parser(in): context
19888  * statement(in): delete parse tree
19889  */
19890 XASL_NODE *
19892 {
19893  XASL_NODE *xasl = NULL;
19894  DELETE_PROC_NODE *delete_ = NULL;
19895  UPDDEL_CLASS_INFO *class_info = NULL;
19896  PT_NODE *aptr_statement = NULL;
19897  PT_NODE *from;
19898  PT_NODE *where;
19899  PT_NODE *with;
19900  PT_NODE *using_index;
19901  PT_NODE *class_specs;
19902  PT_NODE *cl_name_node;
19903  HFID *hfid;
19904  OID *class_oid;
19905  DB_OBJECT *class_obj;
19906  int num_classes = 0, num_subclasses = 0, i, j, num_cond_reev_classes = 0;
19907  int error = NO_ERROR;
19908  PT_NODE *hint_arg, *node;
19909  float hint_wait_secs;
19910  bool has_partitioned = false, abort_reevaluation = false;
19911 
19912  assert (parser != NULL && statement != NULL);
19913 
19914  from = statement->info.delete_.spec;
19915  where = statement->info.delete_.search_cond;
19916  using_index = statement->info.delete_.using_index;
19917  class_specs = statement->info.delete_.class_specs;
19918  with = statement->info.delete_.with;
19919 
19920  if (from && from->node_type == PT_SPEC && from->info.spec.range_var)
19921  {
19922  PT_NODE *select_node, *select_list = NULL;
19923 
19924  node = from;
19925  while (node != NULL && !has_partitioned)
19926  {
19927  cl_name_node = node->info.spec.flat_entity_list;
19928 
19929  while (cl_name_node != NULL && !has_partitioned)
19930  {
19931  error = sm_is_partitioned_class (cl_name_node->info.name.db_object);
19932  if (error < 0)
19933  {
19934  goto error_return;
19935  }
19936  has_partitioned = (error ? true : false);
19937  error = NO_ERROR;
19938  cl_name_node = cl_name_node->next;
19939  }
19940 
19941  node = node->next;
19942  }
19943 
19944  /* Skip reevaluation if MVCC is not enbaled or at least a class referenced in DELETE statement is partitioned.
19945  * The case of partitioned classes referenced in DELETE will be handled in the future */
19946  if (!has_partitioned)
19947  {
19948  /* Flag specs that are referenced in conditions and assignments */
19949 
19950  error = pt_mvcc_flag_specs_cond_reev (parser, from, where);
19951  if (error != NO_ERROR)
19952  {
19953  goto error_return;
19954  }
19955  }
19956 
19957  /* append LOB type attributes to select_list */
19958  node = statement->info.delete_.spec;
19959  while (node)
19960  {
19961  if (!(node->info.spec.flag & PT_SPEC_FLAG_DELETE))
19962  {
19963  node = node->next;
19964  continue;
19965  }
19966 
19967  cl_name_node = node->info.spec.flat_entity_list;
19968  class_obj = cl_name_node->info.name.db_object;
19969  if (class_obj)
19970  {
19971  DB_ATTRIBUTE *attr;
19972  attr = db_get_attributes (class_obj);
19973  while (attr)
19974  {
19975  if (attr->type->id == DB_TYPE_BLOB || attr->type->id == DB_TYPE_CLOB)
19976  {
19977  /* add lob to select list */
19978  select_node = pt_name (parser, attr->header.name);
19979  if (select_node)
19980  {
19981  select_node->info.name.spec_id = node->info.spec.id;
19982  select_node->type_enum = pt_db_to_type_enum (attr->type->id);
19983 
19984  if (attr->header.name_space == ID_SHARED_ATTRIBUTE)
19985  {
19986  select_node->info.name.meta_class = PT_SHARED;
19987  }
19988  else if (attr->header.name_space == ID_ATTRIBUTE)
19989  {
19990  select_node->info.name.meta_class = PT_NORMAL;
19991  }
19992  else
19993  {
19994  assert (0);
19995  }
19996 
19997  select_list = parser_append_node (select_node, select_list);
19998  }
19999  }
20000  attr = db_attribute_next (attr);
20001  }
20002  }
20003 
20004  node = node->next;
20005  }
20006 
20007  if (((aptr_statement =
20008  pt_to_upd_del_query (parser, NULL, select_list, from, with, class_specs, where, using_index, NULL, NULL, 1,
20009  S_DELETE)) == NULL)
20010  || pt_copy_upddel_hints_to_select (parser, statement, aptr_statement) != NO_ERROR
20011  || ((aptr_statement = mq_translate (parser, aptr_statement)) == NULL))
20012  {
20013  goto error_return;
20014  }
20015 
20016  if (aptr_statement->info.query.q.select.group_by != NULL)
20017  {
20018  /* remove reevaluation flags if we have GROUP BY because the locking will be made at SELECT stage */
20019  abort_reevaluation = true;
20020  }
20021  else
20022  {
20023  /* if at least one table involved in reevaluation is a derived table then abort reevaluation and force
20024  * locking on select */
20025  for (cl_name_node = aptr_statement->info.query.q.select.from; cl_name_node != NULL;
20026  cl_name_node = cl_name_node->next)
20027  {
20028  if (cl_name_node->info.spec.derived_table != NULL
20029  && (cl_name_node->info.spec.flag | PT_SPEC_FLAG_MVCC_COND_REEV))
20030  {
20032  abort_reevaluation = true;
20033  break;
20034  }
20035  }
20036  }
20037 
20038  /* These two lines disable reevaluation on UPDATE. To activate it just remove them */
20040  abort_reevaluation = true;
20041 
20042  if (abort_reevaluation)
20043  {
20044  /* In order to abort reevaluation is enough to clear reevaluation flags from all specs (from both, delete and
20045  * select statements) */
20046  for (cl_name_node = aptr_statement->info.query.q.select.from; cl_name_node != NULL;
20047  cl_name_node = cl_name_node->next)
20048  {
20049  cl_name_node->info.spec.flag =
20050  (PT_SPEC_FLAG) (cl_name_node->info.spec.flag & ~PT_SPEC_FLAG_MVCC_COND_REEV);
20051  }
20052  for (cl_name_node = from; cl_name_node != NULL; cl_name_node = cl_name_node->next)
20053  {
20054  cl_name_node->info.spec.flag =
20055  (PT_SPEC_FLAG) (cl_name_node->info.spec.flag & ~PT_SPEC_FLAG_MVCC_COND_REEV);
20056  }
20057  }
20058 
20059  /* In case of locking at select stage add flag used at SELECT ... FOR UPDATE clause to each spec from which rows
20060  * will be deleted. This will ensure that rows will be locked at SELECT stage. */
20062  {
20063  pt_mark_spec_list_for_update_clause (parser, aptr_statement, PT_SPEC_FLAG_DELETE);
20064  }
20065 
20066  /* Prepare generated SELECT statement for mvcc reevaluation */
20067  aptr_statement = pt_mvcc_prepare_upd_del_select (parser, aptr_statement);
20068  if (aptr_statement == NULL)
20069  {
20070  error = er_errid ();
20071  if (error == NO_ERROR)
20072  {
20073  error = ER_GENERIC_ERROR;
20074  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
20075  }
20076  goto error_return;
20077  }
20078 
20079  xasl = pt_make_aptr_parent_node (parser, aptr_statement, DELETE_PROC);
20080  if (xasl == NULL)
20081  {
20082  goto error_return;
20083  }
20084 
20085  while (select_list)
20086  {
20087  select_node = select_list;
20088  select_list = select_list->next;
20089  parser_free_node (parser, select_node);
20090  }
20091  }
20092 
20093  if (xasl != NULL)
20094  {
20095  PT_NODE *node;
20096 
20097  delete_ = &xasl->proc.delete_;
20098 
20099  node = statement->info.delete_.spec;
20100  num_classes = num_cond_reev_classes = 0;
20101  while (node != NULL)
20102  {
20103  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
20104  {
20105  num_classes++;
20106  }
20108  {
20109  ++num_cond_reev_classes;
20110  }
20111  node = node->next;
20112  }
20113  delete_->num_classes = num_classes;
20114  delete_->num_reev_classes = num_cond_reev_classes;
20115  regu_array_alloc (&delete_->classes, num_classes);
20116  if (delete_->classes == NULL)
20117  {
20118  goto error_return;
20119  }
20120 
20122  if (delete_->mvcc_reev_classes == NULL && delete_->num_reev_classes)
20123  {
20124  error = er_errid ();
20125  goto error_return;
20126  }
20127 
20128  /* we iterate through updatable classes from left to right and fill the structures from right to left because we
20129  * must match the order of OID's in the generated SELECT statement */
20130  for (i = num_classes - 1, node = statement->info.delete_.spec; i >= 0 && node != NULL; node = node->next)
20131  {
20132  bool found_lob = false;
20133 
20134  if (!(node->info.spec.flag & PT_SPEC_FLAG_DELETE))
20135  {
20136  /* skip classes from which we're not deleting */
20137  continue;
20138  }
20139 
20140  class_info = &delete_->classes[i--];
20141 
20142  /* setup members not needed for DELETE */
20143  class_info->att_id = NULL;
20144  class_info->num_attrs = 0;
20145  /* assume it always has uniques */
20146  class_info->has_uniques = 1;
20147 
20148  cl_name_node = node->info.spec.flat_entity_list;
20149  class_obj = cl_name_node->info.name.db_object;
20150  if (sm_partitioned_class_type (class_obj, &class_info->needs_pruning, NULL, NULL) != NO_ERROR)
20151  {
20152  PT_ERRORc (parser, statement, er_msg ());
20153  goto error_return;
20154  }
20155 
20156  num_subclasses = 0;
20157  while (cl_name_node)
20158  {
20159  num_subclasses++;
20160  cl_name_node = cl_name_node->next;
20161  }
20162  class_info->num_subclasses = num_subclasses;
20163  class_info->class_oid = regu_oid_array_alloc (num_subclasses);
20164  if (class_info->class_oid == NULL)
20165  {
20166  goto error_return;
20167  }
20168  regu_array_alloc (&class_info->class_hfid, num_subclasses);
20169  if (class_info->class_hfid == NULL)
20170  {
20171  goto error_return;
20172  }
20173 
20174  if (!class_info->needs_pruning)
20175  {
20176  class_info->num_lob_attrs = regu_int_array_alloc (num_subclasses);
20177  if (class_info->num_lob_attrs == NULL)
20178  {
20179  goto error_return;
20180  }
20181  regu_array_alloc (&class_info->lob_attr_ids, num_subclasses);
20182  if (class_info->lob_attr_ids == NULL)
20183  {
20184  goto error_return;
20185  }
20186  }
20187  else
20188  {
20189  class_info->num_lob_attrs = NULL;
20190  class_info->lob_attr_ids = NULL;
20191  }
20192 
20193  j = 0;
20194  cl_name_node = node->info.spec.flat_entity_list;
20195  while (cl_name_node != NULL)
20196  {
20197  class_obj = cl_name_node->info.name.db_object;
20198  class_oid = ws_identifier (class_obj);
20199  if (class_oid == NULL)
20200  {
20202  goto error_return;
20203  }
20204  hfid = sm_get_ch_heap (class_obj);
20205  if (hfid == NULL)
20206  {
20207  goto error_return;
20208  }
20209  COPY_OID (&class_info->class_oid[j], class_oid);
20210  HFID_COPY (&class_info->class_hfid[j], hfid);
20211 
20212  if (!class_info->needs_pruning)
20213  {
20214  class_info->num_lob_attrs[j] = 0;
20215  class_info->lob_attr_ids[j] = NULL;
20216 
20217  if (cl_name_node != node->info.spec.flat_entity_list)
20218  {
20219  /* lob attributes from root table are already handled */
20220  DB_ATTRIBUTE *attrs, *attr;
20221 
20222  attrs = db_get_attributes (class_obj);
20223  for (attr = attrs; attr; attr = (DB_ATTRIBUTE *) attr->header.next)
20224  {
20225  if ((attr->type->id == DB_TYPE_BLOB || attr->type->id == DB_TYPE_CLOB)
20226  && (attr->class_mop != node->info.spec.flat_entity_list->info.name.db_object))
20227  {
20228  /* count lob attributes that don't belong to the root table */
20229  class_info->num_lob_attrs[j]++;
20230  found_lob = true;
20231  }
20232  }
20233  if (class_info->num_lob_attrs[j] > 0)
20234  {
20235  /* some lob attributes were found, save their ids */
20236  int count = 0;
20237 
20238  class_info->lob_attr_ids[j] = regu_int_array_alloc (class_info->num_lob_attrs[j]);
20239  if (!class_info->lob_attr_ids[j])
20240  {
20241  goto error_return;
20242  }
20243  for (attr = attrs; attr; attr = (DB_ATTRIBUTE *) attr->header.next)
20244  {
20245  if ((attr->type->id == DB_TYPE_BLOB || attr->type->id == DB_TYPE_CLOB)
20246  && (attr->class_mop != node->info.spec.flat_entity_list->info.name.db_object))
20247  {
20248  class_info->lob_attr_ids[j][count++] = attr->id;
20249  }
20250  }
20251  }
20252  }
20253  }
20254 
20255  cl_name_node = cl_name_node->next;
20256  j++;
20257  }
20258 
20259  if (!found_lob)
20260  {
20261  /* no lob attributes were found, num_lob_attrs and lob_attr_ids can be set to NULL. this avoids keeping
20262  * useless information in xasl */
20263  class_info->num_lob_attrs = NULL;
20264  class_info->lob_attr_ids = NULL;
20265  }
20266  }
20267 
20268  hint_arg = statement->info.delete_.waitsecs_hint;
20270  if (statement->info.delete_.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
20271  {
20272  hint_wait_secs = (float) atof (hint_arg->info.name.original);
20273  if (hint_wait_secs > 0)
20274  {
20275  delete_->wait_msecs = (int) (hint_wait_secs * 1000);
20276  }
20277  else
20278  {
20279  delete_->wait_msecs = (int) hint_wait_secs;
20280  }
20281  }
20282  delete_->no_logging = (statement->info.delete_.hint & PT_HINT_NO_LOGGING);
20283  }
20284 
20285  if (pt_has_error (parser) || error < 0)
20286  {
20287  pt_report_to_ersys (parser, PT_SEMANTIC);
20288  xasl = NULL;
20289  }
20290 
20291  /* fill in XASL cache related information */
20292  if (xasl)
20293  {
20294  OID *oid;
20295 
20296  /* prepare data for MVCC condition reevaluation. For each class used in condition reevaluation set the position
20297  * (index) into select list. */
20298 
20299  for (cl_name_node = aptr_statement->info.query.q.select.list, i = j = 0;
20300  cl_name_node != NULL
20301  && (i < (aptr_statement->info.query.upd_del_class_cnt + aptr_statement->info.query.mvcc_reev_extra_cls_cnt));
20302  cl_name_node = cl_name_node->next->next, i++)
20303  {
20304  node = pt_find_spec (parser, aptr_statement->info.query.q.select.from, cl_name_node);
20305  assert (node != NULL);
20307  {
20308  /* set the position in SELECT list */
20309  delete_->mvcc_reev_classes[j++] = i;
20310  }
20311  }
20312 
20313  /* OID of the user who is creating this XASL */
20314  if ((oid = ws_identifier (db_get_user ())) != NULL)
20315  {
20316  COPY_OID (&xasl->creator_oid, oid);
20317  }
20318  else
20319  {
20320  OID_SET_NULL (&xasl->creator_oid);
20321  }
20322 
20323 
20324  /* list of class OIDs used in this XASL */
20325  if (xasl->aptr_list != NULL)
20326  {
20327  xasl->n_oid_list = xasl->aptr_list->n_oid_list;
20328  xasl->aptr_list->n_oid_list = 0;
20329 
20330  xasl->class_oid_list = xasl->aptr_list->class_oid_list;
20331  xasl->aptr_list->class_oid_list = NULL;
20332 
20333  xasl->class_locks = xasl->aptr_list->class_locks;
20334  xasl->aptr_list->class_locks = NULL;
20335 
20336  xasl->tcard_list = xasl->aptr_list->tcard_list;
20337  xasl->aptr_list->tcard_list = NULL;
20338 
20339  xasl->dbval_cnt = xasl->aptr_list->dbval_cnt;
20340 
20343  }
20344  }
20345  if (xasl)
20346  {
20347  xasl->query_alias = statement->alias_print;
20348  }
20349 
20350  if (statement->info.delete_.limit)
20351  {
20352  PT_NODE *limit = statement->info.delete_.limit;
20353 
20354  if (limit->next)
20355  {
20356  xasl->limit_offset = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
20357  limit = limit->next;
20358  }
20359  xasl->limit_row_count = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
20360  }
20361  if (aptr_statement)
20362  {
20363  parser_free_tree (parser, aptr_statement);
20364  aptr_statement = NULL;
20365  }
20366 
20367 
20368  return xasl;
20369 
20370 error_return:
20371  if (aptr_statement != NULL)
20372  {
20373  parser_free_tree (parser, aptr_statement);
20374  }
20375 
20376  if (pt_has_error (parser))
20377  {
20378  pt_report_to_ersys (parser, PT_SEMANTIC);
20379  xasl = NULL;
20380  }
20381  else if (error != NO_ERROR)
20382  {
20383  xasl = NULL;
20384  }
20385  return xasl;
20386 }
20387 
20388 /*
20389  * pt_has_reev_in_subquery_pre - increments subquery level and check for
20390  * reevaluation spec in subquery
20391  * returns: unmodified tree
20392  * parser(in): parser context
20393  * tree(in): tree that can be a subquery
20394  * arg(in/out): a pointer to an integer which represents the subquery level
20395  * continue_walk(in/out): walk type
20396  *
20397  * Note: used by pt_has_reev_in_subquery
20398  */
20399 static PT_NODE *
20400 pt_has_reev_in_subquery_pre (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
20401 {
20402  int level = *(int *) arg;
20403 
20404  if (level < 0)
20405  {
20406  return tree;
20407  }
20408 
20409  if (PT_IS_QUERY (tree))
20410  {
20411  level++;
20412  }
20413  else if (tree->node_type == PT_SPEC
20415  {
20416  level = -1;
20417  *continue_walk = PT_STOP_WALK;
20418  }
20419 
20420  return tree;
20421 }
20422 
20423 /*
20424  * pt_has_reev_in_subquery_post - decrements subquery level
20425  * returns: unmodified tree
20426  * parser(in): parser context
20427  * tree(in): tree that can be a subquery
20428  * arg(in/out): a pointer to an integer which represents the subquery level
20429  * continue_walk(in/out): walk type
20430  *
20431  * Note: used by pt_has_reev_in_subquery
20432  */
20433 static PT_NODE *
20434 pt_has_reev_in_subquery_post (PARSER_CONTEXT * parser, PT_NODE * tree, void *arg, int *continue_walk)
20435 {
20436  int level = *(int *) arg;
20437 
20438  if (level < 0)
20439  {
20440  return tree;
20441  }
20442 
20443  if (PT_IS_QUERY (tree))
20444  {
20445  level--;
20446  }
20447 
20448  return tree;
20449 }
20450 
20451 /*
20452  * pt_has_reev_in_subquery () - Checks if the statement has a subquery with
20453  * specs involved in reevaluation
20454  * return:
20455  * parser(in): context
20456  * statement(in): statement to be checked
20457  */
20458 static bool
20460 {
20461  int level = 0;
20462 
20464  &level);
20465  if (level < 0)
20466  {
20467  return true;
20468  }
20469 
20470  return false;
20471 }
20472 
20473 /*
20474  * pt_to_update_xasl () - Converts an update parse tree to
20475  * an XASL graph for an update
20476  * return:
20477  * parser(in): context
20478  * statement(in): update parse tree
20479  * non_null_attrs(in):
20480  */
20481 XASL_NODE *
20482 pt_to_update_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_attrs)
20483 {
20484  XASL_NODE *xasl = NULL;
20485  UPDATE_PROC_NODE *update = NULL;
20486  UPDDEL_CLASS_INFO *upd_cls = NULL;
20487  PT_NODE *assigns = statement->info.update.assignment;
20488  PT_NODE *aptr_statement = NULL;
20489  PT_NODE *p = NULL;
20490  PT_NODE *cl_name_node = NULL;
20491  int num_classes = 0, num_subclasses = 0, num_assign_reev_classes = 0;
20492  int num_cond_reev_classes = 0;
20493  PT_NODE *from = NULL;
20494  PT_NODE *where = NULL;
20495  PT_NODE *with = NULL;
20496  PT_NODE *using_index = NULL;
20497  PT_NODE *class_specs = NULL;
20498  int cl = 0, cls_idx = 0, num_vals = 0, num_consts = 0;
20499  int error = NO_ERROR;
20500  int a = 0, assign_idx = 0;
20501  PT_NODE *att_name_node = NULL;
20502  DB_VALUE *val = NULL;
20503  DB_ATTRIBUTE *attr = NULL;
20504  DB_DOMAIN *dom = NULL;
20505  TP_DOMAIN_STATUS dom_status;
20506  OID *class_oid = NULL;
20507  DB_OBJECT *class_obj = NULL;
20508  HFID *hfid = NULL;
20509  PT_NODE *hint_arg = NULL;
20510  PT_NODE *order_by = NULL;
20511  PT_NODE *orderby_for = NULL;
20512  PT_ASSIGNMENTS_HELPER assign_helper;
20513  PT_NODE **links = NULL;
20514  UPDATE_ASSIGNMENT *assign = NULL;
20515  PT_NODE *select_names = NULL;
20516  PT_NODE *select_values = NULL;
20517  PT_NODE *const_names = NULL;
20518  PT_NODE *const_values = NULL;
20519  OID *oid = NULL;
20520  float hint_wait_secs;
20521  int *mvcc_assign_extra_classes = NULL;
20522  bool has_partitioned = false, abort_reevaluation = false;
20523 
20524 
20525  assert (parser != NULL && statement != NULL);
20526 
20527  from = statement->info.update.spec;
20528  where = statement->info.update.search_cond;
20529  using_index = statement->info.update.using_index;
20530  class_specs = statement->info.update.class_specs;
20531  order_by = statement->info.update.order_by;
20532  orderby_for = statement->info.update.orderby_for;
20533  with = statement->info.update.with;
20534 
20535  /* flush all classes */
20536  p = from;
20537  while (p != NULL && !has_partitioned)
20538  {
20539  cl_name_node = p->info.spec.flat_entity_list;
20540 
20541  while (cl_name_node != NULL && !has_partitioned)
20542  {
20543  error = locator_flush_class (cl_name_node->info.name.db_object);
20544  if (error != NO_ERROR)
20545  {
20546  goto cleanup;
20547  }
20548  error = sm_is_partitioned_class (cl_name_node->info.name.db_object);
20549  if (error < 0)
20550  {
20551  goto cleanup;
20552  }
20553  has_partitioned = (error ? true : false);
20554  error = NO_ERROR;
20555  cl_name_node = cl_name_node->next;
20556  }
20557 
20558  p = p->next;
20559  }
20560 
20561  if (from == NULL || from->node_type != PT_SPEC || from->info.spec.range_var == NULL)
20562  {
20563  PT_INTERNAL_ERROR (parser, "update");
20564  goto cleanup;
20565  }
20566 
20567  error = pt_append_omitted_on_update_expr_assignments (parser, assigns, from);
20568  if (error != NO_ERROR)
20569  {
20570  PT_INTERNAL_ERROR (parser, "update");
20571  goto cleanup;
20572  }
20573 
20574  /* Skip reevaluation if MVCC is not enbaled or at least a class referenced in UPDATE statement is partitioned. The
20575  * case of partitioned classes referenced in UPDATE will be handled in future */
20576  if (!has_partitioned)
20577  {
20578  /* Flag specs that are referenced in conditions and assignments. This must be done before the generation of
20579  * select statement, otherwise it will be difficult to flag specs from select statement */
20580 
20581  error = pt_mvcc_flag_specs_cond_reev (parser, from, where);
20582  if (error != NO_ERROR)
20583  {
20584  goto cleanup;
20585  }
20586  error = pt_mvcc_flag_specs_assign_reev (parser, from, statement->info.update.assignment);
20587  if (error != NO_ERROR)
20588  {
20589  goto cleanup;
20590  }
20591  }
20592 
20593  /* get assignments lists for select statement generation */
20594  error =
20595  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &num_vals, &num_consts,
20596  statement->info.update.assignment, &links);
20597  if (error != NO_ERROR)
20598  {
20599  PT_INTERNAL_ERROR (parser, "update");
20600  goto cleanup;
20601  }
20602 
20603  aptr_statement =
20604  pt_to_upd_del_query (parser, select_names, select_values, from, with, class_specs, where, using_index, order_by,
20605  orderby_for, 1, S_UPDATE);
20606  /* restore assignment list here because we need to iterate through assignments later */
20607  pt_restore_assignment_links (statement->info.update.assignment, links, -1);
20608 
20609  if (aptr_statement == NULL)
20610  {
20611  assert (er_errid () != NO_ERROR);
20612  error = er_errid ();
20613  if (error == NO_ERROR)
20614  {
20615  error = ER_GENERIC_ERROR;
20616  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
20617  }
20618  goto cleanup;
20619  }
20620 
20621  error = pt_copy_upddel_hints_to_select (parser, statement, aptr_statement);
20622  if (error != NO_ERROR)
20623  {
20624  goto cleanup;
20625  }
20626 
20627  aptr_statement = mq_translate (parser, aptr_statement);
20628  if (aptr_statement == NULL)
20629  {
20630  if (pt_has_error (parser))
20631  {
20632  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, aptr_statement);
20633  }
20634  error = er_errid ();
20635  if (error == NO_ERROR)
20636  {
20637  error = ER_GENERIC_ERROR;
20638  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
20639  }
20640  goto cleanup;
20641  }
20642 
20643  if (aptr_statement->info.query.q.select.group_by != NULL)
20644  {
20645  /* remove reevaluation flags if we have GROUP BY because the locking will be made at SELECT stage */
20646  abort_reevaluation = true;
20647  }
20648  else if (has_partitioned || pt_has_reev_in_subquery (parser, aptr_statement))
20649  {
20650  /* if we have at least one class partitioned then perform locking at SELECT stage */
20652  abort_reevaluation = true;
20653  }
20654  else
20655  {
20656  /* if at least one table involved in reevaluation is a derived table then abort reevaluation and force locking on
20657  * select */
20658  for (p = aptr_statement->info.query.q.select.from; p != NULL; p = p->next)
20659  {
20660  if (p->info.spec.derived_table != NULL
20662  {
20664  abort_reevaluation = true;
20665  break;
20666  }
20667  }
20668  }
20669 
20670  /* These two lines disable reevaluation on UPDATE. To activate it just remove them */
20672  abort_reevaluation = true;
20673 
20674  if (abort_reevaluation)
20675  {
20676  /* In order to abort reevaluation is enough to clear reevaluation flags from all specs (from both, update and
20677  * select statements) */
20678  for (p = aptr_statement->info.query.q.select.from; p != NULL; p = p->next)
20679  {
20680  p->info.spec.flag =
20682  }
20683  for (p = from; p != NULL; p = p->next)
20684  {
20685  p->info.spec.flag =
20687  }
20688  }
20689 
20690  /* In case of locking at select stage add flag used at SELECT ... FOR UPDATE clause to each spec from which rows will
20691  * be updated. This will ensure that rows will be locked at SELECT stage. */
20693  {
20694  pt_mark_spec_list_for_update_clause (parser, aptr_statement, PT_SPEC_FLAG_UPDATE);
20695  }
20696 
20697  /* Prepare generated SELECT statement for mvcc reevaluation */
20698  aptr_statement = pt_mvcc_prepare_upd_del_select (parser, aptr_statement);
20699  if (aptr_statement == NULL)
20700  {
20701  error = er_errid ();
20702  if (error == NO_ERROR)
20703  {
20704  error = ER_GENERIC_ERROR;
20705  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
20706  }
20707  goto cleanup;
20708  }
20709 
20710  xasl = pt_make_aptr_parent_node (parser, aptr_statement, UPDATE_PROC);
20711  if (xasl == NULL || xasl->aptr_list == NULL)
20712  {
20713  assert (er_errid () != NO_ERROR);
20714  error = er_errid ();
20715  if (error == NO_ERROR)
20716  {
20717  error = ER_GENERIC_ERROR;
20718  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
20719  }
20720  goto cleanup;
20721  }
20722 
20723  /* flush all classes and count classes for update */
20724  num_classes = num_cond_reev_classes = num_assign_reev_classes = 0;
20725  p = from;
20726  while (p != NULL)
20727  {
20728  if (p->info.spec.flag & PT_SPEC_FLAG_UPDATE)
20729  {
20730  ++num_classes;
20731  }
20733  {
20734  ++num_cond_reev_classes;
20735  }
20738  {
20739  ++num_assign_reev_classes;
20740  }
20741 
20742  cl_name_node = p->info.spec.flat_entity_list;
20743  while (cl_name_node != NULL)
20744  {
20745  error = locator_flush_class (cl_name_node->info.name.db_object);
20746  if (error != NO_ERROR)
20747  {
20748  goto cleanup;
20749  }
20750  cl_name_node = cl_name_node->next;
20751  }
20752  p = p->next;
20753  }
20754 
20755  update = &xasl->proc.update;
20756 
20757  update->num_classes = num_classes;
20758  update->num_assigns = num_vals;
20759  update->num_reev_classes = num_cond_reev_classes + num_assign_reev_classes;
20760 
20761  regu_array_alloc (&update->classes, num_classes);
20762  if (update->classes == NULL)
20763  {
20764  assert (er_errid () != NO_ERROR);
20765  error = er_errid ();
20766  goto cleanup;
20767  }
20768 
20769  regu_array_alloc (&update->assigns, update->num_assigns);
20770  if (update->assigns == NULL)
20771  {
20772  assert (er_errid () != NO_ERROR);
20773  error = er_errid ();
20774  goto cleanup;
20775  }
20776 
20778  if (update->mvcc_reev_classes == NULL && update->num_reev_classes)
20779  {
20780  error = er_errid ();
20781  goto cleanup;
20782  }
20783 
20784  if (num_assign_reev_classes > 0)
20785  {
20786  mvcc_assign_extra_classes = regu_int_array_alloc (num_assign_reev_classes);
20787  if (mvcc_assign_extra_classes == NULL)
20788  {
20789  error = ER_OUT_OF_VIRTUAL_MEMORY;
20790  goto cleanup;
20791  }
20792  }
20793  /* we iterate through updatable classes from left to right and fill the structures from right to left because we must
20794  * match the order of OID's in the generated SELECT statement */
20795  for (p = from, cls_idx = num_classes - 1; cls_idx >= 0 && error == NO_ERROR; p = p->next)
20796  {
20797  /* ignore, this class will not be updated */
20798  if (!(p->info.spec.flag & PT_SPEC_FLAG_UPDATE))
20799  {
20800  continue;
20801  }
20802 
20803  upd_cls = &update->classes[cls_idx--];
20804 
20805  if (num_assign_reev_classes > 0)
20806  {
20807  a =
20809  mvcc_assign_extra_classes, num_assign_reev_classes);
20810  if (a > 0)
20811  {
20813  if (upd_cls->mvcc_extra_assign_reev == NULL)
20814  {
20815  error = er_errid ();
20816  goto cleanup;
20817  }
20818  memcpy (upd_cls->mvcc_extra_assign_reev, mvcc_assign_extra_classes, a * sizeof (int));
20819  upd_cls->num_extra_assign_reev = a;
20820  }
20821  else
20822  {
20823  upd_cls->mvcc_extra_assign_reev = NULL;
20824  upd_cls->num_extra_assign_reev = 0;
20825  }
20826  }
20827  /* count subclasses of current class */
20828  num_subclasses = 0;
20829  cl_name_node = p->info.spec.flat_entity_list;
20830  while (cl_name_node)
20831  {
20832  num_subclasses++;
20833  cl_name_node = cl_name_node->next;
20834  }
20835  upd_cls->num_subclasses = num_subclasses;
20836 
20837  /* count class assignments */
20838  a = 0;
20839  pt_init_assignments_helper (parser, &assign_helper, assigns);
20840  while (pt_get_next_assignment (&assign_helper) != NULL)
20841  {
20842  if (assign_helper.lhs->info.name.spec_id == p->info.spec.id)
20843  {
20844  a++;
20845  }
20846  }
20847  upd_cls->num_attrs = a;
20848 
20849  /* allocate array for subclasses OIDs, hfids, attributes ids, partitions */
20850  upd_cls->class_oid = regu_oid_array_alloc (num_subclasses);
20851  if (upd_cls->class_oid == NULL)
20852  {
20853  assert (er_errid () != NO_ERROR);
20854  error = er_errid ();
20855  goto cleanup;
20856  }
20857 
20858  regu_array_alloc (&upd_cls->class_hfid, num_subclasses);
20859  if (upd_cls->class_hfid == NULL)
20860  {
20861  assert (er_errid () != NO_ERROR);
20862  error = er_errid ();
20863  goto cleanup;
20864  }
20865 
20866  upd_cls->att_id = regu_int_array_alloc (num_subclasses * upd_cls->num_attrs);
20867  if (upd_cls->att_id == NULL)
20868  {
20869  assert (er_errid () != NO_ERROR);
20870  error = er_errid ();
20871  goto cleanup;
20872  }
20873 
20874  cl_name_node = p->info.spec.flat_entity_list;
20875  class_obj = cl_name_node->info.name.db_object;
20876  error = sm_partitioned_class_type (class_obj, &upd_cls->needs_pruning, NULL, NULL);
20877  if (error != NO_ERROR)
20878  {
20879  goto cleanup;
20880  }
20881 
20882  upd_cls->has_uniques = (p->info.spec.flag & PT_SPEC_FLAG_HAS_UNIQUE);
20883 
20884  /* iterate through subclasses */
20885  cl = 0;
20886  cl_name_node = p->info.spec.flat_entity_list;
20887  while (cl_name_node && error == NO_ERROR)
20888  {
20889  class_obj = cl_name_node->info.name.db_object;
20890 
20891  /* get class oid */
20892  class_oid = ws_identifier (class_obj);
20893  if (class_oid == NULL)
20894  {
20896  error = ER_HEAP_UNKNOWN_OBJECT;
20897  goto cleanup;
20898  }
20899 
20900  /* get hfid */
20901  hfid = sm_get_ch_heap (class_obj);
20902  if (hfid == NULL)
20903  {
20904  assert (er_errid () != NO_ERROR);
20905  error = er_errid ();
20906  goto cleanup;
20907  }
20908 
20909  upd_cls->class_oid[cl] = *class_oid;
20910  upd_cls->class_hfid[cl] = *hfid;
20911 
20912  /* Calculate attribute ids and link each assignment to classes and attributes */
20913  pt_init_assignments_helper (parser, &assign_helper, assigns);
20914  assign_idx = a = 0;
20915  while ((att_name_node = pt_get_next_assignment (&assign_helper)) != NULL)
20916  {
20917  if (att_name_node->info.name.spec_id == cl_name_node->info.name.spec_id)
20918  {
20919  assign = &update->assigns[assign_idx];
20920  assign->cls_idx = cls_idx + 1;
20921  assign->att_idx = a;
20922  upd_cls->att_id[cl * upd_cls->num_attrs + a] =
20923  sm_att_id (class_obj, att_name_node->info.name.original);
20924 
20925  if (upd_cls->att_id[cl * upd_cls->num_attrs + a] < 0)
20926  {
20927  assert (er_errid () != NO_ERROR);
20928  error = er_errid ();
20929  goto cleanup;
20930  }
20931  /* count attributes for current class */
20932  a++;
20933  }
20934  /* count assignments */
20935  assign_idx++;
20936  }
20937 
20938  /* count subclasses */
20939  cl++;
20940  cl_name_node = cl_name_node->next;
20941  }
20942  }
20943 
20945  hint_arg = statement->info.update.waitsecs_hint;
20946  if (statement->info.update.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
20947  {
20948  hint_wait_secs = (float) atof (hint_arg->info.name.original);
20949  if (hint_wait_secs > 0)
20950  {
20951  update->wait_msecs = (int) (hint_wait_secs * 1000);
20952  }
20953  else
20954  {
20955  update->wait_msecs = (int) hint_wait_secs;
20956  }
20957  }
20958  update->no_logging = (statement->info.update.hint & PT_HINT_NO_LOGGING);
20959 
20960  /* iterate through classes and check constants */
20961  for (p = from, cls_idx = num_classes; p; p = p->next)
20962  {
20963  /* ignore not updatable classes */
20964  if (!(p->info.spec.flag & PT_SPEC_FLAG_UPDATE))
20965  {
20966  continue;
20967  }
20968  upd_cls = &update->classes[--cls_idx];
20969 
20970  class_obj = p->info.spec.flat_entity_list->info.name.db_object;
20971 
20972  pt_init_assignments_helper (parser, &assign_helper, assigns);
20973  a = 0;
20974  while ((att_name_node = pt_get_next_assignment (&assign_helper)) != NULL)
20975  {
20976  PT_NODE *node, *prev, *next;
20977  /* process only constants assigned to current class attributes */
20978  if (att_name_node->info.name.spec_id != p->info.spec.id || !assign_helper.is_rhs_const)
20979  {
20980  /* this is a constant assignment */
20981  a++;
20982  continue;
20983  }
20984  /* get DB_VALUE of assignment's right argument */
20985  val = pt_value_to_db (parser, assign_helper.assignment->info.expr.arg2);
20986  if (val == NULL)
20987  {
20988  error = ER_GENERIC_ERROR;
20990  goto cleanup;
20991  }
20992 
20993  prev = NULL;
20994  for (node = *non_null_attrs; node != NULL; node = next)
20995  {
20996  /* Check to see if this is a NON NULL attr */
20997  next = node->next;
20998 
20999  if (!pt_name_equal (parser, node, att_name_node))
21000  {
21001  prev = node;
21002  continue;
21003  }
21004 
21005  if (DB_IS_NULL (val))
21006  {
21007  /* assignment of a NULL value to a non null attribute */
21009  att_name_node->info.name.original);
21011  goto cleanup;
21012  }
21013  /* remove the node from the non_null_attrs list since we've already checked that the attr will be
21014  * non-null and the engine need not check again. */
21015  if (prev == NULL)
21016  {
21017  *non_null_attrs = (*non_null_attrs)->next;
21018  }
21019  else
21020  {
21021  prev->next = node->next;
21022  }
21023 
21024  /* free the node */
21025  node->next = NULL; /* cut-off link */
21026  parser_free_tree (parser, node);
21027  break;
21028  }
21029 
21030  /* Coerce constant value to destination attribute type */
21031  regu_alloc (update->assigns[a].constant);
21032  if (update->assigns[a].constant == NULL)
21033  {
21034  assert (er_errid () != NO_ERROR);
21035  error = er_errid ();
21036  goto cleanup;
21037  }
21038  attr = db_get_attribute (class_obj, att_name_node->info.name.original);
21039  if (attr == NULL)
21040  {
21041  assert (er_errid () != NO_ERROR);
21042  error = er_errid ();
21043  goto cleanup;
21044  }
21045  dom = db_attribute_domain (attr);
21046  if (dom == NULL)
21047  {
21048  assert (er_errid () != NO_ERROR);
21049  error = er_errid ();
21050  goto cleanup;
21051  }
21052  dom_status = tp_value_auto_cast (val, update->assigns[a].constant, dom);
21053  if (dom_status != DOMAIN_COMPATIBLE)
21054  {
21055  error = tp_domain_status_er_set (dom_status, ARG_FILE_LINE, val, dom);
21056  goto cleanup;
21057  }
21058 
21059  /* count assignments */
21060  a++;
21061  }
21062  }
21063 
21064  /* store number of ORDER BY keys in XASL tree */
21065  update->num_orderby_keys = (pt_length_of_list (aptr_statement->info.query.q.select.list)
21066  - pt_length_of_select_list (aptr_statement->info.query.q.select.list,
21068  assert (update->num_orderby_keys >= 0);
21069 
21070  /* generate xasl for non-null constraints predicates */
21071  error = pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &num_vals,
21072  &num_consts, statement->info.update.assignment, &links);
21073  if (error != NO_ERROR)
21074  {
21075  goto cleanup;
21076  }
21077  /* need to jump upd_del_class_cnt OID-CLASS OID pairs */
21078  error = pt_to_constraint_pred (parser, xasl, statement->info.update.spec, *non_null_attrs, select_names,
21079  (aptr_statement->info.query.upd_del_class_cnt
21080  + aptr_statement->info.query.mvcc_reev_extra_cls_cnt) * 2);
21081  pt_restore_assignment_links (statement->info.update.assignment, links, -1);
21082  if (error != NO_ERROR)
21083  {
21084  goto cleanup;
21085  }
21086 
21087  update->num_assign_reev_classes = 0;
21088 
21089  /* prepare data for MVCC condition reevaluation. For each class used in reevaluation (condition and assignement) set
21090  * the position (index) into select list. */
21091 
21092  for (cl_name_node = aptr_statement->info.query.q.select.list, cls_idx = 0, cl = 0;
21093  (cl_name_node != NULL
21094  && (cls_idx < (aptr_statement->info.query.upd_del_class_cnt
21095  + aptr_statement->info.query.mvcc_reev_extra_cls_cnt)));
21096  cl_name_node = cl_name_node->next->next, cls_idx++)
21097  {
21098  int idx;
21099 
21100  /* Find spec associated with current OID - CLASS OID pair */
21101  for (p = aptr_statement->info.query.q.select.from, idx = 0; p != NULL; p = p->next, idx++)
21102  {
21103  if (p->info.spec.id == cl_name_node->info.name.spec_id)
21104  {
21105  break;
21106  }
21107  }
21108 
21109  assert (p != NULL);
21110 
21112  {
21113  /* Change index in FROM list with index in SELECT list for classes that appear in right side of assignements
21114  * but not in condition */
21117  {
21118  int idx1, idx2;
21119 
21120  for (idx1 = 0; idx1 < num_classes; idx1++)
21121  {
21122  upd_cls = &update->classes[idx1];
21123  for (idx2 = 0; idx2 < upd_cls->num_extra_assign_reev; idx2++)
21124  {
21125  if (upd_cls->mvcc_extra_assign_reev[idx2] == idx)
21126  {
21127  upd_cls->mvcc_extra_assign_reev[idx2] = cls_idx;
21128  }
21129  }
21130  }
21131  update->num_assign_reev_classes++;
21132  }
21133 
21134  /* set the position in SELECT list */
21135  update->mvcc_reev_classes[cl++] = cls_idx;
21136  }
21137  }
21138 
21139  /* fill in XASL cache related information */
21140  /* OID of the user who is creating this XASL */
21141  if ((oid = ws_identifier (db_get_user ())) != NULL)
21142  {
21143  COPY_OID (&xasl->creator_oid, oid);
21144  }
21145  else
21146  {
21147  OID_SET_NULL (&xasl->creator_oid);
21148  }
21149 
21150 
21151  /* list of class OIDs used in this XASL */
21152  assert (xasl->aptr_list != NULL);
21153  assert (xasl->class_oid_list == NULL);
21154  assert (xasl->class_locks == NULL);
21155  assert (xasl->tcard_list == NULL);
21156 
21157  if (xasl->aptr_list != NULL)
21158  {
21159  xasl->n_oid_list = xasl->aptr_list->n_oid_list;
21160  xasl->aptr_list->n_oid_list = 0;
21161 
21162  xasl->class_oid_list = xasl->aptr_list->class_oid_list;
21163  xasl->aptr_list->class_oid_list = NULL;
21164 
21165  xasl->class_locks = xasl->aptr_list->class_locks;
21166  xasl->aptr_list->class_locks = NULL;
21167 
21168  xasl->tcard_list = xasl->aptr_list->tcard_list;
21169  xasl->aptr_list->tcard_list = NULL;
21170 
21171  xasl->dbval_cnt = xasl->aptr_list->dbval_cnt;
21172 
21175  }
21176 
21177  xasl->query_alias = statement->alias_print;
21178 
21179  if (statement->info.update.limit)
21180  {
21181  PT_NODE *limit = statement->info.update.limit;
21182 
21183  if (limit->next)
21184  {
21185  xasl->limit_offset = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
21186  limit = limit->next;
21187  }
21188  xasl->limit_row_count = pt_to_regu_variable (parser, limit, UNBOX_AS_VALUE);
21189  }
21190 
21191 cleanup:
21192  if (aptr_statement != NULL)
21193  {
21194  parser_free_tree (parser, aptr_statement);
21195  }
21196 
21197  if (pt_has_error (parser))
21198  {
21199  pt_report_to_ersys (parser, PT_SEMANTIC);
21200  xasl = NULL;
21201  }
21202  else if (error != NO_ERROR)
21203  {
21204  xasl = NULL;
21205  }
21206  return xasl;
21207 }
21208 
21209 /*
21210  * pt_find_omitted_default_expr() - Builds a list of attributes that have a default expression and are not found
21211  * in the specified attributes list
21212  * return: Error code
21213  * parser(in/out): Parser context
21214  * class_obj(in):
21215  * specified_attrs(in): the list of attributes that are not to be considered
21216  * default_expr_attrs(out):
21217  */
21218 int
21220  PT_NODE ** default_expr_attrs)
21221 {
21222  SM_CLASS *cls;
21223  SM_ATTRIBUTE *att;
21224  int error = NO_ERROR;
21225  PT_NODE *new_attr = NULL, *node = NULL;
21226 
21227  if (default_expr_attrs == NULL)
21228  {
21229  assert (default_expr_attrs != NULL);
21230  return ER_FAILED;
21231  }
21232 
21233  error = au_fetch_class_force (class_obj, &cls, AU_FETCH_READ);
21234  if (error != NO_ERROR)
21235  {
21236  return error;
21237  }
21238 
21239  for (att = cls->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
21240  {
21241  /* skip if attribute has auto_increment */
21242  if (att->auto_increment != NULL)
21243  {
21244  continue;
21245  }
21246 
21247  /* skip if a value has already been specified for this attribute */
21248  for (node = specified_attrs; node != NULL; node = node->next)
21249  {
21250  if (!pt_str_compare (pt_get_name (node), att->header.name, CASE_INSENSITIVE))
21251  {
21252  break;
21253  }
21254  }
21255  if (node != NULL)
21256  {
21257  continue;
21258  }
21259 
21260  /* add attribute to default_expr_attrs list */
21261  new_attr = parser_new_node (parser, PT_NAME);
21262  if (new_attr == NULL)
21263  {
21264  PT_INTERNAL_ERROR (parser, "allocate new node");
21265  return ER_FAILED;
21266  }
21267 
21268  new_attr->info.name.original = att->header.name;
21269 
21270  if (*default_expr_attrs != NULL)
21271  {
21272  new_attr->next = *default_expr_attrs;
21273  *default_expr_attrs = new_attr;
21274  }
21275  else
21276  {
21277  *default_expr_attrs = new_attr;
21278  }
21279  }
21280 
21281  return NO_ERROR;
21282 }
21283 
21284 /*
21285  * pt_append_omitted_on_update_expr_assignments() - Appends assignment expressions that have a default on update
21286  * expression and are not found in the specified attributes list
21287  * return: Error code
21288  * parser(in/out): Parser context
21289  * assigns(in/out): assignment expr list
21290  * from(in):
21291  */
21292 int
21294 {
21295  int error = NO_ERROR;
21296 
21297  for (PT_NODE * p = from; p != NULL; p = p->next)
21298  {
21299  if ((p->info.spec.flag & PT_SPEC_FLAG_UPDATE) == 0)
21300  {
21301  continue;
21302  }
21303 
21304  UINTPTR spec_id = p->info.spec.id;
21305  PT_NODE *cl_name_node = p->info.spec.flat_entity_list;
21306  DB_OBJECT *class_obj = cl_name_node->info.name.db_object;
21307  SM_CLASS *cls;
21308  SM_ATTRIBUTE *att;
21309  PT_NODE *new_lhs_of_assign = NULL;
21310  PT_NODE *default_expr_attrs = NULL;
21311  PT_ASSIGNMENTS_HELPER assign_helper;
21312 
21313  error = au_fetch_class_force (class_obj, &cls, AU_FETCH_READ);
21314  if (error != NO_ERROR)
21315  {
21316  return error;
21317  }
21318 
21319  for (att = cls->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
21320  {
21322  {
21323  continue;
21324  }
21325 
21326  pt_init_assignments_helper (parser, &assign_helper, assigns);
21327 
21328  /* skip if already in the assign-list */
21329  PT_NODE *att_name_node = NULL;
21330 
21331  while ((att_name_node = pt_get_next_assignment (&assign_helper)) != NULL)
21332  {
21333  if (!pt_str_compare (att_name_node->info.name.original, att->header.name, CASE_INSENSITIVE)
21334  && att_name_node->info.name.spec_id == spec_id)
21335  {
21336  break;
21337  }
21338  }
21339  if (att_name_node != NULL)
21340  {
21341  continue;
21342  }
21343 
21344  /* add attribute to default_expr_attrs list */
21345  new_lhs_of_assign = parser_new_node (parser, PT_NAME);
21346  if (new_lhs_of_assign == NULL)
21347  {
21348  if (default_expr_attrs != NULL)
21349  {
21350  parser_free_tree (parser, default_expr_attrs);
21351  }
21352  PT_INTERNAL_ERROR (parser, "allocate new node");
21353  return ER_FAILED;
21354  }
21355  new_lhs_of_assign->info.name.original = att->header.name;
21356  new_lhs_of_assign->info.name.resolved = cls->header.ch_name;
21357  new_lhs_of_assign->info.name.spec_id = spec_id;
21358 
21360  PT_NODE *new_rhs_of_assign = parser_make_expression (parser, op, NULL, NULL, NULL);
21361  if (new_rhs_of_assign == NULL)
21362  {
21363  if (new_lhs_of_assign != NULL)
21364  {
21365  parser_free_node (parser, new_lhs_of_assign);
21366  }
21367  if (default_expr_attrs != NULL)
21368  {
21369  parser_free_tree (parser, default_expr_attrs);
21370  }
21371  PT_INTERNAL_ERROR (parser, "allocate new node");
21372  return ER_FAILED;
21373  }
21374 
21375  PT_NODE *assign_expr = parser_make_expression (parser, PT_ASSIGN, new_lhs_of_assign, new_rhs_of_assign, NULL);
21376  if (assign_expr == NULL)
21377  {
21378  if (new_lhs_of_assign != NULL)
21379  {
21380  parser_free_node (parser, new_lhs_of_assign);
21381  }
21382  if (new_rhs_of_assign != NULL)
21383  {
21384  parser_free_node (parser, new_rhs_of_assign);
21385  }
21386  if (default_expr_attrs != NULL)
21387  {
21388  parser_free_tree (parser, default_expr_attrs);
21389  }
21390  PT_INTERNAL_ERROR (parser, "allocate new node");
21391  return ER_FAILED;
21392  }
21393 
21394  if (default_expr_attrs != NULL)
21395  {
21396  assign_expr->next = default_expr_attrs;
21397  default_expr_attrs = assign_expr;
21398  }
21399  else
21400  {
21401  default_expr_attrs = assign_expr;
21402  }
21403  }
21404 
21405  if (default_expr_attrs != NULL)
21406  {
21407  parser_append_node (default_expr_attrs, assigns);
21408  }
21409  }
21410 
21411  return NO_ERROR;
21412 }
21413 
21414 /*
21415  * parser_generate_xasl_pre () - builds xasl for query nodes,
21416  * and remembers uncorrelated queries
21417  * return:
21418  * parser(in):
21419  * node(in):
21420  * arg(in):
21421  * continue_walk(in):
21422  */
21423 static PT_NODE *
21424 parser_generate_xasl_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
21425 {
21426  *continue_walk = PT_CONTINUE_WALK;
21427 
21428  if (parser->flag.abort)
21429  {
21430  *continue_walk = PT_STOP_WALK;
21431  return (node);
21432  }
21433 
21434  switch (node->node_type)
21435  {
21436  case PT_SELECT:
21437 #if defined(CUBRID_DEBUG)
21438  PT_NODE_PRINT_TO_ALIAS (parser, node, PT_CONVERT_RANGE);
21439 #endif /* CUBRID_DEBUG */
21440 
21441  /* fall through */
21442  case PT_UNION:
21443  case PT_DIFFERENCE:
21444  case PT_INTERSECTION:
21445  /* The parser tree can be reused when multiple queries are executed through ux_execute_array (). */
21446  /* The XASL object has already been freed at pt_exit_packing_buf (), so only node->info.query.xasl is changed to null. */
21447  node->info.query.xasl = NULL;
21448 
21449  (void) pt_query_set_reference (parser, node);
21450  pt_push_symbol_info (parser, node);
21451  break;
21452 
21453  default:
21454  break;
21455  }
21456 
21457  if (pt_has_error (parser) || er_errid () == ER_LK_UNILATERALLY_ABORTED)
21458  {
21459  *continue_walk = PT_STOP_WALK;
21460  }
21461 
21462  return node;
21463 }
21464 
21465 
21466 /*
21467  * parser_generate_xasl_post () - builds xasl for query nodes
21468  * return:
21469  * parser(in):
21470  * node(in):
21471  * arg(in):
21472  * continue_walk(in/out):
21473  */
21474 static PT_NODE *
21475 parser_generate_xasl_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
21476 {
21477  XASL_NODE *xasl;
21478  XASL_SUPP_INFO *info = (XASL_SUPP_INFO *) arg;
21479 
21480  if (*continue_walk == PT_STOP_WALK)
21481  {
21482  return node;
21483  }
21484 
21485  *continue_walk = PT_CONTINUE_WALK;
21486 
21487  if (parser->flag.abort)
21488  {
21489  *continue_walk = PT_STOP_WALK;
21490  return node;
21491  }
21492 
21493  assert (node != NULL);
21494 
21495  switch (node->node_type)
21496  {
21497  case PT_EXPR:
21498  if (PT_IS_SERIAL (node->info.expr.op))
21499  {
21500  /* fill in XASL cache related information; serial OID used in this XASL */
21501  if (pt_serial_to_xasl_class_oid_list (parser, node, &info->class_oid_list, &info->class_locks,
21502  &info->tcard_list, &info->n_oid_list, &info->oid_list_size) < 0)
21503  {
21505  {
21506  PT_INTERNAL_ERROR (parser, "generate xasl");
21507  }
21508  xasl = NULL;
21509  }
21510  }
21511  break;
21512 
21513  case PT_SELECT:
21514  case PT_UNION:
21515  case PT_DIFFERENCE:
21516  case PT_INTERSECTION:
21517  assert (node->info.query.xasl == NULL);
21518 
21519  /* build XASL for the query */
21520  xasl = parser_generate_xasl_proc (parser, node, info->query_list);
21521  pt_pop_symbol_info (parser);
21522  if (node->node_type == PT_SELECT)
21523  {
21524  /* fill in XASL cache related information; list of class OIDs used in this XASL */
21525  if (xasl
21527  &info->class_locks, &info->tcard_list, &info->n_oid_list,
21528  &info->oid_list_size, &info->includes_tde_class) < 0)
21529  {
21530  /* might be memory allocation error */
21531  PT_INTERNAL_ERROR (parser, "generate xasl");
21532  xasl = NULL;
21533  }
21534  }
21535  break;
21536 
21537  case PT_CTE:
21538  assert (node->info.cte.xasl == NULL);
21539 
21540  xasl = parser_generate_xasl_proc (parser, node, info->query_list);
21541  break;
21542 
21543  default:
21544  break;
21545  }
21546 
21547  if (pt_has_error (parser) || er_errid () == ER_LK_UNILATERALLY_ABORTED)
21548  {
21549  *continue_walk = PT_STOP_WALK;
21550  }
21551 
21552  return node;
21553 }
21554 
21555 
21556 /*
21557  * parser_generate_xasl () - Creates xasl proc for parse tree.
21558  * return:
21559  * parser(in):
21560  * node(in): pointer to a query structure
21561  */
21562 XASL_NODE *
21564 {
21565  XASL_NODE *xasl = NULL;
21566  PT_NODE *next;
21567  bool is_system_generated_stmt;
21568 
21569  assert (parser != NULL && node != NULL);
21570 
21571  next = node->next;
21572  node->next = NULL;
21573  parser->dbval_cnt = 0;
21574 
21575  is_system_generated_stmt = node->flag.is_system_generated_stmt;
21576 
21578  &is_system_generated_stmt);
21579 
21580  /* During the above parser_walk_tree the request to get a driver may cause a deadlock. We give up the following steps
21581  * and propagate the error messages */
21582  if (parser->flag.abort || node == NULL)
21583  {
21584  return NULL;
21585  }
21586 
21587  switch (node->node_type)
21588  {
21589  case PT_SELECT:
21590  case PT_UNION:
21591  case PT_DIFFERENCE:
21592  case PT_INTERSECTION:
21593  /* do not treat the top level like a subquery, even if it is a subquery with respect to something else (eg
21594  * insert). */
21595  node->info.query.is_subquery = (PT_MISC_TYPE) 0;
21596 
21597  /* translate methods in queries to our internal form */
21598  if (node)
21599  {
21600  node = meth_translate (parser, node);
21601  }
21602 
21603  if (node)
21604  {
21605  /* This function might be called recursively by some queries. Therefore, if xasl_Supp_info has the allocated
21606  * memory blocks, we should release them to prevent memory leak. The following query is one of them.
21607  * scenario/medium/_02_xtests/xmother.sql delete from x where xstr > concat_str('string 4', 'string 40') on
21608  * (select y from y where yint = add_int(y, 10, 10)); NOTE: Defining xasl_Supp_info in local scope is one of
21609  * the alternative methods for preventing memory leak. However, it returns a wrong result of a query. */
21610  if (xasl_Supp_info.query_list)
21611  {
21612  parser_free_tree (parser, xasl_Supp_info.query_list);
21613  }
21614  /* add dummy node at the head of list */
21615  xasl_Supp_info.query_list = parser_new_node (parser, PT_SELECT);
21616  xasl_Supp_info.query_list->info.query.xasl = NULL;
21617 
21618  /* XASL cache related information */
21620 
21621  node =
21622  parser_walk_tree (parser, node, parser_generate_xasl_pre, NULL, parser_generate_xasl_post, &xasl_Supp_info);
21623 
21624  parser_free_tree (parser, xasl_Supp_info.query_list);
21625  xasl_Supp_info.query_list = NULL;
21626  }
21627 
21628  if (node && !pt_has_error (parser))
21629  {
21630  node->next = next;
21631  xasl = (XASL_NODE *) node->info.query.xasl;
21632  }
21633  break;
21634 
21635  default:
21636  break;
21637  }
21638 
21639  /* fill in XASL cache related information */
21640  if (xasl)
21641  {
21642  OID *oid = NULL;
21643  int n;
21644  DB_OBJECT *user = NULL;
21645 
21646  /* OID of the user who is creating this XASL */
21647  user = db_get_user ();
21648  if (user != NULL)
21649  {
21650  oid = ws_identifier (user);
21651  }
21652 
21653  if (user != NULL && oid != NULL)
21654  {
21655  COPY_OID (&xasl->creator_oid, oid);
21656  }
21657  else
21658  {
21659  OID_SET_NULL (&xasl->creator_oid);
21660  }
21661 
21662  /* list of class OIDs used in this XASL */
21663  xasl->n_oid_list = 0;
21664  xasl->class_oid_list = NULL;
21665  xasl->class_locks = NULL;
21666  xasl->tcard_list = NULL;
21668 
21669  if ((n = xasl_Supp_info.n_oid_list) > 0 && (xasl->class_oid_list = regu_oid_array_alloc (n))
21670  && (xasl->class_locks = regu_int_array_alloc (n)) && (xasl->tcard_list = regu_int_array_alloc (n)))
21671  {
21672  xasl->n_oid_list = n;
21673  (void) memcpy (xasl->class_oid_list, xasl_Supp_info.class_oid_list, sizeof (OID) * n);
21674  (void) memcpy (xasl->class_locks, xasl_Supp_info.class_locks, sizeof (int) * n);
21675  (void) memcpy (xasl->tcard_list, xasl_Supp_info.tcard_list, sizeof (int) * n);
21676  if (xasl_Supp_info.includes_tde_class == 1)
21677  {
21679  }
21680  }
21681 
21682  xasl->dbval_cnt = parser->dbval_cnt;
21683  }
21684 
21685  /* free what were allocated in pt_spec_to_xasl_class_oid_list() */
21687 
21688  if (xasl)
21689  {
21690  xasl->query_alias = node->alias_print;
21692  }
21693 
21695  {
21696  if (xasl)
21697  {
21698  if (xasl->query_alias == NULL)
21699  {
21700  if (node->alias_print == NULL)
21701  {
21702  node->alias_print = parser_print_tree (parser, node);
21703  }
21704 
21705  xasl->query_alias = node->alias_print;
21706  }
21707 
21708  qdump_print_xasl (xasl);
21709  }
21710  else
21711  {
21712  printf ("<NULL XASL generation>\n");
21713  }
21714  }
21715 
21716  return xasl;
21717 }
21718 
21719 
21720 /*
21721  * pt_set_level_node_etc_pre () -
21722  * return:
21723  * parser(in):
21724  * node(in/out):
21725  * arg(in/out):
21726  * continue_walk(in):
21727  */
21728 static PT_NODE *
21729 pt_set_level_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
21730 {
21731  DB_VALUE **level_valp = (DB_VALUE **) arg;
21732 
21733  if (node->node_type == PT_EXPR)
21734  {
21735  if (node->info.expr.op == PT_LEVEL)
21736  {
21737  if (*level_valp == NULL)
21738  {
21739  regu_alloc (*level_valp);
21740  }
21741 
21742  node->etc = *level_valp;
21743  }
21744  }
21745 
21746  return node;
21747 }
21748 
21749 /*
21750  * pt_set_level_node_etc () - set the db val ponter for LEVEL nodes
21751  * return:
21752  * parser(in):
21753  * node_list(in):
21754  * level_valp(out):
21755  */
21756 void
21758 {
21759  PT_NODE *node, *save_node, *save_next;
21760 
21761  if (node_list)
21762  {
21763  for (node = node_list; node; node = node->next)
21764  {
21765  save_node = node;
21766 
21767  CAST_POINTER_TO_NODE (node);
21768 
21769  /* save and cut-off node link */
21770  save_next = node->next;
21771  node->next = NULL;
21772 
21773  (void) parser_walk_tree (parser, node, pt_set_level_node_etc_pre, level_valp, NULL, NULL);
21774 
21775  if (node)
21776  {
21777  node->next = save_next;
21778  }
21779 
21780  node = save_node;
21781  } /* for (node = ...) */
21782  }
21783 }
21784 
21785 /*
21786  * pt_make_regu_level () - make a regu_variable constant for LEVEL
21787  * return:
21788  * parser(in):
21789  * node(in):
21790  */
21791 static REGU_VARIABLE *
21793 {
21794  REGU_VARIABLE *regu = NULL;
21795  DB_VALUE *dbval;
21796 
21797  dbval = (DB_VALUE *) node->etc;
21798 
21799  if (dbval)
21800  {
21801  regu_alloc (regu);
21802  if (regu)
21803  {
21804  regu->type = TYPE_CONSTANT;
21805  regu->domain = &tp_Integer_domain;
21806  regu->value.dbvalptr = dbval;
21807  }
21808  }
21809  else
21810  {
21811  PT_INTERNAL_ERROR (parser, "generate LEVEL");
21812  }
21813 
21814  return regu;
21815 }
21816 
21817 /*
21818  * pt_set_isleaf_node_etc_pre () -
21819  * return:
21820  * parser(in):
21821  * node(in/out):
21822  * arg(in/out):
21823  * continue_walk(in):
21824  */
21825 static PT_NODE *
21826 pt_set_isleaf_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
21827 {
21828  DB_VALUE **isleaf_valp = (DB_VALUE **) arg;
21829 
21830  if (node->node_type == PT_EXPR)
21831  {
21832  if (node->info.expr.op == PT_CONNECT_BY_ISLEAF)
21833  {
21834  if (*isleaf_valp == NULL)
21835  {
21836  regu_alloc (*isleaf_valp);
21837  }
21838 
21839  node->etc = *isleaf_valp;
21840  }
21841  }
21842 
21843  return node;
21844 }
21845 
21846 /*
21847  * pt_set_isleaf_node_etc () - set the db val ponter for CONNECT_BY_ISLEAF nodes
21848  * return:
21849  * parser(in):
21850  * node_list(in):
21851  * isleaf_valp(out):
21852  */
21853 void
21855 {
21856  PT_NODE *node, *save_node, *save_next;
21857 
21858  if (node_list)
21859  {
21860  for (node = node_list; node; node = node->next)
21861  {
21862  save_node = node;
21863 
21864  CAST_POINTER_TO_NODE (node);
21865 
21866  /* save and cut-off node link */
21867  save_next = node->next;
21868  node->next = NULL;
21869 
21870  (void) parser_walk_tree (parser, node, pt_set_isleaf_node_etc_pre, isleaf_valp, NULL, NULL);
21871 
21872  if (node)
21873  {
21874  node->next = save_next;
21875  }
21876 
21877  node = save_node;
21878  } /* for (node = ...) */
21879  }
21880 }
21881 
21882 /*
21883  * pt_make_regu_isleaf () - make a regu_variable constant for CONNECT_BY_ISLEAF
21884  * return:
21885  * parser(in):
21886  * node(in):
21887  */
21888 static REGU_VARIABLE *
21890 {
21891  REGU_VARIABLE *regu = NULL;
21892  DB_VALUE *dbval;
21893 
21894  dbval = (DB_VALUE *) node->etc;
21895 
21896  if (dbval)
21897  {
21898  regu_alloc (regu);
21899  if (regu)
21900  {
21901  regu->type = TYPE_CONSTANT;
21902  regu->domain = &tp_Integer_domain;
21903  regu->value.dbvalptr = dbval;
21904  }
21905  }
21906  else
21907  {
21908  PT_INTERNAL_ERROR (parser, "generate CONNECT_BY_ISLEAF");
21909  }
21910 
21911  return regu;
21912 }
21913 
21914 
21915 /*
21916  * pt_set_iscycle_node_etc_pre () -
21917  * return:
21918  * parser(in):
21919  * node(in/out):
21920  * arg(in/out):
21921  * continue_walk(in):
21922  */
21923 static PT_NODE *
21924 pt_set_iscycle_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
21925 {
21926  DB_VALUE **iscycle_valp = (DB_VALUE **) arg;
21927 
21928  if (node->node_type == PT_EXPR)
21929  {
21930  if (node->info.expr.op == PT_CONNECT_BY_ISCYCLE)
21931  {
21932  if (*iscycle_valp == NULL)
21933  {
21934  regu_alloc (*iscycle_valp);
21935  }
21936 
21937  node->etc = *iscycle_valp;
21938  }
21939  }
21940 
21941  return node;
21942 }
21943 
21944 /*
21945  * pt_set_iscycle_node_etc () - set the db val ponter for CONNECT_BY_ISCYCLE nodes
21946  * return:
21947  * parser(in):
21948  * node_list(in):
21949  * iscycle_valp(out):
21950  */
21951 void
21953 {
21954  PT_NODE *node, *save_node, *save_next;
21955 
21956  if (node_list)
21957  {
21958  for (node = node_list; node; node = node->next)
21959  {
21960  save_node = node;
21961 
21962  CAST_POINTER_TO_NODE (node);
21963 
21964  /* save and cut-off node link */
21965  save_next = node->next;
21966  node->next = NULL;
21967 
21968  (void) parser_walk_tree (parser, node, pt_set_iscycle_node_etc_pre, iscycle_valp, NULL, NULL);
21969 
21970  if (node)
21971  {
21972  node->next = save_next;
21973  }
21974 
21975  node = save_node;
21976  } /* for (node = ...) */
21977  }
21978 }
21979 
21980 /*
21981  * pt_make_regu_iscycle () - make a regu_variable constant for CONNECT_BY_ISCYCLE
21982  * return:
21983  * parser(in):
21984  * node(in):
21985  */
21986 static REGU_VARIABLE *
21988 {
21989  REGU_VARIABLE *regu = NULL;
21990  DB_VALUE *dbval;
21991 
21992  dbval = (DB_VALUE *) node->etc;
21993 
21994  if (dbval)
21995  {
21996  regu_alloc (regu);
21997  if (regu)
21998  {
21999  regu->type = TYPE_CONSTANT;
22000  regu->domain = &tp_Integer_domain;
22001  regu->value.dbvalptr = dbval;
22002  }
22003  }
22004  else
22005  {
22006  PT_INTERNAL_ERROR (parser, "generate CONNECT_BY_ISCYCLE");
22007  }
22008 
22009  return regu;
22010 }
22011 
22012 /*
22013  * pt_set_connect_by_operator_node_etc_pre () -
22014  * return:
22015  * parser(in):
22016  * node(in/out):
22017  * arg(in/out):
22018  * continue_walk(in):
22019  */
22020 static PT_NODE *
22021 pt_set_connect_by_operator_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
22022 {
22023  XASL_NODE *xasl = (XASL_NODE *) arg;
22024 
22025  if (node->node_type == PT_EXPR)
22026  {
22027  if (node->info.expr.op == PT_CONNECT_BY_ROOT || node->info.expr.op == PT_SYS_CONNECT_BY_PATH)
22028  {
22029  node->etc = xasl;
22030  }
22031  }
22032 
22033  return node;
22034 }
22035 
22036 /*
22037  * pt_set_connect_by_operator_node_etc () - set the select xasl pointer into
22038  * etc of PT_NODEs which are CONNECT BY operators/functions
22039  * return:
22040  * parser(in):
22041  * node_list(in):
22042  * xasl(in):
22043  */
22044 void
22046 {
22047  PT_NODE *node, *save_node, *save_next;
22048 
22049  if (node_list)
22050  {
22051  for (node = node_list; node; node = node->next)
22052  {
22053  save_node = node;
22054 
22055  CAST_POINTER_TO_NODE (node);
22056 
22057  /* save and cut-off node link */
22058  save_next = node->next;
22059  node->next = NULL;
22060 
22061  (void) parser_walk_tree (parser, node, pt_set_connect_by_operator_node_etc_pre, (void *) xasl, NULL, NULL);
22062 
22063  if (node)
22064  {
22065  node->next = save_next;
22066  }
22067 
22068  node = save_node;
22069  } /* for (node = ...) */
22070  }
22071 }
22072 
22073 /*
22074  * pt_set_qprior_node_etc_pre () -
22075  * return:
22076  * parser(in):
22077  * node(in/out):
22078  * arg(in/out):
22079  * continue_walk(in):
22080  */
22081 static PT_NODE *
22082 pt_set_qprior_node_etc_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
22083 {
22084  XASL_NODE *xasl = (XASL_NODE *) arg;
22085 
22086  if (node->node_type == PT_EXPR)
22087  {
22088  if (node->info.expr.op == PT_PRIOR)
22089  {
22090  node->etc = xasl;
22091  node->info.expr.op = PT_QPRIOR;
22092  }
22093  }
22094  else if (node->node_type == PT_SELECT || node->node_type == PT_UNION || node->node_type == PT_DIFFERENCE
22095  || node->node_type == PT_INTERSECTION)
22096  {
22097  *continue_walk = PT_STOP_WALK;
22098  }
22099 
22100  return node;
22101 }
22102 
22103 /*
22104  * pt_set_qprior_node_etc () - set the select xasl pointer into
22105  * etc of PRIOR operator in select list; modifies the operator
22106  * to eliminate any confusion with PRIOR in CONNECT BY clause
22107  * return:
22108  * parser(in):
22109  * node_list(in):
22110  * xasl(in):
22111  */
22112 void
22114 {
22115  PT_NODE *node, *save_node, *save_next;
22116 
22117  if (node_list)
22118  {
22119  for (node = node_list; node; node = node->next)
22120  {
22121  save_node = node;
22122 
22123  CAST_POINTER_TO_NODE (node);
22124 
22125  /* save and cut-off node link */
22126  save_next = node->next;
22127  node->next = NULL;
22128 
22129  (void) parser_walk_tree (parser, node, pt_set_qprior_node_etc_pre, (void *) xasl, NULL, NULL);
22130 
22131  if (node)
22132  {
22133  node->next = save_next;
22134  }
22135 
22136  node = save_node;
22137  } /* for (node = ...) */
22138  }
22139 }
22140 
22141 /*
22142  * pt_make_outlist_from_vallist () - make an outlist with const regu
22143  * variables from a vallist
22144  * return:
22145  * parser(in):
22146  * val_list_p(in):
22147  */
22148 static OUTPTR_LIST *
22150 {
22151  QPROC_DB_VALUE_LIST vallist = val_list_p->valp;
22152  REGU_VARIABLE_LIST regulist = NULL, regu_list = NULL;
22153  int i;
22154 
22155  OUTPTR_LIST *outptr_list = NULL;
22156  regu_alloc (outptr_list);
22157  if (!outptr_list)
22158  {
22159  return NULL;
22160  }
22161 
22162  outptr_list->valptr_cnt = val_list_p->val_cnt;
22163  outptr_list->valptrp = NULL;
22164 
22165  for (i = 0; i < val_list_p->val_cnt; i++)
22166  {
22167  regu_alloc (regu_list);
22168 
22169  if (!outptr_list->valptrp)
22170  {
22171  outptr_list->valptrp = regu_list;
22172  regulist = regu_list;
22173  }
22174 
22175  regu_list->next = NULL;
22176  regu_list->value.type = TYPE_CONSTANT;
22177  regu_list->value.domain = vallist->dom;
22178  regu_list->value.value.dbvalptr = vallist->val;
22179 
22180  if (regulist != regu_list)
22181  {
22182  regulist->next = regu_list;
22183  regulist = regu_list;
22184  }
22185 
22186  vallist = vallist->next;
22187  }
22188 
22189  return outptr_list;
22190 }
22191 
22192 /*
22193  * pt_make_pos_regu_list () - makes a list of positional regu variables
22194  * for the given vallist
22195  * return:
22196  * parser(in):
22197  * val_list_p(in):
22198  */
22199 static REGU_VARIABLE_LIST
22201 {
22202  REGU_VARIABLE_LIST regu_list = NULL;
22203  REGU_VARIABLE_LIST *tail = NULL;
22204  REGU_VARIABLE *regu;
22205  QPROC_DB_VALUE_LIST valp;
22206  int i = 0;
22207 
22208  tail = &regu_list;
22209 
22210  for (valp = val_list_p->valp; valp != NULL; valp = valp->next)
22211  {
22212  regu_alloc (*tail);
22213 
22214  regu = pt_make_pos_regu_var_from_scratch (valp->dom, valp->val, i);
22215  i++;
22216 
22217  if (regu && *tail)
22218  {
22219  (*tail)->value = *regu;
22220  tail = &(*tail)->next;
22221  }
22222  else
22223  {
22224  regu_list = NULL;
22225  break;
22226  }
22227  }
22228 
22229  return regu_list;
22230 }
22231 
22232 /*
22233  * pt_copy_val_list () - makes a copy of the given val list, allocating
22234  * a new VAL_LIST and DB_VALUEs
22235  * return:
22236  * parser(in):
22237  * val_list_p(in):
22238  */
22239 static VAL_LIST *
22241 {
22242  QPROC_DB_VALUE_LIST dblist1, dblist2;
22243  VAL_LIST *new_val_list;
22244 
22245  if (!val_list_p)
22246  {
22247  return NULL;
22248  }
22249 
22250  regu_alloc (new_val_list);
22251  if (!new_val_list)
22252  {
22253  return NULL;
22254  }
22255 
22256  dblist2 = NULL;
22257  new_val_list->val_cnt = 0;
22258 
22259  for (dblist1 = val_list_p->valp; dblist1; dblist1 = dblist1->next)
22260  {
22261  if (!dblist2)
22262  {
22263  regu_alloc (new_val_list->valp); /* don't alloc DB_VALUE */
22264  dblist2 = new_val_list->valp;
22265  }
22266  else
22267  {
22268  regu_alloc (dblist2->next);
22269  dblist2 = dblist2->next;
22270  }
22271 
22272  dblist2->val = db_value_copy (dblist1->val);
22273  dblist2->dom = dblist1->dom;
22274  new_val_list->val_cnt++;
22275  }
22276 
22277  return new_val_list;
22278 }
22279 
22280 /*
22281  * pt_fix_pseudocolumns_pos_regu_list () - modifies pseudocolumns positional
22282  * regu variables in list to fetch into node->etc
22283  * return:
22284  * parser(in):
22285  * node_list(in):
22286  * regu_list(in/out):
22287  */
22288 static void
22290 {
22291  PT_NODE *node, *saved;
22292  REGU_VARIABLE_LIST rl;
22293 
22294  for (node = node_list, rl = regu_list; node != NULL && rl != NULL; node = node->next, rl = rl->next)
22295  {
22296  saved = node;
22297  CAST_POINTER_TO_NODE (node);
22298 
22299  if (node->node_type == PT_EXPR
22300  && (node->info.expr.op == PT_LEVEL || node->info.expr.op == PT_CONNECT_BY_ISLEAF
22301  || node->info.expr.op == PT_CONNECT_BY_ISCYCLE))
22302  {
22303  rl->value.vfetch_to = (DB_VALUE *) node->etc;
22304  }
22305 
22306  node = saved;
22307  }
22308 }
22309 
22310 /*
22311  * pt_split_pred_regu_list () - splits regu list(s) into pred and rest
22312  * return:
22313  * parser(in):
22314  * val_list(in):
22315  * pred(in):
22316  * regu_list_rest(in/out):
22317  * regu_list_pred(out):
22318  * prior_regu_list_rest(in/out):
22319  * prior_regu_list_pred(out):
22320  * split_prior(in):
22321  * regu_list(in/out):
22322  */
22323 static int
22325  REGU_VARIABLE_LIST * regu_list_rest, REGU_VARIABLE_LIST * regu_list_pred,
22326  REGU_VARIABLE_LIST * prior_regu_list_rest, REGU_VARIABLE_LIST * prior_regu_list_pred,
22327  bool split_prior)
22328 {
22329  QPROC_DB_VALUE_LIST valp = NULL;
22330  PRED_REGU_VARIABLE_P_LIST regu_p_list = NULL, list = NULL;
22331  REGU_VARIABLE_LIST rl = NULL, prev_rl = NULL;
22332  REGU_VARIABLE_LIST prior_rl = NULL, prev_prior_rl = NULL;
22333  REGU_VARIABLE_LIST rl_next = NULL, prior_rl_next = NULL;
22334  bool moved_rl = false, moved_prior_rl = false;
22335  int err = NO_ERROR;
22336 
22337  regu_p_list = pt_get_pred_regu_variable_p_list (pred, &err);
22338  if (err != NO_ERROR)
22339  {
22340  goto exit_on_error;
22341  }
22342  if (!regu_p_list)
22343  {
22344  /* predicate is not referencing any of the DB_VALUEs in val_list */
22345  return NO_ERROR;
22346  }
22347 
22348  rl = *regu_list_rest;
22349  prev_rl = NULL;
22350 
22351  if (split_prior)
22352  {
22353  prior_rl = *prior_regu_list_rest;
22354  prev_prior_rl = NULL;
22355  }
22356 
22357  for (valp = val_list->valp; valp != NULL; valp = valp->next)
22358  {
22359  moved_rl = false;
22360  moved_prior_rl = false;
22361 
22362  for (list = regu_p_list; list != NULL; list = list->next)
22363  {
22364  if (list->pvalue->value.dbvalptr == valp->val)
22365  {
22366  if (split_prior && list->is_prior)
22367  {
22368  if (!moved_prior_rl)
22369  {
22370  prior_rl_next = prior_rl->next;
22371  /* move from prior_regu_list_rest into prior_regu_list_pred */
22372  pt_add_regu_var_to_list (prior_regu_list_pred, prior_rl);
22373  if (!prev_prior_rl)
22374  {
22375  /* moved head of the list */
22376  prior_rl = *prior_regu_list_rest = prior_rl_next;
22377  }
22378  else
22379  {
22380  prev_prior_rl->next = prior_rl_next;
22381  prior_rl = prior_rl_next;
22382  }
22383  moved_prior_rl = true;
22384  }
22385  }
22386  else
22387  {
22388  if (!moved_rl)
22389  {
22390  rl_next = rl->next;
22391  /* move from regu_list_rest into regu_list_pred */
22392  pt_add_regu_var_to_list (regu_list_pred, rl);
22393  if (!prev_rl)
22394  {
22395  /* moved head of the list */
22396  rl = *regu_list_rest = rl_next;
22397  }
22398  else
22399  {
22400  prev_rl->next = rl_next;
22401  rl = rl_next;
22402  }
22403  moved_rl = true;
22404  }
22405  }
22406 
22407  if (moved_rl && moved_prior_rl)
22408  {
22409  break;
22410  }
22411  }
22412  }
22413 
22414  if (!moved_rl)
22415  {
22416  prev_rl = rl;
22417  rl = rl->next;
22418  }
22419  if (!moved_prior_rl && split_prior)
22420  {
22421  prev_prior_rl = prior_rl;
22422  prior_rl = prior_rl->next;
22423  }
22424  }
22425 
22426  while (regu_p_list)
22427  {
22428  list = regu_p_list->next;
22429  free (regu_p_list);
22430  regu_p_list = list;
22431  }
22432 
22433  return NO_ERROR;
22434 
22435 exit_on_error:
22436 
22437  while (regu_p_list)
22438  {
22439  list = regu_p_list->next;
22440  free (regu_p_list);
22441  regu_p_list = list;
22442  }
22443 
22444  return ER_FAILED;
22445 }
22446 
22447 /*
22448  * pt_get_pred_regu_variable_p_list () - returns a list of pointers to
22449  * constant regu variables in the predicate
22450  * return:
22451  * pred(in):
22452  * err(out):
22453  */
22454 static PRED_REGU_VARIABLE_P_LIST
22456 {
22457  PRED_REGU_VARIABLE_P_LIST head = NULL, nextl = NULL, nextr = NULL, tail = NULL;
22458 
22459  if (!pred)
22460  {
22461  return NULL;
22462  }
22463 
22464  switch (pred->type)
22465  {
22466  case T_PRED:
22467  nextl = pt_get_pred_regu_variable_p_list (pred->pe.m_pred.lhs, err);
22468  nextr = pt_get_pred_regu_variable_p_list (pred->pe.m_pred.rhs, err);
22469  break;
22470 
22471  case T_EVAL_TERM:
22472  switch (pred->pe.m_eval_term.et_type)
22473  {
22474  case T_COMP_EVAL_TERM:
22475  nextl = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_comp.lhs, false, err);
22476  nextr = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_comp.rhs, false, err);
22477  break;
22478 
22479  case T_ALSM_EVAL_TERM:
22480  nextl = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_alsm.elem, false, err);
22481  nextr = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_alsm.elemset, false, err);
22482  break;
22483 
22484  case T_LIKE_EVAL_TERM:
22485  nextl = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_like.pattern, false, err);
22486  nextr = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_like.src, false, err);
22487  break;
22488 
22489  case T_RLIKE_EVAL_TERM:
22490  nextl = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_rlike.pattern, false, err);
22491  nextr = pt_get_var_regu_variable_p_list (pred->pe.m_eval_term.et.et_rlike.src, false, err);
22492  break;
22493  }
22494  break;
22495 
22496  case T_NOT_TERM:
22497  nextl = pt_get_pred_regu_variable_p_list (pred->pe.m_not_term, err);
22498  break;
22499  }
22500 
22501  if (nextl)
22502  {
22503  if (!head)
22504  {
22505  head = tail = nextl;
22506  }
22507  else
22508  {
22509  tail->next = nextl;
22510  }
22511  while (tail->next)
22512  {
22513  tail = tail->next;
22514  }
22515  }
22516  if (nextr)
22517  {
22518  if (!head)
22519  {
22520  head = tail = nextr;
22521  }
22522  else
22523  {
22524  tail->next = nextr;
22525  }
22526  while (tail->next)
22527  {
22528  tail = tail->next;
22529  }
22530  }
22531 
22532  return head;
22533 }
22534 
22535 /*
22536  * pt_get_var_regu_variable_p_list () - returns a list of pointers to
22537  * constant regu variables referenced by the argument regu variable
22538  * (or the argument regu variable itself)
22539  * return:
22540  * regu(in): the regu variable
22541  * is_prior(in): is it in PRIOR argument expression?
22542  * err(out):
22543  */
22544 static PRED_REGU_VARIABLE_P_LIST
22545 pt_get_var_regu_variable_p_list (const REGU_VARIABLE * regu, bool is_prior, int *err)
22546 {
22547  PRED_REGU_VARIABLE_P_LIST list = NULL;
22548  PRED_REGU_VARIABLE_P_LIST list1 = NULL, list2 = NULL, list3 = NULL;
22549 
22550  if (regu == NULL)
22551  {
22552  return NULL;
22553  }
22554 
22555  switch (regu->type)
22556  {
22557  case TYPE_CONSTANT:
22558  list = (PRED_REGU_VARIABLE_P_LIST) malloc (sizeof (PRED_REGU_VARIABLE_P_LIST_NODE));
22559  if (list)
22560  {
22561  list->pvalue = regu;
22562  list->is_prior = is_prior;
22563  list->next = NULL;
22564  }
22565  else
22566  {
22567  *err = ER_FAILED;
22568  }
22569  break;
22570 
22571  case TYPE_INARITH:
22572  case TYPE_OUTARITH:
22573  if (regu->value.arithptr->opcode == T_PRIOR)
22574  {
22575  list = pt_get_var_regu_variable_p_list (regu->value.arithptr->rightptr, true, err);
22576  }
22577  else
22578  {
22579  list1 = pt_get_var_regu_variable_p_list (regu->value.arithptr->leftptr, is_prior, err);
22580  list2 = pt_get_var_regu_variable_p_list (regu->value.arithptr->rightptr, is_prior, err);
22581  list3 = pt_get_var_regu_variable_p_list (regu->value.arithptr->thirdptr, is_prior, err);
22582  list = list1;
22583  if (!list)
22584  {
22585  list = list2;
22586  }
22587  else
22588  {
22589  while (list1->next)
22590  {
22591  list1 = list1->next;
22592  }
22593  list1->next = list2;
22594  }
22595  if (!list)
22596  {
22597  list = list3;
22598  }
22599  else
22600  {
22601  list1 = list;
22602  while (list1->next)
22603  {
22604  list1 = list1->next;
22605  }
22606  list1->next = list3;
22607  }
22608  }
22609  break;
22610 
22611  case TYPE_FUNC:
22612  {
22613  REGU_VARIABLE_LIST *r = &regu->value.funcp->operand;
22614  while (*r)
22615  {
22616  list1 = pt_get_var_regu_variable_p_list (&(*r)->value, is_prior, err);
22617 
22618  if (!list)
22619  {
22620  list = list1;
22621  }
22622  else
22623  {
22624  list2 = list;
22625  while (list2->next)
22626  {
22627  list2 = list2->next;
22628  }
22629  list2->next = list1;
22630  }
22631 
22632  *r = (*r)->next;
22633  }
22634  }
22635  break;
22636 
22637  default:
22638  break;
22639  }
22640 
22641  return list;
22642 }
22643 
22644 /*
22645  * pt_add_regu_var_to_list () - adds a regu list node to another regu list
22646  * return:
22647  * destination (in/out) :
22648  * source (in/out) :
22649  */
22650 static void
22652 {
22653  source->next = NULL;
22654 
22655  pt_merge_regu_var_lists (destination, source);
22656 }
22657 
22658 /*
22659  * pt_merge_regu_var_lists () - appends the source to the end of the destination regu var list
22660  * return:
22661  * destination (in/out):
22662  * source (in/out):
22663  */
22664 static void
22666 {
22667  REGU_VARIABLE_LIST itr;
22668 
22669  if ((*destination) == NULL)
22670  {
22671  *destination = source;
22672  }
22673  else
22674  {
22675  // get the end of the list
22676  for (itr = *destination; itr->next != NULL; itr = itr->next)
22677  ;
22678 
22679  // append it
22680  itr->next = source;
22681  }
22682 }
22683 
22684 /*
22685  * pt_build_do_stmt_aptr_list_pre () - build an XASL list of top level queries
22686  * returns: original node
22687  * node(in): node to check
22688  * arg(out): first node in list
22689  */
22690 static PT_NODE *
22691 pt_build_do_stmt_aptr_list_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
22692 {
22693  if (arg == NULL)
22694  {
22695  /* function was called with wrong params */
22696  assert (false);
22697  return NULL;
22698  }
22699 
22700  if (node == NULL)
22701  {
22702  /* nothing to do */
22703  return NULL;
22704  }
22705 
22706  if (PT_IS_QUERY_NODE_TYPE (node->node_type) && node->info.query.correlation_level == 0)
22707  {
22708  XASL_NODE **out_xasl = (XASL_NODE **) arg;
22709  XASL_NODE *aptr_list = *((XASL_NODE **) arg);
22710  XASL_NODE *xasl = NULL;
22711 
22712  *continue_walk = PT_LIST_WALK;
22713 
22714  /* generate query XASL */
22715  xasl = parser_generate_xasl (parser, node);
22716  if (xasl == NULL)
22717  {
22718  /* error generating xasl; check for parser messages */
22719  if (pt_has_error (parser))
22720  {
22722  }
22723 
22724  return node;
22725  }
22726 
22727  if (aptr_list != NULL)
22728  {
22729  /* list is not empty, append our XASL node */
22730  while (aptr_list->next)
22731  {
22732  aptr_list = aptr_list->next;
22733  }
22734 
22735  aptr_list->next = xasl;
22736  }
22737  else
22738  {
22739  /* first found query node */
22740  *out_xasl = xasl;
22741  }
22742  }
22743 
22744  return node;
22745 }
22746 
22747 /*
22748  * pt_build_do_stmt_aptr_list () - search for top level queries in node and
22749  * build an XASL list
22750  * returns: XASL node list
22751  * node(in): parser node to search in
22752  *
22753  * NOTE: search includes specified node (if node is a query, it will be
22754  * returned).
22755  */
22756 static XASL_NODE *
22758 {
22759  XASL_NODE *out_node = NULL;
22760 
22762 
22763  return out_node;
22764 }
22765 
22766 /*
22767  * parser_generate_do_stmt_xasl () - Generate xasl for DO statement
22768  * return:
22769  * parser(in):
22770  * node(in):
22771  */
22772 XASL_NODE *
22774 {
22775  XASL_NODE *xasl = NULL;
22776  OID *oid;
22777  DB_OBJECT *user = NULL;
22778 
22779  /* check parameters */
22780  assert (parser != NULL && node != NULL);
22781 
22782  if (node->node_type != PT_DO)
22783  {
22784  return NULL;
22785  }
22786 
22787  if (node->info.do_.expr == NULL)
22788  {
22789  /* do not accept NULL expressions */
22790  assert (false);
22791  return NULL;
22792  }
22793 
22794  parser->dbval_cnt = 0;
22795 
22796  xasl = regu_xasl_node_alloc (DO_PROC);
22797  if (!xasl)
22798  {
22799  return NULL;
22800  }
22801 
22802  /* populate statement's aptr_list; in this context, uncorrelated subqueries mean top level queries in expr tree */
22803  xasl->aptr_list = pt_build_do_stmt_aptr_list (parser, node);
22804  if (er_errid () != NO_ERROR)
22805  {
22806  return NULL;
22807  }
22808 
22809  if (xasl->aptr_list != NULL)
22810  {
22812  }
22813 
22814  xasl->outptr_list = pt_to_outlist (parser, node->info.do_.expr, NULL, UNBOX_AS_VALUE);
22815  if (!xasl->outptr_list)
22816  {
22817  return NULL;
22818  }
22819 
22820  /* OID of the user who is creating this XASL */
22821  if ((user = db_get_user ()) != NULL && (oid = ws_identifier (user)) != NULL)
22822  {
22823  COPY_OID (&xasl->creator_oid, oid);
22824  }
22825  else
22826  {
22827  OID_SET_NULL (&xasl->creator_oid);
22828  }
22829 
22830  xasl->n_oid_list = 0;
22831  xasl->class_oid_list = NULL;
22832  xasl->class_locks = NULL;
22833  xasl->tcard_list = NULL;
22834  xasl->dbval_cnt = parser->dbval_cnt;
22835  xasl->query_alias = node->alias_print;
22837 
22839  {
22840  if (xasl->query_alias == NULL)
22841  {
22842  if (node->alias_print == NULL)
22843  {
22844  node->alias_print = parser_print_tree (parser, node);
22845  }
22846  xasl->query_alias = node->alias_print;
22847  }
22848  qdump_print_xasl (xasl);
22849  }
22850 
22851  return xasl;
22852 }
22853 
22854 /*
22855  * pt_to_order_siblings_by () - modify order by list to match tuples used
22856  * at order siblings by execution
22857  * return:
22858  * parser(in):
22859  * node(in):
22860  */
22861 static SORT_LIST *
22863 {
22864  SORT_LIST *orderby;
22865  REGU_VARIABLE_LIST regu_list1, regu_list2;
22866  int i, j;
22867 
22868  if (!xasl || !xasl->outptr_list || !connect_by_xasl || !connect_by_xasl->outptr_list)
22869  {
22870  return NULL;
22871  }
22872 
22873  for (orderby = xasl->orderby_list; orderby; orderby = orderby->next)
22874  {
22875  for (i = 0, regu_list1 = xasl->outptr_list->valptrp; regu_list1; regu_list1 = regu_list1->next, i++)
22876  {
22877  if (i == orderby->pos_descr.pos_no)
22878  {
22879  if (regu_list1->value.type != TYPE_CONSTANT)
22880  {
22881  PT_INTERNAL_ERROR (parser, "invalid column in order siblings by");
22882  }
22883  for (j = 0, regu_list2 = connect_by_xasl->outptr_list->valptrp; regu_list2;
22884  regu_list2 = regu_list2->next, j++)
22885  {
22886  if (regu_list2->value.type == TYPE_CONSTANT
22887  && regu_list1->value.value.dbvalptr == regu_list2->value.value.dbvalptr)
22888  {
22889  orderby->pos_descr.pos_no = j;
22890  break;
22891  }
22892  }
22893  break;
22894  }
22895  }
22896  }
22897 
22898  return xasl->orderby_list;
22899 }
22900 
22901 /*
22902  * pt_agg_orderby_to_sort_list() - Translates a list of order by PT_SORT_SPEC
22903  * nodes from a aggregate function to a XASL
22904  * SORT_LIST list
22905  *
22906  * return: newly created XASL SORT_LIST
22907  * parser(in): parser context
22908  * order_list(in): list of PT_SORT_SPEC nodes
22909  * agg_args_list(in): list of aggregate function arguments
22910  *
22911  * Note : Code is similar to 'pt_to_sort_list', but tweaked for ORDERBY's for
22912  * aggregate functions.
22913  * Although the existing single aggregate supporting ORDER BY, allows
22914  * only one ORDER BY item, this functions handles the general case of
22915  * multiple ORDER BY items. However, it doesn't handle the 'hidden'
22916  * argument case (see 'pt_to_sort_list'), so it may require extension
22917  * in order to support multiple ORDER BY items.
22918  */
22919 static SORT_LIST *
22921 {
22923  SORT_LIST *sort = NULL;
22924  SORT_LIST *lastsort = NULL;
22925  PT_NODE *node = NULL;
22926  PT_NODE *arg = NULL;
22927  int i, k;
22928 
22929  i = 0; /* SORT_LIST pos_no start from 0 */
22930 
22931  for (node = order_list; node != NULL; node = node->next)
22932  {
22933  /* safe guard: invalid parse tree */
22934  if (node->node_type != PT_SORT_SPEC || node->info.sort_spec.expr == NULL)
22935  {
22937  return NULL;
22938  }
22939 
22940  /* check for end-of-sort */
22941  if (node->info.sort_spec.pos_descr.pos_no <= 0)
22942  {
22943  /* internal error */
22944  if (!pt_has_error (parser))
22945  {
22946  PT_INTERNAL_ERROR (parser, "generate order_by");
22947  }
22948  return NULL;
22949  }
22950 
22951  /* check for domain info */
22953  {
22954  /* get domain from corresponding column node */
22955  for (arg = agg_args_list, k = 1; arg; arg = arg->next, k++)
22956  {
22957  if (node->info.sort_spec.pos_descr.pos_no == k)
22958  {
22959  break; /* match */
22960  }
22961  }
22962 
22963  if (arg != NULL && arg->type_enum != PT_TYPE_NONE)
22964  { /* is resolved */
22965  node->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, arg);
22966  }
22967 
22968  /* still no domain ? -> internal error */
22969  if (node->info.sort_spec.pos_descr.dom == NULL)
22970  {
22971  if (!pt_has_error (parser))
22972  {
22973  PT_INTERNAL_ERROR (parser, "generate order_by");
22974  }
22975  return NULL;
22976  }
22977  }
22978 
22979  regu_alloc (sort);
22980  if (!sort)
22981  {
22983  return NULL;
22984  }
22985 
22986  /* set values */
22987  sort->s_order = (node->info.sort_spec.asc_or_desc == PT_ASC) ? S_ASC : S_DESC;
22988  sort->s_nulls = pt_to_null_ordering (node);
22989  sort->pos_descr = node->info.sort_spec.pos_descr;
22990 
22991  /* PT_SORT_SPEC pos_no start from 1, SORT_LIST pos_no start from 0 */
22992  sort->pos_descr.pos_no--;
22993  assert (sort->pos_descr.pos_no >= 0);
22994 
22995  /* link up */
22996  if (sort_list)
22997  {
22998  lastsort->next = sort;
22999  }
23000  else
23001  {
23002  sort_list = sort;
23003  }
23004 
23005  lastsort = sort;
23006  }
23007 
23008  return sort_list;
23009 }
23010 
23011 /*
23012  * pt_find_oid_scan_block () -
23013  * return: the XASL node or NULL
23014  * xasl (in): the beginning of the XASL chain
23015  * oi (in): the OID we're looking for
23016  *
23017  * note: in trying to optimize a general query (multiple tables, joins etc.)
23018  * for using (index) keylimit for "ORDER BY ... LIMIT n" queries,
23019  * we need to gather information that's scattered around the generated
23020  * XASL blocks and the plan tree that was selected by the optimizer,
23021  * and was used to generate the afore mentioned XASL.
23022  * This method acts as a "link": it connects an xasl block with
23023  * the (sub?) plan that generated it.
23024  */
23025 static XASL_NODE *
23027 {
23028  for (; xasl; xasl = xasl->scan_ptr)
23029  {
23030  /* only check required condition: OID match. Other, more sophisticated conditions should be checked from the
23031  * caller */
23032  if (xasl->spec_list && xasl->spec_list->indexptr && oid_compare (&xasl->spec_list->indexptr->class_oid, oid) == 0)
23033  {
23034  return xasl;
23035  }
23036  }
23037  return NULL;
23038 }
23039 
23040 /*
23041  * pt_ordbynum_to_key_limit_multiple_ranges () - add key limit to optimize
23042  * index access with multiple
23043  * key ranges
23044  *
23045  * return : NO_ERROR if key limit is generated successfully, ER_FAILED
23046  * otherwise
23047  * parser(in) : parser context
23048  * plan(in) : root plan (must support multi range key limit optimization)
23049  * xasl(in) : xasl node
23050  */
23051 static int
23053 {
23054  QO_LIMIT_INFO *limit_infop;
23055  QO_PLAN *subplan = NULL;
23056  XASL_NODE *scan = NULL;
23057  int ret = 0;
23058 
23059  if (!plan) /* simple plan, nothing to do */
23060  {
23061  goto error_exit;
23062  }
23063 
23064  if (!xasl || !xasl->spec_list)
23065  {
23066  goto error_exit;
23067  }
23068 
23069  if (!xasl->orderby_list || !xasl->ordbynum_pred)
23070  {
23071  goto error_exit;
23072  }
23073 
23074  /* find the subplan with multiple key range */
23075  if (qo_find_subplan_using_multi_range_opt (plan, &subplan, NULL) != NO_ERROR)
23076  {
23077  goto error_exit;
23078  }
23079  if (subplan == NULL)
23080  {
23081  goto error_exit;
23082  }
23083 
23084  scan = pt_find_oid_scan_block (xasl, &(subplan->plan_un.scan.index->head->class_->oid));
23085  if (scan == NULL)
23086  {
23087  goto error_exit;
23088  }
23089 
23090  /* check that we have index scan */
23091  if (scan->spec_list->type != TARGET_CLASS || scan->spec_list->access != ACCESS_METHOD_INDEX
23092  || !scan->spec_list->indexptr)
23093  {
23094  goto error_exit;
23095  }
23096 
23097  /* no data filter */
23098  if (scan->spec_list->where_pred)
23099  {
23100  goto error_exit;
23101  }
23102 
23103  /* generate key limit expression from limit/ordbynum */
23104  limit_infop = qo_get_key_limit_from_ordbynum (parser, plan, xasl, true);
23105  if (!limit_infop)
23106  {
23107  goto error_exit;
23108  }
23109 
23110  /* set an auto-resetting key limit for the iscan */
23111  ret = pt_to_key_limit (parser, NULL, limit_infop, &scan->spec_list->indexptr->key_info, true);
23112  db_private_free (NULL, limit_infop);
23113 
23114  if (ret != NO_ERROR)
23115  {
23116  goto error_exit;
23117  }
23118 
23119  return NO_ERROR;
23120 
23121 error_exit:
23122  assert (0);
23123  PT_INTERNAL_ERROR (parser, "Error generating key limit for multiple range \
23124  key limit optimization");
23125  return ER_FAILED;
23126 }
23127 
23128 /*
23129  * pt_to_pos_descr_groupby () - Translate PT_SORT_SPEC node to
23130  * QFILE_TUPLE_VALUE_POSITION node
23131  * return:
23132  * parser(in):
23133  * pos_p(out):
23134  * node(in):
23135  * root(in):
23136  */
23137 void
23139 {
23140  PT_NODE *temp;
23141  char *node_str = NULL;
23142  int i;
23143 
23144  pos_p->pos_no = -1; /* init */
23145  pos_p->dom = NULL; /* init */
23146 
23147  switch (root->node_type)
23148  {
23149  case PT_SELECT:
23150  i = 1; /* PT_SORT_SPEC pos_no start from 1 */
23151 
23152  if (node->node_type == PT_EXPR)
23153  {
23154  unsigned int save_custom;
23155 
23156  save_custom = parser->custom_print; /* save */
23157  parser->custom_print |= PT_CONVERT_RANGE;
23158 
23159  node_str = parser_print_tree (parser, node);
23160 
23161  parser->custom_print = save_custom; /* restore */
23162  }
23163 
23164  for (temp = root->info.query.q.select.group_by; temp != NULL; temp = temp->next)
23165  {
23166  PT_NODE *expr = NULL;
23167  if (temp->node_type != PT_SORT_SPEC)
23168  {
23169  continue;
23170  }
23171 
23172  expr = temp->info.sort_spec.expr;
23173 
23174  if (node->node_type == PT_NAME)
23175  {
23176  if (pt_name_equal (parser, expr, node))
23177  {
23178  pos_p->pos_no = i;
23179  }
23180  }
23181  else if (node->node_type == PT_EXPR)
23182  {
23183  if (pt_str_compare (node_str, parser_print_tree (parser, expr), CASE_INSENSITIVE) == 0)
23184  {
23185  pos_p->pos_no = i;
23186  }
23187  }
23188  else
23189  { /* node type must be an integer */
23190  if (node->info.value.data_value.i == i)
23191  {
23192  pos_p->pos_no = i;
23193  }
23194  }
23195 
23196  if (pos_p->pos_no != -1)
23197  { /* found match */
23198  if (expr->type_enum != PT_TYPE_NONE && expr->type_enum != PT_TYPE_MAYBE)
23199  { /* is resolved */
23200  pos_p->dom = pt_xasl_node_to_domain (parser, expr);
23201  }
23202  break;
23203  }
23204 
23205  i++;
23206  }
23207 
23208  break;
23209 
23210  case PT_UNION:
23211  case PT_INTERSECTION:
23212  case PT_DIFFERENCE:
23213  pt_to_pos_descr_groupby (parser, pos_p, node, root->info.query.q.union_.arg1);
23214  break;
23215 
23216  default:
23217  /* an error */
23218  break;
23219  }
23220 
23221  if (pos_p->pos_no == -1 || pos_p->dom == NULL)
23222  { /* an error */
23223  pos_p->pos_no = -1;
23224  pos_p->dom = NULL;
23225  }
23226 }
23227 
23228 /*
23229  * pt_numbering_set_continue_post () - set PT_PRED_ARG_INSTNUM_CONTINUE,
23230  * PT_PRED_ARG_GRBYNUM_CONTINUE and PT_PRED_ARG_ORDBYNUM_CONTINUE flag
23231  * for numbering node
23232  * return:
23233  * parser(in):
23234  * node(in):
23235  * arg(in/out):
23236  * continue_walk(in/out):
23237  */
23238 PT_NODE *
23239 pt_numbering_set_continue_post (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
23240 {
23241  PT_NODE *child = NULL;
23242  int *flagp = (int *) arg;
23243  PT_NODE *children[3];
23244  int i;
23245 
23246  if (!node)
23247  {
23248  return NULL;
23249  }
23250 
23251  if (node->node_type == PT_EXPR && node->type_enum != PT_TYPE_LOGICAL)
23252  {
23253  children[0] = node->info.expr.arg1;
23254  children[1] = node->info.expr.arg2;
23255  children[2] = node->info.expr.arg3;
23256 
23257  for (i = 0; i < 3; i++)
23258  {
23259  child = children[i];
23260  if (child
23261  && ((child->node_type == PT_FUNCTION && child->info.function.function_type == PT_GROUPBY_NUM)
23262  || (child->node_type == PT_EXPR && PT_IS_NUMBERING_AFTER_EXECUTION (child->info.expr.op))))
23263  {
23264  /* we have a subexpression with numbering functions and we don't have a logical operator therefore we set
23265  * the continue flag to ensure we treat all values in the pred evaluation */
23266  *flagp |= PT_PRED_ARG_INSTNUM_CONTINUE;
23267  *flagp |= PT_PRED_ARG_GRBYNUM_CONTINUE;
23269  }
23270  }
23271  }
23272 
23273  return node;
23274 }
23275 
23276 /*
23277  * pt_to_analytic_node () - build analytic node
23278  * return: NULL if error, input tree otherwise
23279  * parser(in): parser context
23280  * tree(in): input analytic node
23281  * analytic_info(in/out): analytic info structure (will be altered)
23282  */
23283 static PT_NODE *
23285 {
23286  ANALYTIC_TYPE *analytic;
23287  PT_FUNCTION_INFO *func_info;
23288  PT_NODE *list = NULL, *order_list = NULL, *link = NULL;
23289  PT_NODE *sort_list, *list_entry;
23290  PT_NODE *arg_list = NULL;
23291  PT_NODE *percentile = NULL;
23292 
23293  if (parser == NULL || analytic_info == NULL)
23294  {
23295  /* should not get here */
23296  assert (false);
23297  return tree;
23298  }
23299 
23300  if (tree == NULL || !PT_IS_ANALYTIC_NODE (tree))
23301  {
23302  /* nothing to do */
23303  return tree;
23304  }
23305 
23306  /* allocate analytic structure */
23307  regu_alloc (analytic);
23308  if (!analytic)
23309  {
23310  PT_ERROR (parser, tree,
23312  goto exit_on_error;
23313  }
23314 
23315  /* link structure to analytic list */
23316  analytic->next = analytic_info->head_list;
23317  analytic_info->head_list = analytic;
23318 
23319  /* retrieve function info */
23320  func_info = &tree->info.function;
23321 
23322  /* fill in analytic info */
23323  analytic->function = func_info->function_type;
23324  analytic->option = (func_info->all_or_distinct == PT_ALL) ? Q_ALL : Q_DISTINCT;
23325  analytic->domain = pt_xasl_node_to_domain (parser, tree);
23326  analytic->value = (DB_VALUE *) tree->etc;
23327  analytic->from_last = func_info->analytic.from_last;
23328  analytic->ignore_nulls = func_info->analytic.ignore_nulls;
23329 
23330  /* set value types */
23331  regu_dbval_type_init (analytic->value, pt_node_to_db_type (tree));
23332  regu_dbval_type_init (analytic->value2, pt_node_to_db_type (tree));
23333 
23334  /* count partitions */
23335  analytic->sort_prefix_size = 0;
23336  analytic->sort_list_size = 0;
23337  for (list = func_info->analytic.partition_by; list; list = list->next)
23338  {
23339  analytic->sort_prefix_size++;
23340  analytic->sort_list_size++;
23341  link = list; /* save last node in partitions list */
23342  }
23343  for (list = func_info->analytic.order_by; list; list = list->next)
23344  {
23345  analytic->sort_list_size++;
23346  }
23347 
23348  /* link PARTITION BY and ORDER BY sort spec lists (no differentiation is needed from now on) */
23349  if (link != NULL)
23350  {
23351  /* we have PARTITION BY clause */
23352  order_list = func_info->analytic.partition_by;
23353 
23354  /* When arg_list is constant, ignore order by for MEDIAN, PERCENTILE_CONT and PERCENTILE_DISC */
23355  if (!QPROC_IS_INTERPOLATION_FUNC (analytic) || !PT_IS_CONST (func_info->arg_list))
23356  {
23357  link->next = func_info->analytic.order_by;
23358  }
23359  }
23360  else
23361  {
23362  /* no PARTITION BY, only ORDER BY When arg_list is constant, ignore order by for MEDIAN, PERCENTILE_CONT and
23363  * PERCENTILE_DISC */
23364  if (!QPROC_IS_INTERPOLATION_FUNC (analytic) || !PT_IS_CONST (func_info->arg_list))
23365  {
23366  order_list = func_info->analytic.order_by;
23367  }
23368  }
23369 
23370  /* copy sort list for later use */
23371  if (order_list != NULL)
23372  {
23373  sort_list = parser_copy_tree_list (parser, order_list);
23374  if (sort_list == NULL)
23375  {
23376  PT_INTERNAL_ERROR (parser, "copy tree");
23377  goto exit_on_error;
23378  }
23379  }
23380  else
23381  {
23382  sort_list = NULL;
23383  }
23384 
23385  list_entry = parser_new_node (parser, PT_NODE_POINTER);
23386  if (list_entry == NULL)
23387  {
23388  PT_INTERNAL_ERROR (parser, "alloc node");
23389  goto exit_on_error;
23390  }
23391 
23392  if ((order_list != NULL && sort_list == NULL) || list_entry == NULL)
23393  {
23394  PT_ERROR (parser, tree,
23396  goto exit_on_error;
23397  }
23398 
23399  list_entry->info.pointer.node = sort_list;
23400  if (sort_list != NULL)
23401  {
23402  list_entry->line_number = sort_list->line_number;
23403  list_entry->column_number = sort_list->column_number;
23404  }
23405  if (analytic_info->sort_lists != NULL)
23406  {
23407  list_entry->next = analytic_info->sort_lists;
23408  analytic_info->sort_lists = list_entry;
23409  }
23410  else
23411  {
23412  analytic_info->sort_lists = list_entry;
23413  }
23414 
23415  /* find indexes of offset and default values for LEAD/LAG/NTH_VALUE */
23416  if (func_info->function_type == PT_LEAD || func_info->function_type == PT_LAG
23417  || func_info->function_type == PT_NTH_VALUE)
23418  {
23419  bool off_found = false, def_found = false;
23420  int idx = 0;
23421 
23422  for (list = analytic_info->select_list; list != NULL; list = list->next, idx++)
23423  {
23424  if (!off_found && func_info->analytic.offset->info.pointer.node == list)
23425  {
23426  analytic->offset_idx = idx;
23427  off_found = true;
23428  }
23429 
23430  if (!def_found && func_info->analytic.default_value->info.pointer.node == list)
23431  {
23432  analytic->default_idx = idx;
23433  def_found = true;
23434  }
23435  }
23436 
23437  if (!off_found || !def_found)
23438  {
23439  PT_INTERNAL_ERROR (parser, "invalid analytic function structure");
23440  goto exit_on_error;
23441  }
23442  }
23443 
23444  /* percentile of PERCENTILE_CONT and PERCENTILE_DISC */
23445  if (func_info->function_type == PT_PERCENTILE_CONT || func_info->function_type == PT_PERCENTILE_DISC)
23446  {
23447  percentile = func_info->percentile;
23448 
23449  if (!PT_IS_CONST (percentile))
23450  {
23451  CAST_POINTER_TO_NODE (percentile);
23452 
23453  percentile =
23454  pt_resolve_analytic_references (parser, percentile, analytic_info->select_list, analytic_info->val_list);
23455  if (percentile == NULL)
23456  {
23457  /* the error is set in pt_resolve_analytic_references */
23458  goto exit_on_error;
23459  }
23460  }
23461 
23462  analytic->info.percentile.percentile_reguvar =
23463  pt_to_regu_variable (parser, func_info->percentile, UNBOX_AS_VALUE);
23464  if (analytic->info.percentile.percentile_reguvar == NULL)
23465  {
23466  /* error is set in pt_to_regu_variable */
23467  goto exit_on_error;
23468  }
23469  }
23470 
23471  /* process operand (argument) */
23472  if (func_info->arg_list == NULL)
23473  {
23474  /* no argument (e.g. ROW_NUMBER function) */
23475  analytic->opr_dbtype = DB_TYPE_NULL;
23476  analytic->operand.type = TYPE_DBVAL;
23477  analytic->operand.domain = &tp_Null_domain;
23478  db_make_null (&analytic->operand.value.dbval);
23479 
23480  goto unlink_and_exit;
23481  }
23482  else if (PT_IS_POINTER_REF_NODE (func_info->arg_list))
23483  {
23484  /* fetch operand type */
23485  analytic->opr_dbtype = pt_node_to_db_type (func_info->arg_list->info.pointer.node);
23486 
23487  /* for MEDIAN and PERCENTILE functions */
23488  if (QPROC_IS_INTERPOLATION_FUNC (analytic))
23489  {
23490  arg_list = func_info->arg_list->info.pointer.node;
23491  CAST_POINTER_TO_NODE (arg_list);
23492 
23493  assert (arg_list != NULL);
23494 
23495  if (PT_IS_CONST (arg_list))
23496  {
23497  analytic->is_const_operand = true;
23498  }
23499  }
23500 
23501  /* resolve operand dbval_ptr */
23502  if (pt_resolve_analytic_references (parser, func_info->arg_list, analytic_info->select_list,
23503  analytic_info->val_list) == NULL)
23504  {
23505  goto exit_on_error;
23506  }
23507 
23508  /* populate reguvar */
23509  analytic->operand.type = TYPE_CONSTANT;
23510  analytic->operand.domain = pt_xasl_node_to_domain (parser, func_info->arg_list->info.pointer.node);
23511  analytic->operand.value.dbvalptr = (DB_VALUE *) func_info->arg_list->etc;
23512 
23513  goto unlink_and_exit;
23514  }
23515  else
23516  {
23517  /* arg should be a reference pointer that was previously set by pt_expand_analytic_node () */
23518  PT_INTERNAL_ERROR (parser, "unprocessed analytic argument");
23519  goto exit_on_error;
23520  }
23521 
23522 exit_on_error:
23523  /* error, return null */
23524  tree = NULL;
23525 
23526 unlink_and_exit:
23527  /* unlink PARTITION BY and ORDER BY lists if necessary */
23528  if (link != NULL)
23529  {
23530  link->next = NULL;
23531  link = NULL;
23532  }
23533 
23534  return tree;
23535 }
23536 
23537 /*
23538  * pt_to_analytic_final_node () - retrieves the node that will go in the last
23539  * outptr_list of analytic processing
23540  * returns: final node, NULL on error
23541  * parser(in): parser context
23542  * tree(in): analytic node
23543  * ex_list(out): pointer to a PT_NODE list
23544  * instnum_flag(out): see NOTE2
23545  *
23546  * NOTE: This function has the following behavior:
23547  *
23548  * 1. When it receives an analytic function node, it will put it in ex_list
23549  * and will return a reference PT_NODE_POINTER to the node.
23550  *
23551  * 2. When it receives an expression containing analytic functions, it will
23552  * put all analytic nodes AND subexpressions that DO NOT contain analytic
23553  * nodes into the "ex_list". The function will return a PT_EXPR tree of
23554  * reference PT_POINTERs.
23555  *
23556  * The returned node should be used in the "final" outptr_list of analytics
23557  * processing.
23558  *
23559  * NOTE2: The function will set the XASL_INSTNUM_FLAG_SELECTS_INSTNUM bit in
23560  * instnum_flag if an INST_NUM() is found in tree.
23561  */
23562 static PT_NODE *
23563 pt_to_analytic_final_node (PARSER_CONTEXT * parser, PT_NODE * tree, PT_NODE ** ex_list, int *instnum_flag)
23564 {
23565  PT_NODE *ptr;
23566 
23567  if (parser == NULL || ex_list == NULL)
23568  {
23569  /* should not get here */
23570  assert (false);
23571  return tree;
23572  }
23573 
23574  if (tree == NULL)
23575  {
23576  /* nothing to do */
23577  return NULL;
23578  }
23579 
23580  if (PT_IS_ANALYTIC_NODE (tree))
23581  {
23582  /* select ntile(select stddev(...)...)... from ... is allowed */
23583  if (!pt_is_query (tree->info.function.arg_list) && pt_has_analytic (parser, tree->info.function.arg_list))
23584  {
23586  return NULL;
23587  }
23588 
23589  /* analytics go to ex_list, ref pointer is returned */
23590  goto exit_return_ptr;
23591  }
23592 
23593  if (PT_IS_EXPR_NODE (tree))
23594  {
23595  PT_NODE *ret = NULL;
23596 
23597  if (PT_IS_ORDERBYNUM (tree))
23598  {
23599  /* orderby_num() should be evaluated at the write of output */
23600  return tree;
23601  }
23602 
23603  if (PT_IS_INSTNUM (tree))
23604  {
23605  /* inst_num() should be evaluated at the write of output; also set flag so we defer inst_num() incrementation
23606  * to output */
23607  (*instnum_flag) |= XASL_INSTNUM_FLAG_EVAL_DEFER;
23608  return tree;
23609  }
23610 
23611  if (!pt_has_analytic (parser, tree) && !pt_has_inst_or_orderby_num (parser, tree))
23612  {
23613  /* no reason to split this expression tree, we can evaluate it in the initial scan */
23614  goto exit_return_ptr;
23615  }
23616 
23617  /* expression tree with analytic children; walk arguments */
23618  if (tree->info.expr.arg1 != NULL)
23619  {
23620  ret = pt_to_analytic_final_node (parser, tree->info.expr.arg1, ex_list, instnum_flag);
23621  if (ret != NULL)
23622  {
23623  tree->info.expr.arg1 = ret;
23624  }
23625  else
23626  {
23627  return NULL;
23628  }
23629  }
23630 
23631  if (tree->info.expr.arg2 != NULL)
23632  {
23633  ret = pt_to_analytic_final_node (parser, tree->info.expr.arg2, ex_list, instnum_flag);
23634  if (ret != NULL)
23635  {
23636  tree->info.expr.arg2 = ret;
23637  }
23638  else
23639  {
23640  return NULL;
23641  }
23642  }
23643 
23644  if (tree->info.expr.arg3 != NULL)
23645  {
23646  ret = pt_to_analytic_final_node (parser, tree->info.expr.arg3, ex_list, instnum_flag);
23647  if (ret != NULL)
23648  {
23649  tree->info.expr.arg3 = ret;
23650  }
23651  else
23652  {
23653  return NULL;
23654  }
23655  }
23656 
23657  /* we're left with final part of expression */
23658  return tree;
23659  }
23660 
23661  if (PT_IS_FUNCTION (tree) && pt_has_analytic (parser, tree))
23662  {
23663  PT_NODE *ret = NULL, *arg, *save_next;
23664 
23665  /* function with analytic arguments */
23666  arg = tree->info.function.arg_list;
23667  tree->info.function.arg_list = NULL;
23668 
23669  while (arg != NULL)
23670  {
23671  save_next = arg->next;
23672  arg->next = NULL;
23673 
23674  /* get final node */
23675  ret = pt_to_analytic_final_node (parser, arg, ex_list, instnum_flag);
23676  if (ret == NULL)
23677  {
23678  /* error was set */
23679  parser_free_tree (parser, arg);
23680  parser_free_tree (parser, save_next);
23681 
23682  return NULL;
23683  }
23684 
23686 
23687  /* advance */
23688  arg = save_next;
23689  }
23690 
23691  /* we're left with function with PT_NODE_POINTER arguments */
23692  return tree;
23693  }
23694 
23695 exit_return_ptr:
23696 
23697  /* analytic functions, subexpressions without analytic functions and other nodes go to the ex_list */
23698  ptr = pt_point_ref (parser, tree);
23699  if (ptr == NULL)
23700  {
23701  /* allocation failed */
23702  PT_ERROR (parser, tree,
23704  return NULL;
23705  }
23706 
23707  *ex_list = parser_append_node (tree, *ex_list);
23708 
23709  return ptr;
23710 }
23711 
23712 /*
23713  * pt_expand_analytic_node () - allocate value for result and set etc
23714  * returns: NULL on error, original node otherwise
23715  * parser(in): parser context
23716  * node(in): analytic node
23717  * select_list(in/out): select list to work on
23718  *
23719  * NOTE: this function alters the select list!
23720  */
23721 static PT_NODE *
23723 {
23724  PT_NODE *spec, *arg, *ptr;
23725  PT_NODE *old_ex_list = NULL, *new_ex_list = NULL;
23726  PT_NODE *last_node = NULL;
23727  bool visited_part = false;
23728 
23729  if (parser == NULL)
23730  {
23731  /* should not get here */
23732  assert (false);
23733  return NULL;
23734  }
23735 
23736  if (node == NULL || !PT_IS_ANALYTIC_NODE (node))
23737  {
23738  /* nothing to do */
23739  return node;
23740  }
23741 
23742  if (select_list == NULL)
23743  {
23744  PT_INTERNAL_ERROR (parser, "null select list for analytic expansion");
23745  return NULL;
23746  }
23747 
23748  /* add argument to select list */
23749  arg = node->info.function.arg_list;
23750  node->info.function.arg_list = NULL;
23751 
23752  if (arg != NULL)
23753  {
23754  if (arg->next != NULL)
23755  {
23756  /* more than one argument; not allowed */
23757  parser_free_tree (parser, arg);
23758 
23759  PT_INTERNAL_ERROR (parser, "multiple args for analytic function");
23760  return NULL;
23761  }
23762 
23763  /* add a pointer to the node to argument list */
23764  ptr = pt_point_ref (parser, arg);
23765  if (ptr == NULL)
23766  {
23767  /* allocation failed */
23768  parser_free_tree (parser, arg);
23769 
23770  PT_ERROR (parser, node,
23772  return NULL;
23773  }
23774 
23775  node->info.function.arg_list = ptr;
23776 
23777  /* add node to select list (select list is considered to be not null) */
23778  (void) parser_append_node (arg, select_list);
23779  }
23780 
23783  {
23784  /* add offset and default value expressions to select list */
23785  ptr = pt_point_ref (parser, node->info.function.analytic.offset);
23786  if (ptr == NULL)
23787  {
23788  PT_ERROR (parser, node,
23790  return NULL;
23791  }
23792  (void) parser_append_node (node->info.function.analytic.offset, select_list);
23793  node->info.function.analytic.offset = ptr;
23794 
23795  ptr = pt_point_ref (parser, node->info.function.analytic.default_value);
23796  if (ptr == NULL)
23797  {
23798  PT_ERROR (parser, node,
23800  return NULL;
23801  }
23802  (void) parser_append_node (node->info.function.analytic.default_value, select_list);
23803  node->info.function.analytic.default_value = ptr;
23804  }
23805 
23806  /* percentile for PERCENTILE_CONT and PERCENTILE_DISC */
23809  {
23810  ptr = pt_find_name (parser, node->info.function.percentile, select_list);
23811  /* add percentile expression to select list */
23812  if (ptr == NULL)
23813  {
23814  ptr = pt_point_ref (parser, node->info.function.percentile);
23815  parser_append_node (node->info.function.percentile, select_list);
23816  }
23817  else
23818  {
23819  ptr = pt_point_ref (parser, ptr);
23820  }
23821 
23822  if (ptr == NULL)
23823  {
23824  PT_ERROR (parser, node,
23826  return NULL;
23827  }
23828 
23829  node->info.function.percentile = ptr;
23830  }
23831 
23832  if (node->info.function.analytic.adjusted)
23833  {
23834  /* if old expanded list existed, append to the select list */
23835  if (node->info.function.analytic.expanded_list != NULL)
23836  {
23837  old_ex_list = parser_copy_tree_list (parser, node->info.function.analytic.expanded_list);
23838  if (old_ex_list == NULL)
23839  {
23841  return NULL;
23842  }
23843  (void) parser_append_node (old_ex_list, select_list);
23844  }
23845 
23846  return node;
23847  }
23848 
23849  /* get the last node of select_list */
23850  last_node = select_list;
23851  while (last_node->next != NULL)
23852  {
23853  last_node = last_node->next;
23854  }
23855 
23856  /* walk order list and resolve nodes that were not found in select list */
23857  spec = node->info.function.analytic.partition_by;
23858  if (spec == NULL)
23859  {
23860  spec = node->info.function.analytic.order_by;
23861  visited_part = true;
23862  }
23863 
23864  while (spec)
23865  {
23866  PT_NODE *val = NULL, *expr = NULL, *list = select_list, *last = NULL;
23867  int pos = 1; /* sort spec indexing starts from 1 */
23868 
23869  if (spec->node_type != PT_SORT_SPEC)
23870  {
23871  PT_INTERNAL_ERROR (parser, "invalid sort spec");
23872  return NULL;
23873  }
23874 
23875  /* pull sort expression */
23876  expr = spec->info.sort_spec.expr;
23877  if (expr == NULL)
23878  {
23879  PT_INTERNAL_ERROR (parser, "null sort expression");
23880  return NULL;
23881  }
23882 
23883  if (expr->node_type != PT_VALUE)
23884  {
23885  bool found = false;
23886 
23887  /* we have an actual expression; move it in the select list and put a position value here */
23888  while (list != NULL)
23889  {
23890  if ((list->node_type == PT_NAME || list->node_type == PT_DOT_)
23891  && (expr->node_type == PT_NAME || expr->node_type == PT_DOT_))
23892  {
23893  if (pt_check_path_eq (parser, list, expr) == 0)
23894  {
23895  found = true;
23896  break;
23897  }
23898  }
23899 
23900  last = list;
23901  list = list->next;
23902  pos++;
23903  }
23904 
23905  if (!found)
23906  {
23907  /* no match, add it in select list */
23908  last->next = expr;
23909  }
23910 
23911  /* unlink from sort spec */
23912  spec->info.sort_spec.expr = NULL;
23913 
23914  /* create new value spec */
23915  val = parser_new_node (parser, PT_VALUE);
23916  if (val == NULL)
23917  {
23919  return NULL;
23920  }
23921 
23922  val->type_enum = PT_TYPE_INTEGER;
23923  val->info.value.data_value.i = pos;
23924  (void) pt_value_to_db (parser, val);
23925 
23926  /* set value spec and position descriptor */
23927  spec->info.sort_spec.expr = val;
23928  spec->info.sort_spec.pos_descr.pos_no = pos;
23929 
23930  /* resolve domain */
23931  if (expr->type_enum != PT_TYPE_NONE && expr->type_enum != PT_TYPE_MAYBE)
23932  {
23933  spec->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, expr);
23934  }
23935 
23936  if (found)
23937  {
23938  /* cleanup */
23939  parser_free_tree (parser, expr);
23940  }
23941  }
23942 
23943  /* advance */
23944  spec = spec->next;
23945  if (spec == NULL && !visited_part)
23946  {
23947  spec = node->info.function.analytic.order_by;
23948  visited_part = true;
23949  }
23950  }
23951 
23952  /* Since the partition_by and order_by may be replaced as pt_value, the old expr should be reserved. */
23953  if (last_node->next != NULL)
23954  {
23955  new_ex_list = parser_copy_tree_list (parser, last_node->next);
23956  if (new_ex_list == NULL)
23957  {
23959  return NULL;
23960  }
23961 
23963  node->info.function.analytic.expanded_list = new_ex_list;
23964  }
23965 
23966  /* set the analytic has been adjusted and expanded */
23967  node->info.function.analytic.adjusted = true;
23968 
23969  /* all ok */
23970  return node;
23971 }
23972 
23973 /*
23974  * pt_set_analytic_node_etc () - allocate value for result and set etc
23975  * returns: NULL on error, input node otherwise
23976  * parser(in): parser context
23977  * node(in): analytic input node
23978  */
23979 static PT_NODE *
23981 {
23982  DB_VALUE *value;
23983 
23984  if (parser == NULL)
23985  {
23986  /* should not get here */
23987  assert (false);
23988  return node;
23989  }
23990 
23991  if (node == NULL || !PT_IS_ANALYTIC_NODE (node))
23992  {
23993  /* nothing to do */
23994  return node;
23995  }
23996 
23997  /* allocate DB_VALUE and store it in etc */
23998  regu_alloc (value);
23999  if (value == NULL)
24000  {
24001  PT_ERROR (parser, node,
24003  return NULL;
24004  }
24005 
24007  node->etc = (void *) value;
24008 
24009  /* all ok */
24010  return node;
24011 }
24012 
24013 /*
24014  * pt_adjust_analytic_sort_specs () - adjust analytic sort spec indices
24015  * parser(in): parser context
24016  * node(in): analytic node
24017  * idx(in): index of analytic node in list
24018  * adjust(in): amount to adjust for
24019  */
24020 static void
24022 {
24023  PT_NODE *spec;
24024 
24025  if (parser == NULL)
24026  {
24027  /* should not get here */
24028  assert (false);
24029  return;
24030  }
24031 
24032  if (node == NULL || !PT_IS_ANALYTIC_NODE (node))
24033  {
24034  /* nothing to do */
24035  return;
24036  }
24037 
24038  if (node->info.function.analytic.adjusted)
24039  {
24040  /* nothing to do */
24041  return;
24042  }
24043 
24044  /* walk sort specs and adjust */
24045  for (spec = node->info.function.analytic.order_by; spec; spec = spec->next)
24046  {
24047  if (!PT_IS_SORT_SPEC_NODE (spec) || !PT_IS_VALUE_NODE (spec->info.sort_spec.expr))
24048  {
24049  /* nothing to process */
24050  continue;
24051  }
24052 
24053  if (spec->info.sort_spec.pos_descr.pos_no > idx)
24054  {
24055  /* should be adjusted */
24056  spec->info.sort_spec.pos_descr.pos_no += adjust;
24057  spec->info.sort_spec.expr->info.value.data_value.i += adjust;
24058  spec->info.sort_spec.expr->info.value.db_value.data.i += adjust;
24059  }
24060  }
24061 
24062  for (spec = node->info.function.analytic.partition_by; spec; spec = spec->next)
24063  {
24064  if (!PT_IS_SORT_SPEC_NODE (spec) || !PT_IS_VALUE_NODE (spec->info.sort_spec.expr))
24065  {
24066  /* nothing to process */
24067  continue;
24068  }
24069 
24070  if (spec->info.sort_spec.pos_descr.pos_no > idx)
24071  {
24072  /* should be adjusted */
24073  spec->info.sort_spec.pos_descr.pos_no += adjust;
24074  spec->info.sort_spec.expr->info.value.data_value.i += adjust;
24075  spec->info.sort_spec.expr->info.value.db_value.data.i += adjust;
24076  }
24077  }
24078 }
24079 
24080 /*
24081  * pt_resolve_analytic_references () - resolve reference pointers to DB_VALUE
24082  * pointers of vallist
24083  * returns: NULL on error, original node otherwise
24084  * parser(in): parser context
24085  * node(in): node tree to resolve
24086  * select_list(in): select list to resolve to
24087  * vallist(in): value list
24088  *
24089  * NOTE: this function will look up in the select list any reference pointers
24090  * and will set the pointer's "etc" to the corresponding DB_VALUE in the
24091  * vallist.
24092  */
24093 static PT_NODE *
24095 {
24096  if (parser == NULL)
24097  {
24098  /* should not get here */
24099  assert (false);
24100  return node;
24101  }
24102 
24103  if (node == NULL)
24104  {
24105  /* nothing to do */
24106  return node;
24107  }
24108 
24109  if (PT_IS_POINTER_REF_NODE (node))
24110  {
24111  PT_NODE *real_node = node->info.pointer.node;
24112  PT_NODE *list = select_list;
24113  QPROC_DB_VALUE_LIST db_list = vallist->valp;
24114 
24115  /* get real node pointer */
24116  CAST_POINTER_TO_NODE (real_node);
24117 
24118  /* look it up in select list */
24119  for (; list && db_list; list = list->next, db_list = db_list->next)
24120  {
24121  if (list == real_node)
24122  {
24123  /* found */
24124  node->etc = (void *) db_list->val;
24125  return node;
24126  }
24127  }
24128 
24129  if (list == NULL)
24130  {
24131  PT_INTERNAL_ERROR (parser, "pointed node not found in select list");
24132  return NULL;
24133  }
24134  else
24135  {
24136  PT_INTERNAL_ERROR (parser, "invalid size of vallist");
24137  return NULL;
24138  }
24139  }
24140  else if (PT_IS_EXPR_NODE (node))
24141  {
24142  /* resolve expression arguments */
24143  if (node->info.expr.arg1
24144  && pt_resolve_analytic_references (parser, node->info.expr.arg1, select_list, vallist) == NULL)
24145  {
24146  return NULL;
24147  }
24148 
24149  if (node->info.expr.arg2
24150  && pt_resolve_analytic_references (parser, node->info.expr.arg2, select_list, vallist) == NULL)
24151  {
24152  return NULL;
24153  }
24154 
24155  if (node->info.expr.arg3
24156  && pt_resolve_analytic_references (parser, node->info.expr.arg3, select_list, vallist) == NULL)
24157  {
24158  return NULL;
24159  }
24160  }
24161  else if (PT_IS_FUNCTION (node))
24162  {
24163  PT_NODE *arg;
24164 
24165  /* resolve function arguments */
24166  for (arg = node->info.function.arg_list; arg; arg = arg->next)
24167  {
24168  if (pt_resolve_analytic_references (parser, arg, select_list, vallist) == NULL)
24169  {
24170  return NULL;
24171  }
24172  }
24173  }
24174 
24175  /* all ok */
24176  return node;
24177 }
24178 
24179 /*
24180  * pt_substitute_analytic_references () - substitute reference pointers to normal
24181  * nodes
24182  * return: processed node
24183  * parser(in): parser context
24184  * node(in): node tree to resolve
24185  */
24186 static PT_NODE *
24188 {
24189  if (parser == NULL)
24190  {
24191  /* should not get here */
24192  assert (false);
24193  return node;
24194  }
24195 
24196  if (node == NULL)
24197  {
24198  /* nothing to do */
24199  return node;
24200  }
24201 
24202  if (PT_IS_POINTER_REF_NODE (node))
24203  {
24204  PT_NODE *real_node = node->info.pointer.node;
24205  PT_NODE *list, *prev = NULL;
24206 
24207  /* unlink from extended list */
24208  for (list = *ex_list; list; list = list->next)
24209  {
24210  if (list == real_node)
24211  {
24212  if (prev != NULL)
24213  {
24214  prev->next = real_node->next;
24215  }
24216  else
24217  {
24218  /* first node in list */
24219  *ex_list = real_node->next;
24220  }
24221 
24222  break;
24223  }
24224 
24225  /* keep previous */
24226  prev = list;
24227  }
24228 
24229  /* unlink real node */
24230  real_node->next = NULL;
24231 
24232  /* dispose of this node */
24233  node->info.pointer.node = NULL;
24234  parser_free_node (parser, node);
24235 
24236  /* return real node */
24237  return real_node;
24238  }
24239  else if (PT_IS_EXPR_NODE (node))
24240  {
24241  PT_NODE *ret;
24242 
24243  /* walk expression arguments */
24244  if (node->info.expr.arg1)
24245  {
24246  ret = pt_substitute_analytic_references (parser, node->info.expr.arg1, ex_list);
24247  if (ret != NULL)
24248  {
24249  node->info.expr.arg1 = ret;
24250  }
24251  else
24252  {
24253  return NULL;
24254  }
24255  }
24256 
24257  if (node->info.expr.arg2)
24258  {
24259  ret = pt_substitute_analytic_references (parser, node->info.expr.arg2, ex_list);
24260  if (ret != NULL)
24261  {
24262  node->info.expr.arg2 = ret;
24263  }
24264  else
24265  {
24266  return NULL;
24267  }
24268  }
24269 
24270  if (node->info.expr.arg3)
24271  {
24272  ret = pt_substitute_analytic_references (parser, node->info.expr.arg3, ex_list);
24273  if (ret != NULL)
24274  {
24275  node->info.expr.arg3 = ret;
24276  }
24277  else
24278  {
24279  return NULL;
24280  }
24281  }
24282 
24283  return node;
24284  }
24285  else if (PT_IS_FUNCTION (node))
24286  {
24287  PT_NODE *prev = NULL;
24288  for (PT_NODE * arg = node->info.function.arg_list; arg != NULL; arg = arg->next)
24289  {
24290  PT_NODE *save_next = arg->next;
24291 
24292  PT_NODE *ret = pt_substitute_analytic_references (parser, arg, ex_list);
24293  if (ret == NULL)
24294  {
24295  /* error has been set */
24296  parser_free_tree (parser, arg);
24297  parser_free_tree (parser, save_next);
24298 
24299  return NULL;
24300  }
24301 
24302  if (arg != ret)
24303  {
24304  if (prev != NULL)
24305  {
24306  prev->next = arg = ret;
24307  arg->next = save_next;
24308  }
24309  else
24310  {
24311  node->info.function.arg_list = arg = ret;
24312  arg->next = save_next;
24313  }
24314  }
24315 
24316  prev = arg;
24317  }
24318 
24319  return node;
24320  }
24321  else
24322  {
24323  PT_INTERNAL_ERROR (parser, "invalid node type");
24324  return NULL;
24325  }
24326 }
24327 
24328 /*
24329  * pt_get_pred_attrs () - get index filter predicate attributtes
24330  * return: error code
24331  * table_info(in): table info
24332  * pred(in): filter predicate parse tree
24333  * pred_attrs(in/out): filter predicate attributes
24334  */
24335 static int
24337 {
24338  PT_NODE *tmp = NULL, *pointer = NULL, *real_attrs = NULL;
24339  PT_NODE *pred_nodes = NULL;
24340  PT_NODE *node = NULL, *save_node = NULL, *save_next = NULL, *ref_node = NULL;
24341 
24342  /* TO DO : check memory allocation */
24343  if (pred_attrs == NULL || table_info == NULL || table_info->class_spec == NULL)
24344  {
24345  return ER_FAILED;
24346  }
24347 
24348  *pred_attrs = NULL;
24349  /* mq_get_references() is destructive to the real set of referenced attrs, so we need to squirrel it away. */
24350  real_attrs = table_info->class_spec->info.spec.referenced_attrs;
24351  table_info->class_spec->info.spec.referenced_attrs = NULL;
24352 
24353  /* Traverse pred */
24354  for (node = pred; node; node = node->next)
24355  {
24356  save_node = node; /* save */
24357 
24358  CAST_POINTER_TO_NODE (node);
24359 
24360  if (node)
24361  {
24362  /* save and cut-off node link */
24363  save_next = node->next;
24364  node->next = NULL;
24365 
24366  ref_node = mq_get_references (parser, node, table_info->class_spec);
24367  pred_nodes = parser_append_node (ref_node, pred_nodes);
24368 
24369  /* restore node link */
24370  node->next = save_next;
24371  }
24372 
24373  node = save_node; /* restore */
24374  } /* for (node = ...) */
24375 
24376  table_info->class_spec->info.spec.referenced_attrs = real_attrs;
24377 
24378  tmp = pred_nodes;
24379  while (tmp)
24380  {
24381  pointer = pt_point (parser, tmp);
24382  if (pointer == NULL)
24383  {
24384  goto exit_on_error;
24385  }
24386 
24387  *pred_attrs = parser_append_node (pointer, *pred_attrs);
24388  tmp = tmp->next;
24389  }
24390 
24391  return NO_ERROR;
24392 
24393 exit_on_error:
24394 
24395  if (*pred_attrs)
24396  {
24397  parser_free_tree (parser, *pred_attrs);
24398  }
24399  if (pred_nodes)
24400  {
24401  parser_free_tree (parser, pred_nodes);
24402  }
24403 
24404  return ER_FAILED;
24405 }
24406 
24407 /*
24408  * pt_to_func_pred () - converts an expression parse tree to a
24409  * FUNC_PRED structure
24410  * return:
24411  * parser(in):
24412  * spec (in) :
24413  * expr(in):
24414  */
24415 FUNC_PRED *
24417 {
24418  DB_OBJECT *class_obj = NULL;
24419  MOBJ class_ = NULL;
24420  HFID *hfid = NULL;
24422  SYMBOL_INFO *symbols = NULL;
24424 
24425  if (parser == NULL || expr == NULL || spec == NULL)
24426  {
24427  return NULL;
24428  }
24429  if ((parser->symbols = pt_symbol_info_alloc ()) == NULL)
24430  {
24431  goto outofmem;
24432  }
24433  symbols = parser->symbols;
24434 
24435  symbols->table_info = pt_make_table_info (parser, spec);
24436  if (symbols->table_info == NULL)
24437  {
24438  goto outofmem;
24439  }
24440 
24441  table_info = symbols->table_info;
24442  /* should be only one node in flat_entity_list */
24443  symbols->current_class = spec->info.spec.flat_entity_list;
24444  regu_alloc (symbols->cache_attrinfo);
24445  if (symbols->cache_attrinfo == NULL)
24446  {
24447  goto outofmem;
24448  }
24449  table_info->class_spec = spec;
24450  table_info->exposed = spec->info.spec.range_var->info.name.original;
24451  table_info->spec_id = spec->info.spec.id;
24452  /* don't care about attribute_list and value_list */
24453  table_info->attribute_list = NULL;
24454  table_info->value_list = NULL;
24455 
24456  /* flush the class, just to be sure */
24457  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
24458  class_ = locator_create_heap_if_needed (class_obj, sm_is_reuse_oid_class (class_obj));
24459  if (class_ == NULL)
24460  {
24461  return NULL;
24462  }
24463 
24464  hfid = sm_ch_heap (class_);
24465  if (hfid == NULL)
24466  {
24467  return NULL;
24468  }
24469 
24470  regu_alloc (func_pred);
24471  if (func_pred)
24472  {
24473  func_pred->func_regu = pt_to_regu_variable (parser, expr, UNBOX_AS_VALUE);
24474  func_pred->cache_attrinfo = symbols->cache_attrinfo;
24475  }
24476 
24477  if (pt_has_error (parser))
24478  {
24479  pt_report_to_ersys (parser, PT_SEMANTIC);
24480  func_pred = NULL;
24481  }
24482 
24483  return func_pred;
24484 
24485 outofmem:
24487 
24488  return NULL;
24489 }
24490 
24491 /*
24492  * validate_regu_key_function_index () - checks if a regu variable can be used
24493  * as key information when the index scan
24494  * uses a function index.
24495  * return:
24496  * regu_var(in):
24497  */
24498 static bool
24500 {
24501  /* if add it here, add it to pt_expr_is_allowed_as_function_index() as well */
24502  if (regu_var->type == TYPE_INARITH)
24503  {
24504  switch (regu_var->value.arithptr->opcode)
24505  {
24506  case T_MOD:
24507  case T_LEFT:
24508  case T_RIGHT:
24509  case T_REPEAT:
24510  case T_SPACE:
24511  case T_MID:
24512  case T_STRCMP:
24513  case T_REVERSE:
24514  case T_BIT_COUNT:
24515  case T_FLOOR:
24516  case T_CEIL:
24517  case T_ABS:
24518  case T_POWER:
24519  case T_ROUND:
24520  case T_LOG:
24521  case T_EXP:
24522  case T_SQRT:
24523  case T_SIN:
24524  case T_COS:
24525  case T_TAN:
24526  case T_COT:
24527  case T_ACOS:
24528  case T_ASIN:
24529  case T_ATAN:
24530  case T_ATAN2:
24531  case T_DEGREES:
24532  case T_DATE:
24533  case T_TIME:
24534  case T_RADIANS:
24535  case T_LN:
24536  case T_LOG2:
24537  case T_LOG10:
24538  case T_TRUNC:
24539  case T_CHR:
24540  case T_INSTR:
24541  case T_LEAST:
24542  case T_GREATEST:
24543  case T_POSITION:
24544  case T_LOWER:
24545  case T_UPPER:
24546  case T_CHAR_LENGTH:
24547  case T_LTRIM:
24548  case T_RTRIM:
24549  case T_FROM_UNIXTIME:
24550  case T_SUBSTRING_INDEX:
24551  case T_MD5:
24552  case T_AES_ENCRYPT:
24553  case T_AES_DECRYPT:
24554  case T_SHA_ONE:
24555  case T_SHA_TWO:
24556  case T_LPAD:
24557  case T_RPAD:
24558  case T_REPLACE:
24559  case T_TRANSLATE:
24560  case T_ADD_MONTHS:
24561  case T_LAST_DAY:
24562  case T_UNIX_TIMESTAMP:
24563  case T_STR_TO_DATE:
24564  case T_TIME_FORMAT:
24565  case T_TIMESTAMP:
24566  case T_YEAR:
24567  case T_MONTH:
24568  case T_DAY:
24569  case T_HOUR:
24570  case T_MINUTE:
24571  case T_SECOND:
24572  case T_QUARTER:
24573  case T_WEEKDAY:
24574  case T_DAYOFWEEK:
24575  case T_DAYOFYEAR:
24576  case T_TODAYS:
24577  case T_FROMDAYS:
24578  case T_TIMETOSEC:
24579  case T_SECTOTIME:
24580  case T_MAKEDATE:
24581  case T_MAKETIME:
24582  case T_WEEK:
24583  case T_MONTHS_BETWEEN:
24584  case T_FORMAT:
24585  case T_DATE_FORMAT:
24586  case T_ADDDATE:
24587  case T_DATE_ADD:
24588  case T_DATEDIFF:
24589  case T_TIMEDIFF:
24590  case T_SUBDATE:
24591  case T_DATE_SUB:
24592  case T_BIT_LENGTH:
24593  case T_OCTET_LENGTH:
24594  case T_IFNULL:
24595  case T_LOCATE:
24596  case T_SUBSTRING:
24597  case T_NVL:
24598  case T_NVL2:
24599  case T_NULLIF:
24600  case T_TO_CHAR:
24601  case T_TO_DATE:
24602  case T_TO_DATETIME:
24603  case T_TO_TIMESTAMP:
24604  case T_TO_TIME:
24605  case T_TO_NUMBER:
24606  case T_TRIM:
24607  case T_INET_ATON:
24608  case T_INET_NTOA:
24609  case T_TO_BASE64:
24610  case T_FROM_BASE64:
24611  case T_TZ_OFFSET:
24612  case T_TO_DATETIME_TZ:
24613  case T_TO_TIMESTAMP_TZ:
24614  case T_CRC32:
24615  case T_CONV_TZ:
24616  break;
24617  default:
24618  return true;
24619  }
24620  if (regu_var->value.arithptr->leftptr && !VALIDATE_REGU_KEY_HELPER (regu_var->value.arithptr->leftptr))
24621  {
24622  return false;
24623  }
24624  if (regu_var->value.arithptr->rightptr && !VALIDATE_REGU_KEY_HELPER (regu_var->value.arithptr->rightptr))
24625  {
24626  return false;
24627  }
24628  if (regu_var->value.arithptr->thirdptr && !VALIDATE_REGU_KEY_HELPER (regu_var->value.arithptr->thirdptr))
24629  {
24630  return false;
24631  }
24632  return true;
24633  }
24634  return true;
24635 }
24636 
24637 /*
24638  * pt_to_merge_update_query () - Creates a query for MERGE UPDATE part
24639  * return: resulted query, or NULL if error
24640  * parser(in): parser context
24641  * select_list(in): nodes for select list
24642  * info(in): MERGE statement info
24643  *
24644  * Note: Prepends the class oid and the instance oid onto the select list for
24645  * use during the update operation.
24646  * If the operation is a server side update, the prepended class oid is
24647  * put in the list file otherwise the class oid is a hidden column and
24648  * not put in the list file.
24649  */
24650 PT_NODE *
24652 {
24653  PT_NODE *statement, *where, *group_by, *oid, *save_next;
24654 
24655  statement = parser_new_node (parser, PT_SELECT);
24656  if (!statement)
24657  {
24658  PT_INTERNAL_ERROR (parser, "allocate new node");
24659  return NULL;
24660  }
24661 
24662  /* substitute updated columns in delete pred and add it to select list */
24663  if (info->update.has_delete)
24664  {
24665  PT_NODE *node, *del_search_cond;
24666  del_search_cond = parser_copy_tree_list (parser, info->update.del_search_cond);
24667  if (del_search_cond)
24668  {
24669  (void) parser_walk_tree (parser, del_search_cond, NULL, NULL, pt_substitute_assigned_name_node,
24670  (void *) info->update.assignment);
24671  }
24672  else
24673  {
24674  /* delete where (true) */
24675  del_search_cond = pt_make_integer_value (parser, 1);
24676  if (del_search_cond == NULL)
24677  {
24678  PT_INTERNAL_ERROR (parser, "allocate new node");
24679  return NULL;
24680  }
24681  }
24682 
24683  node = parser_new_node (parser, PT_EXPR);
24684  if (node)
24685  {
24686  node->info.expr.op = PT_NE;
24687  node->info.expr.arg1 = del_search_cond;
24688  node->info.expr.arg2 = pt_make_integer_value (parser, 0);
24689  if (node->info.expr.arg2 == NULL)
24690  {
24691  parser_free_tree (parser, node);
24692  parser_free_tree (parser, del_search_cond);
24693  PT_INTERNAL_ERROR (parser, "allocate new node");
24694  return NULL;
24695  }
24696  }
24697  else
24698  {
24699  parser_free_tree (parser, del_search_cond);
24700  PT_INTERNAL_ERROR (parser, "allocate new node");
24701  return NULL;
24702  }
24703 
24704  node->next = select_list;
24705  select_list = node;
24706  }
24707 
24708  /* set select list */
24709  statement->info.query.q.select.list = parser_copy_tree_list (parser, select_list);
24710 
24711  /* set spec list */
24712  statement->info.query.q.select.from = parser_copy_tree_list (parser, info->into);
24713  /* add the class and instance OIDs to the select list */
24714  statement = pt_add_row_classoid_name (parser, statement, (info->flags & PT_MERGE_INFO_SERVER_OP));
24715  statement = pt_add_row_oid_name (parser, statement);
24716  /* add source table to spec */
24717  statement->info.query.q.select.from =
24719 
24720  /* set search condition */
24721  if (info->update.search_cond)
24722  {
24723  if (info->search_cond)
24724  {
24725  where = parser_new_node (parser, PT_EXPR);
24726  if (where)
24727  {
24728  where->info.expr.op = PT_AND;
24729  where->info.expr.arg1 = parser_copy_tree_list (parser, info->search_cond);
24730  where->info.expr.arg2 = parser_copy_tree_list (parser, info->update.search_cond);
24731  }
24732  else
24733  {
24734  PT_INTERNAL_ERROR (parser, "allocate new node");
24735  return NULL;
24736  }
24737  }
24738  else
24739  {
24740  where = parser_copy_tree_list (parser, info->update.search_cond);
24741  }
24742  }
24743  else
24744  {
24745  where = parser_copy_tree_list (parser, info->search_cond);
24746  }
24747  statement->info.query.q.select.where = where;
24748 
24749  /* add group by */
24750  group_by = parser_new_node (parser, PT_SORT_SPEC);
24751  if (group_by)
24752  {
24753  oid = statement->info.query.q.select.list;
24754  save_next = oid->next;
24755  oid->next = NULL;
24756  group_by->info.sort_spec.expr = parser_copy_tree_list (parser, oid);
24757  group_by->info.sort_spec.asc_or_desc = PT_ASC;
24758  group_by->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, oid);
24759  group_by->info.sort_spec.pos_descr.pos_no = 1;
24760  oid->next = save_next;
24761  statement->info.query.q.select.group_by = group_by;
24763  }
24764  else
24765  {
24766  PT_INTERNAL_ERROR (parser, "allocate new node");
24767  return NULL;
24768  }
24769 
24770  statement->info.query.upd_del_class_cnt = 1;
24771  statement->info.query.scan_op_type = S_UPDATE;
24774 
24775  /* no strict oid checking for generated subquery */
24777 
24778  /* we don't need to keep this query */
24779  statement->flag.cannot_prepare = 1;
24780 
24781  /* set index hint */
24782  if (info->hint & PT_HINT_USE_UPDATE_IDX)
24783  {
24784  statement->info.query.q.select.using_index = parser_copy_tree_list (parser, info->update.index_hint);
24785  }
24786 
24788  {
24790  }
24791 
24792  return statement;
24793 }
24794 
24795 /*
24796  * pt_to_merge_insert_query () - Creates a query for MERGE INSERT part
24797  * return: resulted query, or NULL if error
24798  * parser(in): parser context
24799  * select_list(in): nodes for select list
24800  * info(in): MERGE statement info
24801  *
24802  */
24803 PT_NODE *
24805 {
24806  PT_NODE *subq, *corr_subq, *expr, *and_expr, *value;
24807 
24808  subq = parser_new_node (parser, PT_SELECT);
24809  if (subq == NULL)
24810  {
24811  goto error_exit;
24812  }
24813 
24814  corr_subq = parser_new_node (parser, PT_SELECT);
24815  if (corr_subq == NULL)
24816  {
24817  parser_free_tree (parser, subq);
24818  goto error_exit;
24819  }
24820 
24821  expr = parser_new_node (parser, PT_FUNCTION);
24822  if (expr == NULL)
24823  {
24824  parser_free_tree (parser, subq);
24825  parser_free_tree (parser, corr_subq);
24826  goto error_exit;
24827  }
24828 
24829  expr->type_enum = PT_TYPE_INTEGER;
24830  expr->info.function.arg_list = NULL;
24832 
24833  corr_subq->info.query.q.select.list = expr;
24834  corr_subq->info.query.q.select.from = parser_copy_tree (parser, info->into);
24835  corr_subq->info.query.q.select.where = parser_copy_tree_list (parser, info->search_cond);
24836  /* add class where part */
24837  if (info->insert.class_where)
24838  {
24839  corr_subq->info.query.q.select.where =
24841  corr_subq->info.query.q.select.where);
24842  }
24843 
24844  corr_subq->info.query.q.select.flavor = PT_USER_SELECT;
24845  corr_subq->info.query.is_subquery = PT_IS_SUBQUERY;
24846  corr_subq->info.query.correlation_level = 1;
24847  corr_subq->info.query.flag.single_tuple = 1;
24848 
24849  /* set index hint */
24850  if (info->hint & PT_HINT_USE_INSERT_IDX)
24851  {
24852  corr_subq->info.query.q.select.using_index = parser_copy_tree_list (parser, info->insert.index_hint);
24853  }
24854 
24855  subq->info.query.q.select.list = parser_copy_tree_list (parser, select_list);
24856  subq->info.query.q.select.from = parser_copy_tree (parser, info->using_clause);
24857 
24858  expr = parser_new_node (parser, PT_EXPR);
24859  if (expr == NULL)
24860  {
24861  parser_free_tree (parser, subq);
24862  parser_free_tree (parser, corr_subq);
24863  goto error_exit;
24864  }
24865 
24866  value = parser_new_node (parser, PT_VALUE);
24867  if (value == NULL)
24868  {
24869  parser_free_tree (parser, subq);
24870  parser_free_tree (parser, corr_subq);
24871  parser_free_tree (parser, expr);
24872  goto error_exit;
24873  }
24874 
24875  value->type_enum = PT_TYPE_INTEGER;
24876  value->info.value.data_value.i = 0;
24877 
24878  expr->type_enum = PT_TYPE_LOGICAL;
24879  expr->info.expr.op = PT_EQ;
24880  expr->info.expr.arg1 = corr_subq;
24881  expr->info.expr.arg2 = value;
24882 
24883  if (info->insert.search_cond)
24884  {
24885  and_expr = parser_new_node (parser, PT_EXPR);
24886  if (and_expr == NULL)
24887  {
24888  parser_free_tree (parser, subq);
24889  parser_free_tree (parser, expr); /* corr_subq is now in this tree */
24890  goto error_exit;
24891  }
24892 
24893  and_expr->type_enum = PT_TYPE_LOGICAL;
24894  and_expr->info.expr.op = PT_AND;
24895  and_expr->info.expr.arg1 = expr;
24896  and_expr->info.expr.arg2 = parser_copy_tree_list (parser, info->insert.search_cond);
24897 
24898  subq->info.query.q.select.where = and_expr;
24899  }
24900  else
24901  {
24902  subq->info.query.q.select.where = expr;
24903  }
24905 
24906  /* we don't need to keep this query */
24907  subq->flag.cannot_prepare = 1;
24908 
24909  return subq;
24910 
24911 error_exit:
24912  PT_INTERNAL_ERROR (parser, "allocate new node");
24913  return NULL;
24914 }
24915 
24916 /*
24917  * pt_to_merge_xasl () - Generate XASL for MERGE statement
24918  * return:
24919  * parser(in):
24920  * statement(in):
24921  * non_null_upd_attrs(in):
24922  * non_null_ins_attrs(in):
24923  * default_expr_attrs(in):
24924  */
24925 XASL_NODE *
24926 pt_to_merge_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_upd_attrs,
24927  PT_NODE ** non_null_ins_attrs, PT_NODE * default_expr_attrs)
24928 {
24929  XASL_NODE *xasl, *xptr;
24930  XASL_NODE *update_xasl = NULL, *insert_xasl = NULL;
24931  OID *oid = NULL;
24932  int error = NO_ERROR;
24933  bool insert_only = (statement->info.merge.flags & PT_MERGE_INFO_INSERT_ONLY);
24934 
24936  if (xasl == NULL)
24937  {
24938  assert (er_errid () != NO_ERROR);
24939  error = er_errid ();
24940  if (error == NO_ERROR)
24941  {
24942  error = ER_GENERIC_ERROR;
24943  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
24944  }
24945  return NULL;
24946  }
24947 
24948  if (statement->info.merge.update.assignment && !insert_only)
24949  {
24950  /* generate XASL for UPDATE part */
24951  update_xasl = pt_to_merge_update_xasl (parser, statement, non_null_upd_attrs);
24952  if (update_xasl == NULL)
24953  {
24954  return NULL;
24955  }
24956  }
24957 
24958  if (statement->info.merge.insert.value_clauses)
24959  {
24960  /* generate XASL for INSERT part */
24961  insert_xasl = pt_to_merge_insert_xasl (parser, statement, *non_null_ins_attrs, default_expr_attrs);
24962  if (insert_xasl == NULL)
24963  {
24964  return NULL;
24965  }
24966  }
24967 
24968  /* finalize XASL */
24969  xasl->proc.merge.update_xasl = update_xasl;
24970  xasl->proc.merge.insert_xasl = insert_xasl;
24971  xasl->proc.merge.has_delete = statement->info.merge.update.has_delete;
24972  xasl->query_alias = statement->alias_print;
24973 
24974  if ((oid = ws_identifier (db_get_user ())) != NULL)
24975  {
24976  COPY_OID (&xasl->creator_oid, oid);
24977  }
24978  else
24979  {
24980  OID_SET_NULL (&xasl->creator_oid);
24981  }
24982 
24983  /* list of class OIDs used in this XASL */
24984  xptr = (update_xasl ? update_xasl : insert_xasl);
24985 
24988  xasl->tcard_list = regu_int_array_alloc (xptr->n_oid_list);
24989  if (xasl->class_oid_list == NULL || xasl->class_locks == NULL || xasl->tcard_list == NULL)
24990  {
24991  assert (er_errid () != NO_ERROR);
24992  error = er_errid ();
24993  if (error == NO_ERROR)
24994  {
24995  error = ER_GENERIC_ERROR;
24996  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
24997  }
24998  return NULL;
24999  }
25000 
25001  xasl->n_oid_list = xptr->n_oid_list;
25002 
25003  /* copy xptr oids to xasl */
25004  (void) memcpy (xasl->class_oid_list, xptr->class_oid_list, sizeof (OID) * xptr->n_oid_list);
25005  (void) memcpy (xasl->class_locks, xptr->class_locks, sizeof (int) * xptr->n_oid_list);
25006  (void) memcpy (xasl->tcard_list, xptr->tcard_list, sizeof (int) * xptr->n_oid_list);
25007 
25008  /* set host variable count */
25009  xasl->dbval_cnt = parser->dbval_cnt;
25010 
25011  /* set TDE flag */
25012  XASL_SET_FLAG (xasl, xptr->flag & XASL_INCLUDES_TDE_CLASS);
25013 
25014  return xasl;
25015 }
25016 
25017 /*
25018  * pt_to_merge_update_xasl () - Generate XASL for UPDATE part of MERGE
25019  * return:
25020  * parser(in):
25021  * statement(in):
25022  * non_null_attrs(in):
25023  */
25024 static XASL_NODE *
25025 pt_to_merge_update_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_attrs)
25026 {
25027  XASL_NODE *xasl = NULL, *aptr;
25028  UPDATE_PROC_NODE *update = NULL;
25029  UPDDEL_CLASS_INFO *upd_cls = NULL;
25030  PT_NODE *assigns = statement->info.merge.update.assignment;
25031  PT_NODE *aptr_statement = NULL;
25032  PT_NODE *p = NULL;
25033  PT_NODE *cl_name_node = NULL;
25034  int num_subclasses = 0;
25035  PT_NODE *from = NULL;
25036  int cl = 0, num_vals = 0, num_consts = 0;
25037  int error = NO_ERROR;
25038  int a = 0, assign_idx = 0, attr_offset = 0;
25039  PT_NODE *att_name_node = NULL;
25040  DB_VALUE *val = NULL;
25041  DB_ATTRIBUTE *attr = NULL;
25042  DB_DOMAIN *dom = NULL;
25043  OID *class_oid = NULL;
25044  DB_OBJECT *class_obj = NULL;
25045  HFID *hfid = NULL;
25046  PT_NODE *hint_arg = NULL;
25047  PT_ASSIGNMENTS_HELPER assign_helper;
25048  PT_NODE **links = NULL;
25049  UPDATE_ASSIGNMENT *assign = NULL;
25050  PT_NODE *select_names = NULL;
25051  PT_NODE *select_values = NULL;
25052  PT_NODE *const_names = NULL;
25053  PT_NODE *const_values = NULL;
25054  OID *oid = NULL;
25055  PT_MERGE_INFO *info = &statement->info.merge;
25056  PT_NODE *copy_assigns, *save_assigns;
25057 
25058  from = parser_copy_tree (parser, info->into);
25059  from = parser_append_node (parser_copy_tree_list (parser, info->using_clause), from);
25060 
25061  if (from == NULL || from->node_type != PT_SPEC || from->info.spec.range_var == NULL)
25062  {
25063  PT_INTERNAL_ERROR (parser, "invalid spec");
25064  goto cleanup;
25065  }
25066 
25067  error = pt_append_omitted_on_update_expr_assignments (parser, assigns, from);
25068  if (error != NO_ERROR)
25069  {
25070  PT_INTERNAL_ERROR (parser, "merge update");
25071  goto cleanup;
25072  }
25073 
25074  /* make a copy of assignment list to be able to iterate later */
25075  copy_assigns = parser_copy_tree_list (parser, info->update.assignment);
25076 
25077  /* get assignments lists for select statement generation */
25078  error =
25079  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &num_vals, &num_consts,
25080  info->update.assignment, &links);
25081  if (error != NO_ERROR)
25082  {
25083  PT_INTERNAL_ERROR (parser, "merge update");
25084  parser_free_tree (parser, copy_assigns);
25085  goto cleanup;
25086  }
25087 
25088  /* save assignment list and replace within statement with the copy */
25089  save_assigns = info->update.assignment;
25090  info->update.assignment = copy_assigns;
25091 
25092  aptr_statement = pt_to_merge_update_query (parser, select_values, info);
25093 
25094  /* restore assignment list and destroy the copy */
25095  info->update.assignment = save_assigns;
25096  parser_free_tree (parser, copy_assigns);
25097 
25098  /* restore tree structure; pt_get_assignment_lists() */
25099  pt_restore_assignment_links (info->update.assignment, links, -1);
25100 
25101  if (aptr_statement == NULL)
25102  {
25103  assert (er_errid () != NO_ERROR);
25104  error = er_errid ();
25105  if (error == NO_ERROR && !pt_has_error (parser))
25106  {
25107  error = ER_GENERIC_ERROR;
25108  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25109  }
25110  goto cleanup;
25111  }
25112 
25113  aptr_statement = mq_translate (parser, aptr_statement);
25114  if (aptr_statement == NULL)
25115  {
25116  if (pt_has_error (parser))
25117  {
25118  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, aptr_statement);
25119  }
25120  error = er_errid ();
25121  if (error == NO_ERROR)
25122  {
25123  error = ER_GENERIC_ERROR;
25124  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25125  }
25126  goto cleanup;
25127  }
25128 
25129  xasl = pt_make_aptr_parent_node (parser, aptr_statement, UPDATE_PROC);
25130  if (xasl == NULL || xasl->aptr_list == NULL)
25131  {
25132  assert (er_errid () != NO_ERROR);
25133  error = er_errid ();
25134  if (error == NO_ERROR && !pt_has_error (parser))
25135  {
25136  error = ER_GENERIC_ERROR;
25137  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25138  }
25139  goto cleanup;
25140  }
25141 
25142  /* flush all classes */
25143  p = from;
25144  while (p != NULL)
25145  {
25146  cl_name_node = p->info.spec.flat_entity_list;
25147  while (cl_name_node != NULL)
25148  {
25149  error = locator_flush_class (cl_name_node->info.name.db_object);
25150  if (error != NO_ERROR)
25151  {
25152  goto cleanup;
25153  }
25154  cl_name_node = cl_name_node->next;
25155  }
25156  p = p->next;
25157  }
25158 
25159  update = &xasl->proc.update;
25160 
25161  update->num_classes = 1;
25162  update->num_assigns = num_vals;
25163 
25164  regu_array_alloc (&update->classes, 1);
25165  if (update->classes == NULL)
25166  {
25167  assert (er_errid () != NO_ERROR);
25168  error = er_errid ();
25169  if (error == NO_ERROR)
25170  {
25171  error = ER_GENERIC_ERROR;
25172  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25173  }
25174  goto cleanup;
25175  }
25176 
25177  regu_array_alloc (&update->assigns, update->num_assigns);
25178  if (update->assigns == NULL)
25179  {
25180  assert (er_errid () != NO_ERROR);
25181  error = er_errid ();
25182  if (error == NO_ERROR)
25183  {
25184  error = ER_GENERIC_ERROR;
25185  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25186  }
25187  goto cleanup;
25188  }
25189 
25190  upd_cls = &update->classes[0];
25191 
25192  upd_cls->has_uniques = (from->info.spec.flag & PT_SPEC_FLAG_HAS_UNIQUE);
25193 
25194  /* count subclasses of update class */
25195  num_subclasses = 0;
25196  cl_name_node = from->info.spec.flat_entity_list;
25197  while (cl_name_node)
25198  {
25199  num_subclasses++;
25200  cl_name_node = cl_name_node->next;
25201  }
25202  upd_cls->num_subclasses = num_subclasses;
25203 
25204  /* count class assignments */
25205  a = 0;
25206  pt_init_assignments_helper (parser, &assign_helper, assigns);
25207  while (pt_get_next_assignment (&assign_helper) != NULL)
25208  {
25209  if (assign_helper.lhs->info.name.spec_id == from->info.spec.id)
25210  {
25211  a++;
25212  }
25213  }
25214  upd_cls->num_attrs = a;
25215 
25216  /* allocate array for subclasses OIDs, hfids, attributes ids */
25217  upd_cls->class_oid = regu_oid_array_alloc (num_subclasses);
25218  if (upd_cls->class_oid == NULL)
25219  {
25220  assert (er_errid () != NO_ERROR);
25221  error = er_errid ();
25222  if (error == NO_ERROR)
25223  {
25224  error = ER_GENERIC_ERROR;
25225  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25226  }
25227  goto cleanup;
25228  }
25229 
25230  regu_array_alloc (&upd_cls->class_hfid, num_subclasses);
25231  if (upd_cls->class_hfid == NULL)
25232  {
25233  assert (er_errid () != NO_ERROR);
25234  error = er_errid ();
25235  if (error == NO_ERROR)
25236  {
25237  error = ER_GENERIC_ERROR;
25238  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25239  }
25240  goto cleanup;
25241  }
25242 
25243  upd_cls->att_id = regu_int_array_alloc (num_subclasses * upd_cls->num_attrs);
25244  if (upd_cls->att_id == NULL)
25245  {
25246  assert (er_errid () != NO_ERROR);
25247  error = er_errid ();
25248  if (error == NO_ERROR)
25249  {
25250  error = ER_GENERIC_ERROR;
25251  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25252  }
25253  goto cleanup;
25254  }
25255 
25256  cl_name_node = from->info.spec.flat_entity_list;
25257  class_obj = cl_name_node->info.name.db_object;
25258  error = sm_partitioned_class_type (class_obj, &upd_cls->needs_pruning, NULL, NULL);
25259  if (error != NO_ERROR)
25260  {
25261  goto cleanup;
25262  }
25263 
25264  /* iterate through subclasses */
25265  cl = 0;
25266  cl_name_node = from->info.spec.flat_entity_list;
25267  while (cl_name_node && error == NO_ERROR)
25268  {
25269  class_obj = cl_name_node->info.name.db_object;
25270 
25271  /* get class oid */
25272  class_oid = ws_identifier (class_obj);
25273  if (class_oid == NULL)
25274  {
25276  error = ER_HEAP_UNKNOWN_OBJECT;
25277  goto cleanup;
25278  }
25279 
25280  /* get hfid */
25281  hfid = sm_get_ch_heap (class_obj);
25282  if (hfid == NULL)
25283  {
25284  assert (er_errid () != NO_ERROR);
25285  error = er_errid ();
25286  if (error == NO_ERROR)
25287  {
25288  error = ER_GENERIC_ERROR;
25289  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25290  }
25291  goto cleanup;
25292  }
25293 
25294  upd_cls->class_oid[cl] = *class_oid;
25295  upd_cls->class_hfid[cl] = *hfid;
25296 
25297  /* Calculate attribute ids and link each assignment to classes and attributes */
25298  pt_init_assignments_helper (parser, &assign_helper, assigns);
25299  assign_idx = a = 0;
25300  while ((att_name_node = pt_get_next_assignment (&assign_helper)) != NULL)
25301  {
25302  if (att_name_node->info.name.spec_id == cl_name_node->info.name.spec_id)
25303  {
25304  assign = &update->assigns[assign_idx];
25305  assign->cls_idx = 0;
25306  assign->att_idx = a;
25307  upd_cls->att_id[cl * upd_cls->num_attrs + a] = sm_att_id (class_obj, att_name_node->info.name.original);
25308 
25309  if (upd_cls->att_id[cl * upd_cls->num_attrs + a] < 0)
25310  {
25311  assert (er_errid () != NO_ERROR);
25312  error = er_errid ();
25313  if (error == NO_ERROR && !pt_has_error (parser))
25314  {
25315  error = ER_GENERIC_ERROR;
25316  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25317  }
25318  goto cleanup;
25319  }
25320  /* count attributes for current class */
25321  a++;
25322  }
25323  /* count assignments */
25324  assign_idx++;
25325  }
25326 
25327  /* count subclasses */
25328  cl++;
25329  cl_name_node = cl_name_node->next;
25330  }
25331 
25333  hint_arg = info->waitsecs_hint;
25334  if (info->hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
25335  {
25336  float hint_wait_secs = (float) atof (hint_arg->info.name.original);
25337  if (hint_wait_secs > 0)
25338  {
25339  update->wait_msecs = (int) (hint_wait_secs * 1000);
25340  }
25341  else
25342  {
25343  update->wait_msecs = (int) hint_wait_secs;
25344  }
25345  }
25346  update->no_logging = (info->hint & PT_HINT_NO_LOGGING);
25347 
25348  /* check constants */
25349  class_obj = from->info.spec.flat_entity_list->info.name.db_object;
25350 
25351  pt_init_assignments_helper (parser, &assign_helper, assigns);
25352  a = 0;
25353  while ((att_name_node = pt_get_next_assignment (&assign_helper)) != NULL)
25354  {
25355  PT_NODE *node, *prev, *next;
25356  /* process only constants assigned to current class attributes */
25357  if (att_name_node->info.name.spec_id != from->info.spec.id || !assign_helper.is_rhs_const)
25358  {
25359  /* this is a constant assignment */
25360  a++;
25361  continue;
25362  }
25363  /* get DB_VALUE of assignment's right argument */
25364  val = pt_value_to_db (parser, assign_helper.assignment->info.expr.arg2);
25365  if (val == NULL)
25366  {
25367  error = ER_GENERIC_ERROR;
25369  goto cleanup;
25370  }
25371 
25372  prev = NULL;
25373  for (node = *non_null_attrs; node != NULL; node = next)
25374  {
25375  /* Check to see if this is a NON NULL attr */
25376  next = node->next;
25377 
25378  if (!pt_name_equal (parser, node, att_name_node))
25379  {
25380  prev = node;
25381  continue;
25382  }
25383 
25384  if (DB_IS_NULL (val))
25385  {
25386  /* assignment of a NULL value to a non null attribute */
25388  att_name_node->info.name.original);
25390  goto cleanup;
25391  }
25392  /* remove the node from the non_null_attrs list since we've already checked that the attr will be non-null
25393  * and the engine need not check again. */
25394  if (prev == NULL)
25395  {
25396  *non_null_attrs = (*non_null_attrs)->next;
25397  }
25398  else
25399  {
25400  prev->next = node->next;
25401  }
25402 
25403  /* free the node */
25404  node->next = NULL; /* cut-off link */
25405  parser_free_tree (parser, node);
25406  break;
25407  }
25408 
25409  /* Coerce constant value to destination attribute type */
25410  regu_alloc (update->assigns[a].constant);
25411  if (update->assigns[a].constant == NULL)
25412  {
25413  assert (er_errid () != NO_ERROR);
25414  error = er_errid ();
25415  if (error == NO_ERROR)
25416  {
25417  error = ER_GENERIC_ERROR;
25418  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25419  }
25420  goto cleanup;
25421  }
25422  attr = db_get_attribute (class_obj, att_name_node->info.name.original);
25423  if (attr == NULL)
25424  {
25425  assert (er_errid () != NO_ERROR);
25426  error = er_errid ();
25427  if (error == NO_ERROR)
25428  {
25429  error = ER_GENERIC_ERROR;
25430  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25431  }
25432  goto cleanup;
25433  }
25434  dom = db_attribute_domain (attr);
25435  error = tp_value_coerce (val, update->assigns[a].constant, dom);
25436  if (error != DOMAIN_COMPATIBLE)
25437  {
25438  error = ER_OBJ_DOMAIN_CONFLICT;
25439  er_set (ER_ERROR_SEVERITY, __FILE__, __LINE__, error, 1, att_name_node->info.name.original);
25440  goto cleanup;
25441  }
25442 
25443  /* count assignments */
25444  a++;
25445  }
25446 
25447  /* generate xasl for non-null constraints predicates */
25448  error =
25449  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &num_vals, &num_consts,
25450  info->update.assignment, &links);
25451  if (error != NO_ERROR)
25452  {
25453  PT_INTERNAL_ERROR (parser, "merge update");
25454  goto cleanup;
25455  }
25456 
25457  /* need to jump upd_del_class_cnt OID-CLASS OID pairs */
25458  attr_offset = ((aptr_statement->info.query.upd_del_class_cnt + aptr_statement->info.query.mvcc_reev_extra_cls_cnt) * 2
25459  + (info->update.has_delete ? 1 : 0));
25460 
25461  error = pt_to_constraint_pred (parser, xasl, info->into, *non_null_attrs, select_names, attr_offset);
25462 #if 0
25463 /* disabled temporary in MVCC */
25464  attr_offset = aptr_statement->info.query.upd_del_class_cnt * 2 + (info->update.has_delete ? 1 : 0);
25465  error = pt_to_constraint_pred (parser, xasl, info->into, *non_null_attrs, select_names, attr_offset);
25466 #endif
25467 
25468  pt_restore_assignment_links (info->update.assignment, links, -1);
25469  if (error != NO_ERROR)
25470  {
25471  goto cleanup;
25472  }
25473 
25474  aptr = xasl->aptr_list;
25475 
25476  xasl->n_oid_list = aptr->n_oid_list;
25477  aptr->n_oid_list = 0;
25478  xasl->class_oid_list = aptr->class_oid_list;
25479  aptr->class_oid_list = NULL;
25480  xasl->class_locks = aptr->class_locks;
25481  aptr->class_locks = NULL;
25482  xasl->tcard_list = aptr->tcard_list;
25483  aptr->tcard_list = NULL;
25484  xasl->dbval_cnt = aptr->dbval_cnt;
25485 
25486  /* set TDE flag */
25487  XASL_SET_FLAG (xasl, aptr->flag & XASL_INCLUDES_TDE_CLASS);
25489 
25490  /* fill in XASL cache related information */
25491  /* OID of the user who is creating this XASL */
25492  if ((oid = ws_identifier (db_get_user ())) != NULL)
25493  {
25494  COPY_OID (&xasl->creator_oid, oid);
25495  }
25496  else
25497  {
25498  OID_SET_NULL (&xasl->creator_oid);
25499  }
25500 
25501 cleanup:
25502  if (aptr_statement != NULL)
25503  {
25504  parser_free_tree (parser, aptr_statement);
25505  }
25506  if (from != NULL)
25507  {
25508  parser_free_tree (parser, from);
25509  }
25510  if (error != NO_ERROR)
25511  {
25512  xasl = NULL;
25513  }
25514 
25515  return xasl;
25516 }
25517 
25518 /*
25519  * pt_to_merge_insert_xasl () - Generate XASL for INSERT part of MERGE
25520  * return:
25521  * parser(in):
25522  * statement(in):
25523  * non_null_attrs(in):
25524  * default_expr_attrs(in):
25525  */
25526 static XASL_NODE *
25528  PT_NODE * default_expr_attrs)
25529 {
25530  XASL_NODE *xasl = NULL, *aptr;
25531  INSERT_PROC_NODE *insert = NULL;
25532  PT_NODE *aptr_statement = NULL;
25533  PT_NODE *values_list;
25534  PT_NODE *attr, *attrs;
25535  MOBJ class_;
25536  OID *class_oid, *oid;
25537  DB_OBJECT *class_obj;
25538  SM_CLASS *smclass = NULL;
25539  HFID *hfid;
25540  int num_vals, num_default_expr, a;
25541  int error = NO_ERROR;
25542  PT_NODE *hint_arg;
25543 
25544  values_list = statement->info.merge.insert.value_clauses;
25545  if (values_list == NULL)
25546  {
25547  error = ER_GENERIC_ERROR;
25548  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25549  return NULL;
25550  }
25551 
25552  aptr_statement = pt_to_merge_insert_query (parser, values_list->info.node_list.list, &statement->info.merge);
25553  if (aptr_statement == NULL)
25554  {
25555  assert (er_errid () != NO_ERROR);
25556  error = er_errid ();
25557  if (error == NO_ERROR && !pt_has_error (parser))
25558  {
25559  error = ER_GENERIC_ERROR;
25560  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25561  }
25562  return NULL;
25563  }
25564  aptr_statement = mq_translate (parser, aptr_statement);
25565  if (aptr_statement == NULL)
25566  {
25567  if (pt_has_error (parser))
25568  {
25569  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, aptr_statement);
25570  }
25571  error = er_errid ();
25572  if (error == NO_ERROR)
25573  {
25574  error = ER_GENERIC_ERROR;
25575  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25576  }
25577  return NULL;
25578  }
25579 
25580  attrs = statement->info.merge.insert.attr_list;
25581  class_obj = statement->info.merge.into->info.spec.flat_entity_list->info.name.db_object;
25582 
25583  class_ = locator_create_heap_if_needed (class_obj, sm_is_reuse_oid_class (class_obj));
25584  if (class_ == NULL)
25585  {
25586  assert (er_errid () != NO_ERROR);
25587  error = er_errid ();
25588  if (error == NO_ERROR)
25589  {
25590  error = ER_GENERIC_ERROR;
25591  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25592  }
25593  goto cleanup;
25594  }
25595 
25596  hfid = sm_ch_heap (class_);
25597  if (hfid == NULL)
25598  {
25599  assert (er_errid () != NO_ERROR);
25600  error = er_errid ();
25601  if (error == NO_ERROR)
25602  {
25603  error = ER_GENERIC_ERROR;
25604  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25605  }
25606  goto cleanup;
25607  }
25608 
25609  if (locator_flush_class (class_obj) != NO_ERROR)
25610  {
25611  assert (er_errid () != NO_ERROR);
25612  error = er_errid ();
25613  if (error == NO_ERROR)
25614  {
25615  error = ER_GENERIC_ERROR;
25616  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25617  }
25618  goto cleanup;
25619  }
25620 
25621  num_default_expr = pt_length_of_list (default_expr_attrs);
25622  num_vals = pt_length_of_select_list (pt_get_select_list (parser, aptr_statement), EXCLUDE_HIDDEN_COLUMNS);
25623 
25624  xasl = pt_make_aptr_parent_node (parser, aptr_statement, INSERT_PROC);
25625  if (xasl == NULL || xasl->aptr_list == NULL)
25626  {
25627  assert (er_errid () != NO_ERROR);
25628  error = er_errid ();
25629  if (error == NO_ERROR && !pt_has_error (parser))
25630  {
25631  error = ER_GENERIC_ERROR;
25632  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25633  }
25634  goto cleanup;
25635  }
25636 
25637  insert = &xasl->proc.insert;
25638  insert->class_hfid = *hfid;
25639  class_oid = ws_identifier (class_obj);
25640  if (class_oid)
25641  {
25642  insert->class_oid = *class_oid;
25643  }
25644  else
25645  {
25646  error = ER_HEAP_UNKNOWN_OBJECT;
25647  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25648  goto cleanup;
25649  }
25650 
25651  insert->has_uniques = (statement->info.merge.flags & PT_MERGE_INFO_HAS_UNIQUE);
25653  hint_arg = statement->info.merge.waitsecs_hint;
25654  if (statement->info.merge.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
25655  {
25656  float hint_wait_secs = (float) atof (hint_arg->info.name.original);
25657  if (hint_wait_secs > 0)
25658  {
25659  insert->wait_msecs = (int) (hint_wait_secs * 1000);
25660  }
25661  else
25662  {
25663  insert->wait_msecs = (int) hint_wait_secs;
25664  }
25665  }
25666  insert->no_logging = (statement->info.merge.hint & PT_HINT_NO_LOGGING);
25667  insert->do_replace = 0;
25668 
25669  if (num_vals + num_default_expr > 0)
25670  {
25671  insert->att_id = regu_int_array_alloc (num_vals + num_default_expr);
25672  if (insert->att_id)
25673  {
25674  /* the identifiers of the attributes that have a default expression are placed first */
25675  for (attr = default_expr_attrs, a = 0; error >= 0 && a < num_default_expr; attr = attr->next, ++a)
25676  {
25677  if ((insert->att_id[a] = sm_att_id (class_obj, attr->info.name.original)) < 0)
25678  {
25679  assert (er_errid () != NO_ERROR);
25680  error = er_errid ();
25681  }
25682  }
25683  for (attr = attrs, a = num_default_expr; error >= 0 && a < num_default_expr + num_vals;
25684  attr = attr->next, ++a)
25685  {
25686  if ((insert->att_id[a] = sm_att_id (class_obj, attr->info.name.original)) < 0)
25687  {
25688  assert (er_errid () != NO_ERROR);
25689  error = er_errid ();
25690  }
25691  }
25692  insert->vals = NULL;
25693  insert->num_vals = num_vals + num_default_expr;
25694  insert->num_default_expr = num_default_expr;
25695  }
25696  else
25697  {
25698  assert (er_errid () != NO_ERROR);
25699  error = er_errid ();
25700  }
25701  if (error != NO_ERROR)
25702  {
25703  goto cleanup;
25704  }
25705  }
25706 
25707  error = sm_partitioned_class_type (class_obj, &insert->pruning_type, NULL, NULL);
25708  if (error != NO_ERROR)
25709  {
25710  goto cleanup;
25711  }
25712 
25713  error = pt_to_constraint_pred (parser, xasl, statement->info.merge.into, non_null_attrs, attrs, 0);
25714  if (error != NO_ERROR)
25715  {
25716  goto cleanup;
25717  }
25718 
25719  /* fill in XASL cache related information */
25720  aptr = xasl->aptr_list;
25721 
25722  /* OID of the user who is creating this XASL */
25723  oid = ws_identifier (db_get_user ());
25724  if (oid != NULL)
25725  {
25726  COPY_OID (&xasl->creator_oid, oid);
25727  }
25728  else
25729  {
25730  OID_SET_NULL (&xasl->creator_oid);
25731  }
25732 
25733  assert (locator_is_class (class_obj, DB_FETCH_QUERY_READ) > 0);
25734  (void) au_fetch_class (class_obj, &smclass, AU_FETCH_READ, AU_SELECT);
25735 
25736  /* list of class OIDs used in this XASL */
25737  /* reserve spec oid space by 1+ */
25738  xasl->class_oid_list = regu_oid_array_alloc (1 + aptr->n_oid_list);
25739  xasl->class_locks = regu_int_array_alloc (1 + aptr->n_oid_list);
25740  xasl->tcard_list = regu_int_array_alloc (1 + aptr->n_oid_list);
25741  if (xasl->class_oid_list == NULL || xasl->class_locks == NULL || xasl->tcard_list == NULL)
25742  {
25743  assert (er_errid () != NO_ERROR);
25744  error = er_errid ();
25745  if (error == NO_ERROR)
25746  {
25747  error = ER_GENERIC_ERROR;
25748  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
25749  }
25750  goto cleanup;
25751  }
25752 
25753  xasl->n_oid_list = 1 + aptr->n_oid_list;
25754 
25755  /* copy aptr oids to xasl */
25756  (void) memcpy (xasl->class_oid_list + 1, aptr->class_oid_list, sizeof (OID) * aptr->n_oid_list);
25757  (void) memcpy (xasl->class_locks + 1, aptr->class_locks, sizeof (int) * aptr->n_oid_list);
25758  (void) memcpy (xasl->tcard_list + 1, aptr->tcard_list, sizeof (int) * aptr->n_oid_list);
25759 
25760  /* set spec oid */
25761  xasl->class_oid_list[0] = insert->class_oid;
25762  xasl->class_locks[0] = (int) IX_LOCK;
25763  xasl->tcard_list[0] = XASL_CLASS_NO_TCARD; /* init #pages */
25764  xasl->dbval_cnt = aptr->dbval_cnt;
25765 
25766  /* set TDE flag */
25767  XASL_SET_FLAG (xasl, aptr->flag & XASL_INCLUDES_TDE_CLASS);
25768 
25769  if (smclass)
25770  {
25771  if (smclass->tde_algorithm != TDE_ALGORITHM_NONE)
25772  {
25774  }
25775  }
25776 
25777 cleanup:
25778  if (aptr_statement != NULL)
25779  {
25780  parser_free_tree (parser, aptr_statement);
25781  }
25782  if (error != NO_ERROR)
25783  {
25784  xasl = NULL;
25785  }
25786 
25787  return xasl;
25788 }
25789 
25790 /*
25791  * pt_substitute_assigned_name_node () - substitute name node with assigned
25792  * expression
25793  * return:
25794  * parser(in):
25795  * node(in):
25796  * arg(in/out):
25797  * continue_walk(in):
25798  */
25799 PT_NODE *
25800 pt_substitute_assigned_name_node (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
25801 {
25802  PT_NODE *assignments = (PT_NODE *) arg;
25804 
25805  if (node->node_type == PT_NAME)
25806  {
25807  pt_init_assignments_helper (parser, &ea, assignments);
25808  while (pt_get_next_assignment (&ea) != NULL)
25809  {
25810  if (pt_name_equal (parser, ea.lhs, node))
25811  {
25812  parser_free_tree (parser, node);
25813  node = parser_copy_tree_list (parser, ea.rhs);
25814  break;
25815  }
25816  }
25817  }
25818 
25819  return node;
25820 }
25821 
25822 /*
25823  * pt_set_orderby_for_sort_limit_plan () - setup ORDER BY list to be applied
25824  * to a SORT-LIMIT plan
25825  * return : ORDER BY list on success, NULL on error
25826  * parser (in) : parser context
25827  * statement (in) : statement
25828  * nodes_list (in/out) : list of nodes referenced by the plan
25829  *
25830  * Note: if an ORDER BY spec is not a name, the node it references is added
25831  * to the nodes_list nodes.
25832  */
25833 PT_NODE *
25835 {
25836  PT_NODE *order_by = NULL, *select_list = NULL, *new_order_by = NULL;
25837  PT_NODE *sort_spec = NULL, *node = NULL, *name = NULL, *sort = NULL;
25838  PT_NODE *prev = NULL;
25839  int pos = 0, names_count = 0, added_count = 0;
25840  bool add_node = false;
25841 
25842  order_by = statement->info.query.order_by;
25843  select_list = pt_get_select_list (parser, statement);
25844 
25845  /* count nodes in name_list, we will add new nodes at the end of the list */
25846  node = nodes_list;
25847  names_count = 0;
25848  while (node)
25849  {
25850  prev = node;
25851  names_count++;
25852  node = node->next;
25853  }
25854 
25855  /* create a new ORDER BY list which reflects positions of nodes in the nodes_list */
25856  for (sort_spec = order_by; sort_spec != NULL; sort_spec = sort_spec->next)
25857  {
25858  add_node = true;
25859 
25860  if (sort_spec->node_type != PT_SORT_SPEC)
25861  {
25862  assert_release (sort_spec->node_type == PT_SORT_SPEC);
25863  goto error_return;
25864  }
25865  /* find the node which is referenced by this sort_spec */
25866  for (pos = 1, node = select_list; node != NULL; pos++, node = node->next)
25867  {
25868  if (pos == sort_spec->info.sort_spec.pos_descr.pos_no)
25869  {
25870  break;
25871  }
25872  }
25873 
25874  if (node == NULL)
25875  {
25876  assert_release (node != NULL);
25877  goto error_return;
25878  }
25879 
25880  CAST_POINTER_TO_NODE (node);
25881 
25882  if (node->node_type == PT_NAME)
25883  {
25884  /* SORT-LIMIT plans are build over the subset of classes referenced in the ORDER BY clause. This means that
25885  * any name referenced in ORDER BY must also be a segment for one of the classes of this subplan. We just
25886  * need to update the sort_spec position. */
25887  for (pos = 1, name = nodes_list; name != NULL; pos++, name = name->next)
25888  {
25889  if (pt_name_equal (parser, name, node))
25890  {
25891  break;
25892  }
25893  }
25894 
25895  if (name != NULL)
25896  {
25897  add_node = false;
25898  }
25899  }
25900 
25901  if (add_node)
25902  {
25903  /* this node was not found in the node_list. In order to be able to execute the ORDER BY clause, we have to
25904  * add it to the list */
25905  pos = names_count + added_count + 1;
25906  name = pt_point (parser, node);
25907  if (name == NULL)
25908  {
25909  PT_INTERNAL_ERROR (parser, "allocate new node");
25910  goto error_return;
25911  }
25912  /* add node to the end of name_list */
25913  prev->next = name;
25914  prev = prev->next;
25915  added_count++;
25916  }
25917  else
25918  {
25919  /* just point to it */
25920  name = pt_point (parser, name);
25921  if (name == NULL)
25922  {
25923  PT_INTERNAL_ERROR (parser, "allocate new node");
25924  goto error_return;
25925  }
25926  }
25927 
25928  /* create a new sort_spec for the original one and add it to the list */
25929  sort = parser_new_node (parser, PT_SORT_SPEC);
25930  if (sort == NULL)
25931  {
25932  PT_INTERNAL_ERROR (parser, "allocate new node");
25933  goto error_return;
25934  }
25935 
25936  sort->info.sort_spec.expr = name;
25937  sort->info.sort_spec.pos_descr.pos_no = pos;
25938  sort->info.sort_spec.asc_or_desc = sort_spec->info.sort_spec.asc_or_desc;
25939 
25940  CAST_POINTER_TO_NODE (name);
25941  sort->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, name);
25942 
25943  new_order_by = parser_append_node (sort, new_order_by);
25944  }
25945 
25946  return new_order_by;
25947 
25948 error_return:
25949  if (new_order_by != NULL)
25950  {
25951  parser_free_tree (parser, new_order_by);
25952  }
25953  return NULL;
25954 }
25955 
25956 /*
25957  * pt_is_sort_list_covered () - same as qfile_is_sort_list_covered ()
25958  * return: true or false
25959  * parser (in) : parser context
25960  * covering_list(in): covering sort item list pointer
25961  * covered_list(in): covered sort item list pointer
25962  *
25963  * Note: if covering_list covers covered_list returns true.
25964  * otherwise, returns false.
25965  */
25966 static bool
25967 pt_is_sort_list_covered (PARSER_CONTEXT * parser, SORT_LIST * covering_list_p, SORT_LIST * covered_list_p)
25968 {
25969  SORT_LIST *s1, *s2;
25970 
25971  if (covered_list_p == NULL)
25972  {
25973  return false;
25974  }
25975 
25976  for (s1 = covering_list_p, s2 = covered_list_p; s1 && s2; s1 = s1->next, s2 = s2->next)
25977  {
25978  if (s1->s_order != s2->s_order || s1->s_nulls != s2->s_nulls || s1->pos_descr.pos_no != s2->pos_descr.pos_no)
25979  {
25980  return false;
25981  }
25982  }
25983 
25984  if (s1 == NULL && s2)
25985  {
25986  return false;
25987  }
25988  else
25989  {
25990  return true;
25991  }
25992 }
25993 
25994 /*
25995  * pt_reserved_id_to_valuelist_index () - Generate the index of value for
25996  * reserved attribute in the array
25997  * of cached attribute values.
25998  *
25999  * return : Index of value.
26000  * parser (in) : Parser context.
26001  * reserved_id (in) : Reserved name id.
26002  */
26003 static int
26005 {
26006  switch (reserved_id)
26007  {
26008  /* Record info names */
26009  case RESERVED_T_PAGEID:
26011  case RESERVED_T_SLOTID:
26013  case RESERVED_T_VOLUMEID:
26015  case RESERVED_T_OFFSET:
26017  case RESERVED_T_LENGTH:
26019  case RESERVED_T_REC_TYPE:
26021  case RESERVED_T_REPRID:
26023  case RESERVED_T_CHN:
26024  return HEAP_RECORD_INFO_T_CHN;
26025  case RESERVED_T_MVCC_INSID:
26027  case RESERVED_T_MVCC_DELID:
26029  case RESERVED_T_MVCC_FLAGS:
26033 
26034  /* Page info names */
26035  case RESERVED_P_CLASS_OID:
26036  return HEAP_PAGE_INFO_CLASS_OID;
26038  return HEAP_PAGE_INFO_PREV_PAGE;
26040  return HEAP_PAGE_INFO_NEXT_PAGE;
26041  case RESERVED_P_NUM_SLOTS:
26042  return HEAP_PAGE_INFO_NUM_SLOTS;
26047  case RESERVED_P_ALIGNMENT:
26048  return HEAP_PAGE_INFO_ALIGNMENT;
26049  case RESERVED_P_TOTAL_FREE:
26051  case RESERVED_P_CONT_FREE:
26052  return HEAP_PAGE_INFO_CONT_FREE;
26055  case RESERVED_P_IS_SAVING:
26056  return HEAP_PAGE_INFO_IS_SAVING;
26059 
26060  /* Key info names */
26061  case RESERVED_KEY_VOLUMEID:
26062  return BTREE_KEY_INFO_VOLUMEID;
26063  case RESERVED_KEY_PAGEID:
26064  return BTREE_KEY_INFO_PAGEID;
26065  case RESERVED_KEY_SLOTID:
26066  return BTREE_KEY_INFO_SLOTID;
26067  case RESERVED_KEY_KEY:
26068  return BTREE_KEY_INFO_KEY;
26070  return BTREE_KEY_INFO_OID_COUNT;
26072  return BTREE_KEY_INFO_FIRST_OID;
26077 
26078  /* B-tree node info names */
26080  return BTREE_NODE_INFO_VOLUMEID;
26082  return BTREE_NODE_INFO_PAGEID;
26083  case RESERVED_BT_NODE_TYPE:
26090  return BTREE_NODE_INFO_LAST_KEY;
26091 
26092  default:
26093  /* unknown reserved id or not handled */
26094  assert (0);
26095  return RESERVED_NAME_INVALID;
26096  }
26097 }
26098 
26099 /*
26100  * pt_to_null_ordering () - get null ordering from a sort spec
26101  * return : null ordering
26102  * sort_spec (in) : sort spec
26103  */
26104 SORT_NULLS
26106 {
26107  assert_release (sort_spec != NULL);
26108  assert_release (sort_spec->node_type == PT_SORT_SPEC);
26109 
26110  switch (sort_spec->info.sort_spec.nulls_first_or_last)
26111  {
26112  case PT_NULLS_FIRST:
26113  return S_NULLS_FIRST;
26114 
26115  case PT_NULLS_LAST:
26116  return S_NULLS_LAST;
26117 
26118  case PT_NULLS_DEFAULT:
26119  default:
26120  break;
26121  }
26122 
26123  if (sort_spec->info.sort_spec.asc_or_desc == PT_ASC)
26124  {
26125  return S_NULLS_FIRST;
26126  }
26127 
26128  return S_NULLS_LAST;
26129 }
26130 
26131 /*
26132  * pt_to_cume_dist_percent_rank_regu_variable () - generate regu_variable
26133  * for 'CUME_DIST' and 'PERCENT_RANK'
26134  * return: REGU_VARIABLE*
26135  * parser(in):
26136  * tree(in):
26137  * unbox(in):
26138  */
26139 static REGU_VARIABLE *
26141 {
26142  REGU_VARIABLE *regu = NULL;
26143  PT_NODE *arg_list = NULL, *orderby_list = NULL, *node = NULL;
26144  REGU_VARIABLE_LIST regu_var_list, regu_var;
26145 
26146  /* set up regu var */
26147  regu_alloc (regu);
26148  if (regu == NULL)
26149  {
26150  return NULL;
26151  }
26152 
26153  regu->type = TYPE_REGU_VAR_LIST;
26155  /* for cume_dist and percent_rank, regu_variable should be hidden */
26157  arg_list = tree->info.function.arg_list;
26158  orderby_list = tree->info.function.order_by;
26159  assert (arg_list != NULL && orderby_list != NULL);
26160 
26161  /* first insert the first order by item */
26162  regu_var_list = pt_to_regu_variable_list (parser, orderby_list->info.sort_spec.expr, UNBOX_AS_VALUE, NULL, NULL);
26163  if (regu_var_list == NULL)
26164  {
26165  return NULL;
26166  }
26167 
26168  /* insert order by items one by one */
26169  regu_var = regu_var_list;
26170  for (node = orderby_list->next; node != NULL; node = node->next)
26171  {
26172  regu_var->next = pt_to_regu_variable_list (parser, node->info.sort_spec.expr, UNBOX_AS_VALUE, NULL, NULL);
26173  regu_var = regu_var->next;
26174  }
26175 
26176  /* order by items have been attached, now the arguments */
26177  regu_var->next = pt_to_regu_variable_list (parser, arg_list, UNBOX_AS_VALUE, NULL, NULL);
26178 
26179  /* finally setup regu: */
26180  regu->value.regu_var_list = regu_var_list;
26181 
26182  return regu;
26183 }
26184 
26185 /*
26186  * pt_set_limit_optimization_flags () - setup XASL flags according to
26187  * query limit optimizations applied
26188  * during plan generation
26189  * return : error code or NO_ERROR
26190  * parser (in) : parser context
26191  * qo_plan (in) : query plan
26192  * xasl (in) : xasl node
26193  */
26194 static int
26196 {
26197  if (qo_plan == NULL)
26198  {
26199  return NO_ERROR;
26200  }
26201 
26202  /* Set SORT-LIMIT flags */
26203  if (qo_has_sort_limit_subplan (qo_plan))
26204  {
26205  xasl->header.xasl_flag |= SORT_LIMIT_USED;
26207  }
26208  else
26209  {
26210  switch (qo_plan->info->env->use_sort_limit)
26211  {
26212  case QO_SL_USE:
26213  /* A SORT-LIMIT plan can be created but planner found a better plan. In this case, there is no point in
26214  * recompiling the plan a second time. There are cases in which suppling a smaller limit to the query will
26215  * cause planner to choose a SORT-LIMIT plan over the current one but, since there is no way to know if this
26216  * is the case, it is better to consider that this query will never use SORT-LIMIT. */
26217  break;
26218 
26219  case QO_SL_INVALID:
26220  /* A SORT-LIMIT plan cannot be generated for this query */
26221  break;
26222 
26223  case QO_SL_POSSIBLE:
26224  /* The query might produce a SORT-LIMIT plan but the supplied limit. could not be evaluated. */
26226  break;
26227  }
26228  }
26229 
26230  /* Set MULTI-RANGE-OPTIMIZATION flags */
26231  if (qo_plan_multi_range_opt (qo_plan))
26232  {
26233  /* qo_plan->multi_range_opt_use == PLAN_MULTI_RANGE_OPT_USE */
26234  /* convert ordbynum to key limit if we have iscan with multiple key ranges */
26235  int err = pt_ordbynum_to_key_limit_multiple_ranges (parser, qo_plan,
26236  xasl);
26237  if (err != NO_ERROR)
26238  {
26239  return err;
26240  }
26241 
26242  xasl->header.xasl_flag |= MRO_CANDIDATE;
26243  xasl->header.xasl_flag |= MRO_IS_USED;
26244  }
26246  {
26247  /* Query could use multi range optimization, but limit was too large */
26248  xasl->header.xasl_flag |= MRO_CANDIDATE;
26249  }
26250 
26251  return NO_ERROR;
26252 }
26253 
26254 /*
26255  * pt_aggregate_info_append_value_list () - Appends the value_list in the aggregate info->value_list, increasing also
26256  * the val_cnt
26257  * info (in/out) :
26258  * value_list (in) :
26259  */
26260 static void
26262 {
26263  assert (info != NULL && info->value_list != NULL && value_list != NULL);
26264 
26265  // increase the size with the number of elements in the value_list
26266  info->value_list->val_cnt += value_list->val_cnt;
26267 
26268  QPROC_DB_VALUE_LIST value_temp = NULL;
26269 
26270  // get the end of the list
26271  for (value_temp = info->value_list->valp; value_temp->next != NULL; value_temp = value_temp->next)
26272  ;
26273 
26274  assert (value_temp != NULL);
26275 
26276  // append to the end
26277  value_temp->next = value_list->valp;
26278 }
26279 
26280 /*
26281  * pt_aggregate_info_update_value_and_reguvar_lists () - Merges the arguments in the aggregate info corresponding lists
26282  * info (in/out) :
26283  * value_list (in) :
26284  * regu_position_list (in) :
26285  * regu_constant_list (in) :
26286  */
26287 static void
26289  REGU_VARIABLE_LIST regu_position_list,
26290  REGU_VARIABLE_LIST regu_constant_list)
26291 {
26292  pt_aggregate_info_append_value_list (info, value_list);
26293 
26294  pt_merge_regu_var_lists (&info->regu_list, regu_position_list);
26295 
26296  pt_merge_regu_var_lists (&info->out_list->valptrp, regu_constant_list);
26297 
26298  // also increment list count
26299  int regu_constant_list_size = 0;
26300 
26301  for (REGU_VARIABLE_LIST ptr = regu_constant_list; ptr != NULL; ptr = ptr->next, regu_constant_list_size++)
26302  ;
26303 
26304  info->out_list->valptr_cnt += regu_constant_list_size;
26305 }
26306 
26307 /*
26308  * pt_aggregate_info_update_scan_regu_list () - Merges scan_regu_list in the aggregate info->scan_regu_list
26309  * info (in/out) :
26310  * scan_regu_list (in) :
26311  */
26312 static void
26314 {
26315  REGU_VARIABLE_LIST tail = NULL;
26316  int scan_regu_list_size = 0;
26317  int index = 0;
26318 
26319  // calculate the size of scan_regu_var_list
26320  for (tail = scan_regu_list; tail != NULL; tail = tail->next, scan_regu_list_size++)
26321  ;
26322 
26323  // start fetching for the last scan_regu_var_list_size elements
26324  index = info->value_list->val_cnt - scan_regu_list_size;
26325 
26326  for (REGU_VARIABLE_LIST itr = scan_regu_list; itr != NULL; itr = itr->next)
26327  {
26328  // get the value from the value_list
26329  itr->value.vfetch_to = pt_index_value (info->value_list, index++);
26330  }
26331 
26332  // append scan_regu_list to info
26333  pt_merge_regu_var_lists (&info->scan_regu_list, scan_regu_list);
26334 }
26335 
26336 /*
26337  * pt_node_list_to_value_and_reguvar_list () - Constructs the value_list and regu_position_list from node
26338  * parser (in) :
26339  * node (in) :
26340  * value_list (in/out) :
26341  * regu_position_list (in/out) :
26342  */
26343 static PT_NODE *
26345  REGU_VARIABLE_LIST * regu_position_list)
26346 {
26347  assert (node != NULL && value_list != NULL);
26348 
26349  *value_list = pt_make_val_list (parser, node);
26350 
26351  if (*value_list == NULL)
26352  {
26353  return NULL;
26354  }
26355 
26356  if (pt_make_regu_list_from_value_list (parser, node, *value_list, regu_position_list) == NULL)
26357  {
26358  return NULL;
26359  }
26360 
26361  return node;
26362 }
26363 
26364 /*
26365  * pt_make_regu_list_from_value_list () - creates a regu_list from value_list with TYPE POSITION
26366  * parser (in) :
26367  * node (in) :
26368  * value_list (in) :
26369  * regu_list (in/out) :
26370  */
26371 static PT_NODE *
26373  REGU_VARIABLE_LIST * regu_list)
26374 {
26375  assert (node != NULL && value_list != NULL && regu_list != NULL);
26376 
26377  int *attr_offsets = NULL;
26378  bool out_of_memory = false;
26379 
26380  attr_offsets = pt_make_identity_offsets (node);
26381  if (attr_offsets == NULL)
26382  {
26383  out_of_memory = true;
26384  goto end;
26385  }
26386 
26387  *regu_list = pt_to_position_regu_variable_list (parser, node, value_list, attr_offsets);
26388  if (*regu_list == NULL)
26389  {
26390  out_of_memory = true;
26391  goto end;
26392  }
26393 
26394 end:
26395  if (attr_offsets != NULL)
26396  {
26397  free_and_init (attr_offsets);
26398  }
26399 
26400  if (out_of_memory)
26401  {
26402  /* on error, return NULL The error should be reported by the caller */
26403  node = NULL;
26404  }
26405 
26406  return node;
26407 }
26408 
26409 /*
26410  * pt_make_constant_regu_list_from_val_list () - creates a regu list with constant type from value_list
26411  * parser (in) :
26412  * value_list (in) :
26413  * regu_list (in/out) :
26414  */
26415 static int
26417  REGU_VARIABLE_LIST * regu_list)
26418 {
26419  assert (*regu_list == NULL);
26420 
26421  size_t value_list_size = value_list->val_cnt;
26422  QPROC_DB_VALUE_LIST crt_val = value_list->valp;
26423  REGU_VARIABLE_LIST last = NULL;
26424 
26425  for (size_t i = 0; i < value_list_size; i++, crt_val = crt_val->next)
26426  {
26427  REGU_VARIABLE_LIST crt_regu;
26428  regu_alloc (crt_regu);
26429  if (crt_regu == NULL)
26430  {
26431  return ER_OUT_OF_VIRTUAL_MEMORY;
26432  }
26433 
26434  crt_regu->value.type = TYPE_CONSTANT;
26435  crt_regu->value.domain = crt_val->dom;
26436  crt_regu->value.value.dbvalptr = crt_val->val;
26437 
26438  // set head
26439  if (*regu_list == NULL)
26440  {
26441  *regu_list = crt_regu;
26442  last = *regu_list;
26443  }
26444  // append
26445  else
26446  {
26447  last->next = crt_regu;
26448  last = last->next;
26449  }
26450  }
26451 
26452  return NO_ERROR;
26453 }
26454 
26455 static void
26456 pt_set_regu_list_pos_descr_from_idx (REGU_VARIABLE_LIST & regu_list, size_t starting_index)
26457 {
26458  for (REGU_VARIABLE_LIST crt_regu = regu_list; crt_regu != NULL; crt_regu = crt_regu->next)
26459  {
26460  assert (crt_regu->value.type == TYPE_POSITION);
26461  crt_regu->value.value.pos_descr.pos_no = (int) starting_index++;
26462  }
26463 }
26464 
26465 /*
26466  * pt_fix_interpolation_aggregate_function_order_by () -
26467  *
26468  * return :
26469  * parser (in) :
26470  * node (in) :
26471  */
26472 static PT_NODE *
26474 {
26475  PT_FUNCTION_INFO *func_info_p = NULL;
26476  PT_NODE *sort_spec = NULL;
26477 
26478  assert (parser != NULL && node != NULL && node->node_type == PT_FUNCTION);
26479 
26480  func_info_p = &node->info.function;
26481  assert (!func_info_p->analytic.is_analytic);
26482 
26483  if (func_info_p->function_type == PT_GROUP_CONCAT || func_info_p->function_type == PT_CUME_DIST
26484  || func_info_p->function_type == PT_PERCENT_RANK)
26485  {
26486  /* nothing to be done for these cases */
26487  return node;
26488  }
26489  else if ((func_info_p->function_type == PT_PERCENTILE_CONT || func_info_p->function_type == PT_PERCENTILE_DISC)
26490  && func_info_p->order_by != NULL && func_info_p->order_by->info.sort_spec.pos_descr.pos_no == 0)
26491  {
26492  func_info_p->order_by->info.sort_spec.pos_descr.pos_no = 1;
26493  func_info_p->order_by->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, func_info_p->arg_list);
26494  }
26495  else if (func_info_p->function_type == PT_MEDIAN && func_info_p->arg_list != NULL
26496  && !PT_IS_CONST (func_info_p->arg_list) && func_info_p->order_by == NULL)
26497  {
26498  /* generate the sort spec for median */
26499  sort_spec = parser_new_node (parser, PT_SORT_SPEC);
26500  if (sort_spec == NULL)
26501  {
26503  return NULL;
26504  }
26505 
26506  sort_spec->info.sort_spec.asc_or_desc = PT_ASC;
26508  sort_spec->info.sort_spec.expr = parser_copy_tree (parser, node->info.function.arg_list);
26509  if (sort_spec->info.sort_spec.expr == NULL)
26510  {
26512  return NULL;
26513  }
26514 
26515  sort_spec->info.sort_spec.pos_descr.pos_no = 1;
26516  sort_spec->info.sort_spec.pos_descr.dom = pt_xasl_node_to_domain (parser, func_info_p->arg_list);
26517 
26518  func_info_p->order_by = sort_spec;
26519  }
26520 
26521  return node;
26522 }
26523 
26524 
26525 /*
26526  * pt_fix_buildlist_aggregate_cume_dist_percent_rank () - This function generates
26527  * aggregate info for aggregate CUME_DIST/PERCENT_RANK in buildlist.
26528  * This is neccesary because for evaluation in buildlist, two functions
26529  * need re-scan order-by values therefore we must add function order-by elements
26530  * into regu_list, scan_regu_list, value_list and out_list.
26531  *
26532  * return : ERROR CODE
26533  * parser (in) :
26534  * node (in) : order by node of CUME_DIST/PERCENT_RANK
26535  * info (in) :
26536  * regu (in) :
26537  */
26538 static int
26540  REGU_VARIABLE * regu)
26541 {
26542  REGU_VARIABLE_LIST regu_list, regu_var, regu_const, new_regu, tail, scan_regu_list, out_list;
26543  REGU_VARIABLE *scan_regu;
26544  QPROC_DB_VALUE_LIST value_tmp;
26545  VAL_LIST *value_list;
26546  TP_DOMAIN *domain;
26547  PT_NODE *pnode, *order, *pname;
26548  int i;
26549 
26550  assert (parser != NULL && node != NULL && info != NULL && regu != NULL && regu->type == TYPE_REGU_VAR_LIST);
26551 
26552  /* initialize variables */
26553  order = node;
26554  regu_list = regu->value.regu_var_list;
26555  regu_var = regu_const = regu_list;
26556  tail = info->regu_list;
26557 
26558  /* find length and tail of regu_list */
26559  if (tail == NULL)
26560  {
26561  i = 0;
26562  }
26563  else
26564  {
26565  for (tail = info->regu_list, i = 1; tail->next != NULL; i++, tail = tail->next);
26566  }
26567 
26568  /* for order by regu, we need to link the value pointer */
26569  while (regu_const != NULL)
26570  {
26571  /* create a new regu for function order by clause */
26572  regu_alloc (new_regu);
26573  if (new_regu == NULL)
26574  {
26576  return ER_FAILED;
26577  }
26578 
26579  domain = pt_xasl_node_to_domain (parser, order->info.sort_spec.expr);
26580  if (domain == NULL)
26581  {
26582  return ER_FAILED;
26583  }
26584 
26585  /* regu list must be a position, and set the scan value to the regu_var which is used in the
26586  * CUME_DIST/PERCENT_RANK evaluation. */
26587  new_regu->value.type = TYPE_POSITION;
26588  new_regu->value.domain = domain;
26589  new_regu->value.value.pos_descr.pos_no = i++;
26590  new_regu->value.value.pos_descr.dom = domain;
26591  new_regu->value.vfetch_to = regu_var->value.value.dbvalptr;
26592 
26593  if (tail == NULL)
26594  {
26595  tail = new_regu;
26596  }
26597  else
26598  {
26599  tail->next = new_regu;
26600  tail = new_regu;
26601  }
26602 
26603  /* since the first half of regu_list are order by regu */
26604  order = order->next;
26605  regu_var = regu_var->next;
26606  regu_const = regu_const->next->next;
26607  }
26608 
26609  /* append scan_regu_list, out_list and value_list */
26610  scan_regu_list = info->scan_regu_list;
26611  out_list = info->out_list->valptrp;
26612  value_tmp = info->value_list->valp;
26613 
26614  for (pnode = node, regu_var = regu_list; pnode != NULL; pnode = pnode->next, regu_var = regu_var->next)
26615  {
26616  /* append scan_list */
26617  scan_regu = pt_to_regu_variable (parser, pnode->info.sort_spec.expr, UNBOX_AS_VALUE);
26618  if (scan_regu == NULL)
26619  {
26620  return ER_FAILED;
26621  }
26622 
26623  /* scan_regu->vfetch_to is also needed for domain checking */
26624  scan_regu->vfetch_to = regu_var->value.value.dbvalptr;
26625 
26626  if (scan_regu_list == NULL)
26627  {
26628  regu_alloc (scan_regu_list);
26629  if (scan_regu_list == NULL)
26630  {
26632  return ER_FAILED;
26633  }
26634  }
26635  else
26636  {
26637  while (scan_regu_list->next != NULL)
26638  {
26639  scan_regu_list = scan_regu_list->next;
26640  }
26641  regu_alloc (scan_regu_list->next);
26642  if (scan_regu_list->next == NULL)
26643  {
26645  return ER_FAILED;
26646  }
26647 
26648  scan_regu_list = scan_regu_list->next;
26649  }
26650 
26651  scan_regu_list->next = NULL;
26652  scan_regu_list->value = *scan_regu;
26653 
26654  /* appende out_list */
26655  pname = parser_new_node (parser, PT_VALUE);
26656 
26657  if (pname == NULL)
26658  {
26660  return ER_FAILED;
26661  }
26662 
26663  pname->type_enum = PT_TYPE_INTEGER;
26664  pname->info.value.data_value.i = 0;
26665  parser_append_node (pname, info->out_names);
26666 
26667  if (out_list == NULL)
26668  {
26669  regu_alloc (out_list);
26670  if (out_list == NULL)
26671  {
26673  return ER_FAILED;
26674  }
26675  }
26676  else
26677  {
26678  while (out_list->next != NULL)
26679  {
26680  out_list = out_list->next;
26681  }
26682 
26683  regu_alloc (out_list->next);
26684  if (out_list->next == NULL)
26685  {
26687  return ER_FAILED;
26688  }
26689 
26690  out_list = out_list->next;
26691  }
26692 
26693  out_list->next = NULL;
26694  out_list->value = *scan_regu;
26695  info->out_list->valptr_cnt++;
26696 
26697  /* append value list, although this value in the value_list are useless for further evaluation, it is needed to
26698  * reserve the corresponding positions, otherwise out_list will be messed up. */
26699  value_list = pt_make_val_list (parser, pnode->info.sort_spec.expr);
26700  if (value_list == NULL)
26701  {
26702  return ER_FAILED;
26703  }
26704 
26705  if (value_tmp == NULL)
26706  {
26707  value_tmp = value_list->valp;
26708  }
26709  else
26710  {
26711  while (value_tmp->next != NULL)
26712  {
26713  value_tmp = value_tmp->next;
26714  }
26715  value_tmp->next = value_list->valp;
26716  }
26717 
26718  info->value_list->val_cnt++;
26719  } /* for(pnode...) ends */
26720 
26721  return NO_ERROR;
26722 }
26723 
26724 /*
26725  * pt_to_instnum_pred () -
26726  *
26727  * return : XASL
26728  * parser (in) :
26729  * xasl (in) :
26730  * pred (in)
26731  */
26732 XASL_NODE *
26734 {
26735  int flag = 0;
26736 
26737  if (xasl && pred)
26738  {
26739  xasl->instnum_pred = pt_to_pred_expr_with_arg (parser, pred, &flag);
26740  if (flag & PT_PRED_ARG_INSTNUM_CONTINUE)
26741  {
26743  }
26744  }
26745 
26746  return xasl;
26747 }
void REGU_VARIABLE_SET_FLAG(regu_variable_node *regu, int flag)
Definition: regu_var.hpp:259
PT_NODE * pt_get_numbering_node_etc(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static XASL_NODE * pt_to_buildvalue_proc(PARSER_CONTEXT *parser, PT_NODE *select_node, QO_PLAN *qo_plan)
static PT_NODE * parser_generate_xasl_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
REGU_VARIABLE_LIST regu_list
TP_DOMAIN tp_String_domain
PT_NODE * meth_translate(PARSER_CONTEXT *parser, PT_NODE *volatile node)
pred_expr * lhs
static PRED_EXPR * pt_make_pred_term_rlike(REGU_VARIABLE *arg1, REGU_VARIABLE *arg2, REGU_VARIABLE *case_sensitive)
regu_variable_node * key1
Definition: access_spec.hpp:67
PT_NODE * pt_point_l(PARSER_CONTEXT *parser, const PT_NODE *in_tree)
#define pt_is_expr_node(n)
Definition: parse_tree.h:261
PT_NODE * pt_name(PARSER_CONTEXT *parser_ptr, const char *name)
PT_NODE * order_by
Definition: parse_tree.h:2769
void regu_array_alloc(T **ptr, size_t size)
#define ER_REGU_SYSTEM
Definition: error_code.h:193
const char * class_name
int * mvcc_extra_assign_reev
Definition: xasl.h:243
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
OUTPTR_LIST * outptr_list
Definition: xasl.h:968
DB_OBJECT * pt_resolve_serial(PARSER_CONTEXT *parser, PT_NODE *serial_name_node)
#define XASL_WAIT_MSECS_NOCHANGE
Definition: xasl.h:454
static PT_NODE * pt_is_hash_agg_eligible(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
QO_CLASS_INFO_ENTRY * class_
Definition: query_graph.h:105
ACCESS_SPEC_TYPE * pt_to_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *where_key_part, PT_NODE *where_part, QO_PLAN *plan, QO_XASL_INDEX_INFO *index_part, PT_NODE *src_derived_tbl, PT_NODE *where_hash_part)
static int pt_initialize_analytic_info(PARSER_CONTEXT *parser, ANALYTIC_INFO *analytic_info, PT_NODE *select_node, PT_NODE *select_list_ex, BUILDLIST_PROC_NODE *buildlist)
PT_NODE * next
Definition: parse_tree.h:3447
QO_INFO * info
REGU_VARIABLE_LIST prior_regu_list_pred
Definition: xasl.h:427
#define MSGCAT_SEMANTIC_IS_NOT_DEFINED
int num_extra_assign_reev
Definition: xasl.h:242
static ACCESS_SPEC_TYPE * pt_to_showstmt_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *where_part)
PT_NAME_INFO name
Definition: parse_tree.h:3318
SORT_LIST * orderby_list
Definition: xasl.h:957
bool qo_plan_skip_orderby(QO_PLAN *plan)
static void pt_aggregate_info_update_scan_regu_list(AGGREGATE_INFO *info, REGU_VARIABLE_LIST scan_regu_list)
void qo_plan_dump(QO_PLAN *, FILE *)
TP_DOMAIN_STATUS tp_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
PT_HINT_ENUM hint
Definition: parse_tree.h:2877
static PRED_EXPR * pt_make_pred_term_is(PARSER_CONTEXT *parser, PT_NODE *arg1, PT_NODE *arg2, const BOOL_OP bop)
QFILE_TUPLE_VALUE_POSITION pos_descr
Definition: parse_tree.h:2829
FUNC_PRED * pt_to_func_pred(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *expr)
REGU_VALUE_ITEM * regu_list
Definition: regu_var.hpp:105
#define MSGCAT_SEMANTIC_SERIAL_NOT_DEFINED
#define VALIDATE_REGU_KEY(r)
#define PT_IS_QUERY(n)
Definition: parse_tree.h:296
unsigned char key[ANALYTIC_OPT_MAX_FUNCTIONS]
static PRED_EXPR * pt_make_pred_term_not(const PRED_EXPR *arg1)
#define ER_TP_CANT_COERCE
Definition: error_code.h:250
int upd_del_class_cnt
Definition: parse_tree.h:2752
#define WS_IS_DELETED(mop)
Definition: work_space.h:284
static VAL_LIST * pt_clone_val_list(PARSER_CONTEXT *parser, PT_NODE *attribute_list)
int db_strftime(char *s, int smax, const char *fmt, DB_DATE *date, DB_TIME *timeval)
Definition: db_date.c:973
unsigned with_rollup
Definition: parse_tree.h:3472
void qo_check_coll_optimization(QO_INDEX_ENTRY *ent, COLL_OPT *collation_opt)
Definition: query_graph.c:9254
PT_NODE * arg_list
Definition: parse_tree.h:2258
static XASL_NODE * pt_to_merge_update_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **non_null_attrs)
#define NO_ERROR
Definition: error_code.h:46
PT_UNION_INFO union_
Definition: parse_tree.h:2782
aggregate_specific_function_info info
bool is_iss_candidate
Definition: query_graph.h:155
static PRED_REGU_VARIABLE_P_LIST pt_get_pred_regu_variable_p_list(const PRED_EXPR *pred, int *err)
static PT_NODE * pt_check_hashable(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_arg, int *continue_walk)
static REGU_VARIABLE * pt_make_regu_iscycle(PARSER_CONTEXT *parser, const PT_NODE *node)
COMPATIBLE_LEVEL compatible
static REGU_VARIABLE * pt_make_regu_hostvar(PARSER_CONTEXT *parser, const PT_NODE *node)
static int pt_split_hash_attrs(PARSER_CONTEXT *parser, TABLE_INFO *table_info, PT_NODE *pred, PT_NODE **build_attrs, PT_NODE **probe_attrs)
#define AU_DISABLE(save)
Definition: authenticate.h:106
#define PT_IS_NUMBERING_AFTER_EXECUTION(op)
Definition: parse_tree.h:455
MISC_OPERAND pt_misc_to_qp_misc_operand(PT_MISC_TYPE misc_specifier)
Definition: parse_dbi.c:91
PRED_EXPR * set_pred
Definition: xasl.h:298
int db_value_put_null(DB_VALUE *value)
Definition: db_macro.c:122
char * ustr_upper(char *s)
Definition: misc_string.c:98
static int pt_to_rangelist_key(PARSER_CONTEXT *parser, PT_NODE **term_exprs, int nterms, bool multi_col, KEY_INFO *key_infop, int rangelist_idx, int *multi_col_pos)
PT_NODE * pt_set_orderby_for_sort_limit_plan(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *nodes_list)
VAL_LIST * prior_val_list
Definition: xasl.h:425
static int pt_fix_buildlist_aggregate_cume_dist_percent_rank(PARSER_CONTEXT *parser, PT_NODE *node, AGGREGATE_INFO *info, REGU_VARIABLE *regu)
DB_COLLECTION * db_get_set(const DB_VALUE *value)
PT_METHOD_CALL_INFO method_call
Definition: parse_tree.h:3316
#define DB_MAX_BIT_PRECISION
Definition: dbtype_def.h:549
int db_value_scale(const DB_VALUE *value)
char buf[DB_SMALL_CHAR_BUF_SIZE]
Definition: dbtype_def.h:991
#define PT_SELECT_INFO_IS_FLAGED(s, f)
Definition: parse_tree.h:2735
static int pt_is_subquery(PT_NODE *node)
static PT_NODE * pt_make_prefix_index_data_filter(PARSER_CONTEXT *parser, PT_NODE *where_key_part, PT_NODE *where_part, QO_XASL_INDEX_INFO *index_pred)
bool pt_is_aggregate_function(PARSER_CONTEXT *parser, const PT_NODE *node)
VAL_LIST * value_list
HEAP_CACHE_ATTRINFO * cache_pred
Definition: xasl.h:733
PT_UPDATE_INFO update
Definition: parse_tree.h:3353
static bool pt_analytic_to_metadomain(ANALYTIC_TYPE *func_p, PT_NODE *sort_list, ANALYTIC_KEY_METADOMAIN *func_meta, PT_NODE **index, int *index_size)
int sm_att_id(MOP classop, const char *name)
XASL_NODE * fptr_list
Definition: xasl.h:984
bool ws_has_updated(void)
Definition: work_space.c:2536
const int REGU_VARIABLE_ANALYTIC_WINDOW
Definition: regu_var.hpp:161
PT_MERGE_INFO merge
Definition: parse_tree.h:3315
UINTPTR id
Definition: parse_tree.h:2144
TP_DOMAIN * dom
Definition: xasl.h:197
#define PT_SELECT_INFO_NO_STRICT_OID_CHECK
Definition: parse_tree.h:2726
key_range * key_ranges
Definition: access_spec.hpp:75
static PT_NODE * pt_node_list_to_value_and_reguvar_list(PARSER_CONTEXT *parser, PT_NODE *node, VAL_LIST **value_list, REGU_VARIABLE_LIST *regu_position_list)
static PRED_EXPR * pt_make_pred_term_comp(const REGU_VARIABLE *arg1, const REGU_VARIABLE *arg2, const REL_OP rop, const DB_TYPE data_type)
SORT_NULLS
Definition: query_list.h:404
DB_VALUE * save_instnum_val
Definition: xasl.h:981
int do_get_serial_cached_num(int *cached_num, MOP serial_obj)
#define PT_MERGE_INFO_HAS_UNIQUE
Definition: parse_tree.h:2946
#define XASL_CLEAR_FLAG(x, f)
Definition: xasl.h:497
XASL_NODE * ptqo_to_list_scan_proc(PARSER_CONTEXT *parser, XASL_NODE *xasl, PROC_TYPE proc_type, XASL_NODE *listfile, PT_NODE *namelist, PT_NODE *pred, int *poslist)
static AGGREGATE_TYPE * pt_to_aggregate(PARSER_CONTEXT *parser, PT_NODE *select_node, OUTPTR_LIST *out_list, VAL_LIST *value_list, REGU_VARIABLE_LIST regu_list, REGU_VARIABLE_LIST scan_regu_list, PT_NODE *out_names, DB_VALUE **grbynum_valp)
#define PT_IS_SORT_SPEC_NODE(n)
Definition: parse_tree.h:473
ACCESS_SPEC_TYPE * merge_spec
Definition: xasl.h:971
static PT_NODE * pt_uncorr_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE ** parser_parse_string_use_sys_charset(PARSER_CONTEXT *parser, const char *buffer)
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
TP_DOMAIN * expected_domain
Definition: parse_tree.h:3452
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
SORT_LIST * ptqo_single_orderby(PARSER_CONTEXT *parser)
static TABLE_INFO * pt_table_info_alloc(void)
regu_variable_node * key_limit_u
Definition: access_spec.hpp:81
PT_NODE * show_args
Definition: parse_tree.h:2816
OUTPTR_LIST * out_list
static PT_NODE * pt_set_is_system_generated_stmt(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_arg, int *continue_walk)
bool cover_segments
Definition: query_graph.h:140
PT_NODE * using_index
Definition: parse_tree.h:2693
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2701
enum json_table_column_function func
Definition: parse_tree.h:3240
static PT_NODE * pt_table_compatible_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_info, int *continue_walk)
void qo_top_plan_print_text(PARSER_CONTEXT *parser, xasl_node *xasl, PT_NODE *select, QO_PLAN *plan)
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
void qo_get_optimization_param(void *, QO_PARAM,...)
Definition: query_graph.c:269
static void pt_metadomain_build_comp_graph(ANALYTIC_KEY_METADOMAIN *af_meta, int af_count, int level)
void * parser_alloc(const PARSER_CONTEXT *parser, const int length)
Definition: parse_tree.c:951
static PT_NODE * pt_has_reev_in_subquery_pre(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * assignment
Definition: parse_tree.h:2861
BITSET terms
Definition: query_graph.h:134
BTID * sm_find_index(MOP classop, char **att_names, int num_atts, bool unique_index_only, bool skip_prefix_index, BTID *btid)
REGU_DATATYPE type
Definition: regu_var.hpp:172
REGU_VARIABLE_LIST cls_regu_list_key
Definition: xasl.h:719
static SORT_LIST * pt_to_groupby(PARSER_CONTEXT *parser, PT_NODE *group_list, PT_NODE *root)
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
static int pt_to_index_attrs(PARSER_CONTEXT *parser, TABLE_INFO *table_info, QO_XASL_INDEX_INFO *index_pred, PT_NODE *pred, PT_NODE **pred_attrs, int **pred_offsets)
REGU_VARIABLE * rightptr
Definition: regu_var.hpp:129
PT_NODE * expr
Definition: parse_tree.h:3188
static REGU_VARIABLE * pt_function_to_regu(PARSER_CONTEXT *parser, PT_NODE *function)
ANALYTIC_KEY_METADOMAIN * links[ANALYTIC_OPT_MAX_FUNCTIONS]
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
QL_FLAG
int g_hash_eligible
Definition: xasl.h:330
VAL_LIST * a_val_list
Definition: xasl.h:327
static XASL_NODE * pt_set_connect_by_xasl(PARSER_CONTEXT *parser, PT_NODE *select_node, XASL_NODE *xasl)
REGU_VARIABLE * value
Definition: regu_var.hpp:96
OUTPTR_LIST * a_outptr_list_interm
Definition: xasl.h:326
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2339
const REGU_VARIABLE * pvalue
SM_PREDICATE_INFO * filter_predicate
Definition: class_object.h:536
METHOD_SIG * method_sig
Definition: method_def.hpp:69
static ANALYTIC_KEY_METADOMAIN analitic_key_metadomain_Initializer
unsigned char codeset
Definition: object_domain.h:91
DB_OBJECT * db_real_instance(DB_OBJECT *obj)
Definition: db_virt.c:247
void qstr_make_typed_string(const DB_TYPE db_type, DB_VALUE *value, const int precision, DB_CONST_C_CHAR src, const int s_unit, const int codeset, const int collation_id)
#define PT_SELECT_INFO_MVCC_LOCK_NEEDED
Definition: parse_tree.h:2732
PT_JSON_TABLE_COLUMN_INFO json_table_column_info
Definition: parse_tree.h:3314
char * MOBJ
Definition: work_space.h:174
XASL_NODE * pt_to_insert_xasl(PARSER_CONTEXT *parser, PT_NODE *statement)
static int * pt_make_identity_offsets(PT_NODE *attr_list)
ANALYTIC_KEY_METADOMAIN * children[2]
PRED_EXPR * if_pred
Definition: xasl.h:978
regu_variable_node * m_json_reguvar
void pt_to_pos_descr_groupby(PARSER_CONTEXT *parser, QFILE_TUPLE_VALUE_POSITION *pos_p, PT_NODE *node, PT_NODE *root)
DB_SET * db_seq_create(MOP classop, const char *name, int size)
Definition: db_set.c:252
Definition: query_graph.h:209
int needs_pruning
Definition: xasl.h:236
#define DETAILED_DUMP(level)
Definition: optimizer.h:86
BUILDVALUE_PROC_NODE buildvalue
Definition: xasl.h:1020
void pt_register_orphan_db_value(PARSER_CONTEXT *parser, const DB_VALUE *orphan)
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 METHOD_SIG_LIST * pt_to_method_sig_list(PARSER_CONTEXT *parser, PT_NODE *node_list, PT_NODE *subquery_as_attr_list)
PT_NODE * pt_point_ref(PARSER_CONTEXT *parser, const PT_NODE *node)
#define XASL_HAS_CONNECT_BY
Definition: xasl.h:483
int val_cnt
Definition: xasl.h:208
PT_NODE * mq_translate(PARSER_CONTEXT *parser, PT_NODE *volatile node)
struct table_info * next
PT_NODE * index_hint
Definition: parse_tree.h:2931
static XASL_NODE * pt_to_fetch_as_scan_proc(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *join_term, XASL_NODE *xasl_to_scan)
XASL_NODE * pt_to_merge_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **non_null_upd_attrs, PT_NODE **non_null_ins_attrs, PT_NODE *default_expr_attrs)
PARSER_VARCHAR * pt_append_nulstring(const PARSER_CONTEXT *parser, PARSER_VARCHAR *bstring, const char *nulstring)
Definition: parse_tree.c:1072
void pt_report_to_ersys_with_statement(PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type, PT_NODE *statement)
Definition: query_result.c:338
int ils_prefix_len
analytic_list_node * head
static void pt_set_aptr(PARSER_CONTEXT *parser, PT_NODE *select_node, XASL_NODE *xasl)
PRED_EXPR * pt_to_pred_expr_with_arg(PARSER_CONTEXT *parser, PT_NODE *node_list, int *argp)
MOBJ locator_create_heap_if_needed(MOP class_mop, bool reuse_oid)
Definition: locator_cl.c:5690
ATTR_ID * attrids_key
Definition: xasl.h:728
#define PT_EXPR_INFO_CAST_WRAP
Definition: parse_tree.h:2236
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
#define XASL_G_GRBYNUM_FLAG_SCAN_CONTINUE
Definition: xasl.h:471
json_table_column_behavior m_on_empty
cubxasl::json_table::node json_table_node
int n_oid_list
Definition: xasl.h:1035
static void pt_aggregate_info_append_value_list(AGGREGATE_INFO *info, VAL_LIST *value_list)
int ils_prefix_len
Definition: query_graph.h:158
#define db_get_collection
Definition: dbtype.h:60
DB_TYPE
Definition: dbtype_def.h:670
#define PT_SELECT_INFO_IS_UPD_DEL_QUERY
Definition: parse_tree.h:2729
regu_variable_node * src
PT_NODE * assignment
Definition: parse_tree.h:2928
INDX_INFO * indexptr
Definition: xasl.h:927
static REGU_VARIABLE * pt_to_regu_attr_descr(PARSER_CONTEXT *parser, DB_OBJECT *class_object, HEAP_CACHE_ATTRINFO *cache_attrinfo, PT_NODE *attr)
static XASL_NODE * pt_to_corr_subquery_list(PARSER_CONTEXT *parser, PT_NODE *node, UINTPTR id)
DB_VALUE ** cache_reserved
Definition: xasl.h:738
#define ER_FAILED
Definition: error_code.h:47
TYPE_EVAL_TERM et_type
REGU_VARIABLE_LIST next
Definition: regu_var.hpp:221
PT_NODE * sort_lists
bool ql_flag
Definition: xasl.h:300
static SORT_LIST * pt_sort_list_from_metadomain(PARSER_CONTEXT *parser, ANALYTIC_KEY_METADOMAIN *meta, PT_NODE **sort_list_index, PT_NODE *select_list)
const int REGU_VARIABLE_HIDDEN_COLUMN
Definition: regu_var.hpp:156
int db_seq_put(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:745
#define WS_REAL_OID(mop)
Definition: work_space.h:294
int wait_msecs
Definition: xasl.h:224
int db_datetime_decode(const DB_DATETIME *datetime, int *month, int *day, int *year, int *hour, int *minute, int *second, int *millisecond)
Definition: db_date.c:4574
static void pt_make_json_table_spec_node_internal(PARSER_CONTEXT *parser, PT_JSON_TABLE_NODE_INFO *jt_node_info, size_t &current_id, TABLE_INFO *tbl_info, json_table_node &result)
PT_NODE ** qo_xasl_get_terms(QO_XASL_INDEX_INFO *)
#define MSGCAT_SEMANTIC_OUT_OF_MEMORY
int * mvcc_reev_classes
Definition: xasl.h:412
#define PT_REQUIRES_HIERARCHICAL_QUERY(op)
Definition: parse_tree.h:439
bool qo_check_type_index_covering(QO_INDEX_ENTRY *ent)
Definition: query_graph.c:9302
UPDDEL_CLASS_INFO * classes
Definition: xasl.h:407
PT_RESERVED_NAME_TYPE
Definition: parse_tree.h:2387
int db_get_string_collation(const DB_VALUE *value)
int nsegs
Definition: query_graph.h:119
PT_MISC_TYPE all_or_distinct
Definition: parse_tree.h:2260
bool pt_is_op_hv_late_bind(PT_OP_TYPE op)
struct json_table_column_behavior on_empty
Definition: parse_tree.h:3242
REGU_VARIABLE * limit_row_count
Definition: xasl.h:983
static PT_NODE * pt_set_isleaf_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static ANALYTIC_EVAL_TYPE * pt_generate_simple_analytic_eval_type(PARSER_CONTEXT *parser, ANALYTIC_INFO *info)
PT_HINT_ENUM hint
Definition: parse_tree.h:2340
static void pt_fill_in_attrid_array(REGU_VARIABLE_LIST attr_list, ATTR_ID *attr_array, int *next_pos)
PT_NODE * search_cond
Definition: parse_tree.h:2925
PT_NODE * arg3
Definition: parse_tree.h:2202
static void pt_set_regu_list_pos_descr_from_idx(REGU_VARIABLE_LIST &regu_list, size_t starting_index)
TP_DOMAIN * domain
Definition: class_object.h:444
union xasl_node::@155 proc
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
PT_HINT_ENUM hint
Definition: parse_tree.h:2074
#define QO_SEG_HEAD(seg)
Definition: query_graph.h:510
ATTR_ID * attrids_pred
Definition: xasl.h:1060
PT_NODE * pt_get_select_list(PARSER_CONTEXT *parser, PT_NODE *query)
Definition: query_result.c:404
bool qo_is_interesting_order_scan(QO_PLAN *plan)
const int REGU_VARIABLE_FIELD_NESTED
Definition: regu_var.hpp:158
SORT_LIST * pt_to_orderby(PARSER_CONTEXT *parser, PT_NODE *order_list, PT_NODE *root)
bool has_delete
Definition: xasl.h:440
PT_NODE * arg2
Definition: parse_tree.h:2664
int orderby_desc
Definition: access_spec.hpp:92
int db_value_clone(DB_VALUE *src, DB_VALUE *dest)
Definition: db_macro.c:1564
#define PT_EXPR_INFO_CAST_NOFAIL
Definition: parse_tree.h:2225
int correlation_level
Definition: parse_tree.h:2745
TP_DOMAIN_STATUS tp_value_auto_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
REGU_VARIABLE * leftptr
Definition: regu_var.hpp:128
#define PT_NODE_PRINT_TO_ALIAS(p, n, c)
Definition: parse_tree.h:578
CLASS_STATS * stats
Definition: class_object.h:747
int no_logging
Definition: xasl.h:410
bool groupby_skip
Definition: query_graph.h:149
int db_col_get(DB_COLLECTION *col, int element_index, DB_VALUE *value)
Definition: db_set.c:1222
REGU_VARIABLE_LIST set_regu_list
Definition: xasl.h:764
int num_assign_reev_classes
Definition: xasl.h:377
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
SHOWSTMT_TYPE show_type
Definition: xasl.h:758
enum pt_type_enum PT_TYPE_ENUM
Definition: parse_tree.h:962
regu_variable_node * elem
PT_NODE * select_node
SM_PARTITION * partition
Definition: class_object.h:760
#define ASSERT_ERROR_AND_SET(error_code)
analytic_eval_type * next
static bool pt_has_reev_in_subquery(PARSER_CONTEXT *parser, PT_NODE *statement)
static void pt_aggregate_info_update_value_and_reguvar_lists(AGGREGATE_INFO *info, VAL_LIST *value_list, REGU_VARIABLE_LIST regu_position_list, REGU_VARIABLE_LIST regu_constant_list)
PRED_EXPR * g_grbynum_pred
Definition: xasl.h:316
int num_val_lists
Definition: xasl.h:399
#define PT_IS_SPEC_FLAG_SET(spec_, flags_)
Definition: parse_tree.h:653
static REGU_VARIABLE * pt_make_vid(PARSER_CONTEXT *parser, const PT_NODE *data_type, const REGU_VARIABLE *regu3)
#define MSGCAT_RUNTIME_NESTED_AGGREGATE
cubxasl::analytic_list_node * head_list
#define XASL_G_GRBYNUM_FLAG_LIMIT_GT_LT
Definition: xasl.h:475
#define assert_release(e)
Definition: error_manager.h:96
static int pt_fix_first_term_func_index_for_iss(PARSER_CONTEXT *parser, QO_INDEX_ENTRY *index_entryp, PT_NODE **term_exprs)
#define pt_is_query(n)
Definition: parse_tree.h:258
QO_PLAN * qo_optimize_query(PARSER_CONTEXT *, PT_NODE *)
Definition: query_graph.c:358
#define DB_MAX_NCHAR_PRECISION
Definition: dbtype_def.h:541
XASL_NODE * pt_skeleton_buildlist_proc(PARSER_CONTEXT *parser, PT_NODE *namelist)
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
VAL_LIST * val_list
PT_NODE * with
Definition: parse_tree.h:2075
TARGET_TYPE type
Definition: xasl.h:925
PT_NODE * spec
Definition: parse_tree.h:2859
static int pt_make_constant_regu_list_from_val_list(PARSER_CONTEXT *parser, VAL_LIST *value_list, REGU_VARIABLE_LIST *regu_list)
ATTR_ID * attrids_pred
Definition: xasl.h:732
DB_DOMAIN * pt_node_data_type_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *dt, PT_TYPE_ENUM type)
Definition: parse_dbi.c:2029
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
static REGU_VARIABLE * pt_make_regu_subquery(PARSER_CONTEXT *parser, XASL_NODE *xasl, const UNBOX unbox, const PT_NODE *node)
static int pt_split_pred_regu_list(PARSER_CONTEXT *parser, const VAL_LIST *val_list, const PRED_EXPR *pred, REGU_VARIABLE_LIST *regu_list_rest, REGU_VARIABLE_LIST *regu_list_pred, REGU_VARIABLE_LIST *prior_regu_list_rest, REGU_VARIABLE_LIST *prior_regu_list_pred, bool split_prior)
FUNC_TYPE
SYMBOL_INFO * stack
union regu_variable_node::regu_data_value value
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
static int pt_mvcc_set_spec_assign_reev_extra_indexes(PARSER_CONTEXT *parser, PT_NODE *spec_assign, PT_NODE *spec_list, PT_NODE *assign_list, int *indexes, int indexes_alloc_size)
PT_NODE * qo_plan_iscan_sort_list(QO_PLAN *)
void regu_alloc(T *&ptr)
static void pt_fix_pseudocolumns_pos_regu_list(PARSER_CONTEXT *parser, PT_NODE *node_list, REGU_VARIABLE_LIST regu_list)
REGU_VARLIST_LIST select_list
Definition: xasl.h:223
void pt_set_isleaf_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, DB_VALUE **isleaf_valp)
static PT_NODE * parser_generate_xasl_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
XASL_NODE * inner_xasl
Definition: xasl.h:359
static REGU_VARIABLE * pt_make_regu_constant(PARSER_CONTEXT *parser, DB_VALUE *db_value, const DB_TYPE db_type, const PT_NODE *node)
REGU_VARIABLE * orderby_limit
Definition: xasl.h:960
PT_TYPE_ENUM pt_db_to_type_enum(const DB_TYPE t)
Definition: parse_dbi.c:2595
CL_ATTR_ID id
Definition: regu_var.hpp:76
static ODKU_INFO * pt_to_odku_info(PARSER_CONTEXT *parser, PT_NODE *insert, XASL_NODE *xasl)
struct pt_query_info::@123 flag
PT_NODE * mq_get_references_helper(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *spec, bool get_spec_referenced_attr)
int select_list_size
Definition: xasl.h:222
static TABLE_INFO * pt_find_table_info(UINTPTR spec_id, TABLE_INFO *exposed_list)
QUERY_OPTIONS option
Definition: xasl.h:967
PT_NODE * pt_expression_2(PARSER_CONTEXT *parser_ptr, PT_OP_TYPE op, PT_NODE *arg1, PT_NODE *arg2)
#define XASL_LINK_TO_REGU_VARIABLE
Definition: xasl.h:477
PT_NODE * attribute_list
int num_default_expr
Definition: xasl.h:389
UNION_PROC_NODE union_
Definition: xasl.h:1017
#define MSGCAT_SEMANTIC_NO_ORDERBY_ALLOWED
static int pt_cnt_attrs(const REGU_VARIABLE_LIST attr_list)
PT_SPEC_FLAG
Definition: parse_tree.h:1517
int * mvcc_reev_classes
Definition: xasl.h:379
#define WS_ISVID(mop)
Definition: work_space.h:288
#define PT_SHOULD_BIND_RESERVED_NAME(spec_)
Definition: parse_tree.h:686
OID * ws_identifier(MOP mop)
Definition: work_space.c:2805
struct sm_component * next
Definition: class_object.h:384
union pt_query_info::@124 q
HEAP_CACHE_ATTRINFO * cache_attrinfo
char * pt_alloc_packing_buf(int size)
#define OID_SET_NULL(oidp)
Definition: oid.h:85
PT_NODE * class_specs
Definition: parse_tree.h:2062
PT_NODE * path_entities
Definition: parse_tree.h:2138
ANALYTIC_EVAL_TYPE * a_eval_list
Definition: xasl.h:322
PT_NODE * node
Definition: parse_tree.h:3133
VALPTR_LIST ** valptr_lists
Definition: xasl.h:400
static XASL_NODE * pt_to_union_proc(PARSER_CONTEXT *parser, PT_NODE *node, PROC_TYPE type)
TP_DOMAIN * tp_domain_resolve_value(const DB_VALUE *val, TP_DOMAIN *dbuf)
int projected_size
Definition: xasl.h:1034
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
int groupby_desc
Definition: access_spec.hpp:93
struct pt_merge_info::@125 update
#define TP_IS_STRING_TYPE(typeid)
void vid_get_keys(MOP mop, DB_VALUE *value)
static SYMBOL_INFO * pt_push_symbol_info(PARSER_CONTEXT *parser, PT_NODE *select_node)
struct xasl_node * parent_proc_xasl
Definition: parse_tree.h:3592
SM_FUNCTION_INFO * func_index_info
Definition: class_object.h:541
bool pt_false_search_condition(PARSER_CONTEXT *parser, const PT_NODE *statement)
unsigned int custom_print
Definition: parse_tree.h:3556
aggregate_accumulator accumulator
int has_uniques
Definition: xasl.h:237
TP_DOMAIN * tp_domain_copy(const TP_DOMAIN *domain, bool check_cache)
SM_ATTRIBUTE * classobj_find_attribute(SM_CLASS *class_, const char *name, int class_attribute)
void pt_set_level_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, DB_VALUE **level_valp)
PT_NODE * group_by
Definition: parse_tree.h:2688
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
static PT_NODE * pt_to_aggregate_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
PT_NODE * pt_flat_spec_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
XASL_NODE * update_xasl
Definition: xasl.h:438
MERGELIST_PROC_NODE mergelist
Definition: xasl.h:1021
METHOD_SPEC_TYPE method_node
Definition: xasl.h:788
XASL_NODE * ptqo_to_scan_proc(PARSER_CONTEXT *parser, QO_PLAN *plan, XASL_NODE *xasl, PT_NODE *spec, PT_NODE *where_key_part, PT_NODE *where_part, QO_XASL_INDEX_INFO *info, PT_NODE *where_hash_part)
XASL_NODE * aptr_list
Definition: xasl.h:974
SM_CLASS_CONSTRAINT * constraints
Definition: query_graph.h:108
TP_DOMAIN tp_Integer_domain
SM_NAME_SPACE name_space
Definition: class_object.h:386
int pt_append_omitted_on_update_expr_assignments(PARSER_CONTEXT *parser, PT_NODE *assigns, PT_NODE *from)
static XASL_NODE * pt_append_scan(const XASL_NODE *to, const XASL_NODE *from)
int er_errid(void)
#define PT_IS_STRING_TYPE(t)
Definition: parse_tree.h:148
static void pt_add_regu_var_to_list(REGU_VARIABLE_LIST *destination, REGU_VARIABLE_LIST source)
PROC_TYPE type
Definition: xasl.h:953
#define READONLY_SCAN(scan_op_type)
SHOWSTMT_TYPE show_type
Definition: parse_tree.h:2815
void db_string_free(char *string)
Definition: db_admin.c:2596
REL_OP
#define QPROC_IS_INTERPOLATION_FUNC(func_p)
Definition: xasl.h:531
static ACCESS_SPEC_TYPE * pt_make_cselect_access_spec(XASL_NODE *xasl, METHOD_SIG_LIST *method_sig_list, ACCESS_METHOD access, INDX_INFO *indexptr, PRED_EXPR *where_pred, REGU_VARIABLE_LIST attr_list)
PT_NODE_LIST_INFO node_list
Definition: parse_tree.h:3320
OID class_oid
Definition: xasl.h:386
static PT_NODE * pt_append_assignment_references(PARSER_CONTEXT *parser, PT_NODE *assignments, PT_NODE *from, PT_NODE *select_list)
XASL_NODE * xasl_head
DB_SET * db_set_create_multi(MOP classop, const char *name)
Definition: db_set.c:192
#define XASL_INCLUDES_TDE_CLASS
Definition: xasl.h:493
UPDDEL_CLASS_INFO * classes
Definition: xasl.h:370
void regu_dbval_type_init(db_value *ptr, DB_TYPE type)
static void pt_split_access_if_instnum(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *where, PT_NODE **access_part, PT_NODE **if_part, PT_NODE **instnum_part)
SCAN_OPERATION_TYPE scan_op_type
Definition: parse_tree.h:2751
static OUTPTR_LIST * pt_to_outlist(PARSER_CONTEXT *parser, PT_NODE *node_list, SELUPD_LIST **selupd_list_ptr, UNBOX unbox)
bool orderby_skip
Definition: query_graph.h:146
PT_NODE * pt_to_merge_update_query(PARSER_CONTEXT *parser, PT_NODE *select_list, PT_MERGE_INFO *info)
int no_logging
Definition: xasl.h:375
SHOWSTMT_TYPE
static ACCESS_SPEC_TYPE * pt_make_access_spec(TARGET_TYPE spec_type, ACCESS_METHOD access, INDX_INFO *indexptr, PRED_EXPR *where_key, PRED_EXPR *where_pred, PRED_EXPR *where_range)
UNBOX
#define PT_MERGE_INFO_INSERT_ONLY
Definition: parse_tree.h:2948
DB_VALUE * arg
Definition: xasl.h:297
static bool pt_metadomains_compatible(ANALYTIC_KEY_METADOMAIN *f1, ANALYTIC_KEY_METADOMAIN *f2, ANALYTIC_KEY_METADOMAIN *out, int *lost_link_count, int level)
int num_reev_classes
Definition: xasl.h:411
HFID * sm_get_ch_heap(MOP classmop)
static void pt_to_misc_operand(REGU_VARIABLE *regu, PT_MISC_TYPE misc_specifier)
BUILDLIST_PROC_NODE buildlist
Definition: xasl.h:1019
AGGREGATE_TYPE * head_list
static SORT_LIST * pt_agg_orderby_to_sort_list(PARSER_CONTEXT *parser, PT_NODE *order_list, PT_NODE *agg_args_list)
TP_DOMAIN tp_Null_domain
DB_VALUE ** reserved_values
static PT_NODE * pt_filter_pseudo_specs(PARSER_CONTEXT *parser, PT_NODE *spec)
enum tp_domain_status TP_DOMAIN_STATUS
#define WS_ISDIRTY(mop)
Definition: work_space.h:259
Definition: xasl.h:189
static int pt_mvcc_flag_specs_assign_reev(PARSER_CONTEXT *parser, PT_NODE *spec_list, PT_NODE *assign_list)
MOP mop
Definition: query_graph.h:63
bool mq_is_outer_join_spec(PARSER_CONTEXT *parser, PT_NODE *spec)
int * attr_ids
Definition: xasl.h:266
regu_variable_node operand
VAL_LIST * listfile_value_list
PT_NODE * attr_list
Definition: parse_tree.h:2333
static int pt_ordbynum_to_key_limit_multiple_ranges(PARSER_CONTEXT *parser, QO_PLAN *plan, XASL_NODE *xasl)
static REGU_VARIABLE * pt_attribute_to_regu(PARSER_CONTEXT *parser, PT_NODE *attr)
DB_VALUE * host_variables
Definition: parse_tree.h:3560
JOIN_TYPE
Definition: query_list.h:32
cub_regex_object * compiled_regex
int * att_id
Definition: xasl.h:390
unsigned char style
Definition: dbtype_def.h:979
PT_NODE * pt_add_row_oid_name(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: compile.c:347
DB_OBJECT * virt_object
Definition: parse_tree.h:2548
HYBRID_NODE s
Definition: xasl.h:932
UPDATE_PROC_NODE update
Definition: xasl.h:1022
static ACCESS_SPEC_TYPE * pt_to_set_expr_table_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *set_expr, PT_NODE *where_part)
regu_variable_node * lhs
METHOD_SIG * next
Definition: method_def.hpp:56
PT_NODE * class_specs
Definition: parse_tree.h:2860
XASL_NODE_HEADER header
Definition: xasl.h:951
DELETE_PROC_NODE delete_
Definition: xasl.h:1024
PT_NODE * data_type
Definition: parse_tree.h:3453
static int pt_get_mvcc_reev_range_data(PARSER_CONTEXT *parser, TABLE_INFO *table_info, PT_NODE *where_key_part, QO_XASL_INDEX_INFO *index_pred, PRED_EXPR **where_range, REGU_VARIABLE_LIST *regu_attributes_range, HEAP_CACHE_ATTRINFO **cache_range)
#define DB_DEFAULT_NUMERIC_SCALE
Definition: dbtype_def.h:567
#define SIMPLE_DUMP(level)
Definition: optimizer.h:85
unsigned single_table_opt
Definition: parse_tree.h:2711
DB_VALUE * g_grbynum_val
Definition: xasl.h:317
#define PT_IS_OID_NAME(n)
Definition: parse_tree.h:323
static PT_NODE * pt_resolve_analytic_references(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_list, VAL_LIST *vallist)
const char * pt_get_name(PT_NODE *nam)
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
struct parser_context::@134 flag
SORT_ORDER s_order
Definition: query_list.h:417
static REGU_VARIABLE * pt_make_regu_numbering(PARSER_CONTEXT *parser, const PT_NODE *node)
int num_attrs_reserved
Definition: xasl.h:739
char hidden_column
Definition: parse_tree.h:2556
PT_DOT_INFO dot
Definition: parse_tree.h:3287
struct set_numbering_node_etc_info SET_NUMBERING_NODE_ETC_INFO
void pt_set_connect_by_operator_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, XASL_NODE *xasl)
unsigned abort
Definition: parse_tree.h:3603
#define PT_PRED_ARG_ORDBYNUM_CONTINUE
SELUPD_LIST * selected_upd_list
Definition: xasl.h:969
int is_single_tuple
Definition: xasl.h:965
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
json_table_column_behavior m_on_error
PT_NODE * arg2
Definition: parse_tree.h:2086
ACCESS_SCHEMA_TYPE
Definition: xasl.h:703
VAL_LIST * val_list
Definition: xasl.h:972
PRED_EXPR * ordbynum_pred
Definition: xasl.h:958
REGU_VARIABLE_LIST list_regu_list_probe
Definition: xasl.h:751
bool iscan_oid_order
Definition: xasl.h:1041
#define MSGCAT_SEMANTIC_NOT_HIERACHICAL_QUERY
TP_DOMAIN * pt_xasl_node_to_domain(PARSER_CONTEXT *parser, const PT_NODE *node)
REGU_VARIABLE_LIST list_regu_list_build
Definition: xasl.h:750
int listfile_attr_offset
TABLE_INFO * table_info
void pt_to_regu_resolve_domain(int *p_precision, int *p_scale, const PT_NODE *node)
PT_NODE * index_ss
Definition: parse_tree.h:2698
PT_NODE * next_row
Definition: parse_tree.h:3449
PT_NODE * parser_get_tree_list_diff(PARSER_CONTEXT *parser, PT_NODE *list1, PT_NODE *list2)
PT_NODE * non_null_attrs
Definition: parse_tree.h:2344
PT_JSON_TABLE_INFO json_table_info
Definition: parse_tree.h:3312
static PRED_EXPR * pt_make_pred_expr_pred(const PRED_EXPR *arg1, const PRED_EXPR *arg2, const BOOL_OP bop)
DB_VALUE * val
Definition: xasl.h:196
PT_CTE_INFO cte
Definition: parse_tree.h:3282
int no_logging
Definition: xasl.h:396
int db_date_encode(DB_DATE *date, int month, int day, int year)
Definition: db_date.c:275
static ACCESS_SPEC_TYPE * pt_to_cselect_table_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *cselect, PT_NODE *src_derived_tbl)
int ATTR_ID
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
FUNC_TYPE function_type
Definition: parse_tree.h:2259
PT_TYPE_ENUM type_enum
Definition: parse_tree.h:3457
HEAP_CACHE_ATTRINFO * attr_info
Definition: xasl.h:265
static DB_VALUE * pt_index_value(const VAL_LIST *value, int index)
void pt_report_to_ersys(const PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type)
Definition: query_result.c:287
RANGE range
Definition: access_spec.hpp:69
PT_NODE * select_list
PT_NODE * use_merge_hint
Definition: parse_tree.h:2071
#define XASL_NEED_SINGLE_TUPLE_SCAN
Definition: xasl.h:492
PT_NODE * or_next
Definition: parse_tree.h:3448
OPERATOR_TYPE opcode
Definition: regu_var.hpp:131
KEY_INFO key_info
Definition: access_spec.hpp:91
XASL_NODE * pt_remove_xasl(XASL_NODE *xasl_list, XASL_NODE *remove)
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
DB_TYPE pt_type_enum_to_db(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:2314
ACCESS_METHOD access
Definition: xasl.h:926
ACCESS_METHOD
Definition: xasl.h:687
PT_NODE * class_where
Definition: parse_tree.h:2940
SCAN_OPERATION_TYPE scan_op_type
Definition: xasl.h:1005
static ACCESS_SPEC_TYPE * pt_to_cte_table_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *cte_def, PT_NODE *where_part)
const int REGU_VARIABLE_UPD_INS_LIST
Definition: regu_var.hpp:166
void port_close_memstream(FILE *fp, char **ptr, size_t *sizeloc)
Definition: porting.c:2220
XASL_NODE * next
Definition: xasl.h:952
bool pr_is_set_type(DB_TYPE type)
PT_NODE * limit
Definition: parse_tree.h:2773
bool qo_is_index_loose_scan(QO_PLAN *plan)
DB_DATA data
Definition: dbtype_def.h:1083
PT_MISC_TYPE class_or_inst
Definition: parse_tree.h:2368
bool use_descending
Definition: query_graph.h:152
HEAP_CACHE_ATTRINFO * cache_rest
Definition: xasl.h:735
bool single_table_opt
Definition: xasl.h:431
#define CHECK_HASH_ATTR(hashable_arg, hash_attr)
DB_VALUE * s_dbval
Definition: xasl.h:934
regu_variable_node * lower
Definition: optimizer.h:144
int flag
Definition: xasl.h:954
PT_MISC_TYPE derived_table_type
Definition: parse_tree.h:2147
int qo_xasl_get_num_terms(QO_XASL_INDEX_INFO *info)
static int pt_serial_to_xasl_class_oid_list(PARSER_CONTEXT *parser, const PT_NODE *serial, OID **oid_listp, int **lock_listp, int **tcard_listp, int *nump, int *sizep)
static PT_NODE * pt_set_qprior_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
XASL_NODE * recursive_part
Definition: xasl.h:447
#define PT_MERGE_INFO_SERVER_OP
Definition: parse_tree.h:2947
#define DB_MAX_VARBIT_PRECISION
Definition: dbtype_def.h:552
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
static XASL_NODE * pt_find_xasl(XASL_NODE *list, XASL_NODE *match)
PT_NODE * arg1
Definition: parse_tree.h:2663
#define PT_NODE_PRINT_VALUE_TO_TEXT(p, n)
Definition: parse_tree.h:597
#define PT_IS_SELECT(n)
Definition: parse_tree.h:284
PT_OP_TYPE pt_converse_op(PT_OP_TYPE op)
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,...)
ACCESS_SPEC_TYPE * next
Definition: xasl.h:935
Definition: db_set.h:35
PT_HINT_ENUM
Definition: parse_tree.h:1161
PT_NODE * arg2
Definition: parse_tree.h:2198
PRED_EXPR * start_with_pred
Definition: xasl.h:419
cubxasl::pred_expr * pred
Definition: regu_var.hpp:133
PT_NODE * del_search_cond
Definition: parse_tree.h:2930
int num_assigns
Definition: xasl.h:372
analytic_percentile_function_info percentile
int db_set_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:508
PT_FUNCTION_INFO function
Definition: parse_tree.h:3301
PT_CONNECT_BY_CHECK_CYCLES check_cycles
Definition: parse_tree.h:2710
KEY_RANGE iss_range
Definition: access_spec.hpp:99
XASL_NODE * outer_xasl
Definition: xasl.h:356
#define XASL_SET_FLAG(x, f)
Definition: xasl.h:496
static PT_NODE * pt_find_hq_op_except_prior(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
#define CAST_POINTER_TO_NODE(p)
Definition: parse_tree.h:607
#define DB_MAX_VARCHAR_PRECISION
Definition: dbtype_def.h:536
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)
PT_NODE * parser_make_expression(PARSER_CONTEXT *parser, PT_OP_TYPE OP, PT_NODE *arg1, PT_NODE *arg2, PT_NODE *arg3)
TP_DOMAIN tp_Vobj_domain
#define PT_ERRORmf2(parser, node, setNo, msgNo, arg1, arg2)
Definition: parse_tree.h:65
static XASL_NODE * pt_make_aptr_parent_node(PARSER_CONTEXT *parser, PT_NODE *node, PROC_TYPE type)
bool is_NAME_without_prior
XASL_NODE * pt_to_delete_xasl(PARSER_CONTEXT *parser, PT_NODE *statement)
#define assert(x)
#define MSGCAT_RUNTIME_OUTER_JOIN_OPT_FAILED
ACCESS_SPEC_TYPE * curr_spec
Definition: xasl.h:996
static PT_NODE * pt_substitute_assigned_name_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
REGU_VARIABLE * func_regu
Definition: xasl.h:277
bool qdump_print_xasl(xasl_node *xasl_p)
Definition: query_dump.c:2294
int ordbynum_flag
Definition: xasl.h:961
bool pt_has_inst_or_orderby_num(PARSER_CONTEXT *parser, PT_NODE *node)
#define XASL_TOP_MOST_XASL
Definition: xasl.h:480
PT_MISC_TYPE qualifier
Definition: parse_tree.h:2204
CONNECTBY_PROC_NODE connect_by
Definition: xasl.h:1025
static DB_VALUE ** pt_make_reserved_value_list(PARSER_CONTEXT *parser, PT_RESERVED_NAME_TYPE type)
PT_NODE * use_nl_hint
Definition: parse_tree.h:2871
PT_NODE * pt_find_spec(PARSER_CONTEXT *parser, const PT_NODE *from, const PT_NODE *name)
PT_NODE * pt_check_groupbynum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
static PRED_EXPR * pt_to_pred_expr_local_with_arg(PARSER_CONTEXT *parser, PT_NODE *node, int *argp)
XASL_NODE * pt_to_update_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **non_null_attrs)
int use_desc_index
Definition: access_spec.hpp:94
#define PT_IS_QUERY_NODE_TYPE(x)
Definition: parse_tree.h:115
static REGU_VARIABLE * pt_make_regu_level(PARSER_CONTEXT *parser, const PT_NODE *node)
static XASL_NODE * pt_to_buildschema_proc(PARSER_CONTEXT *parser, PT_NODE *select_node)
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)
#define LANG_COERCIBLE_CODESET
#define PT_SELECT_INFO_MULTI_UPDATE_AGG
Definition: parse_tree.h:2719
PT_SPEC_FLAG flag
Definition: parse_tree.h:2155
unsigned order_siblings
Definition: parse_tree.h:2765
XASL_NODE * dptr_list
Definition: xasl.h:976
REGU_VARIABLE_LIST after_cb_regu_list_rest
Definition: xasl.h:430
OPERATOR_TYPE
int db_make_set(DB_VALUE *value, DB_C_SET *set)
PT_POINTER_INFO pointer
Definition: parse_tree.h:3359
static PRED_EXPR * pt_make_pred_term_some_all(const REGU_VARIABLE *arg1, const REGU_VARIABLE *arg2, const REL_OP rop, const DB_TYPE data_type, const QL_FLAG some_all)
int prm_get_integer_value(PARAM_ID prm_id)
void pt_evaluate_tree(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_values, int values_count)
PT_MISC_TYPE asc_or_desc
Definition: parse_tree.h:2830
int db_make_multiset(DB_VALUE *value, DB_C_SET *set)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define PT_SPEC_IS_ENTITY(spec_)
Definition: parse_tree.h:698
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
PRED_EXPR * where_range
Definition: xasl.h:931
PRED_EXPR * cons_pred
Definition: xasl.h:392
DB_OBJECT * op
Definition: parse_tree.h:3039
int num_vals
Definition: xasl.h:388
char * db_get_database_name(void)
Definition: db_admin.c:432
PT_TYPE_ENUM virt_type_enum
Definition: parse_tree.h:2042
const int REGU_VARIABLE_FIELD_COMPARE
Definition: regu_var.hpp:157
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)
struct db_char::@52 info
PT_NODE * pt_to_upd_del_query(PARSER_CONTEXT *parser, PT_NODE *select_names, PT_NODE *select_list, PT_NODE *from, PT_NODE *with, PT_NODE *class_specs, PT_NODE *where, PT_NODE *using_index, PT_NODE *order_by, PT_NODE *orderby_for, int server_op, SCAN_OPERATION_TYPE scan_op_type)
DB_VALUE db_value
Definition: parse_tree.h:3059
PT_NODE * odku_assignments
Definition: parse_tree.h:2341
INSERT_PROC_NODE insert
Definition: xasl.h:1023
ACCESS_SPEC_FLAG
Definition: xasl.h:711
DB_IDENTIFIER * db_identifier(DB_OBJECT *obj)
Definition: db_admin.c:2629
char * db_get_user_and_host_name(void)
Definition: db_admin.c:1932
PT_NODE * offset
Definition: parse_tree.h:2273
PT_NODE * cte_pointer
Definition: parse_tree.h:2132
struct sort_list * next
Definition: query_list.h:415
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
comp_eval_term et_comp
#define PT_GET_COLLATION_MODIFIER(p)
Definition: parse_tree.h:619
void regu_set_error_with_zero_args(int err_type)
PT_NODE * entity
Definition: parse_tree.h:2038
int db_seq_size(DB_SET *set)
Definition: db_set.c:848
#define MSGCAT_SET_PARSER_RUNTIME
REGU_VARIABLE value
Definition: regu_var.hpp:222
static PT_NODE * pt_substitute_analytic_references(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE **ex_list)
static PT_NODE * pt_flush_class_and_null_xasl(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_arg, int *continue_walk)
static int pt_reserved_id_to_valuelist_index(PARSER_CONTEXT *parser, PT_RESERVED_NAME_ID reserved_id)
xasl_node * regu_xasl_node_alloc(PROC_TYPE type)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
PT_NODE * recursive_part
Definition: parse_tree.h:1978
#define XASL_CLASS_NO_TCARD
Definition: xasl.h:1068
static void pt_to_pred_terms(PARSER_CONTEXT *parser, PT_NODE *terms, UINTPTR id, PRED_EXPR **pred)
int xasl_flag
Definition: xasl.h:69
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
void qo_top_plan_print_json(PARSER_CONTEXT *parser, xasl_node *xasl, PT_NODE *select, QO_PLAN *plan)
QFILE_LIST_ID * list_id
Definition: xasl.h:955
static void pt_to_fetch_proc_list(PARSER_CONTEXT *parser, PT_NODE *spec, XASL_NODE *root)
REGU_VARIABLE_LIST list_regu_list_pred
Definition: xasl.h:748
json_table_column_function m_function
HEAP_CACHE_ATTRINFO * cache_range
Definition: xasl.h:742
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
int sm_is_partitioned_class(MOP op)
static int pt_add_pseudocolumns_placeholders(PARSER_CONTEXT *parser, OUTPTR_LIST *outptr_list, bool alloc_vals)
static int pt_to_list_key(PARSER_CONTEXT *parser, PT_NODE **term_exprs, int nterms, bool multi_col, KEY_INFO *key_infop)
const char * original
Definition: parse_tree.h:2544
PT_NODE * using_index
Definition: parse_tree.h:2064
HFID * sm_ch_heap(MOBJ clobj)
union cubxasl::pred_expr::@185 pe
PT_MISC_TYPE nulls_first_or_last
Definition: parse_tree.h:2831
PT_HINT_ENUM hint
Definition: parse_tree.h:2707
PT_NODE * pt_make_string_value(PARSER_CONTEXT *parser, const char *value_string)
static ANALYTIC_EVAL_TYPE * pt_build_analytic_eval_list(PARSER_CONTEXT *parser, ANALYTIC_KEY_METADOMAIN *meta, ANALYTIC_EVAL_TYPE *eval, PT_NODE **sort_list_index, ANALYTIC_INFO *info)
OID class_oid
Definition: xasl.h:220
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
#define PT_IS_HINT_NODE(n)
Definition: parse_tree.h:406
static PRED_REGU_VARIABLE_P_LIST pt_get_var_regu_variable_p_list(const REGU_VARIABLE *regu, bool is_prior, int *err)
regu_variable_node * percentile_reguvar
char * query_Plan_dump_filename
ACCESS_SPEC_FLAG flags
Definition: xasl.h:937
int orderby_skip
Definition: access_spec.hpp:95
struct json_table_column_behavior on_error
Definition: parse_tree.h:3241
#define QO_NODE_IS_CLASS_HIERARCHY(node)
Definition: query_graph.h:411
#define MSGCAT_RUNTIME_RESOURCES_EXHAUSTED
UPDATE_ASSIGNMENT * assigns
Definition: xasl.h:373
PT_NODE * query_node
#define PT_EXPR_INFO_GROUPBYNUM_LIMIT
Definition: parse_tree.h:2233
#define TP_DOMAIN_COLLATION(dom)
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
#define PT_GET_RESERVED_NAME_FIRST_AND_LAST(type, first, last)
Definition: parse_tree.h:2501
int locator_flush_class(MOP class_mop)
Definition: locator_cl.c:5068
#define PT_IS_NATIONAL_CHAR_STRING_TYPE(t)
Definition: parse_tree.h:156
REGU_VARIABLE_LIST cls_regu_val_list
Definition: xasl.h:725
PT_NODE * parser_copy_tree(PARSER_CONTEXT *parser, const PT_NODE *tree)
struct drand48_data * rand_seed
Definition: regu_var.hpp:136
json_table_spec_node json_table_node
Definition: xasl.h:790
#define XASL_OBJFETCH_IGNORE_CLASSOID
Definition: xasl.h:486
#define PT_IS_VALUE_QUERY(n)
Definition: parse_tree.h:476
static int pt_mvcc_flag_specs_cond_reev(PARSER_CONTEXT *parser, PT_NODE *spec_list, PT_NODE *cond)
PT_NODE * pt_semantic_type(PARSER_CONTEXT *parser, PT_NODE *tree, SEMANTIC_CHK_INFO *sc_info)
void pt_set_numbering_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, DB_VALUE **instnum_valp, DB_VALUE **ordbynum_valp)
REGU_VARIABLE_LIST method_regu_list
Definition: xasl.h:770
#define OPTIMIZATION_ENABLED(level)
Definition: optimizer.h:83
const char * exposed
REGU_VARIABLE * level_regu
Definition: xasl.h:989
SHOWSTMT_SPEC_TYPE showstmt_node
Definition: xasl.h:786
FILE * query_Plan_dump_fp
#define HFID_SET_NULL(hfid)
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
ARITH_TYPE * outarith_list
Definition: xasl.h:348
PT_SHOWSTMT_INFO showstmt
Definition: parse_tree.h:3342
PT_NODE * having
Definition: parse_tree.h:2692
static PT_NODE * pt_build_do_stmt_aptr_list_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
REGU_VARIABLE_LIST a_regu_list
Definition: xasl.h:323
DB_DOMAIN * pt_data_type_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *dt, const char *class_name)
Definition: parse_dbi.c:1805
static PT_NODE * pt_has_reev_in_subquery_post(PARSER_CONTEXT *parser, PT_NODE *tree, void *arg, int *continue_walk)
DB_OBJECT * db_get_object(const DB_VALUE *value)
PT_NODE * from
Definition: parse_tree.h:2686
const char * pt_show_binopcode(PT_OP_TYPE n)
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
#define PT_SELECT_INFO_COLS_SCHEMA
Definition: parse_tree.h:2721
static bool validate_regu_key_function_index(REGU_VARIABLE *regu_var)
VID_OID oid_info
Definition: work_space.h:120
static XASL_NODE * pt_plan_cte(PARSER_CONTEXT *parser, PT_NODE *node, PROC_TYPE proc_type)
XASL_NODE * xasl_node
Definition: xasl.h:771
#define PT_IS_CONST(n)
Definition: parse_tree.h:364
int db_string_put_cs_and_collation(DB_VALUE *value, const int codeset, const int collation_id)
Definition: db_macro.c:4164
PT_NODE * pt_make_prim_data_type_fortonum(PARSER_CONTEXT *parser, int prec, int scale)
union qo_plan::@100 plan_un
UINTPTR spec_id
Definition: parse_tree.h:2543
#define PT_IS_VALUE_NODE(n)
Definition: parse_tree.h:330
DB_VALUE * db_value_copy(DB_VALUE *value)
Definition: db_macro.c:1537
#define PT_SELECT_INFO_IS_MERGE_QUERY
Definition: parse_tree.h:2723
PT_NODE * use_merge_hint
Definition: parse_tree.h:2873
PT_NODE * value_clauses
Definition: parse_tree.h:2938
REGU_VALUE_ITEM * next
Definition: regu_var.hpp:97
PT_NODE * limit
Definition: parse_tree.h:2072
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
int classobj_get_cached_constraint(SM_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type, BTID *id)
#define MSGCAT_RUNTIME_WANT_ONE_COL
#define PT_IS_INSTNUM(n)
Definition: parse_tree.h:387
static REGU_VARIABLE * pt_make_function(PARSER_CONTEXT *parser, int function_code, const REGU_VARIABLE_LIST arg_list, const DB_TYPE result_type, const PT_NODE *node)
#define TP_DOMAIN_TYPE(dom)
int pruning_type
Definition: xasl.h:398
XASL_NODE * pt_to_fetch_proc(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *pred)
REGU_VARIABLE * iscycle_regu
Definition: xasl.h:994
PRED_EXPR * after_connect_by_pred
Definition: xasl.h:420
TP_DOMAIN * fi_domain
Definition: class_object.h:502
static PT_NODE * pt_expand_analytic_node(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_list)
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
#define ACCESS_SPEC_CLS_OID(ptr)
Definition: xasl.h:806
DB_VALUE * db_value_create(void)
Definition: db_macro.c:1517
#define PCOL_ISLEAF_TUPLE_OFFSET
Definition: xasl.h:538
#define XASL_NO_FIXED_SCAN
Definition: xasl.h:491
#define XASL_HAS_NOCYCLE
Definition: xasl.h:482
struct uncorr_info UNCORR_INFO
#define XASL_MULTI_UPDATE_AGG
Definition: xasl.h:484
static void cleanup(int signo)
Definition: broker.c:717
PARSER_VARCHAR * str
Definition: parse_tree.h:3036
#define PT_SET_VALUE_QUERY(n)
Definition: parse_tree.h:479
int pt_str_compare(const char *p, const char *q, CASE_SENSITIVENESS case_flag)
PT_NODE * pt_spec_to_oid_attr(PARSER_CONTEXT *parser, PT_NODE *spec, VIEW_HANDLING how)
Definition: compile.c:101
static PT_NODE * pt_set_level_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
SP_PARSER_CTX * parser
#define ANALYTIC_OPT_MAX_SORT_LIST_COLUMNS
static int pt_to_single_key(PARSER_CONTEXT *parser, PT_NODE **term_exprs, int nterms, bool multi_col, KEY_INFO *key_infop, int *multi_col_pos)
PT_NODE * arg1
Definition: parse_tree.h:2197
int wait_msecs
Definition: xasl.h:374
DB_VALUE * isleaf_val
Definition: xasl.h:991
#define SORT_SPEC_EQ(a, b)
PT_DO_INFO do_
Definition: parse_tree.h:3286
static int pt_to_constraint_pred(PARSER_CONTEXT *parser, XASL_NODE *xasl, PT_NODE *spec, PT_NODE *non_null_attrs, PT_NODE *attr_list, int attr_offset)
#define NULL
Definition: freelistheap.h:34
OID oid
Definition: work_space.h:65
PT_NODE * as_attr_list
Definition: parse_tree.h:2136
LIST_SPEC_TYPE list_node
Definition: xasl.h:785
PT_NODE * pt_add_row_classoid_name(PARSER_CONTEXT *parser, PT_NODE *statement, int server_op)
Definition: compile.c:361
bool qo_is_index_covering_scan(QO_PLAN *plan)
int * att_id
Definition: xasl.h:235
ATTR_ID * attrids_rest
Definition: xasl.h:734
XASL_NODE * pt_append_xasl(XASL_NODE *to, XASL_NODE *from_list)
int ** lob_attr_ids
Definition: xasl.h:240
PT_NODE * use_nl_hint
Definition: parse_tree.h:2069
XASL_NODE * connect_by_ptr
Definition: xasl.h:987
const char * er_msg(void)
int groupby_skip
Definition: access_spec.hpp:96
static void pt_create_json_table_column(PARSER_CONTEXT *parser, PT_NODE *jt_column, TABLE_INFO *tbl_info, json_table_column &col_result)
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
PT_NODE * referenced_attrs
Definition: parse_tree.h:2137
struct pr_type * type
Definition: object_domain.h:76
static void pt_mark_spec_list_for_update_clause(PARSER_CONTEXT *parser, PT_NODE *statement, PT_SPEC_FLAG spec_flag)
PT_NODE * current_class
REGU_VARIABLE_LIST regu_list_rest
Definition: xasl.h:424
PT_NODE * order_by
Definition: parse_tree.h:2875
PT_NODE * out_names
ACCESS_SCHEMA_TYPE schema_type
Definition: xasl.h:737
DB_CHAR ch
Definition: dbtype_def.h:1070
REGU_VARIABLE_LIST regu_list_pred
Definition: xasl.h:423
static REGU_VARIABLE_LIST pt_to_position_regu_variable_list(PARSER_CONTEXT *parser, PT_NODE *node_list, VAL_LIST *value_list, int *attr_offsets)
#define LANG_COERCIBLE_COLL
DB_OBJECT * db_get_class(MOP obj)
Definition: db_info.c:589
unsigned char size
Definition: dbtype_def.h:990
PT_NODE * value_clauses
Definition: parse_tree.h:2334
unsigned recompile
Definition: parse_tree.h:3461
OUTPTR_LIST * a_outptr_list_ex
Definition: xasl.h:325
const char * pr_type_name(DB_TYPE id)
static PT_NODE * pt_set_connect_by_operator_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
VAL_LIST * single_tuple
Definition: xasl.h:963
static char * dbname
PT_MISC_TYPE is_subquery
Definition: parse_tree.h:2747
if(extra_options)
Definition: dynamic_load.c:958
void qo_plan_lite_print(QO_PLAN *plan, FILE *f, int howfar)
int num_assigns
Definition: xasl.h:263
static SORT_LIST * pt_to_order_siblings_by(PARSER_CONTEXT *parser, XASL_NODE *xasl, XASL_NODE *connect_by_xasl)
REGU_VARIABLE_LIST after_cb_regu_list_pred
Definition: xasl.h:429
regu_variable_node * rhs
static XASL_NODE * pt_plan_single_table_hq_iterations(PARSER_CONTEXT *parser, PT_NODE *select_node, XASL_NODE *xasl)
static PT_NODE * pt_fix_interpolation_aggregate_function_order_by(PARSER_CONTEXT *parser, PT_NODE *node)
#define APPEND_TO_XASL(xasl_head, list, xasl_tail)
PT_JSON_TABLE_NODE_INFO json_table_node_info
Definition: parse_tree.h:3313
static void pt_merge_regu_var_lists(REGU_VARIABLE_LIST *destination, REGU_VARIABLE_LIST source)
QFILE_TUPLE_VALUE_POSITION pos_descr
Definition: query_list.h:416
DB_VALUE ** grbynum_valp
struct pr_type * type
Definition: class_object.h:443
PRED_REGU_VARIABLE_P_LIST next
HFID class_hfid
Definition: xasl.h:221
#define PT_SPEC_IS_DERIVED(spec_)
Definition: parse_tree.h:690
XASL_NODE * pt_gen_simple_merge_plan(PARSER_CONTEXT *parser, PT_NODE *select_node, QO_PLAN *plan, XASL_NODE *xasl)
VAL_LIST * g_val_list
Definition: xasl.h:314
#define BTID_SET_NULL(btid)
int db_set_add(DB_SET *set, DB_VALUE *value)
Definition: db_set.c:465
aggregate_list_node * next
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
static int pt_create_iss_range(INDX_INFO *indx_infop, TP_DOMAIN *domain)
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
QO_PLAN_ULTI_RANGE_OPT_USE multi_range_opt_use
static TABLE_INFO * pt_make_table_info(PARSER_CONTEXT *parser, PT_NODE *table_spec)
PT_NODE * default_value
Definition: parse_tree.h:2272
DB_SET * db_set_create_basic(MOP classop, const char *name)
Definition: db_set.c:134
int pt_check_order_by(PARSER_CONTEXT *parser, PT_NODE *query)
struct db_char::@53 sm
XASL_NODE * pt_to_instnum_pred(PARSER_CONTEXT *parser, XASL_NODE *xasl, PT_NODE *pred)
int pt_check_path_eq(PARSER_CONTEXT *parser, const PT_NODE *p, const PT_NODE *q)
XASL_NODE * insert_xasl
Definition: xasl.h:439
static int pt_to_range_key(PARSER_CONTEXT *parser, PT_NODE **term_exprs, int nterms, bool multi_col, KEY_INFO *key_infop)
SORT_LIST_MODE
REGU_VARIABLE_LIST list_regu_list_rest
Definition: xasl.h:749
static XASL_NODE * pt_gen_optimized_plan(PARSER_CONTEXT *parser, PT_NODE *select_node, QO_PLAN *plan, XASL_NODE *xasl)
bool qo_plan_multi_range_opt(QO_PLAN *plan)
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
#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)
SCAN_OPERATION_TYPE
static REGU_VARIABLE * pt_to_cume_dist_percent_rank_regu_variable(PARSER_CONTEXT *parser, PT_NODE *tree, UNBOX unbox)
DB_VALUE * value
Definition: regu_var.hpp:127
AGGREGATE_TYPE * agg_list
Definition: xasl.h:347
regu_variable_node * src
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
static int * pt_to_method_arglist(PARSER_CONTEXT *parser, PT_NODE *target, PT_NODE *node_list, PT_NODE *subquery_as_attr_list)
static ANALYTIC_EVAL_TYPE * pt_optimize_analytic_list(PARSER_CONTEXT *parser, ANALYTIC_INFO *info, bool *no_optimization)
PT_NODE * with
Definition: parse_tree.h:2778
PT_NODE * pt_make_prim_data_type(PARSER_CONTEXT *parser, PT_TYPE_ENUM e)
PT_NODE * pt_get_next_assignment(PT_ASSIGNMENTS_HELPER *ea)
Definition: parse_tree.c:1360
static SORT_LIST * pt_to_sort_list(PARSER_CONTEXT *parser, PT_NODE *node_list, PT_NODE *col_list, SORT_LIST_MODE sort_mode)
int func_idx_col_id
Definition: access_spec.hpp:98
static PT_NODE * pt_query_set_reference(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * where
Definition: parse_tree.h:2687
QFILE_LIST_ID * push_list_id
Definition: xasl.h:311
PT_QUERY_INFO query
Definition: parse_tree.h:3325
bool qo_is_index_iss_scan(QO_PLAN *plan)
PT_NODE * use_idx
Definition: parse_tree.h:2697
need_clear_type need_clear
Definition: dbtype_def.h:1084
static PRED_EXPR * pt_make_pred_term_like(const REGU_VARIABLE *arg1, const REGU_VARIABLE *arg2, const REGU_VARIABLE *arg3)
#define XASL_INSTNUM_FLAG_SCAN_STOP_AT_ANALYTIC
Definition: xasl.h:465
static const int OID_LIST_GROWTH
static SORT_LIST * pt_to_after_iscan(PARSER_CONTEXT *parser, PT_NODE *iscan_list, PT_NODE *root)
bool pt_has_aggregate(PARSER_CONTEXT *parser, PT_NODE *node)
REGU_VALUE_ITEM * current_value
Definition: regu_var.hpp:106
struct db_objlist * next
Definition: dbtype_def.h:442
static int pt_instnum_to_key_limit(PARSER_CONTEXT *parser, QO_PLAN *plan, XASL_NODE *xasl)
int num_orderby_keys
Definition: xasl.h:376
PT_NODE * with
Definition: parse_tree.h:2878
static SYMBOL_INFO * pt_symbol_info_alloc(void)
int num_attrs_key
Definition: xasl.h:730
int pt_is_between_range_op(PT_OP_TYPE op)
int db_col_size(DB_COLLECTION *col)
Definition: db_set.c:1167
int sm_flush_objects(MOP obj)
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
#define MSGCAT_CATALOG_CUBRID
DB_OBJECT * db_get_user(void)
Definition: db_admin.c:1974
bool qo_need_skip_execution(void)
Definition: query_graph.c:297
DB_TYPE pt_node_to_db_type(PT_NODE *node)
Definition: parse_dbi.c:2453
static REGU_VARIABLE * pt_make_regu_insert(PARSER_CONTEXT *parser, PT_NODE *statement)
#define XASL_G_GRBYNUM_FLAG_LIMIT_LT
Definition: xasl.h:474
static int pt_set_limit_optimization_flags(PARSER_CONTEXT *parser, QO_PLAN *plan, XASL_NODE *xasl)
PT_NODE * use_idx_hint
Definition: parse_tree.h:2872
#define DB_DEFAULT_NUMERIC_PRECISION
Definition: dbtype_def.h:564
static REGU_VARIABLE * pt_make_regu_pred(const PRED_EXPR *pred)
int db_value_domain_default(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale, const int codeset, const int collation_id, DB_ENUMERATION *enumeration)
Definition: db_macro.c:756
DB_TYPE type
Definition: regu_var.hpp:77
static REGU_VARIABLE_LIST pt_make_pos_regu_list(PARSER_CONTEXT *parser, VAL_LIST *val_list_p)
static ACCESS_SPEC_TYPE * pt_make_set_access_spec(REGU_VARIABLE *set_expr, ACCESS_METHOD access, INDX_INFO *indexptr, PRED_EXPR *where_pred, REGU_VARIABLE_LIST attr_list)
OID * class_oid
Definition: xasl.h:232
#define MSGCAT_SEMANTIC_INSTORDERBY_NUM_NOT_ALLOWED
DB_DOMAIN * db_attribute_domain(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1165
xasl_node * qo_to_xasl(QO_PLAN *, xasl_node *)
#define DB_DEFAULT_SCALE
Definition: dbtype_def.h:561
SM_CONSTRAINT * constraints
Definition: class_object.h:454
DB_VALUE * pt_find_value_of_label(const char *label)
struct corr_info CORR_INFO
FETCH_PROC_NODE fetch
Definition: xasl.h:1018
PT_NODE * set
Definition: parse_tree.h:3047
PT_NODE * pt_check_instnum_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
HASH_ATTR
AGGREGATE_TYPE * g_agg_list
Definition: xasl.h:318
#define MSGCAT_SEMANTIC_NOT_ALLOWED_IN_WINDOW
PT_NODE * pt_make_integer_value(PARSER_CONTEXT *parser, const int value_int)
PT_NODE * partition_by
Definition: parse_tree.h:2270
const int REGU_VARIABLE_APPLY_COLLATION
Definition: regu_var.hpp:159
int num_attrs_rest
Definition: xasl.h:736
#define MSGCAT_SEMANTIC_NO_GROUPBY_ALLOWED
static XASL_NODE * pt_to_buildlist_proc(PARSER_CONTEXT *parser, PT_NODE *select_node, QO_PLAN *qo_plan)
PRED_EXPR * where_pred
Definition: xasl.h:930
PRED_EXPR * after_join_pred
Definition: xasl.h:977
PT_NODE * expanded_list
Definition: parse_tree.h:2274
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)
QO_LIMIT_INFO * qo_get_key_limit_from_ordbynum(PARSER_CONTEXT *parser, QO_PLAN *plan, xasl_node *xasl, bool ignore_lower)
static XASL_NODE * pt_build_do_stmt_aptr_list(PARSER_CONTEXT *parser, PT_NODE *node)
TP_DOMAIN * pt_xasl_type_enum_to_domain(const PT_TYPE_ENUM type)
CTE_PROC_NODE cte
Definition: xasl.h:1027
XASL_NODE * eptr_list
Definition: xasl.h:308
OID creator_oid
Definition: xasl.h:1033
int pt_find_attribute(PARSER_CONTEXT *parser, const PT_NODE *name, const PT_NODE *attributes)
#define pt_is_value_node(n)
Definition: parse_tree.h:266
DB_ENUMERATION enumeration
Definition: object_domain.h:84
#define TP_IS_CHAR_TYPE(typeid)
PT_NODE * orderby_for
Definition: parse_tree.h:2876
XASL_NODE * parser_generate_xasl(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * parser_new_node(PARSER_CONTEXT *parser, PT_NODE_TYPE node_type)
static void error(const char *msg)
Definition: gencat.c:331
PT_NODE * entity_spec
Definition: query_graph.h:279
#define PT_NODE_MOVE_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:572
COMPILE_CONTEXT context
Definition: parse_tree.h:3591
#define QO_ENTRY_MULTI_COL(entry)
Definition: query_graph.h:187
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
PRED_EXPR * cons_pred
Definition: xasl.h:371
#define XASL_SKIP_ORDERBY_LIST
Definition: xasl.h:478
int g_grbynum_flag
Definition: xasl.h:328
static int rc
Definition: serial.c:50
static void pt_split_if_instnum(PARSER_CONTEXT *parser, PT_NODE *where, PT_NODE **if_part, PT_NODE **instnum_part)
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
unsigned is_system_generated_stmt
Definition: parse_tree.h:3484
VAL_LIST * pt_to_val_list(PARSER_CONTEXT *parser, UINTPTR id)
#define PCOL_ISCYCLE_TUPLE_OFFSET
Definition: xasl.h:537
SM_CLASS_HEADER header
Definition: class_object.h:710
static PT_NODE * pt_uncorr_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int sm_att_info(MOP classop, const char *name, int *idp, TP_DOMAIN **domainp, int *sharedp, int class_attr)
double cardinality
Definition: xasl.h:1030
#define PT_IS_POINTER_REF_NODE(n)
Definition: parse_tree.h:493
#define TP_TYPE_HAS_COLLATION(typeid)
int g_output_first_tuple
Definition: xasl.h:331
#define MSGCAT_SEMANTIC_ISCYCLE_REQUIRES_NOCYCLE
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2944
short db_value_is_initialized
Definition: parse_tree.h:3060
#define AU_SELECT
Definition: authenticate.h:69
#define MSGCAT_SET_ERROR
PT_SORT_SPEC_INFO sort_spec
Definition: parse_tree.h:3343
#define ARG_FILE_LINE
Definition: error_manager.h:44
void pt_data_type_init_value(const PT_NODE *node, DB_VALUE *value_out)
Definition: parse_dbi.c:1264
static PT_NODE * pt_to_analytic_node(PARSER_CONTEXT *parser, PT_NODE *tree, ANALYTIC_INFO *analytic_info)
bool qo_is_prefix_index(QO_INDEX_ENTRY *ent)
Definition: query_graph.c:9203
#define XASL_INSTNUM_FLAG_SCAN_CONTINUE
Definition: xasl.h:460
regu_variable_node * upper
Definition: optimizer.h:145
struct qo_plan::@100::@102 scan
analytic_function_info info
XASL_NODE * xasl
PT_NODE * odku_non_null_attrs
Definition: parse_tree.h:2345
PT_NODE * index_ls
Definition: parse_tree.h:2699
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
XASL_NODE * left
Definition: xasl.h:289
const char * query_alias
Definition: xasl.h:1039
bool pt_name_equal(PARSER_CONTEXT *parser, const PT_NODE *name1, const PT_NODE *name2)
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
static void pt_init_xasl_supp_info()
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
static ACCESS_SPEC_TYPE * pt_make_list_access_spec(XASL_NODE *xasl, ACCESS_METHOD access, INDX_INFO *indexptr, PRED_EXPR *where_pred, REGU_VARIABLE_LIST attr_list_pred, REGU_VARIABLE_LIST attr_list_rest, REGU_VARIABLE_LIST attr_list_build, REGU_VARIABLE_LIST attr_list_probe)
XASL_NODE * right
Definition: xasl.h:290
#define WS_OID(mop)
Definition: work_space.h:293
OUTPTR_LIST * prior_outptr_list
Definition: xasl.h:426
void pt_set_dptr(PARSER_CONTEXT *parser, PT_NODE *node, XASL_NODE *xasl, UINTPTR id)
regu_variable_node * key2
Definition: access_spec.hpp:68
unsigned int DB_TIME
Definition: dbtype_def.h:754
int instnum_flag
Definition: xasl.h:997
#define AU_ENABLE(save)
Definition: authenticate.h:113
static XASL_NODE * pt_to_scan_proc_list(PARSER_CONTEXT *parser, PT_NODE *node, XASL_NODE *root)
bool key_limit_reset
Definition: access_spec.hpp:78
DB_VALUE * level_val
Definition: xasl.h:988
PT_NODE * ordered_hint
Definition: parse_tree.h:2068
OID * class_oid_list
Definition: xasl.h:1036
PT_NODE * pt_resolve_names(PARSER_CONTEXT *parser, PT_NODE *statement, SEMANTIC_CHK_INFO *sc_info)
PT_NODE * pt_convert_to_logical_expr(PARSER_CONTEXT *parser, PT_NODE *node, bool use_parens_inside, bool use_parens_outside)
PT_NODE * use_idx_hint
Definition: parse_tree.h:2070
PT_NODE * into
Definition: parse_tree.h:2923
unsigned int DB_DATE
Definition: dbtype_def.h:771
#define VALIDATE_REGU_KEY_HELPER(r)
#define MSGCAT_SET_PARSER_SEMANTIC
static int pt_spec_to_xasl_class_oid_list(PARSER_CONTEXT *parser, const PT_NODE *spec, OID **oid_listp, int **lock_listp, int **tcard_listp, int *nump, int *sizep, int includes_tde_class)
#define PT_IS_ORDERBYNUM(n)
Definition: parse_tree.h:392
OUTPTR_LIST * g_outptr_list
Definition: xasl.h:312
XASL_NODE * xasl_node
Definition: xasl.h:753
#define pt_is_name_node(n)
Definition: parse_tree.h:264
static XASL_NODE * pt_plan_set_query(PARSER_CONTEXT *parser, PT_NODE *node, PROC_TYPE proc_type)
PRED_EXPR * having_pred
Definition: xasl.h:345
regu_variable_node * elemset
UINTPTR spec_id
DB_VALUE * ordbynum_val
Definition: xasl.h:959
PT_NODE * using_index
Definition: parse_tree.h:2863
int qo_find_subplan_using_multi_range_opt(QO_PLAN *plan, QO_PLAN **result, int *join_idx)
struct qo_index_entry * next
Definition: query_graph.h:102
RANGE_TYPE range_type
Definition: access_spec.hpp:90
bool allow_index_opt
XASL_NODE * scan_ptr
Definition: xasl.h:985
#define free_and_init(ptr)
Definition: memory_alloc.h:147
REGU_VARIABLE_LIST list
Definition: regu_var.hpp:229
static INDX_INFO * pt_to_index_info(PARSER_CONTEXT *parser, DB_OBJECT *class_, PRED_EXPR *where_pred, QO_PLAN *plan, QO_XASL_INDEX_INFO *qo_index_infop)
SORT_LIST * after_groupby_list
Definition: xasl.h:310
QFILE_LIST_ID * push_list
Definition: parse_tree.h:2706
char * db_get_database_version(void)
Definition: db_admin.c:455
struct pt_merge_info::@126 insert
ACCESS_SPEC_TYPE * spec_list
Definition: xasl.h:970
#define PT_IS_EXPR_NODE(n)
Definition: parse_tree.h:305
#define strlen(s1)
Definition: intl_support.c:43
#define BTID_COPY(btid_ptr1, btid_ptr2)
ODKU_INFO * odku
Definition: xasl.h:393
REGU_VARIABLE * pt_make_regu_arith(const REGU_VARIABLE *arg1, const REGU_VARIABLE *arg2, const REGU_VARIABLE *arg3, const OPERATOR_TYPE op, const TP_DOMAIN *domain)
#define PT_CHECK_HQ_OP_EXCEPT_PRIOR(op)
Definition: parse_tree.h:448
bool is_user_given_keylimit
Definition: access_spec.hpp:79
static REGU_VARIABLE * pt_to_regu_reserved_name(PARSER_CONTEXT *parser, PT_NODE *attr)
SELUPD_LIST * next
Definition: xasl.h:219
bool sm_is_reuse_oid_class(MOP op)
static XASL_SUPP_INFO xasl_Supp_info
int num_subclasses
Definition: xasl.h:231
static SYMBOL_INFO * pt_push_fetch_spec_info(PARSER_CONTEXT *parser, SYMBOL_INFO *symbols, PT_NODE *fetch_spec)
int oid_compare(const void *a, const void *b)
Definition: oid.c:243
TP_DOMAIN tp_Bit_domain
HEAP_CACHE_ATTRINFO * cache_attrinfo
Definition: regu_var.hpp:78
#define XASL_IS_MERGE_QUERY
Definition: xasl.h:487
SM_COMPONENT header
Definition: class_object.h:441
PT_NODE * pt_point(PARSER_CONTEXT *parser, const PT_NODE *in_tree)
OID * regu_oid_array_alloc(int size)
PT_NODE * non_recursive_part
Definition: parse_tree.h:1977
int db_value_precision(const DB_VALUE *value)
PT_NODE * attr_list
Definition: parse_tree.h:2937
OUTPTR_LIST * a_outptr_list
Definition: xasl.h:324
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
PT_OP_TYPE
Definition: parse_tree.h:1320
int num_classes
Definition: xasl.h:408
#define PT_SELECT_INFO_SET_FLAG(s, f)
Definition: parse_tree.h:2737
struct pred_regu_variable_p_list_node * PRED_REGU_VARIABLE_P_LIST
PT_NODE * connect_by
Definition: parse_tree.h:2689
int mvcc_reev_extra_cls_cnt
Definition: xasl.h:1008
#define MATCH_ALL
bool qo_has_sort_limit_subplan(QO_PLAN *plan)
const char * ch_name
Definition: class_object.h:350
PRED_EXPR * pt_to_pred_expr(PARSER_CONTEXT *parser, PT_NODE *node)
#define PT_SELECT_FULL_INFO_COLS_SCHEMA
Definition: parse_tree.h:2722
unsigned int date
Definition: dbtype_def.h:776
unsigned single_tuple
Definition: parse_tree.h:2760
DB_OBJECT * virt_object
Definition: parse_tree.h:2040
int hash_list_scan_yn
Definition: xasl.h:752
#define PT_IS_FUNCTION(n)
Definition: parse_tree.h:311
static PT_NODE * pt_mvcc_prepare_upd_del_select(PARSER_CONTEXT *parser, PT_NODE *select_stmt)
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
QPROC_DB_VALUE_LIST valp
Definition: xasl.h:207
QO_SORT_LIMIT_USE use_sort_limit
Definition: query_graph.h:907
PT_NODE * pt_flush_classes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
QFILE_LIST_ID * input_list_id
Definition: xasl.h:421
REGU_VARIABLE_LIST g_hk_scan_regu_list
Definition: xasl.h:319
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
PT_NODE * search_cond
Definition: parse_tree.h:2063
bool prm_get_bool_value(PARAM_ID prm_id)
OUTPTR_LIST * cls_output_val_list
Definition: xasl.h:724
PT_NODE * start_with
Definition: parse_tree.h:2690
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
static ACCESS_SPEC_TYPE * pt_make_json_table_access_spec(PARSER_CONTEXT *parser, REGU_VARIABLE *json_reguvar, PRED_EXPR *where_pred, PT_JSON_TABLE_INFO *json_table, TABLE_INFO *tbl_info)
PT_NODE ** term_exprs
Definition: query_graph.h:981
int * num_lob_attrs
Definition: xasl.h:239
class regu_variable_node REGU_VARIABLE
Definition: regu_var.hpp:64
HEAP_CACHE_ATTRINFO * cache_attrinfo
Definition: xasl.h:278
PT_RESERVED_NAME_ID reserved_id
Definition: parse_tree.h:2581
int pt_is_single_tuple(PARSER_CONTEXT *parser, PT_NODE *select_node)
PRED_EXPR_WITH_CONTEXT * pt_to_pred_with_context(PARSER_CONTEXT *parser, PT_NODE *predicate, PT_NODE *spec)
REGU_VARIABLE_LIST g_hk_sort_regu_list
Definition: xasl.h:320
PT_NODE * after_cb_filter
Definition: parse_tree.h:2691
PT_MISC_TYPE only_all
Definition: parse_tree.h:2145
static PT_NODE * pt_set_analytic_node_etc(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * pt_find_name(PARSER_CONTEXT *parser, const PT_NODE *name, const PT_NODE *list)
#define PT_PRED_ARG_GRBYNUM_CONTINUE
PRED_EXPR * where_key
Definition: xasl.h:929
PT_MISC_TYPE list_type
Definition: parse_tree.h:2324
static XASL_NODE * pt_to_uncorr_subquery_list(PARSER_CONTEXT *parser, PT_NODE *node)
static VAL_LIST * pt_make_val_list(PARSER_CONTEXT *parser, PT_NODE *attribute_list)
UPDATE_ASSIGNMENT * assignments
Definition: xasl.h:264
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2146
int upd_del_class_cnt
Definition: xasl.h:1006
REGU_VARIABLE_LIST cls_regu_list_pred
Definition: xasl.h:720
DB_VALUE * grbynum_val
Definition: xasl.h:346
REGU_VARIABLE * regu_var
Definition: xasl.h:254
LOCK lock_Conv[12][12]
Definition: lock_table.c:179
static ACCESS_SPEC_TYPE * pt_to_json_table_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *json_table, PT_NODE *src_derived_tbl, PT_NODE *where_p)
int * seg_idxs
Definition: query_graph.h:122
unsigned cannot_prepare
Definition: parse_tree.h:3462
PT_DELETE_INFO delete_
Definition: parse_tree.h:3285
VAL_LIST * value_list
PT_NODE * limit
Definition: parse_tree.h:2874
PRED_EXPR * cons_pred
Definition: xasl.h:262
static XASL_NODE * pt_plan_query(PARSER_CONTEXT *parser, PT_NODE *select_node)
void * etc
Definition: parse_tree.h:3450
PRED_EXPR * pred
Definition: xasl.h:1058
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2067
void qo_plan_discard(QO_PLAN *)
static REGU_VARIABLE * pt_make_regu_isleaf(PARSER_CONTEXT *parser, const PT_NODE *node)
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
SET_SPEC_TYPE set_node
Definition: xasl.h:787
static void pt_adjust_analytic_sort_specs(PARSER_CONTEXT *parser, PT_NODE *node, int idx, int adjust)
static PT_NODE * pt_to_analytic_final_node(PARSER_CONTEXT *parser, PT_NODE *tree, PT_NODE **ex_list, int *instnum_flag)
xasl_node * qo_add_hq_iterations_access_spec(QO_PLAN *plan, xasl_node *xasl)
#define QO_ENV_SEG(env, n)
Definition: query_graph.h:957
PT_NODE * ordered
Definition: parse_tree.h:2695
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
struct qo_node_index_entry * ni_entry
Definition: query_graph.h:987
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)
static PT_NODE * pt_numbering_set_continue_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PROC_TYPE
Definition: xasl.h:172
int pt_length_of_select_list(PT_NODE *list, int hidden_col)
OID cls_oid
Definition: xasl.h:727
#define XASL_INSTNUM_FLAG_EVAL_DEFER
Definition: xasl.h:464
int db_make_null(DB_VALUE *value)
int heap_num_pages
Definition: statistics.h:90
char * msgcat_message(int cat_id, int set_id, int msg_id)
void pt_set_iscycle_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, DB_VALUE **iscycle_valp)
static PT_NODE * pt_corr_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
HFID * class_hfid
Definition: xasl.h:233
PT_NODE * class_spec
DB_TYPE id
#define PT_SELECT_INFO_LIST_PUSHER
Definition: parse_tree.h:2724
PT_NODE * list
Definition: parse_tree.h:2685
static SELUPD_LIST * pt_link_regu_to_selupd_list(PARSER_CONTEXT *parser, REGU_VARIABLE_LIST regulist, SELUPD_LIST *selupd_list, DB_OBJECT *target_class)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
PT_NODE * use_merge
Definition: parse_tree.h:2700
#define PCOL_LEVEL_TUPLE_OFFSET
Definition: xasl.h:539
REGU_VARIABLE_LIST cls_regu_list_rest
Definition: xasl.h:721
static XASL_NODE * parser_generate_xasl_proc(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *query_list)
static REGU_VARIABLE * pt_make_regu_reguvalues_list(PARSER_CONTEXT *parser, const PT_NODE *node, UNBOX unbox)
#define ER_OBJ_DOMAIN_CONFLICT
Definition: error_code.h:285
static int set_has_objs(DB_SET *seq)
int has_uniques
Definition: xasl.h:394
static void pt_split_having_grbynum(PARSER_CONTEXT *parser, PT_NODE *having, PT_NODE **having_part, PT_NODE **grbynum_part)
PT_OP_TYPE op
Definition: parse_tree.h:2200
static int pt_get_pred_attrs(PARSER_CONTEXT *parser, TABLE_INFO *table_info, PT_NODE *pred, PT_NODE **pred_attrs)
PRED_EXPR * instnum_pred
Definition: xasl.h:979
static int pt_split_attrs(PARSER_CONTEXT *parser, TABLE_INFO *table_info, PT_NODE *pred, PT_NODE **pred_attrs, PT_NODE **rest_attrs, PT_NODE **reserved_attrs, int **pred_offsets, int **rest_offsets, int **reserved_offsets)
void * xasl
Definition: parse_tree.h:1980
int * regu_int_array_alloc(int size)
int dbval_cnt
Definition: xasl.h:1040
QPROC_DB_VALUE_LIST next
Definition: xasl.h:195
REGU_VARIABLE_LIST prior_regu_list_rest
Definition: xasl.h:428
#define pt_is_set_type(n)
Definition: parse_tree.h:267
static DB_VALUE * pt_regu_to_dbvalue(PARSER_CONTEXT *parser, REGU_VARIABLE *regu)
int mvcc_reev_extra_cls_cnt
Definition: parse_tree.h:2753
const char * name
Definition: class_object.h:385
VAL_LIST * merge_val_list
Definition: xasl.h:973
int wait_msecs
Definition: xasl.h:409
int wait_msecs
Definition: xasl.h:395
static PT_NODE * pt_set_iscycle_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * path_conjuncts
Definition: parse_tree.h:2139
#define PT_SPEC_SPECIAL_INDEX_SCAN(spec_)
Definition: parse_tree.h:656
TP_DOMAIN * tp_domain_resolve(DB_TYPE domain_type, DB_OBJECT *class_obj, int precision, int scale, TP_DOMAIN *setdomain, int collation)
struct xasl_supp_info XASL_SUPP_INFO
static int pt_table_compatible(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *spec)
static ACCESS_SPEC_TYPE * pt_make_class_access_spec(PARSER_CONTEXT *parser, PT_NODE *flat, DB_OBJECT *class_, TARGET_TYPE scan_type, ACCESS_METHOD access, INDX_INFO *indexptr, PRED_EXPR *where_key, PRED_EXPR *where_pred, PRED_EXPR *where_range, REGU_VARIABLE_LIST attr_list_key, REGU_VARIABLE_LIST attr_list_pred, REGU_VARIABLE_LIST attr_list_rest, REGU_VARIABLE_LIST attr_list_range, OUTPTR_LIST *output_val_list, REGU_VARIABLE_LIST regu_val_list, HEAP_CACHE_ATTRINFO *cache_key, HEAP_CACHE_ATTRINFO *cache_pred, HEAP_CACHE_ATTRINFO *cache_rest, HEAP_CACHE_ATTRINFO *cache_range, ACCESS_SCHEMA_TYPE schema_type, DB_VALUE **cache_recordinfo, REGU_VARIABLE_LIST reserved_val_list)
static XASL_NODE * pt_make_connect_by_proc(PARSER_CONTEXT *parser, PT_NODE *select_node, XASL_NODE *select_xasl)
ATTR_ID * attrids_range
Definition: xasl.h:741
PT_NODE * parser_reinit_node(PT_NODE *node)
TYPE_PRED_EXPR type
static int pt_fix_first_term_expr_for_iss(PARSER_CONTEXT *parser, QO_INDEX_ENTRY *index_entryp, PT_NODE **term_exprs)
SORT_LIST * groupby_list
Definition: xasl.h:309
PT_NODE * orderby_for
Definition: parse_tree.h:2770
#define pt_is_function(n)
Definition: parse_tree.h:262
HFID hfid
Definition: xasl.h:726
#define DB_MAX_VARNCHAR_PRECISION
Definition: dbtype_def.h:546
int * class_locks
Definition: xasl.h:1037
REGU_VARIABLE_LIST cls_regu_list_range
Definition: xasl.h:722
unsigned return_generated_keys
Definition: parse_tree.h:3622
analytic_list_node * next
static json_table_node * pt_make_json_table_spec_node(PARSER_CONTEXT *parser, PT_JSON_TABLE_INFO *json_table, size_t &start_id, TABLE_INFO *tbl_info)
REGU_VARIABLE_LIST arg_list
Definition: xasl.h:759
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
void pt_set_qprior_node_etc(PARSER_CONTEXT *parser, PT_NODE *node_list, XASL_NODE *xasl)
#define XASL_ORDBYNUM_FLAG_SCAN_CONTINUE
Definition: xasl.h:456
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
DB_TYPE db_set_type(DB_SET *set)
Definition: db_set.c:683
int db_make_int(DB_VALUE *value, const int num)
void pt_to_pos_descr(PARSER_CONTEXT *parser, QFILE_TUPLE_VALUE_POSITION *pos_p, PT_NODE *node, PT_NODE *root, PT_NODE **referred_node)
PT_HINT_ENUM hint
Definition: parse_tree.h:2945
static RANGE op_type_to_range(const PT_OP_TYPE op_type, const int nterms)
PT_NODE * current_listfile
REGU_VARIABLE * thirdptr
Definition: regu_var.hpp:130
#define pt_has_error(parser)
Definition: parser.h:507
static REGU_VARIABLE * pt_join_term_to_regu_variable(PARSER_CONTEXT *parser, PT_NODE *join_term)
bool qo_is_filter_index(QO_INDEX_ENTRY *ent)
Definition: query_graph.c:9228
alsm_eval_term et_alsm
PT_NODE * query_list
int db_make_oid(DB_VALUE *value, const OID *oid)
MOP sm_find_class(const char *name)
const char * alias_print
Definition: parse_tree.h:3455
static void pt_pop_symbol_info(PARSER_CONTEXT *parser)
bool qo_plan_skip_groupby(QO_PLAN *plan)
static OUTPTR_LIST * pt_make_outlist_from_vallist(PARSER_CONTEXT *parser, VAL_LIST *val_list_p)
PT_NODE * pt_domain_to_data_type(PARSER_CONTEXT *parser, DB_DOMAIN *domain)
REGU_VARIABLE * limit_offset
Definition: xasl.h:982
regu_variable_node * pattern
union cubxasl::eval_term::@184 et
#define PT_IS_EXPR_NODE_WITH_OPERATOR(n, op_type)
Definition: parse_tree.h:464
QFILE_LIST_ID * start_with_list_id
Definition: xasl.h:422
const char * resolved
Definition: parse_tree.h:2545
#define OID_ISNULL(oidp)
Definition: oid.h:81
struct pred_regu_variable_p_list_node PRED_REGU_VARIABLE_P_LIST_NODE
PT_NODE * mq_get_references(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *spec)
int locator_is_class(MOP mop, DB_FETCH_MODE hint_purpose)
Definition: locator_cl.c:239
SORT_NULLS s_nulls
Definition: query_list.h:418
SORT_NULLS pt_to_null_ordering(PT_NODE *sort_spec)
UNBOX listfile_unbox
#define PT_SELECT_INFO_IDX_SCHEMA
Definition: parse_tree.h:2720
like_eval_term et_like
DB_TIMESTAMP DB_UTIME
Definition: dbtype_def.h:761
PT_NODE * using_clause
Definition: parse_tree.h:2924
#define TP_DOMAIN_CODESET(dom)
XASL_NODE * parser_generate_do_stmt_xasl(PARSER_CONTEXT *parser, PT_NODE *node)
#define PT_HAS_COLLATION(t)
Definition: parse_tree.h:243
static ACCESS_SPEC_TYPE * pt_make_showstmt_access_spec(PRED_EXPR *where_pred, SHOWSTMT_TYPE show_type, REGU_VARIABLE_LIST arg_list)
int collation_id
Definition: object_domain.h:92
#define XASL_ZERO_CORR_LEVEL
Definition: xasl.h:479
static int regu_make_constant_vid(DB_VALUE *val, DB_VALUE **dbvalptr)
PT_NODE * use_nl
Definition: parse_tree.h:2696
access_spec_node * regu_spec_alloc(TARGET_TYPE type)
static REGU_VARIABLE * pt_make_position_regu_variable(PARSER_CONTEXT *parser, const PT_NODE *node, int i)
static ACCESS_SPEC_TYPE * pt_to_class_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *where_key_part, PT_NODE *where_part, QO_PLAN *plan, QO_XASL_INDEX_INFO *index_pred)
static TP_DOMAIN * pt_xasl_data_type_to_domain(PARSER_CONTEXT *parser, const PT_NODE *node)
const char * au_user_name(void)
static int pt_to_key_limit(PARSER_CONTEXT *parser, PT_NODE *key_limit, QO_LIMIT_INFO *limit_infop, KEY_INFO *key_infop, bool key_limit_reset)
regu_variable_node * pattern
struct symbol_info * symbols
Definition: parse_tree.h:3572
QO_ENV * env
static bool pt_is_sort_list_covered(PARSER_CONTEXT *parser, SORT_LIST *covering_list_p, SORT_LIST *covered_list_p)
REGU_VARIABLE_LIST g_regu_list
Definition: xasl.h:313
PT_NODE * pt_dbval_to_value(PARSER_CONTEXT *parser, const DB_VALUE *val)
Definition: parse_dbi.c:574
QPROC_SINGLE_FETCH single_fetch
Definition: xasl.h:933
UINTPTR spec_ident
Definition: parse_tree.h:3451
pred_expr * rhs
int pt_get_assignment_lists(PARSER_CONTEXT *parser, PT_NODE **select_names, PT_NODE **select_values, PT_NODE **const_names, PT_NODE **const_values, int *no_vals, int *no_consts, PT_NODE *assign, PT_NODE ***old_links)
PRED_EXPR * g_having_pred
Definition: xasl.h:315
REGU_VARIABLE_LIST g_scan_regu_list
Definition: xasl.h:321
XASL_NODE * bptr_list
Definition: xasl.h:975
int column_number
Definition: parse_tree.h:3442
int pt_length_of_list(const PT_NODE *list)
struct parser_node::@132 flag
Definition: query_graph.h:99
PT_NODE * entity_name
Definition: parse_tree.h:2130
#define PT_IS_SERIAL(op)
Definition: parse_tree.h:461
int pt_find_omitted_default_expr(PARSER_CONTEXT *parser, DB_OBJECT *class_obj, PT_NODE *specified_attrs, PT_NODE **default_expr_attrs)
static PT_NODE * pt_make_regu_list_from_value_list(PARSER_CONTEXT *parser, PT_NODE *node, VAL_LIST *value_list, REGU_VARIABLE_LIST *regu_list)
static int pt_init_pred_expr_context(PARSER_CONTEXT *parser, PT_NODE *predicate, PT_NODE *spec, PRED_EXPR_WITH_CONTEXT *pred_expr)
#define PT_IS_ANALYTIC_NODE(n)
Definition: parse_tree.h:489
static PT_NODE * pt_is_spec_node(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_arg, int *continue_walk)
PT_NODE * order_by
Definition: parse_tree.h:2263
PT_NODE * mq_set_references(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *spec)
RANGE
Definition: access_spec.hpp:32
static REGU_VARIABLE * pt_make_pos_regu_var_from_scratch(TP_DOMAIN *dom, DB_VALUE *fetch_to, int pos_no)
PT_NODE * ordered_hint
Definition: parse_tree.h:2870
QO_INDEX_ENTRY * head
Definition: query_graph.h:212
REGU_VARLIST_LIST next
Definition: regu_var.hpp:228
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
static int setof_mop_to_setof_vobj(PARSER_CONTEXT *parser, DB_SET *seq, DB_VALUE *new_val)
static REGU_VARIABLE_LIST pt_to_regu_variable_list(PARSER_CONTEXT *p, PT_NODE *node, UNBOX unbox, VAL_LIST *value_list, int *attr_offsets)
#define pt_is_const(n)
Definition: parse_tree.h:271
PT_NODE * percentile
Definition: parse_tree.h:2264
HEAP_CACHE_ATTRINFO * cache_key
Definition: xasl.h:729
regu_variable_node * esc_char
static SORT_LIST * pt_to_after_groupby(PARSER_CONTEXT *parser, PT_NODE *group_list, PT_NODE *root)
PT_NODE * pt_to_merge_insert_query(PARSER_CONTEXT *parser, PT_NODE *select_list, PT_MERGE_INFO *info)
Definition: xasl.h:186
void pt_restore_assignment_links(PT_NODE *assigns, PT_NODE **links, int count)
#define XASL_SERIAL_OID_TCARD
Definition: xasl.h:1069
TP_DOMAIN * domain
Definition: regu_var.hpp:175
TARGET_TYPE
Definition: xasl.h:675
cubxasl::analytic_eval_type * analytic_eval_list
bool db_json_path_contains_wildcard(const char *sql_path)
Definition: db_json.cpp:2776
REGU_VARIABLE_LIST scan_regu_list
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
PT_HOST_VAR_INFO host_var
Definition: parse_tree.h:3307
static PT_NODE * pt_null_xasl(PARSER_CONTEXT *parser, PT_NODE *tree, void *void_arg, int *continue_walk)
int pruning_type
Definition: xasl.h:936
DB_VALUE * iscycle_val
Definition: xasl.h:993
#define MSGCAT_SEMANTIC_WANT_ESC_LIT_STRING
QO_LIMIT_INFO * qo_get_key_limit_from_instnum(PARSER_CONTEXT *parser, QO_PLAN *plan, xasl_node *xasl)
static XASL_NODE * pt_plan_schema(PARSER_CONTEXT *parser, PT_NODE *select_node)
int ws_has_dirty_objects(MOP op, int *isvirt)
Definition: work_space.c:3752
static XASL_NODE * pt_to_merge_insert_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *non_null_attrs, PT_NODE *default_expr_attrs)
PT_NODE * key_limit
Definition: query_graph.h:167
MERGE_PROC_NODE merge
Definition: xasl.h:1026
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
METHOD_SIG_LIST * method_sig_list
Definition: xasl.h:774
#define PT_EXPR_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2238
REGU_VARIABLE_LIST valptrp
Definition: regu_var.hpp:116
PT_NODE * spec_parent
Definition: parse_tree.h:3421
#define PT_ERRORf(parser, node, msg, arg1)
Definition: parse_tree.h:57
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
int db_get_string_codeset(const DB_VALUE *value)
#define HFID_COPY(hfid_ptr1, hfid_ptr2)
static int pt_split_hash_attrs_for_HQ(PARSER_CONTEXT *parser, PT_NODE *pred, PT_NODE **build_attrs, PT_NODE **probe_attrs, PT_NODE **pred_without_HQ)
DB_VALUE * instnum_val
Definition: xasl.h:980
rlike_eval_term et_rlike
SORT_LIST * after_iscan_list
Definition: xasl.h:956
PT_NODE * parser_copy_tree_list(PARSER_CONTEXT *parser, PT_NODE *tree)
int num_classes
Definition: xasl.h:369
PT_NODE * pt_check_instnum_post(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int num_attrs_pred
Definition: xasl.h:731
PT_RESERVED_NAME_ID
Definition: parse_tree.h:2397
int num_attrs_range
Definition: xasl.h:743
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
const char ** p
Definition: dynamic_load.c:945
cubxasl::json_table::column json_table_column
static VAL_LIST * pt_copy_val_list(PARSER_CONTEXT *parser, VAL_LIST *val_list_p)
HFID class_hfid
Definition: xasl.h:387
REGU_VARIABLE * pt_to_regu_variable(PARSER_CONTEXT *parser, PT_NODE *node, UNBOX unbox)
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
#define XASL_IGNORE_CYCLES
Definition: xasl.h:485
REGU_VARIABLE * isleaf_regu
Definition: xasl.h:992
static XASL_NODE * pt_gen_simple_plan(PARSER_CONTEXT *parser, PT_NODE *select_node, QO_PLAN *plan, XASL_NODE *xasl)
XASL_NODE * ptqo_to_merge_list_proc(PARSER_CONTEXT *parser, XASL_NODE *left, XASL_NODE *right, JOIN_TYPE join_type)
REGU_VARIABLE_LIST cls_regu_list_reserved
Definition: xasl.h:740
XASL_NODE * non_recursive_part
Definition: xasl.h:446
struct db_char::@54 medium
unsigned int time
Definition: dbtype_def.h:777
#define PT_PRED_ARG_INSTNUM_CONTINUE
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2869
int num_reev_classes
Definition: xasl.h:378
regu_variable_list_node * operands
HEAP_CACHE_ATTRINFO * cache_pred
Definition: xasl.h:1061
PT_JOIN_TYPE join_type
Definition: parse_tree.h:2151
DB_VALUE ** vals
Definition: xasl.h:391
static void pt_to_fetch_proc_list_recurse(PARSER_CONTEXT *parser, PT_NODE *spec, XASL_NODE *root)
PT_NODE * on_call_target
Definition: parse_tree.h:2365
int pt_copy_upddel_hints_to_select(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *select_stmt)
#define PT_EXPR_INFO_CAST_COLL_MODIFIER
Definition: parse_tree.h:2231
#define XASL_RETURN_GENERATED_KEYS
Definition: xasl.h:490
int tde_algorithm
Definition: class_object.h:767
static void pt_metadomain_adjust_key_prefix(ANALYTIC_KEY_METADOMAIN *meta)
PT_INSERT_VALUE_INFO insert_value
Definition: parse_tree.h:3310
static PT_NODE * pt_set_numbering_node_etc_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
REGU_VARIABLE * set_ptr
Definition: xasl.h:765
bool g_with_rollup
Definition: xasl.h:329
int * tcard_list
Definition: xasl.h:1038
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
static ACCESS_SPEC_TYPE * pt_to_subquery_table_spec_list(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *subquery, PT_NODE *where_part, PT_NODE *where_hash_part)
DB_VALUE * constant
Definition: xasl.h:253
PT_NODE * derived_table
Definition: parse_tree.h:2134
PT_NODE * original_node
Definition: parse_tree.h:3227
int do_replace
Definition: xasl.h:397
regu_variable_node * case_sensitive
DB_VALUE * obj_oid
Definition: xasl.h:401
FILE * port_open_memstream(char **ptr, size_t *sizeloc)
Definition: porting.c:2198
bool is_constant
Definition: access_spec.hpp:77
static XASL_NODE * pt_find_oid_scan_block(XASL_NODE *xasl, OID *oid)
static bool pt_is_analytic_eval_list_valid(ANALYTIC_EVAL_TYPE *eval_list)
int db_value_alter_type(DB_VALUE *value, const DB_TYPE type)
Definition: db_macro.c:1225
BOOL_OP
PT_NODE * search_cond
Definition: parse_tree.h:2862
PT_NODE * range_var
Definition: parse_tree.h:2135
QFILE_LIST_ID * list_id
Definition: query_list.h:533
regu_variable_node * key_limit_l
Definition: access_spec.hpp:80
#define DB_MAX_CHAR_PRECISION
Definition: dbtype_def.h:533
CLS_SPEC_TYPE cls_node
Definition: xasl.h:784
#define ANALYTIC_OPT_MAX_FUNCTIONS
TP_DOMAIN * domain
Definition: regu_var.hpp:125