CUBRID Engine  latest
execute_statement.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  * execute_statement.c - functions to do execute
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #if defined(WINDOWS)
31 #include <process.h> /* for getpid() */
32 #include <winsock2.h> /* for struct timeval */
33 #else /* WINDOWS */
34 #include <unistd.h> /* for getpid() */
35 #include <libgen.h> /* for dirname, basename() */
36 #include <sys/time.h> /* for struct timeval */
37 #endif /* WINDOWS */
38 #include <string.h>
39 #include <limits.h>
40 #include <errno.h>
41 #include <stdarg.h>
42 #include <ctype.h>
43 
44 
45 #include "error_manager.h"
46 #include "db.h"
47 #include "dbi.h"
48 #include "dbtype.h"
49 #include "parser.h"
50 #include "porting.h"
51 #include "schema_manager.h"
52 #include "transform.h"
53 #include "parser_message.h"
54 #include "system_parameter.h"
55 #include "execute_statement.h"
56 #if defined(WINDOWS)
57 #include "misc_string.h"
58 #endif
59 
60 #include "semantic_check.h"
61 #include "execute_schema.h"
62 #include "server_interface.h"
63 #include "transaction_cl.h"
64 #include "object_print.h"
65 #include "jansson.h"
66 #include "jsp_cl.h"
67 #include "optimizer.h"
68 #include "memory_alloc.h"
69 #include "object_domain.h"
70 #include "object_primitive.h"
71 #include "object_representation.h"
72 #include "trigger_manager.h"
73 #include "release_string.h"
74 #include "object_accessor.h"
75 #include "locator_cl.h"
76 #include "authenticate.h"
77 #include "xasl_generation.h"
78 #include "virtual_object.h"
79 #include "environment_variable.h"
80 #include "set_object.h"
81 #include "intl_support.h"
82 #include "replication.h"
83 #include "view_transform.h"
84 #include "network_interface_cl.h"
85 #include "arithmetic.h"
86 #include "xasl_to_stream.h"
87 #include "query_cl.h"
88 #include "parser_support.h"
89 #include "tz_support.h"
90 #include "dbtype.h"
91 
92 #if defined (SUPPRESS_STRLEN_WARNING)
93 #define strlen(s1) ((int) strlen(s1))
94 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
95 
96 #define DB_SERIAL_MAX "99999999999999999999999999999999999999"
97 #define DB_SERIAL_MIN "-99999999999999999999999999999999999999"
98 
99 #define UNIQUE_SAVEPOINT_ALTER_TRIGGER "aLTERtRIGGER"
100 /*
101  * Function Group:
102  * Do create/alter/drop serial statement
103  *
104  */
105 
106 #define PT_NODE_SR_NAME(node) \
107  ((node)->info.serial.serial_name->info.name.original)
108 #define PT_NODE_SR_START_VAL(node) \
109  ((node)->info.serial.start_val)
110 #define PT_NODE_SR_INCREMENT_VAL(node) \
111  ((node)->info.serial.increment_val)
112 #define PT_NODE_SR_MAX_VAL(node) \
113  ((node)->info.serial.max_val)
114 #define PT_NODE_SR_MIN_VAL(node) \
115  ((node)->info.serial.min_val)
116 #define PT_NODE_SR_CYCLIC(node) \
117  ((node)->info.serial.cyclic )
118 #define PT_NODE_SR_NO_MAX(node) \
119  ((node)->info.serial.no_max )
120 #define PT_NODE_SR_NO_MIN(node) \
121  ((node)->info.serial.no_min )
122 #define PT_NODE_SR_NO_CYCLIC(node) \
123  ((node)->info.serial.no_cyclic )
124 #define PT_NODE_SR_CACHED_NUM_VAL(node) \
125  ((node)->info.serial.cached_num_val)
126 #define PT_NODE_SR_NO_CACHE(node) \
127  ((node)->info.serial.no_cache)
128 
129 static void do_set_trace_to_query_flag (QUERY_FLAG * query_flag);
131 static int do_vacuum (PARSER_CONTEXT * parser, PT_NODE * statement);
132 static int do_insert_checks (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** class_,
133  PT_NODE ** update, PT_NODE * values);
134 
135 #define MAX_SERIAL_INVARIANT 8
137 
138 /* an invariant which serial must hold */
140 {
144  int val1_msgid; /* the proper message id for val1. 0 means val1 should not be responsible for the
145  * invariant violation */
146  int val2_msgid; /* the proper message id for val2. 0 means val2 should not be responsible for the
147  * invariant violation */
148  int error_type; /* ER_QPROC_SERIAL_RANGE_OVERFLOW or ER_INVALID_SERIAL_VALUE */
149 };
150 
151 /*
152  * eval_insert_value -
153  * Structure is passed as argument to parser_walk_tree when insert values are
154  * evaluated and stores the information required for evaluation.
155  */
158 {
159  UINTPTR spec_id; /* insert spec_id */
160  PT_NODE *attr_list; /* list of insert attribute names */
161  PT_NODE *value_list; /* list of insert values values */
162  int crt_attr_index; /* current attribute index */
163  bool reevaluate_needed; /* currently evaluated insert value may need to be reevaluated with next execution */
164  bool replace_names; /* true if names may need to be replaced with each evaluation */
165 };
166 
169 static int check_serial_invariants (SERIAL_INVARIANT * invariants, int num_invariants, int *ret_msg_id);
170 static bool truncate_need_repl_log (PT_NODE * statement);
172 
173 static int do_evaluate_insert_values (PARSER_CONTEXT * parser, PT_NODE * insert_statement);
174 static void do_clear_insert_values (PARSER_CONTEXT * parser, PT_NODE * insert_statement);
176  int *continue_walk);
177 static int do_prepare_insert_internal (PARSER_CONTEXT * parser, PT_NODE * statement);
178 static int do_insert_template (PARSER_CONTEXT * parser, DB_OTMPL ** otemplate, PT_NODE * statement,
179  const char **savepoint_name, int *row_count_ptr);
181 
182 static int do_select_internal (PARSER_CONTEXT * parser, PT_NODE * statement, bool for_ins_upd);
183 
184 /*
185  * initialize_serial_invariant() - initialize a serial invariant
186  * return: None
187  * invariant(out):
188  * val1(in):
189  * val2(in):
190  * cmp_op(in):
191  * val1_msgid(in):
192  * val2_msgid(in):
193  * error_type(in):
194  *
195  * Note:
196  */
197 static void
199  int val1_msgid, int val2_msgid, int error_type)
200 {
201  invariant->val1 = val1;
202  invariant->val2 = val2;
203  invariant->cmp_op = cmp_op;
204  invariant->val1_msgid = val1_msgid;
205  invariant->val2_msgid = val2_msgid;
206  invariant->error_type = error_type;
207 }
208 
209 /*
210  * check_serial_invariants() - check whether invariants have been violated
211  * return: Error code
212  * invariants(in):
213  * num_invariants(in):
214  * ret_msg_id(out):
215  *
216  * Note:
217  */
218 
219 static int
220 check_serial_invariants (SERIAL_INVARIANT * invariants, int num_invariants, int *ret_msg_id)
221 {
222  int i, c;
223  int error;
224  DB_VALUE cmp_result;
225 
226  for (i = 0; i < num_invariants; i++)
227  {
228 
229  error = numeric_db_value_compare (&invariants[i].val1, &invariants[i].val2, &cmp_result);
230  if (error != NO_ERROR)
231  {
232  return error;
233  }
234 
235  c = db_get_int (&cmp_result);
236  switch (invariants[i].cmp_op)
237  {
238  case PT_GT:
239  if (c > 0)
240  {
241  /* same as expected */
242  continue;
243  }
244  break;
245  case PT_GE:
246  if (c >= 0)
247  {
248  continue;
249  }
250  break;
251  case PT_LT:
252  if (c < 0)
253  {
254  continue;
255  }
256  break;
257  case PT_LE:
258  if (c <= 0)
259  {
260  continue;
261  }
262  break;
263  case PT_EQ:
264  if (c == 0)
265  {
266  continue;
267  }
268  break;
269  case PT_NE:
270  if (c != 0)
271  {
272  continue;
273  }
274  break;
275  default:
276  /* impossible to get here! */
277  assert (0);
278  break;
279  }
280 
281  /* get here means invariant violated! */
282  if (invariants[i].val1_msgid != 0)
283  {
284  *ret_msg_id = invariants[i].val1_msgid;
285  return invariants[i].error_type;
286  }
287 
288  if (invariants[i].val2_msgid != 0)
289  {
290  *ret_msg_id = invariants[i].val2_msgid;
291  return invariants[i].error_type;
292  }
293 
294  /* impossible to get here! */
295  assert (0);
296  }
297 
298  return NO_ERROR;
299 }
300 
301 /*
302  * truncate_need_repl_log() - check whether truncate stmt need a replicate log
303  * return: true if the table has primary key,
304  * otherwise false
305  * statement(in):
306  */
307 static bool
309 {
310  PT_NODE *entity_spec = NULL;
311  PT_NODE *entity_list = NULL;
312  PT_NODE *entity = NULL;
313  const char *class_name = NULL;
314  MOP class_mop = NULL;
315  SM_CLASS *class_ = NULL;
316  SM_CLASS_CONSTRAINT *cons = NULL;
317  int error = NO_ERROR;
318 
319  assert (statement != NULL);
320 
321  entity_spec = statement->info.truncate.spec;
322  assert (entity_spec != NULL);
323 
324  entity_list = entity_spec->info.spec.flat_entity_list;
325  assert (entity_list != NULL);
326 
327  for (entity = entity_list; entity != NULL; entity = entity->next)
328  {
329  class_name = entity->info.name.original;
330  class_mop = db_find_class (class_name);
331  if (class_mop == NULL)
332  {
333  return false;
334  }
335 
336  error = au_fetch_class (class_mop, &class_, AU_FETCH_READ, DB_AUTH_NONE);
337  if (error != NO_ERROR)
338  {
339  return false;
340  }
341 
343  if (cons != NULL)
344  {
345  return true;
346  }
347  }
348 
349  return false;
350 }
351 
352 /*
353  * is_stmt_based_repl_type()
354  * return: true if it's a statement-based replication log statement
355  * otherwise false
356  * node(in):
357  */
358 bool
360 {
361  /* All DDLs will be replicated via schema replication */
362  if (pt_is_ddl_statement (node))
363  {
364  return true;
365  }
366 
367  /* some DMLs will also be replicated via schema replication instead of data replication */
368  switch (node->node_type)
369  {
370  case PT_DROP_VARIABLE:
371  case PT_TRUNCATE:
372  return true;
373  case PT_INSERT:
374  if (node->info.insert.hint & PT_HINT_USE_SBR)
375  {
376  return true;
377  }
378  break;
379  case PT_DELETE:
380  if (node->info.delete_.hint & PT_HINT_USE_SBR)
381  {
382  return true;
383  }
384  break;
385  case PT_UPDATE:
386  if (node->info.update.hint & PT_HINT_USE_SBR)
387  {
388  return true;
389  }
390  break;
391  default:
392  break;
393  }
394 
395  return false;
396 }
397 
398 /*
399  * do_evaluate_default_expr() - evaluates the default expressions, if any, for
400  * the attributes of a given class
401  * return: Error code
402  * parser(in):
403  * class_name(in):
404  */
405 int
407 {
408  SM_ATTRIBUTE *att;
409  SM_CLASS *smclass;
410  int error;
411  TP_DOMAIN_STATUS dom_status;
412  char *user_name;
413  DB_DATETIME *datetime;
414  int month, day, year, hour, minute, second, millisecond;
415  DB_VALUE default_value, format_val, lang_val;
416  char *lang_str = NULL;
417  int flag;
418  TP_DOMAIN *result_domain = NULL;
419  bool has_user_format;
420 
421  assert (class_name->node_type == PT_NAME);
422 
423  error = au_fetch_class_force (class_name->info.name.db_object, &smclass, AU_FETCH_READ);
424  if (error != NO_ERROR)
425  {
426  return error;
427  }
428 
429  for (att = smclass->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
430  {
432  {
434  {
435  case DB_DEFAULT_SYSTIME:
436  if (DB_IS_NULL (&parser->sys_datetime))
437  {
438  db_make_null (&default_value);
439  }
440  else
441  {
442  db_datetime_decode ((DB_DATETIME *) db_get_datetime (&parser->sys_datetime), &month, &day, &year,
443  &hour, &minute, &second, &millisecond);
444  db_make_time (&default_value, hour, minute, second);
445  }
446  break;
448  if (DB_IS_NULL (&parser->sys_datetime))
449  {
450  db_make_null (&default_value);
451  }
452  else
453  {
454  DB_TIME cur_time, db_time;
455  const char *t_source, *t_dest;
456  DB_DATETIME *datetime;
457 
458  datetime = db_get_datetime (&parser->sys_datetime);
459  t_source = tz_get_system_timezone ();
460  t_dest = tz_get_session_local_timezone ();
461  db_time = datetime->time / 1000;
462  error = tz_conv_tz_time_w_zone_name (&db_time, t_source, strlen (t_source), t_dest,
463  strlen (t_dest), &cur_time);
464  db_value_put_encoded_time (&default_value, &cur_time);
465  }
466  break;
467  case DB_DEFAULT_SYSDATE:
468  if (DB_IS_NULL (&parser->sys_datetime))
469  {
470  db_make_null (&default_value);
471  }
472  else
473  {
474  datetime = db_get_datetime (&parser->sys_datetime);
475  error = db_value_put_encoded_date (&default_value, &datetime->date);
476  }
477  break;
479  error = pr_clone_value (&parser->sys_datetime, &default_value);
480  break;
482  error = db_datetime_to_timestamp (&parser->sys_datetime, &default_value);
483  break;
485  error = db_unix_timestamp (&parser->sys_datetime, &default_value);
486  break;
487  case DB_DEFAULT_USER:
488  user_name = db_get_user_and_host_name ();
489  error = db_make_string (&default_value, user_name);
490  default_value.need_clear = true;
491  break;
493  user_name = db_get_user_name ();
494  error = db_make_string (&default_value, user_name);
495  default_value.need_clear = true;
496  break;
499  if (DB_IS_NULL (&parser->sys_datetime))
500  {
501  db_make_null (&default_value);
502  }
503  else
504  {
505  TZ_REGION system_tz_region, session_tz_region;
506  DB_DATETIME dest_dt;
507  DB_DATETIME *src_dt;
508 
509  src_dt = db_get_datetime (&parser->sys_datetime);
510  tz_get_system_tz_region (&system_tz_region);
511  tz_get_session_tz_region (&session_tz_region);
512  error =
513  tz_conv_tz_datetime_w_region (src_dt, &system_tz_region, &session_tz_region, &dest_dt, NULL, NULL);
515  {
516  db_value_put_encoded_date (&default_value, &dest_dt.date);
517  }
518  else
519  {
520  db_make_datetime (&default_value, &dest_dt);
521  }
522  }
523  break;
525  if (DB_IS_NULL (&parser->sys_datetime))
526  {
527  db_make_null (&default_value);
528  }
529  else
530  {
531  DB_DATE tmp_date;
532  DB_TIME tmp_time;
533  DB_TIMESTAMP tmp_timestamp;
534  DB_DATETIME *sys_datetime;
535 
536  sys_datetime = db_get_datetime (&parser->sys_datetime);
537  tmp_date = sys_datetime->date;
538  tmp_time = sys_datetime->time / 1000;
539  db_timestamp_encode_sys (&tmp_date, &tmp_time, &tmp_timestamp, NULL);
540  db_make_timestamp (&default_value, tmp_timestamp);
541  }
542  break;
543  default:
544  break;
545  }
546 
547  if (error != NO_ERROR)
548  {
549  break;
550  }
551 
553  {
555  {
556  has_user_format = 1;
558  }
559  else
560  {
561  has_user_format = 0;
562  db_make_null (&format_val);
563  }
564 
566  lang_set_flag_from_lang (lang_str, has_user_format, 0, &flag);
567  db_make_int (&lang_val, flag);
568 
569  if (!TP_IS_CHAR_TYPE (TP_DOMAIN_TYPE (att->domain)))
570  {
571  /* TO_CHAR returns a string value, we need to pass an expected domain of the result */
572  if (TP_IS_CHAR_TYPE (DB_VALUE_TYPE (&default_value)))
573  {
574  result_domain = NULL;
575  }
576  else if (DB_IS_NULL (&format_val))
577  {
578  result_domain = tp_domain_resolve_default (DB_TYPE_STRING);
579  }
580  else
581  {
582  result_domain = tp_domain_resolve_value (&format_val, NULL);
583  }
584  }
585  else
586  {
587  result_domain = att->domain;
588  }
589 
590  error = db_to_char (&default_value, &format_val, &lang_val, &att->default_value.value, result_domain);
591 
592  if (has_user_format)
593  {
594  pr_clear_value (&format_val);
595  }
596 
597  if (error != NO_ERROR)
598  {
599  break;
600  }
601  }
602  else
603  {
604  pr_clone_value (&default_value, &att->default_value.value);
605  }
606 
607  db_value_clear (&default_value);
608 
609  /* make sure the default value can be used for this attribute */
610  dom_status = tp_value_cast (&att->default_value.value, &att->default_value.value, att->domain, false);
611  if (dom_status != DOMAIN_COMPATIBLE)
612  {
613  error = tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &att->default_value.value, att->domain);
614  assert_release (error != NO_ERROR);
615 
616  break;
617  }
618  }
619  }
620 
621  return error;
622 }
623 
624 /*
625  * do_create_serial_internal() -
626  * return: Error code
627  * serial_object(out):
628  * serial_name(in):
629  * current_val(in):
630  * inc_val(in):
631  * min_val(in):
632  * max_val(in):
633  * cyclic(in):
634  * started(in):
635  * comment(in):
636  * class_name(in):
637  * att_name(in):
638  *
639  * Note:
640  */
641 static int
642 do_create_serial_internal (MOP * serial_object, const char *serial_name, DB_VALUE * current_val, DB_VALUE * inc_val,
643  DB_VALUE * min_val, DB_VALUE * max_val, const int cyclic, const int cached_num,
644  const int started, const char *comment, const char *class_name, const char *att_name)
645 {
646  DB_OBJECT *ret_obj = NULL;
647  DB_OTMPL *obj_tmpl = NULL;
648  DB_VALUE value;
649  DB_OBJECT *serial_class = NULL;
650  int au_save, error = NO_ERROR;
651 
652  db_make_null (&value);
653 
654  /* temporarily disable authorization to access db_serial class */
655  AU_DISABLE (au_save);
656 
657  serial_class = sm_find_class (CT_SERIAL_NAME);
658  if (serial_class == NULL)
659  {
662  goto end;
663  }
664 
665  obj_tmpl = dbt_create_object_internal ((MOP) serial_class);
666  if (obj_tmpl == NULL)
667  {
668  assert (er_errid () != NO_ERROR);
669  error = er_errid ();
670  goto end;
671  }
672 
673  /* name */
674  db_make_string (&value, serial_name);
675  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_NAME, &value);
676  pr_clear_value (&value);
677  if (error != NO_ERROR)
678  {
679  goto end;
680  }
681 
682  /* owner */
683  db_make_object (&value, Au_user);
684  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_OWNER, &value);
685  pr_clear_value (&value);
686  if (error != NO_ERROR)
687  {
688  goto end;
689  }
690 
691  /* current_val */
692  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CURRENT_VAL, current_val);
693  if (error != NO_ERROR)
694  {
695  goto end;
696  }
697 
698  /* increment_val */
699  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_INCREMENT_VAL, inc_val);
700  if (error != NO_ERROR)
701  {
702  goto end;
703  }
704 
705  /* min_val */
706  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MIN_VAL, min_val);
707  if (error != NO_ERROR)
708  {
709  goto end;
710  }
711 
712  /* max_val */
713  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MAX_VAL, max_val);
714  if (error != NO_ERROR)
715  {
716  goto end;
717  }
718 
719  /* cyclic */
720  db_make_int (&value, cyclic); /* always false */
721  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CYCLIC, &value);
722  pr_clear_value (&value);
723  if (error != NO_ERROR)
724  {
725  goto end;
726  }
727 
728  /* started */
729  db_make_int (&value, started);
730  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_STARTED, &value);
731  pr_clear_value (&value);
732  if (error != NO_ERROR)
733  {
734  goto end;
735  }
736 
737  /* comment */
738  db_make_string (&value, comment);
739  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_COMMENT, &value);
740  pr_clear_value (&value);
741  if (error != NO_ERROR)
742  {
743  goto end;
744  }
745 
746  /* class name */
747  if (class_name)
748  {
749  db_make_string (&value, class_name);
750  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CLASS_NAME, &value);
751  pr_clear_value (&value);
752  if (error != NO_ERROR)
753  {
754  goto end;
755  }
756  }
757 
758  /* att name */
759  if (att_name)
760  {
761  db_make_string (&value, att_name);
762  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATT_NAME, &value);
763  pr_clear_value (&value);
764  if (error != NO_ERROR)
765  {
766  goto end;
767  }
768  }
769 
770  /* cached num */
771  if (cached_num > 0)
772  {
773  db_make_int (&value, cached_num);
774  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CACHED_NUM, &value);
775  pr_clear_value (&value);
776  if (error != NO_ERROR)
777  {
778  goto end;
779  }
780  }
781 
782  ret_obj = dbt_finish_object (obj_tmpl);
783 
784  if (ret_obj == NULL)
785  {
786  assert (er_errid () != NO_ERROR);
787  error = er_errid ();
788  }
789  else if (serial_object != NULL)
790  {
791  *serial_object = ret_obj;
792  }
793 
794 end:
795  if (obj_tmpl != NULL && ret_obj == NULL)
796  {
797  dbt_abort_object (obj_tmpl);
798  }
799  AU_ENABLE (au_save);
800  return error;
801 }
802 
803 /*
804  * do_update_auto_increment_serial_on_rename() -
805  * return: Error code
806  * serial_obj(in/out):
807  * class_name(in):
808  * att_name(in):
809  *
810  * Note:
811  */
812 int
813 do_update_auto_increment_serial_on_rename (MOP serial_obj, const char *class_name, const char *att_name)
814 {
815  int error = NO_ERROR;
816  DB_OBJECT *serial_object = NULL;
817  DB_VALUE value;
818  DB_OTMPL *obj_tmpl = NULL;
819  char *serial_name = NULL;
820  char att_downcase_name[SM_MAX_IDENTIFIER_LENGTH];
821  size_t name_len;
822  int save;
823  bool au_disable_flag = false;
824 
825  if (!serial_obj || !class_name || !att_name)
826  {
828  }
829 
830  db_make_null (&value);
831 
832  serial_object = serial_obj;
833  sm_downcase_name (att_name, att_downcase_name, SM_MAX_IDENTIFIER_LENGTH);
834  att_name = att_downcase_name;
835 
836  /* serial_name : <class_name>_ai_<att_name> */
837  name_len = (strlen (class_name) + strlen (att_name) + AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH + 1);
838  serial_name = (char *) malloc (name_len);
839  if (serial_name == NULL)
840  {
843  }
844 
845  SET_AUTO_INCREMENT_SERIAL_NAME (serial_name, class_name, att_name);
846 
847  AU_DISABLE (save);
848  au_disable_flag = true;
849 
850  /*
851  * after serial.next_value, the currect value maybe changed, but cub_cas
852  * still hold the old value. To get the new value. we need decache it
853  * then refetch it from server again.
854  */
855  assert (WS_ISDIRTY (serial_object) == false);
856 
857  ws_decache (serial_object);
858  /* no need to get last version for serial - actually, the purpose is AU_FETCH_WRITE, so fetch type is not relevant;
859  * the last version will be locked and it will be considered visibile only if delid is not set */
861  if (error != NO_ERROR)
862  {
863  goto update_auto_increment_error;
864  }
865 
866  obj_tmpl = dbt_edit_object (serial_object);
867  if (obj_tmpl == NULL)
868  {
869  assert (er_errid () != NO_ERROR);
870  error = er_errid ();
871  goto update_auto_increment_error;
872  }
873 
874  /* name */
875  db_make_string (&value, serial_name);
876  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_NAME, &value);
877  if (error != NO_ERROR)
878  {
879  goto update_auto_increment_error;
880  }
881 
882  /* class name */
883  pr_clear_value (&value);
884  db_make_string (&value, class_name);
885  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CLASS_NAME, &value);
886  pr_clear_value (&value);
887  if (error != NO_ERROR)
888  {
889  goto update_auto_increment_error;
890  }
891 
892  /* att name */
893  db_make_string (&value, att_name);
894  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATT_NAME, &value);
895  pr_clear_value (&value);
896  if (error != NO_ERROR)
897  {
898  goto update_auto_increment_error;
899  }
900 
901  serial_object = dbt_finish_object (obj_tmpl);
902 
903  AU_ENABLE (save);
904  au_disable_flag = false;
905 
906  if (serial_object == NULL)
907  {
908  assert (er_errid () != NO_ERROR);
909  error = er_errid ();
910  goto update_auto_increment_error;
911  }
912 
913  free_and_init (serial_name);
914  return NO_ERROR;
915 
916 update_auto_increment_error:
917  if (serial_name)
918  {
919  free_and_init (serial_name);
920  }
921 
922  if (au_disable_flag == true)
923  {
924  AU_ENABLE (save);
925  }
926 
927  /* if dbt_finish_object() succeeded, it would never come here, so we just check if obj_tmpl and clear it. */
928  if (obj_tmpl != NULL)
929  {
930  dbt_abort_object (obj_tmpl);
931  }
932 
933  return (error);
934 }
935 
936 /*
937  * do_reset_auto_increment_serial() -
938  * return: Error code
939  * serial_obj(in/out):
940  */
941 int
943 {
944  int error_code = NO_ERROR;
945  DB_OBJECT *const serial_object = serial_obj;
946  DB_OBJECT *edit_serial_object = NULL;
947  DB_OTMPL *obj_tmpl = NULL;
948  DB_VALUE start_value;
949  DB_VALUE started_flag;
950 
951  if (serial_object == NULL)
952  {
954  }
955 
956  db_make_null (&start_value);
957  db_make_null (&started_flag);
958 
959  error_code = db_get (serial_object, SERIAL_ATTR_MIN_VAL, &start_value);
960  if (error_code != NO_ERROR)
961  {
962  goto error_exit;
963  }
964 
965  obj_tmpl = dbt_edit_object (serial_object);
966  if (obj_tmpl == NULL)
967  {
968  assert (er_errid () != NO_ERROR);
969  error_code = er_errid ();
970  goto error_exit;
971  }
972 
973  error_code = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CURRENT_VAL, &start_value);
974  if (error_code != NO_ERROR)
975  {
976  goto error_exit;
977  }
978 
979  db_make_int (&started_flag, 0);
980  error_code = dbt_put_internal (obj_tmpl, SERIAL_ATTR_STARTED, &started_flag);
981  if (error_code != NO_ERROR)
982  {
983  goto error_exit;
984  }
985 
986  edit_serial_object = dbt_finish_object (obj_tmpl);
987  if (edit_serial_object == NULL)
988  {
989  assert (er_errid () != NO_ERROR);
990  error_code = er_errid ();
991  goto error_exit;
992  }
993 
994  assert (edit_serial_object == serial_object);
995  obj_tmpl = NULL;
996 
997  error_code = locator_flush_instance (edit_serial_object);
998  if (error_code != NO_ERROR)
999  {
1000  goto error_exit;
1001  }
1002 
1003  db_value_clear (&start_value);
1004  db_value_clear (&started_flag);
1005 
1006  return error_code;
1007 
1008 error_exit:
1009 
1010  /* We don't need to check return value of dbt_finish_object() since if it succeeded, it would never come here. */
1011  if (obj_tmpl != NULL)
1012  {
1013  dbt_abort_object (obj_tmpl);
1014  }
1015 
1016  db_value_clear (&start_value);
1017  db_value_clear (&started_flag);
1018 
1019  return error_code;
1020 }
1021 
1022 
1023 /*
1024  * do_change_auto_increment_serial() -
1025  * return: Error code
1026  * serial_obj(in/out):
1027  */
1028 int
1029 do_change_auto_increment_serial (PARSER_CONTEXT * const parser, MOP serial_obj, PT_NODE * node_new_val)
1030 {
1031  int error_code = NO_ERROR;
1032  DB_OBJECT *const serial_object = serial_obj;
1033  DB_OBJECT *edit_serial_object = NULL;
1034  DB_OTMPL *obj_tmpl = NULL;
1035 
1036  DB_VALUE max_val;
1037  DB_VALUE started;
1038  DB_VALUE new_val;
1039  DB_VALUE cmp_result;
1040  DB_VALUE *pval = NULL;
1041  DB_DATA_STATUS data_status;
1042 
1043 
1044  int cmp;
1045 
1046 
1047  /*
1048  * 1. obtain NUMERIC value from node_new_val
1049  * 2. obtain max value of the serial.
1050  * 3. if the new value is greater than max, throw an error
1051  * 4. reset the serial: started = 0, cur = min = new cur;
1052  */
1053 
1054 
1055  if (serial_object == NULL)
1056  {
1057  return ER_OBJ_INVALID_ARGUMENTS;
1058  }
1059 
1060  db_make_null (&max_val);
1061  db_make_null (&new_val);
1062  db_make_null (&started);
1063  db_make_int (&cmp_result, 0);
1064 
1065 
1066  /* create a NUMERIC value in new_val */
1068  pval = pt_value_to_db (parser, node_new_val);
1069  if (pval == NULL)
1070  {
1071  assert (er_errid () != NO_ERROR);
1072  error_code = er_errid ();
1073  goto error_exit;
1074  }
1075 
1076  error_code = numeric_db_value_coerce_to_num (pval, &new_val, &data_status);
1077  if (error_code != NO_ERROR)
1078  {
1079  goto error_exit;
1080  }
1081 
1082 
1083  /* get the serial's max from db. */
1084  error_code = db_get (serial_object, SERIAL_ATTR_MAX_VAL, &max_val);
1085  if (error_code != NO_ERROR)
1086  {
1087  goto error_exit;
1088  }
1089 
1090 
1091  /* The new value must be lower than the max value */
1092  error_code = numeric_db_value_compare (&new_val, &max_val, &cmp_result);
1093  if (error_code != NO_ERROR)
1094  {
1095  goto error_exit;
1096  }
1097 
1098  cmp = db_get_int (&cmp_result);
1099  if (cmp >= 0)
1100  {
1103  goto error_exit;
1104  }
1105 
1106  /*
1107  * RESET serial: min = new_val; cur = new_val; started = 0 */
1108 
1109  obj_tmpl = dbt_edit_object (serial_object);
1110  if (obj_tmpl == NULL)
1111  {
1112  assert (er_errid () != NO_ERROR);
1113  error_code = er_errid ();
1114  goto error_exit;
1115  }
1116 
1117  error_code = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CURRENT_VAL, &new_val);
1118  if (error_code != NO_ERROR)
1119  {
1120  goto error_exit;
1121  }
1122 
1123  error_code = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MIN_VAL, &new_val);
1124  if (error_code != NO_ERROR)
1125  {
1126  goto error_exit;
1127  }
1128 
1129  db_make_int (&started, 0);
1130  error_code = dbt_put_internal (obj_tmpl, SERIAL_ATTR_STARTED, &started);
1131  if (error_code != NO_ERROR)
1132  {
1133  goto error_exit;
1134  }
1135 
1136  edit_serial_object = dbt_finish_object (obj_tmpl);
1137  if (edit_serial_object == NULL)
1138  {
1139  assert (er_errid () != NO_ERROR);
1140  error_code = er_errid ();
1141  goto error_exit;
1142  }
1143 
1144  assert (edit_serial_object == serial_object);
1145  obj_tmpl = NULL;
1146 
1147  error_code = locator_flush_instance (edit_serial_object);
1148  if (error_code != NO_ERROR)
1149  {
1150  goto error_exit;
1151  }
1152 
1153  goto normal_exit;
1154 
1155 
1156 error_exit:
1157 
1158  if (obj_tmpl != NULL)
1159  {
1160  dbt_abort_object (obj_tmpl);
1161  }
1162 
1163 normal_exit:
1164 
1165  db_value_clear (&max_val);
1166  db_value_clear (&new_val);
1167  db_value_clear (&started);
1168  db_value_clear (&cmp_result);
1169 
1170  return error_code;
1171 }
1172 
1173 
1174 /*
1175  * do_get_serial_obj_id() -
1176  * return: serial object
1177  * serial_obj_id(out):
1178  * serial_class_mop(in):
1179  * serial_name(in):
1180  *
1181  * Note:
1182  */
1183 MOP
1184 do_get_serial_obj_id (DB_IDENTIFIER * serial_obj_id, DB_OBJECT * serial_class_mop, const char *serial_name)
1185 {
1186  DB_OBJECT *mop;
1187  DB_VALUE val;
1188  DB_IDENTIFIER *db_id;
1189  char *p;
1190  size_t serial_name_size;
1191  int save;
1192 
1193  OID_SET_NULL (serial_obj_id);
1194 
1195  if (serial_class_mop == NULL || serial_name == NULL)
1196  {
1197  return NULL;
1198  }
1199 
1200  serial_name_size = intl_identifier_lower_string_size (serial_name);
1201  p = (char *) malloc (serial_name_size + 1);
1202  if (p == NULL)
1203  {
1204  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (serial_name_size + 1));
1205  return NULL;
1206  }
1207 
1208  intl_identifier_lower (serial_name, p);
1209  db_make_string (&val, p);
1210 
1211  AU_DISABLE (save);
1212  mop = db_find_unique (serial_class_mop, SERIAL_ATTR_NAME, &val);
1213  AU_ENABLE (save);
1214 
1215  if (mop == NULL)
1216  {
1217  assert (er_errid () != NO_ERROR);
1218 
1220  {
1221  er_clear ();
1222  }
1223  }
1224  else
1225  {
1226  db_id = ws_identifier (mop);
1227 
1228  if (db_id != NULL)
1229  {
1230  *serial_obj_id = *db_id;
1231  }
1232  else
1233  {
1234  mop = NULL;
1235  }
1236  }
1237 
1238  pr_clear_value (&val);
1239  free_and_init (p);
1240 
1241  return mop;
1242 }
1243 
1244 /*
1245  * do_get_serial_cached_num() -
1246  * return: Error code
1247  * cached_num(out) :
1248  * serial_obj(in) :
1249  *
1250  * Note:
1251  */
1252 int
1253 do_get_serial_cached_num (int *cached_num, MOP serial_obj)
1254 {
1255  DB_VALUE cached_num_val;
1256  int error;
1257 
1258  error = db_get (serial_obj, SERIAL_ATTR_CACHED_NUM, &cached_num_val);
1259  if (error != NO_ERROR)
1260  {
1261  return error;
1262  }
1263 
1264  assert (DB_VALUE_TYPE (&cached_num_val) == DB_TYPE_INTEGER);
1265 
1266  *cached_num = db_get_int (&cached_num_val);
1267 
1268  return NO_ERROR;
1269 }
1270 
1271 /*
1272  * do_create_serial() -
1273  * return: Error code
1274  * parser(in): Parser context
1275  * statement(in):
1276  *
1277  * Note:
1278  */
1279 int
1281 {
1282  DB_OBJECT *serial_class = NULL, *serial_object = NULL;
1283  MOP serial_mop;
1284  DB_IDENTIFIER serial_obj_id;
1285  DB_VALUE value, *pval = NULL;
1286 
1287  char *name = NULL;
1288  PT_NODE *start_val_node;
1289  PT_NODE *inc_val_node;
1290  PT_NODE *max_val_node;
1291  PT_NODE *min_val_node;
1292  PT_NODE *cached_num_node;
1293 
1294  DB_VALUE zero, e38, negative_e38;
1295  DB_VALUE start_val, inc_val, max_val, min_val, cached_num_val;
1296  DB_VALUE cmp_result;
1297  DB_VALUE tmp_val;
1298  DB_VALUE abs_inc_val, range_val;
1299 
1300  int min_val_msgid = 0;
1301  int max_val_msgid = 0;
1302  int start_val_msgid = 0;
1303  int inc_val_msgid = 0;
1304  int ret_msg_id = 0;
1306  int ninvars = 0;
1307  int inc_val_flag = 0, cyclic;
1308  int cached_num;
1309  DB_DATA_STATUS data_stat;
1310  int error = NO_ERROR;
1311  int save;
1312  bool au_disable_flag = false;
1313  char *p = NULL;
1314  size_t name_size;
1315  const char *comment = NULL;
1316 
1318 
1319  db_make_null (&value);
1320  db_make_null (&zero);
1321  db_make_null (&e38);
1322  db_make_null (&negative_e38);
1323  db_make_null (&start_val);
1324  db_make_null (&inc_val);
1325  db_make_null (&max_val);
1326  db_make_null (&min_val);
1327  db_make_null (&abs_inc_val);
1328  db_make_null (&range_val);
1329 
1330  /*
1331  * find db_serial_class
1332  */
1333  serial_class = sm_find_class (CT_SERIAL_NAME);
1334  if (serial_class == NULL)
1335  {
1337  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1338  goto end;
1339  }
1340 
1341  /*
1342  * lookup if serial object name already exists?
1343  */
1344 
1345  name = (char *) PT_NODE_SR_NAME (statement);
1346  name_size = intl_identifier_lower_string_size (name);
1347  p = (char *) malloc (name_size + 1);
1348  if (p == NULL)
1349  {
1350  error = ER_OUT_OF_VIRTUAL_MEMORY;
1351  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, (name_size + 1));
1352  goto end;
1353  }
1354  intl_identifier_lower (name, p);
1355 
1356  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class, p);
1357  if (serial_mop != NULL)
1358  {
1360  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, name);
1362  goto end;
1363  }
1364 
1365  /* get all values as string */
1369  db_make_int (&cmp_result, 0);
1370 
1371  start_val_node = PT_NODE_SR_START_VAL (statement);
1372  inc_val_node = PT_NODE_SR_INCREMENT_VAL (statement);
1373  min_val_node = PT_NODE_SR_MIN_VAL (statement);
1374  max_val_node = PT_NODE_SR_MAX_VAL (statement);
1375 
1376  /* increment_val */
1378  if (inc_val_node != NULL)
1379  {
1380  pval = pt_value_to_db (parser, inc_val_node);
1381  if (pval == NULL)
1382  {
1383  assert (er_errid () != NO_ERROR);
1384  error = er_errid ();
1385  goto end;
1386  }
1387 
1388  error = numeric_db_value_coerce_to_num (pval, &inc_val, &data_stat);
1389  if (error != NO_ERROR)
1390  {
1391  goto end;
1392  }
1393  pval = NULL;
1394 
1395  /* check if increment value is 0 */
1396  error = numeric_db_value_compare (&inc_val, &zero, &cmp_result);
1397  if (error != NO_ERROR)
1398  {
1399  goto end;
1400  }
1401 
1402  inc_val_flag = db_get_int (&cmp_result);
1403  if (inc_val_flag == 0)
1404  {
1405  error = ER_INVALID_SERIAL_VALUE;
1407  goto end;
1408  }
1410  }
1411  else
1412  {
1413  /* inc_val = 1; */
1414  db_make_int (&value, 1);
1415  error = numeric_db_value_coerce_to_num (&value, &inc_val, &data_stat);
1416  if (error != NO_ERROR)
1417  {
1418  goto end;
1419  }
1420 
1421  inc_val_flag = +1;
1422  }
1423 
1424  /* start_val 1 */
1426  if (start_val_node != NULL)
1427  {
1428  pval = pt_value_to_db (parser, start_val_node);
1429  if (pval == NULL)
1430  {
1431  assert (er_errid () != NO_ERROR);
1432  error = er_errid ();
1433  goto end;
1434  }
1435  error = numeric_db_value_coerce_to_num (pval, &start_val, &data_stat);
1436  if (error != NO_ERROR)
1437  {
1438  goto end;
1439  }
1440  pval = NULL;
1441  start_val_msgid = MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID;
1442  }
1443 
1445  /*
1446  * min_val comes from several sources, it can be one of them:
1447  * 1. user input
1448  * 2. start_val
1449  * 3. 1
1450  * 4. -e36
1451  * min_val_msgid is the proper message id. it's for error message generation
1452  * when min_val violates some invariants.
1453  * if min_val is 1 or -e36, min_val_msgid is set to 0 (default value) because
1454  * constants can't be the reason which violate invariants.
1455  * if min_val is from user input, min_val_msgid is set to
1456  * MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID.
1457  * if min_val is from start_val, min_val_msgid is set to
1458  * MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID.
1459  */
1460  if (min_val_node != NULL)
1461  {
1462  pval = pt_value_to_db (parser, min_val_node);
1463  if (pval == NULL)
1464  {
1465  assert (er_errid () != NO_ERROR);
1466  error = er_errid ();
1467  goto end;
1468  }
1469 
1470  error = numeric_db_value_coerce_to_num (pval, &min_val, &data_stat);
1471  if (error != NO_ERROR)
1472  {
1473  goto end;
1474  }
1475  pval = NULL;
1477  }
1478  else
1479  {
1480  if (inc_val_flag > 0)
1481  {
1482  if (start_val_node != NULL)
1483  {
1484  db_value_clone (&start_val, &min_val);
1486  }
1487  else
1488  {
1489  /* min_val = 1; */
1490  db_make_int (&value, 1);
1491  error = numeric_db_value_coerce_to_num (&value, &min_val, &data_stat);
1492  if (error != NO_ERROR)
1493  {
1494  goto end;
1495  }
1496  }
1497  }
1498  else
1499  {
1500  /* min_val */
1501  db_value_clone (&negative_e38, &min_val);
1502  }
1503  }
1504 
1505  /* max_val */
1507 
1508  if (max_val_node != NULL)
1509  {
1510  pval = pt_value_to_db (parser, max_val_node);
1511  if (pval == NULL)
1512  {
1513  assert (er_errid () != NO_ERROR);
1514  error = er_errid ();
1515  goto end;
1516  }
1517 
1518  error = numeric_db_value_coerce_to_num (pval, &max_val, &data_stat);
1519  if (error != NO_ERROR)
1520  {
1521  goto end;
1522  }
1523  pval = NULL;
1525  }
1526  else
1527  {
1528  if (inc_val_flag > 0)
1529  {
1530  /* max_val */
1531  db_value_clone (&e38, &max_val);
1532  }
1533  else
1534  {
1535  if (start_val_node != NULL)
1536  {
1537  /* max_val = start_val */
1538  db_value_clone (&start_val, &max_val);
1540  }
1541  else
1542  {
1543  /* max_val = -1; */
1544  db_make_int (&value, -1);
1545  error = numeric_db_value_coerce_to_num (&value, &max_val, &data_stat);
1546  if (error != NO_ERROR)
1547  {
1548  goto end;
1549  }
1550  }
1551  }
1552  }
1553 
1554  /* start_val 2 */
1555  if (start_val_node == NULL)
1556  {
1557  pr_clear_value (&start_val);
1558  if (inc_val_flag > 0)
1559  {
1560  /* start_val = min_val; */
1561  db_value_clone (&min_val, &start_val);
1562  start_val_msgid = MSGCAT_SEMANTIC_SERIAL_MAX_VAL_INVALID;
1563  }
1564  else
1565  {
1566  /* start_val = max_val; */
1567  db_value_clone (&max_val, &start_val);
1568  start_val_msgid = MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID;
1569  }
1570  }
1571 
1572  /* cyclic */
1573  cyclic = PT_NODE_SR_CYCLIC (statement);
1574 
1575  /*
1576  * check values
1577  * min_val start_val max_val
1578  * |--^--^--^--o--^--^--^--^---|
1579  * <--> inc_val
1580  */
1581 
1582  /*
1583  * the following invariants must hold:
1584  * min_val >= negative_e38
1585  * max_val <= e38
1586  * min_val < max_val
1587  * min_val <= start_val
1588  * max_val >= start_val
1589  * inc_val != zero
1590  * abs(inc_val) <= (max_val - min_val)
1591  */
1592 
1593  /*
1594  * invariant for min_val >= negative_e38.
1595  * if min_val_msgid == MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID,
1596  * that means the value of min_val is from start_val, if the invariant
1597  * is violated, start_val invalid error message should be displayed
1598  * instead of min_val underflow. the val2_msgid is 0 because negative_e38
1599  * cannot be the reason which violates the invariant.
1600  */
1601  initialize_serial_invariant (&invariants[ninvars++], min_val, negative_e38, PT_GE,
1602  ((min_val_msgid == MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID)
1605 
1606  /*
1607  * invariant for max_val <= e38. Like the above invariant, if
1608  * max_val_msgid == MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID,
1609  * start_val invalid error message should be displayed if the invariant
1610  * is violated.
1611  */
1612  initialize_serial_invariant (&invariants[ninvars++], max_val, e38, PT_LE,
1613  ((max_val_msgid == MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID)
1616 
1617  /* invariant for min_val < max_val. */
1618  initialize_serial_invariant (&invariants[ninvars++], min_val, max_val, PT_LT, min_val_msgid, max_val_msgid,
1620 
1621  /* invariant for min_val <= start_val */
1622  initialize_serial_invariant (&invariants[ninvars++], min_val, start_val, PT_LE, min_val_msgid, start_val_msgid,
1624 
1625  /* invariant for max_val >= start_val */
1626  initialize_serial_invariant (&invariants[ninvars++], max_val, start_val, PT_GE, max_val_msgid, start_val_msgid,
1628 
1629  /* invariant for inc_val != zero */
1630  initialize_serial_invariant (&invariants[ninvars++], inc_val, zero, PT_NE, MSGCAT_SEMANTIC_SERIAL_INC_VAL_ZERO, 0,
1632 
1633  /*
1634  * invariant for abs(inc_val) <= (max_val - min_val).
1635  * if this invariant is violated, inc_val, min_val or max_val should be
1636  * responsible for it. If max_val_msgid == 0, which means max_val is
1637  * initialized from a constant, not inputted by user, in this case, we don't
1638  * expect max_val should be responsible for the violation.
1639  */
1640  error = numeric_db_value_sub (&max_val, &min_val, &range_val);
1641  if (error == ER_IT_DATA_OVERFLOW)
1642  {
1643  // max - min might be flooded. Regard the range is big enough.
1645  er_clear ();
1646  }
1647 
1648  db_abs_dbval (&abs_inc_val, &inc_val);
1649  initialize_serial_invariant (&invariants[ninvars++], abs_inc_val, range_val, PT_LE, inc_val_msgid,
1650  (max_val_msgid == 0) ? min_val_msgid : max_val_msgid, ER_INVALID_SERIAL_VALUE);
1651 
1652  /* cached num */
1653  cached_num_node = PT_NODE_SR_CACHED_NUM_VAL (statement);
1654  if (cached_num_node != NULL)
1655  {
1656  DB_VALUE cached_num_int_val, abs_cached_range_val;
1657  assert (cached_num_node->type_enum == PT_TYPE_INTEGER);
1658 
1659  cached_num = cached_num_node->info.value.data_value.i;
1660 
1661  /* ABS (cache_num * inc_val) <= range_val */
1662 
1663  db_make_int (&cached_num_int_val, cached_num);
1665  error = numeric_db_value_coerce_to_num (&cached_num_int_val, &cached_num_val, &data_stat);
1666  if (error != NO_ERROR)
1667  {
1668  goto end;
1669  }
1670 
1671  /* ABS (cache_num * inc_val) */
1672  error = numeric_db_value_mul (&inc_val, &cached_num_val, &tmp_val);
1673  if (error != NO_ERROR)
1674  {
1675  goto end;
1676  }
1677 
1678  error = db_abs_dbval (&abs_cached_range_val, &tmp_val);
1679  if (error != NO_ERROR)
1680  {
1681  goto end;
1682  }
1683 
1684  initialize_serial_invariant (&invariants[ninvars++], abs_cached_range_val, range_val, PT_LE,
1686 
1687  pr_clear_value (&tmp_val);
1688  pr_clear_value (&abs_cached_range_val);
1689  }
1690  else
1691  {
1692  cached_num = 0;
1693  }
1694 
1695  assert (ninvars <= MAX_SERIAL_INVARIANT);
1696  error = check_serial_invariants (invariants, ninvars, &ret_msg_id);
1697 
1698  if (error != NO_ERROR)
1699  {
1701  {
1702  PT_ERRORmf (parser, statement, MSGCAT_SET_PARSER_SEMANTIC, ret_msg_id, 0);
1703  }
1704  goto end;
1705  }
1706 
1707  /* comment */
1708  if (statement->info.serial.comment != NULL)
1709  {
1710  assert (statement->info.serial.comment->node_type == PT_VALUE);
1711  comment = (char *) PT_VALUE_GET_BYTES (statement->info.serial.comment);
1712  if (comment == NULL)
1713  {
1714  error = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
1715  goto end;
1716  }
1717  }
1718 
1719  /* now create serial object which is insert into db_serial */
1720  AU_DISABLE (save);
1721  au_disable_flag = true;
1722 
1723  error = do_create_serial_internal (&serial_object, p, &start_val, &inc_val, &min_val, &max_val, cyclic, cached_num,
1724  0, comment, NULL, NULL);
1725 
1726  AU_ENABLE (save);
1727  au_disable_flag = false;
1728 
1729  if (error < 0)
1730  {
1731  goto end;
1732  }
1733 
1734  if (p != NULL)
1735  {
1736  free_and_init (p);
1737  }
1738 
1739  return NO_ERROR;
1740 
1741 end:
1742  if (au_disable_flag == true)
1743  {
1744  AU_ENABLE (save);
1745  }
1746 
1747  if (p != NULL)
1748  {
1749  free_and_init (p);
1750  }
1751 
1752  return error;
1753 }
1754 
1755 /*
1756  * do_create_auto_increment_serial() -
1757  * return: Error code
1758  * parser(in): Parser context
1759  * serial_object(out):
1760  * class_name(in):
1761  * att(in):
1762  *
1763  * Note:
1764  */
1765 int
1766 do_create_auto_increment_serial (PARSER_CONTEXT * parser, MOP * serial_object, const char *class_name, PT_NODE * att)
1767 {
1768  MOP serial_class = NULL, serial_mop;
1769  DB_IDENTIFIER serial_obj_id;
1770  DB_DATA_STATUS data_stat;
1771  int error = NO_ERROR;
1772  PT_NODE *auto_increment_node, *start_val_node, *inc_val_node;
1773  PT_NODE *dtyp;
1774  char *att_name = NULL, *serial_name = NULL;
1775  DB_VALUE start_val, inc_val, max_val, min_val;
1776  DB_VALUE zero, value, *pval = NULL;
1777  DB_VALUE cmp_result;
1778  int i;
1779  DB_VALUE e38;
1780  char *p, num[DB_MAX_NUMERIC_PRECISION + 1];
1781  char att_downcase_name[SM_MAX_IDENTIFIER_LENGTH];
1782  size_t name_len;
1783 
1784  db_make_null (&e38);
1785  db_make_null (&value);
1786  db_make_null (&zero);
1787  db_make_null (&cmp_result);
1788  db_make_null (&start_val);
1789  db_make_null (&inc_val);
1790  db_make_null (&max_val);
1791  db_make_null (&min_val);
1792 
1795 
1797  auto_increment_node = att->info.attr_def.auto_increment;
1798  if (auto_increment_node == NULL)
1799  {
1800  goto end;
1801  }
1802 
1803  /*
1804  * find db_serial
1805  */
1806  serial_class = sm_find_class (CT_SERIAL_NAME);
1807  if (serial_class == NULL)
1808  {
1810  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1811  goto end;
1812  }
1813 
1814  att_name = (char *) (att->info.attr_def.attr_name->alias_print
1816 
1817  sm_downcase_name (att_name, att_downcase_name, SM_MAX_IDENTIFIER_LENGTH);
1818  att_name = att_downcase_name;
1819 
1820  /* serial_name : <class_name>_ai_<att_name> */
1821  name_len = (strlen (class_name) + strlen (att_name) + AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH + 1);
1822  serial_name = (char *) malloc (name_len);
1823  if (serial_name == NULL)
1824  {
1825  error = ER_OUT_OF_VIRTUAL_MEMORY;
1826  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, name_len);
1827  goto end;
1828  }
1829 
1830  SET_AUTO_INCREMENT_SERIAL_NAME (serial_name, class_name, att_name);
1831 
1832  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class, serial_name);
1833  if (serial_mop != NULL)
1834  {
1836  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1837  goto end;
1838  }
1839 
1840  error = er_errid ();
1841  if (error != NO_ERROR)
1842  {
1843  goto end;
1844  }
1845 
1846  start_val_node = auto_increment_node->info.auto_increment.start_val;
1847  inc_val_node = auto_increment_node->info.auto_increment.increment_val;
1848 
1849  /* increment_val */
1851 
1852  if (inc_val_node != NULL)
1853  {
1854  pval = pt_value_to_db (parser, inc_val_node);
1855  if (pval == NULL)
1856  {
1857  error = ER_INVALID_SERIAL_VALUE;
1858  goto end;
1859  }
1860 
1861  error = numeric_db_value_coerce_to_num (pval, &inc_val, &data_stat);
1862  if (error != NO_ERROR)
1863  {
1864  goto end;
1865  }
1866 
1867  pval = NULL;
1868 
1869  /* check increment value */
1870  error = numeric_db_value_compare (&inc_val, &zero, &cmp_result);
1871  if (error != NO_ERROR)
1872  {
1873  goto end;
1874  }
1875 
1876  if (db_get_int (&cmp_result) <= 0)
1877  {
1879  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1880  goto end;
1881  }
1882  }
1883  else
1884  {
1885  /* set to 1 */
1886  db_make_int (&value, 1);
1887  error = numeric_db_value_coerce_to_num (&value, &inc_val, &data_stat);
1888  if (error != NO_ERROR)
1889  {
1890  goto end;
1891  }
1892  }
1893 
1894  /* start_val */
1896  if (start_val_node != NULL)
1897  {
1898  pval = pt_value_to_db (parser, start_val_node);
1899  if (pval == NULL)
1900  {
1901  error = ER_INVALID_SERIAL_VALUE;
1902  goto end;
1903  }
1904  error = numeric_db_value_coerce_to_num (pval, &start_val, &data_stat);
1905  if (error != NO_ERROR)
1906  {
1907  goto end;
1908  }
1909  pval = NULL;
1910  }
1911  else
1912  {
1913  /* set to 1 */
1914  db_make_int (&value, 1);
1915  error = numeric_db_value_coerce_to_num (&value, &start_val, &data_stat);
1916  if (error != NO_ERROR)
1917  {
1918  goto end;
1919  }
1920  }
1921 
1922  /* min value = start_val */
1923  db_value_clone (&start_val, &min_val);
1924 
1925  /* max value - depends on att's domain */
1927 
1928  dtyp = att->data_type;
1929  switch (att->type_enum)
1930  {
1931  case PT_TYPE_INTEGER:
1932  db_make_int (&value, DB_INT32_MAX);
1933  break;
1934  case PT_TYPE_BIGINT:
1935  db_make_bigint (&value, DB_BIGINT_MAX);
1936  break;
1937  case PT_TYPE_SMALLINT:
1938  db_make_int (&value, DB_INT16_MAX);
1939  break;
1940  case PT_TYPE_NUMERIC:
1941  memset (num, '\0', DB_MAX_NUMERIC_PRECISION + 1);
1942  for (i = 0, p = num; i < dtyp->info.data_type.precision; i++, p++)
1943  {
1944  *p = '9';
1945  }
1946 
1947  *p = '\0';
1948 
1950  break;
1951  default:
1952  /* max numeric */
1953  db_value_clone (&e38, &value);
1954  }
1955 
1956  error = numeric_db_value_coerce_to_num (&value, &max_val, &data_stat);
1957  if (error != NO_ERROR)
1958  {
1959  goto end;
1960  }
1961 
1962  /* check (start_val < max_val) */
1963  if (tp_value_compare (&start_val, &max_val, 1, 0) != DB_LT)
1964  {
1966  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1967  goto end;
1968  }
1969 
1970  /* create auto increment serial object */
1971  error =
1972  do_create_serial_internal (serial_object, serial_name, &start_val, &inc_val, &min_val, &max_val, 0, 0, 0, NULL,
1973  class_name, att_name);
1974  if (error < 0)
1975  {
1976  goto end;
1977  }
1978 
1979  pr_clear_value (&e38);
1980  pr_clear_value (&value);
1981  pr_clear_value (&zero);
1982  pr_clear_value (&cmp_result);
1983  pr_clear_value (&start_val);
1984  pr_clear_value (&inc_val);
1985  pr_clear_value (&max_val);
1986  pr_clear_value (&min_val);
1987 
1988  free_and_init (serial_name);
1989 
1990  return NO_ERROR;
1991 
1992 end:
1993  pr_clear_value (&e38);
1994  pr_clear_value (&value);
1995  pr_clear_value (&zero);
1996  pr_clear_value (&cmp_result);
1997  pr_clear_value (&start_val);
1998  pr_clear_value (&inc_val);
1999  pr_clear_value (&max_val);
2000  pr_clear_value (&min_val);
2001 
2002  if (serial_name)
2003  {
2004  free_and_init (serial_name);
2005  }
2006 
2007  return error;
2008 }
2009 
2010 /*
2011  * do_update_maxvalue_of_auto_increment_serial()
2012  * usage: update max_val of serial object
2013  * return: Error code
2014  * parser(in): Parser context
2015  * serial_object(out):
2016  * class_name(in):
2017  * att(in):
2018  *
2019  * Note:
2020  */
2021 int
2022 do_update_maxvalue_of_auto_increment_serial (PARSER_CONTEXT * parser, MOP * serial_object, const char *class_name,
2023  PT_NODE * att)
2024 {
2025  MOP serial_class, serial_mop;
2026  DB_OTMPL *obj_tmpl = NULL;
2027  DB_IDENTIFIER serial_obj_id;
2028  DB_DATA_STATUS data_stat;
2029  int error = NO_ERROR;
2030  PT_NODE *dtyp;
2031  char *att_name = NULL, *serial_name = NULL;
2032  DB_VALUE e38, current_val, max_val, value;
2033  int i, compare_result, save;
2034  char *p, num[DB_MAX_NUMERIC_PRECISION + 1];
2035  char att_downcase_name[SM_MAX_IDENTIFIER_LENGTH];
2036  size_t name_len;
2037  bool au_disable_flag = false;
2038 
2039  db_make_null (&e38);
2040  db_make_null (&value);
2041  db_make_null (&current_val);
2042  db_make_null (&max_val);
2043  OID_SET_NULL (&serial_obj_id);
2044 
2046 
2048  assert (serial_object != NULL);
2049 
2050  /* find db_serial */
2051  serial_class = sm_find_class (CT_SERIAL_NAME);
2052  if (serial_class == NULL)
2053  {
2055  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2056  goto end;
2057  }
2058 
2059  att_name = (char *) (att->info.attr_def.attr_name->alias_print
2061 
2062  sm_downcase_name (att_name, att_downcase_name, SM_MAX_IDENTIFIER_LENGTH);
2063  att_name = att_downcase_name;
2064 
2065  /* serial_name : <class_name>_ai_<att_name> */
2066  name_len = (strlen (class_name) + strlen (att_name) + AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH + 1);
2067  serial_name = (char *) malloc (name_len);
2068  if (serial_name == NULL)
2069  {
2070  error = ER_OUT_OF_VIRTUAL_MEMORY;
2071  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, name_len);
2072  goto end;
2073  }
2074 
2075  SET_AUTO_INCREMENT_SERIAL_NAME (serial_name, class_name, att_name);
2076 
2077  /* get serial mop by serial name */
2078  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class, serial_name);
2079  if (serial_mop == NULL)
2080  {
2081  error = ER_QPROC_SERIAL_NOT_FOUND;
2082  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, serial_name);
2083  goto end;
2084  }
2085 
2086  /*
2087  * after serial.next_value, the currect value maybe changed, but cub_cas
2088  * still hold the old value. To get the new value. we need decache it
2089  * then refetch it from server again.
2090  */
2091  assert (WS_ISDIRTY (serial_mop) == false);
2092 
2093  ws_decache (serial_mop);
2094 
2095  /* no need to get the last version for serial - actually, AU_FETCH_WRITE will get only last version, for locking */
2097  if (error != NO_ERROR)
2098  {
2099  goto end;
2100  }
2101 
2102  /* get current value */
2103  error = db_get (serial_mop, SERIAL_ATTR_CURRENT_VAL, &current_val);
2104  if (error < 0)
2105  {
2106  goto end;
2107  }
2108 
2109  /* max value - depends on att's domain */
2111 
2112  dtyp = att->data_type;
2113  switch (att->type_enum)
2114  {
2115  case PT_TYPE_INTEGER:
2116  db_make_int (&value, DB_INT32_MAX);
2117  break;
2118  case PT_TYPE_BIGINT:
2119  db_make_bigint (&value, DB_BIGINT_MAX);
2120  break;
2121  case PT_TYPE_SMALLINT:
2122  db_make_int (&value, DB_INT16_MAX);
2123  break;
2124  case PT_TYPE_NUMERIC:
2125  memset (num, '\0', DB_MAX_NUMERIC_PRECISION + 1);
2126  for (i = 0, p = num; i < dtyp->info.data_type.precision; i++, p++)
2127  {
2128  *p = '9';
2129  }
2130 
2131  *p = '\0';
2132 
2134  break;
2135  default:
2136  /* max numeric */
2137  db_value_clone (&e38, &value);
2138  }
2139 
2140  error = numeric_db_value_coerce_to_num (&value, &max_val, &data_stat);
2141  if (error != NO_ERROR)
2142  {
2143  goto end;
2144  }
2145 
2146  /* check (current_val <= max_val) */
2147  compare_result = tp_value_compare (&current_val, &max_val, 1, 0);
2148  if (compare_result != DB_LT && compare_result != DB_EQ)
2149  {
2151  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2152  goto end;
2153  }
2154 
2155  /* update serial object in db_serial */
2156  AU_DISABLE (save);
2157  au_disable_flag = true;
2158 
2159  obj_tmpl = dbt_edit_object (serial_mop);
2160  if (obj_tmpl == NULL)
2161  {
2162  assert (er_errid () != NO_ERROR);
2163  error = er_errid ();
2164  goto end;
2165  }
2166 
2167  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MAX_VAL, &max_val);
2168  if (error < 0)
2169  {
2170  goto end;
2171  }
2172 
2173  serial_mop = dbt_finish_object (obj_tmpl);
2174  if (serial_mop == NULL)
2175  {
2176  assert (er_errid () != NO_ERROR);
2177  error = er_errid ();
2178  goto end;
2179  }
2180  else
2181  {
2182  *serial_object = serial_mop;
2183  /* obj_tmpl has been released by dbt_finish_object() */
2184  obj_tmpl = NULL;
2185  }
2186 
2187 end:
2188  if (!OID_ISNULL (&serial_obj_id))
2189  {
2190  (void) serial_decache ((OID *) (&serial_obj_id));
2191  }
2192 
2193  if (au_disable_flag == true)
2194  {
2195  AU_ENABLE (save);
2196  }
2197 
2198  pr_clear_value (&e38);
2199  pr_clear_value (&value);
2200  pr_clear_value (&current_val);
2201  pr_clear_value (&max_val);
2202 
2203  if (serial_name != NULL)
2204  {
2205  free_and_init (serial_name);
2206  }
2207 
2208  if (obj_tmpl != NULL)
2209  {
2210  dbt_abort_object (obj_tmpl);
2211  }
2212 
2213  return error;
2214 }
2215 
2216 /*
2217  * do_alter_serial() -
2218  * return: Error code
2219  * parser(in): Parser context
2220  * statement(in):
2221  *
2222  * Note:
2223  */
2224 int
2226 {
2227  DB_OBJECT *serial_class = NULL, *serial_object = NULL;
2228  DB_IDENTIFIER serial_obj_id;
2229  DB_OTMPL *obj_tmpl = NULL;
2230  DB_VALUE value, *pval;
2231 
2232  char *name = NULL;
2233  PT_NODE *start_val_node;
2234  PT_NODE *inc_val_node;
2235  PT_NODE *max_val_node;
2236  PT_NODE *min_val_node;
2237  PT_NODE *cached_num_node;
2238 
2239  DB_VALUE zero, e38, negative_e38;
2240  DB_DATA_STATUS data_stat;
2241  DB_VALUE old_inc_val, old_max_val, old_min_val, old_cached_num;
2242  DB_VALUE current_val, start_val, cached_num_val;
2243  DB_VALUE new_inc_val, new_max_val, new_min_val;
2244  DB_VALUE cmp_result;
2245  DB_VALUE class_name_val;
2246  DB_VALUE tmp_val;
2247  DB_VALUE abs_inc_val, range_val;
2248  int cached_num;
2249  int ret_msg_id = 0;
2250  const char *comment = NULL;
2251 
2252  int new_inc_val_flag = 0, new_cyclic;
2253  bool cur_val_change, inc_val_change, max_val_change, min_val_change, cyclic_change, cached_num_change;
2254 
2255  int error = NO_ERROR;
2256  int save;
2257  bool au_disable_flag = false;
2258 
2260  int ninvars = 0;
2261 
2263 
2264  db_make_null (&value);
2265  db_make_null (&zero);
2266  db_make_null (&e38);
2267  db_make_null (&negative_e38);
2268  db_make_null (&old_inc_val);
2269  db_make_null (&old_max_val);
2270  db_make_null (&old_min_val);
2271  db_make_null (&new_inc_val);
2272  db_make_null (&new_max_val);
2273  db_make_null (&new_min_val);
2274  db_make_null (&current_val);
2275  db_make_null (&start_val);
2276  db_make_null (&class_name_val);
2277  db_make_null (&abs_inc_val);
2278  db_make_null (&range_val);
2279  OID_SET_NULL (&serial_obj_id);
2280 
2281  /*
2282  * find db_serial_class
2283  */
2284  serial_class = sm_find_class (CT_SERIAL_NAME);
2285  if (serial_class == NULL)
2286  {
2288  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2289  goto end;
2290  }
2291 
2292  /*
2293  * lookup if serial object name already exists?
2294  */
2295 
2296  name = (char *) PT_NODE_SR_NAME (statement);
2297 
2298  serial_object = do_get_serial_obj_id (&serial_obj_id, serial_class, name);
2299  if (serial_object == NULL)
2300  {
2301  error = ER_QPROC_SERIAL_NOT_FOUND;
2302  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, name);
2304  goto end;
2305  }
2306 
2307  /*
2308  * after serial.next_value, the currect value maybe changed, but cub_cas
2309  * still hold the old value. To get the new value. we need decache it
2310  * then refetch it from server again.
2311  */
2312  assert (WS_ISDIRTY (serial_object) == false);
2313 
2314  ws_decache (serial_object);
2315 
2316  /* no need to get the last version for serial - actually, AU_FETCH_WRITE will get only last version, for locking */
2318  if (error != NO_ERROR)
2319  {
2320  goto end;
2321  }
2322 
2323  error = db_get (serial_object, SERIAL_ATTR_CLASS_NAME, &class_name_val);
2324  if (error < 0)
2325  {
2326  goto end;
2327  }
2328 
2329  /*
2330  * check if user is creator or DBA
2331  */
2332  error = au_check_serial_authorization (serial_object);
2333  if (error != NO_ERROR)
2334  {
2335  if (error == ER_QPROC_CANNOT_UPDATE_SERIAL)
2336  {
2338  }
2339  goto end;
2340  }
2341 
2342  /* get old values */
2343  error = db_get (serial_object, SERIAL_ATTR_CURRENT_VAL, &current_val);
2344  if (error < 0)
2345  {
2346  goto end;
2347  }
2348 
2349  error = db_get (serial_object, SERIAL_ATTR_INCREMENT_VAL, &old_inc_val);
2350  if (error < 0)
2351  {
2352  goto end;
2353  }
2354 
2355  error = db_get (serial_object, SERIAL_ATTR_MAX_VAL, &old_max_val);
2356  if (error < 0)
2357  {
2358  goto end;
2359  }
2360 
2361  error = db_get (serial_object, SERIAL_ATTR_MIN_VAL, &old_min_val);
2362  if (error < 0)
2363  {
2364  goto end;
2365  }
2366 
2367  error = db_get (serial_object, SERIAL_ATTR_CACHED_NUM, &old_cached_num);
2368  if (error < 0)
2369  {
2370  cached_num = 0;
2371  }
2372  else
2373  {
2374  cached_num = db_get_int (&old_cached_num);
2375  }
2376 
2377  /* Now, get new values from node */
2378 
2382  db_make_int (&cmp_result, 0);
2383 
2385  inc_val_node = PT_NODE_SR_INCREMENT_VAL (statement);
2386  if (inc_val_node != NULL)
2387  {
2388  inc_val_change = true;
2389  pval = pt_value_to_db (parser, inc_val_node);
2390  if (pval == NULL)
2391  {
2392  assert (er_errid () != NO_ERROR);
2393  error = er_errid ();
2394  goto end;
2395  }
2396  error = numeric_db_value_coerce_to_num (pval, &new_inc_val, &data_stat);
2397  if (error != NO_ERROR)
2398  {
2399  goto end;
2400  }
2401  pval = NULL;
2402 
2403  error = numeric_db_value_compare (&new_inc_val, &zero, &cmp_result);
2404  if (error != NO_ERROR)
2405  {
2406  goto end;
2407  }
2408 
2409  new_inc_val_flag = db_get_int (&cmp_result);
2410  /* new_inc_val == 0 */
2411  if (new_inc_val_flag == 0)
2412  {
2413  error = ER_INVALID_SERIAL_VALUE;
2415  goto end;
2416  }
2417  }
2418  else
2419  {
2420  inc_val_change = false;
2421  /* new_inc_val = old_inc_val; */
2422  db_value_clone (&old_inc_val, &new_inc_val);
2423  error = numeric_db_value_compare (&new_inc_val, &zero, &cmp_result);
2424  if (error != NO_ERROR)
2425  {
2426  goto end;
2427  }
2428 
2429  new_inc_val_flag = db_get_int (&cmp_result);
2430  }
2431 
2432  /* start_val */
2434  start_val_node = PT_NODE_SR_START_VAL (statement);
2435  if (start_val_node != NULL)
2436  {
2437  cur_val_change = true;
2438  pval = pt_value_to_db (parser, start_val_node);
2439  if (pval == NULL)
2440  {
2441  assert (er_errid () != NO_ERROR);
2442  error = er_errid ();
2443  goto end;
2444  }
2445  error = numeric_db_value_coerce_to_num (pval, &start_val, &data_stat);
2446  if (error != NO_ERROR)
2447  {
2448  goto end;
2449  }
2450  pval = NULL;
2451  }
2452  else
2453  {
2454  cur_val_change = false;
2455  db_value_clone (&current_val, &start_val);
2456  }
2457 
2458  /* max_val */
2460  max_val_node = PT_NODE_SR_MAX_VAL (statement);
2461  if (max_val_node != NULL)
2462  {
2463  max_val_change = true;
2464  pval = pt_value_to_db (parser, max_val_node);
2465  if (pval == NULL)
2466  {
2467  assert (er_errid () != NO_ERROR);
2468  error = er_errid ();
2469  goto end;
2470  }
2471  error = numeric_db_value_coerce_to_num (pval, &new_max_val, &data_stat);
2472  if (error != NO_ERROR)
2473  {
2474  goto end;
2475  }
2476  pval = NULL;
2477  }
2478  else
2479  {
2480  if (PT_NODE_SR_NO_MAX (statement) == 1)
2481  {
2482  max_val_change = true;
2483  if (new_inc_val_flag > 0)
2484  {
2485  /* new_max_val */
2486  db_value_clone (&e38, &new_max_val);
2487  }
2488  else
2489  {
2490  /* new_max_val = -1; */
2491  db_make_int (&value, -1);
2492  error = numeric_db_value_coerce_to_num (&value, &new_max_val, &data_stat);
2493  if (error != NO_ERROR)
2494  {
2495  goto end;
2496  }
2497  }
2498  }
2499  else
2500  {
2501  max_val_change = false;
2502  /* new_max_val = old_max_val; */
2503  db_value_clone (&old_max_val, &new_max_val);
2504  }
2505  }
2506 
2507  /* min_val */
2509  min_val_node = PT_NODE_SR_MIN_VAL (statement);
2510  if (min_val_node != NULL)
2511  {
2512  min_val_change = true;
2513  pval = pt_value_to_db (parser, min_val_node);
2514  if (pval == NULL)
2515  {
2516  assert (er_errid () != NO_ERROR);
2517  error = er_errid ();
2518  goto end;
2519  }
2520  error = numeric_db_value_coerce_to_num (pval, &new_min_val, &data_stat);
2521  if (error != NO_ERROR)
2522  {
2523  goto end;
2524  }
2525  pval = NULL;
2526  }
2527  else
2528  {
2529  if (PT_NODE_SR_NO_MIN (statement) == 1)
2530  {
2531  min_val_change = true;
2532 
2533  if (new_inc_val_flag > 0)
2534  {
2535  /* new_min_val = 1; */
2536  db_make_int (&value, 1);
2537  error = numeric_db_value_coerce_to_num (&value, &new_min_val, &data_stat);
2538  if (error != NO_ERROR)
2539  {
2540  goto end;
2541  }
2542  }
2543  else
2544  {
2545  /* new_min_val */
2546  db_value_clone (&negative_e38, &new_min_val);
2547  }
2548  }
2549  else
2550  {
2551  min_val_change = false;
2552  /* new_min_val = old_min_val; */
2553  db_value_clone (&old_min_val, &new_min_val);
2554  }
2555  }
2556 
2557  /* cyclic */
2558  new_cyclic = PT_NODE_SR_CYCLIC (statement);
2559  if ((new_cyclic == 1) || (PT_NODE_SR_NO_CYCLIC (statement) == 1))
2560  {
2561  cyclic_change = true;
2562  }
2563  else
2564  {
2565  cyclic_change = false;
2566  }
2567 
2568  /*
2569  * check values
2570  * min_val start_val max_val
2571  * |--^--^--^--o--^--^--^--^---|
2572  * <--> inc_val
2573  */
2574 
2575  /* invariant for min_val >= negative_e38. */
2576  initialize_serial_invariant (&invariants[ninvars++], new_min_val, negative_e38, PT_GE,
2578 
2579  /* invariant for max_val <= e38. */
2580  initialize_serial_invariant (&invariants[ninvars++], new_max_val, e38, PT_LE, MSGCAT_SEMANTIC_SERIAL_MAX_VAL_OVERFLOW,
2582 
2583  /* invariant for min_val < max_val. */
2584  initialize_serial_invariant (&invariants[ninvars++], new_min_val, new_max_val, PT_LT,
2585  (min_val_change) ? MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID : 0,
2587 
2588  /* invariant for min_val <= start_val */
2589  initialize_serial_invariant (&invariants[ninvars++], new_min_val, start_val, PT_LE,
2590  (min_val_change) ? MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID : 0,
2591  (cur_val_change) ? MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID : 0,
2593 
2594  /* invariant for max_val >= start_val */
2595  initialize_serial_invariant (&invariants[ninvars++], new_max_val, start_val, PT_GE,
2596  (max_val_change) ? MSGCAT_SEMANTIC_SERIAL_MAX_VAL_INVALID : 0,
2597  (cur_val_change) ? MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID : 0,
2599 
2600  /* invariant for inc_val != zero */
2601  initialize_serial_invariant (&invariants[ninvars++], new_inc_val, zero, PT_NE, MSGCAT_SEMANTIC_SERIAL_INC_VAL_ZERO, 0,
2603 
2604  /* invariant for abs(inc_val) <= (max_val - min_val). */
2605  error = numeric_db_value_sub (&new_max_val, &new_min_val, &range_val);
2606  if (error == ER_IT_DATA_OVERFLOW)
2607  {
2608  // max - min might be flooded. Regard the range is big enough.
2610  er_clear ();
2611  }
2612 
2613  db_abs_dbval (&abs_inc_val, &new_inc_val);
2614  initialize_serial_invariant (&invariants[ninvars++], abs_inc_val, range_val, PT_LE,
2615  (inc_val_change) ? MSGCAT_SEMANTIC_SERIAL_INC_VAL_INVALID : 0,
2616  (max_val_change) ? MSGCAT_SEMANTIC_SERIAL_MAX_VAL_INVALID :
2617  MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID, ER_INVALID_SERIAL_VALUE);
2618 
2619  /* cached num */
2620  cached_num_node = PT_NODE_SR_CACHED_NUM_VAL (statement);
2621  if (cached_num_node != NULL)
2622  {
2623  DB_VALUE cached_num_int_val, abs_cached_range_val;
2624  assert (cached_num_node->type_enum == PT_TYPE_INTEGER);
2625 
2626  cached_num_change = true;
2627  cached_num = cached_num_node->info.value.data_value.i;
2628 
2629  /* ABS (cache_num * inc_val) <= range_val */
2630 
2631  db_make_int (&cached_num_int_val, cached_num);
2633  error = numeric_db_value_coerce_to_num (&cached_num_int_val, &cached_num_val, &data_stat);
2634  if (error != NO_ERROR)
2635  {
2636  goto end;
2637  }
2638 
2639  /* ABS (cache_num * inc_val) */
2640  error = numeric_db_value_mul (&new_inc_val, &cached_num_val, &tmp_val);
2641  if (error != NO_ERROR)
2642  {
2643  goto end;
2644  }
2645 
2646  error = db_abs_dbval (&abs_cached_range_val, &tmp_val);
2647  if (error != NO_ERROR)
2648  {
2649  goto end;
2650  }
2651 
2652  initialize_serial_invariant (&invariants[ninvars++], abs_cached_range_val, range_val, PT_LE,
2654 
2655  pr_clear_value (&tmp_val);
2656  pr_clear_value (&abs_cached_range_val);
2657  }
2658  else
2659  {
2660  if (PT_NODE_SR_NO_CACHE (statement) == 1)
2661  {
2662  cached_num_change = true;
2663  cached_num = 0;
2664  }
2665  else
2666  {
2667  cached_num_change = false;
2668  }
2669  }
2670 
2671  assert (ninvars <= MAX_SERIAL_INVARIANT);
2672  error = check_serial_invariants (invariants, ninvars, &ret_msg_id);
2673 
2674  if (error != NO_ERROR)
2675  {
2677  {
2678  PT_ERRORmf (parser, statement, MSGCAT_SET_PARSER_SEMANTIC, ret_msg_id, 0);
2679  }
2680  goto end;
2681  }
2682  /* now update serial object in db_serial */
2683  AU_DISABLE (save);
2684  au_disable_flag = true;
2685 
2686  obj_tmpl = dbt_edit_object (serial_object);
2687  if (obj_tmpl == NULL)
2688  {
2689  assert (er_errid () != NO_ERROR);
2690  error = er_errid ();
2691  goto end;
2692  }
2693 
2694  /* current_val */
2695  if (cur_val_change)
2696  {
2697  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CURRENT_VAL, &start_val);
2698  if (error < 0)
2699  {
2700  goto end;
2701  }
2702  /* reset started flag because current_val changed */
2703  db_make_int (&value, 0);
2704  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_STARTED, &value);
2705  if (error < 0)
2706  {
2707  goto end;
2708  }
2709  pr_clear_value (&value);
2710  }
2711 
2712  /* increment_val */
2713  if (inc_val_change)
2714  {
2715  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_INCREMENT_VAL, &new_inc_val);
2716  if (error < 0)
2717  {
2718  goto end;
2719  }
2720  }
2721 
2722  /* max_val */
2723  if (max_val_change)
2724  {
2725  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MAX_VAL, &new_max_val);
2726  if (error < 0)
2727  {
2728  goto end;
2729  }
2730  }
2731 
2732  /* min_val */
2733  if (min_val_change)
2734  {
2735  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_MIN_VAL, &new_min_val);
2736  if (error < 0)
2737  {
2738  goto end;
2739  }
2740  }
2741 
2742  /* cyclic */
2743  if (cyclic_change)
2744  {
2745  db_make_int (&value, new_cyclic);
2746  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CYCLIC, &value);
2747  if (error < 0)
2748  {
2749  goto end;
2750  }
2751  pr_clear_value (&value);
2752  }
2753 
2754  /* cached num */
2755  if (cached_num_change)
2756  {
2757 
2758  /* Here we need class_name and att_name to see if this serial is auto_increment. Cause for an auto_increment
2759  * serial, it is not allowed to change the cached_num for it. */
2760  if (!DB_IS_NULL (&class_name_val))
2761  {
2762 
2764 
2765  PT_ERRORmf (parser, statement, MSGCAT_SET_PARSER_RUNTIME, error, name);
2766 
2767  goto end;
2768 
2769  }
2770 
2771  db_make_int (&value, cached_num);
2772  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_CACHED_NUM, &value);
2773  if (error < 0)
2774  {
2775  goto end;
2776  }
2777  pr_clear_value (&value);
2778  }
2779 
2780  /* comment */
2781  if (statement->info.serial.comment != NULL)
2782  {
2783  assert (statement->info.serial.comment->node_type == PT_VALUE);
2784  comment = (char *) PT_VALUE_GET_BYTES (statement->info.serial.comment);
2785  db_make_string (&value, comment);
2786  error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_COMMENT, &value);
2787  pr_clear_value (&value);
2788  if (error < 0)
2789  {
2790  goto end;
2791  }
2792  }
2793 
2794  serial_object = dbt_finish_object (obj_tmpl);
2795  if (serial_object == NULL)
2796  {
2797  assert (er_errid () != NO_ERROR);
2798  error = er_errid ();
2799  goto end;
2800  }
2801 
2802  /* obj_tmpl has been released by dbt_finish_object */
2803  obj_tmpl = NULL;
2804 
2805 end:
2806  if (!OID_ISNULL (&serial_obj_id))
2807  {
2808  (void) serial_decache ((OID *) (&serial_obj_id));
2809  }
2810 
2811  if (au_disable_flag == true)
2812  {
2813  AU_ENABLE (save);
2814  }
2815 
2816  if (obj_tmpl != NULL)
2817  {
2818  dbt_abort_object (obj_tmpl);
2819  }
2820 
2821  return error;
2822 }
2823 
2824 /*
2825  * do_drop_serial() -
2826  * return: Error code
2827  * parser(in): Parser context
2828  * statement(in):
2829  *
2830  * Note:
2831  */
2832 int
2834 {
2835  DB_OBJECT *serial_class = NULL, *serial_object = NULL;
2836  DB_IDENTIFIER serial_obj_id;
2837  DB_VALUE class_name_val;
2838  char *name;
2839  int error = NO_ERROR;
2840  int save;
2841  bool au_disable_flag = false;
2842 
2844 
2845  db_make_null (&class_name_val);
2846  OID_SET_NULL (&serial_obj_id);
2847 
2848  serial_class = sm_find_class (CT_SERIAL_NAME);
2849  if (serial_class == NULL)
2850  {
2852  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2853  goto end;
2854  }
2855 
2856  name = (char *) PT_NODE_SR_NAME (statement);
2857 
2858  serial_object = do_get_serial_obj_id (&serial_obj_id, serial_class, name);
2859  if (serial_object == NULL)
2860  {
2861  if (statement->info.serial.if_exists)
2862  {
2863  return NO_ERROR;
2864  }
2865  error = ER_QPROC_SERIAL_NOT_FOUND;
2866  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, name);
2868  goto end;
2869  }
2870 
2871  error = db_get (serial_object, SERIAL_ATTR_CLASS_NAME, &class_name_val);
2872  if (error < 0)
2873  {
2874  goto end;
2875  }
2876 
2877  if (!DB_IS_NULL (&class_name_val))
2878  {
2881  pr_clear_value (&class_name_val);
2882  goto end;
2883  }
2884 
2885  /*
2886  * check if user is creator or DBA
2887  */
2888  error = au_check_serial_authorization (serial_object);
2889  if (error != NO_ERROR)
2890  {
2891  if (error == ER_QPROC_CANNOT_UPDATE_SERIAL)
2892  {
2894  }
2895  goto end;
2896  }
2897 
2898  AU_DISABLE (save);
2899  au_disable_flag = true;
2900 
2901  error = db_drop (serial_object);
2902  if (error < 0)
2903  {
2904  goto end;
2905  }
2906 
2907 end:
2908  if (!OID_ISNULL (&serial_obj_id))
2909  {
2910  (void) serial_decache (&serial_obj_id);
2911  }
2912 
2913  if (au_disable_flag == true)
2914  {
2915  AU_ENABLE (save);
2916  }
2917 
2918  return error;
2919 }
2920 
2921 
2922 
2923 /*
2924  * Function Group:
2925  * Entry functions to do execute
2926  *
2927  */
2928 
2929 #define ER_PT_UNKNOWN_STATEMENT ER_GENERIC_ERROR
2930 #define UNIQUE_SAVEPOINT_EXTERNAL_STATEMENT "eXTERNALsTATEMENT"
2931 
2933 
2934 /*
2935  * do_statement() -
2936  * return: Error code
2937  * parser(in): Parser context
2938  * statement(in): Parse tree of a statement
2939  *
2940  * Note: Side effects can exist at the statement, especially schema information
2941  */
2942 int
2944 {
2945  int error = NO_ERROR;
2946  bool need_stmt_replication = false;
2947  int suppress_repl_error = NO_ERROR;
2948  LC_FETCH_VERSION_TYPE read_fetch_instance_version;
2949 
2950  /* save old read fetch instance version */
2951  read_fetch_instance_version = TM_TRAN_READ_FETCH_VERSION ();
2952  /* If it is an internally created statement, set its host variable info again to search host variables at parent
2953  * parser */
2955 
2956  if (statement)
2957  {
2958  /* skip ddl execution in case of parameter or opt. level */
2959  if (pt_is_ddl_statement (statement) != 0)
2960  {
2962  {
2963  const char *cp = statement->sql_user_text;
2964  if (cp == NULL)
2965  {
2966  cp = statement->alias_print;
2967  }
2968 
2969  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 1, cp ? cp : "unknown");
2970  error = ER_BLOCK_DDL_STMT;
2971  goto end;
2972  }
2973 
2974  /* if QO_PARAM_LEVEL indicate no execution, just return */
2975  if (qo_need_skip_execution ())
2976  {
2977  error = NO_ERROR;
2978  goto end;
2979  }
2980  }
2981 
2982  /* for the subset of nodes which represent top level statements, process them. For any other node, return an
2983  * error. */
2984 
2985  /* disable data replication log for schema replication log types in HA mode */
2986  if (!HA_DISABLED () && is_stmt_based_repl_type (statement))
2987  {
2988  need_stmt_replication = true;
2989 
2990  /* since we are going to suppress writing replication logs, we need to flush all dirty objects to server not
2991  * to lose them. */
2992  error = locator_all_flush ();
2993  if (error != NO_ERROR)
2994  {
2995  /* restore execution flag */
2996  goto end;
2997  }
2998 
2999  suppress_repl_error = db_set_suppress_repl_on_transaction (true);
3000  if (suppress_repl_error != NO_ERROR)
3001  {
3002  goto end;
3003  }
3004  }
3005 
3006  switch (statement->node_type)
3007  {
3008  case PT_GET_TRIGGER:
3009  case PT_GET_XACTION:
3010  case PT_SAVEPOINT:
3011  case PT_PREPARE_TO_COMMIT:
3012  case PT_COMMIT_WORK:
3013  case PT_ROLLBACK_WORK:
3014  case PT_SCOPE:
3015  case PT_INSERT:
3016  case PT_SELECT:
3017  case PT_DIFFERENCE:
3018  case PT_INTERSECTION:
3019  case PT_UNION:
3020  case PT_EVALUATE:
3021  case PT_GET_STATS:
3022  case PT_GET_OPT_LVL:
3023  case PT_SET_OPT_LVL:
3024  case PT_SET_SYS_PARAMS:
3025  case PT_DO:
3026  case PT_EXECUTE_PREPARE:
3027  case PT_VACUUM:
3028  case PT_QUERY_TRACE:
3029  case PT_KILL_STMT:
3031  break;
3032 
3033  case PT_EXECUTE_TRIGGER:
3034  case PT_CREATE_ENTITY:
3035  case PT_CREATE_INDEX:
3036  case PT_CREATE_SERIAL:
3037  case PT_CREATE_TRIGGER:
3038  case PT_CREATE_USER:
3039  case PT_ALTER:
3040  case PT_ALTER_INDEX:
3041  case PT_ALTER_SERIAL:
3042  case PT_ALTER_TRIGGER:
3043  case PT_ALTER_USER:
3044  case PT_DROP:
3045  case PT_DROP_INDEX:
3046  case PT_DROP_SERIAL:
3047  case PT_DROP_TRIGGER:
3048  case PT_DROP_USER:
3049  case PT_DROP_VARIABLE:
3050  case PT_RENAME:
3051  case PT_RENAME_TRIGGER:
3052  case PT_SET_TRIGGER:
3053  case PT_REMOVE_TRIGGER:
3054  case PT_GRANT:
3055  case PT_REVOKE:
3056  case PT_2PC_ATTACH:
3057  case PT_SET_XACTION:
3058  case PT_DELETE:
3059  case PT_UPDATE:
3060  case PT_MERGE:
3061  case PT_METHOD_CALL:
3062  case PT_UPDATE_STATS:
3066  case PT_TRUNCATE:
3069  case PT_SET_NAMES:
3070  case PT_SET_TIMEZONE:
3071 
3072  /* Need to get dirty version when fetch the instance. That's because we are in an update command. */
3074  break;
3075 
3076  default:
3078  break;
3079  }
3080 
3081  switch (statement->node_type)
3082  {
3083  case PT_ALTER:
3084  error = do_check_internal_statements (parser, statement,
3085  /* statement->info.alter. internal_stmts, */
3086  do_alter);
3087  break;
3088 
3089  case PT_2PC_ATTACH:
3090  error = do_attach (parser, statement);
3091  break;
3092 
3093  case PT_PREPARE_TO_COMMIT:
3094  error = do_prepare_to_commit (parser, statement);
3095  break;
3096 
3097  case PT_COMMIT_WORK:
3098  error = do_commit (parser, statement);
3099  break;
3100 
3101  case PT_CREATE_ENTITY:
3102  error = do_check_internal_statements (parser, statement,
3103  /* statement->info.create_entity. internal_stmts, */
3105  break;
3106 
3107  case PT_CREATE_INDEX:
3108  error = do_create_index (parser, statement);
3109  break;
3110 
3111  case PT_EVALUATE:
3112  error = do_evaluate (parser, statement);
3113  break;
3114 
3115  case PT_SCOPE:
3116  error = do_scope (parser, statement);
3117  break;
3118 
3119  case PT_DELETE:
3120  error = do_check_delete_trigger (parser, statement, do_delete);
3121  break;
3122 
3123  case PT_DROP:
3124  error = do_check_internal_statements (parser, statement,
3125  /* statement->info.drop. internal_stmts, */
3126  do_drop);
3127  break;
3128 
3129  case PT_DROP_INDEX:
3130  error = do_drop_index (parser, statement);
3131  break;
3132 
3133  case PT_ALTER_INDEX:
3134  error = do_alter_index (parser, statement);
3135  break;
3136 
3137  case PT_DROP_VARIABLE:
3138  error = do_drop_variable (parser, statement);
3139  break;
3140 
3141  case PT_GRANT:
3142  error = do_grant (parser, statement);
3143  break;
3144 
3145  case PT_INSERT:
3146  error = do_check_insert_trigger (parser, statement, do_insert);
3147  break;
3148 
3149  case PT_RENAME:
3150  error = do_rename (parser, statement);
3151  break;
3152 
3153  case PT_REVOKE:
3154  error = do_revoke (parser, statement);
3155  break;
3156 
3157  case PT_CREATE_USER:
3158  error = do_create_user (parser, statement);
3159  break;
3160 
3161  case PT_DROP_USER:
3162  error = do_drop_user (parser, statement);
3163  break;
3164 
3165  case PT_ALTER_USER:
3166  error = do_alter_user (parser, statement);
3167  break;
3168 
3169  case PT_SET_XACTION:
3170  error = do_set_xaction (parser, statement);
3171  break;
3172 
3173  case PT_GET_XACTION:
3174  error = do_get_xaction (parser, statement);
3175  break;
3176 
3177  case PT_ROLLBACK_WORK:
3178  error = do_rollback (parser, statement);
3179  break;
3180 
3181  case PT_SAVEPOINT:
3182  error = do_savepoint (parser, statement);
3183  break;
3184 
3185  case PT_UNION:
3186  case PT_DIFFERENCE:
3187  case PT_INTERSECTION:
3188  case PT_SELECT:
3189  error = do_select (parser, statement);
3190  break;
3191 
3192  case PT_TRUNCATE:
3193  error = do_truncate (parser, statement);
3194  break;
3195 
3196  case PT_DO:
3197  error = do_execute_do (parser, statement);
3198  break;
3199 
3200  case PT_UPDATE:
3201  error = do_check_update_trigger (parser, statement, do_update);
3202  break;
3203 
3204  case PT_MERGE:
3205  error = do_check_merge_trigger (parser, statement, do_merge);
3206  break;
3207 
3208  case PT_UPDATE_STATS:
3209  error = do_update_stats (parser, statement);
3210  break;
3211 
3212  case PT_GET_STATS:
3213  error = do_get_stats (parser, statement);
3214  break;
3215 
3216  case PT_METHOD_CALL:
3217  error = do_call_method (parser, statement);
3218  break;
3219 
3220  case PT_CREATE_TRIGGER:
3221  error = do_create_trigger (parser, statement);
3222  break;
3223 
3224  case PT_DROP_TRIGGER:
3225  error = do_drop_trigger (parser, statement);
3226  break;
3227 
3228  case PT_SET_TRIGGER:
3229  error = do_set_trigger (parser, statement);
3230  break;
3231 
3232  case PT_GET_TRIGGER:
3233  error = do_get_trigger (parser, statement);
3234  break;
3235 
3236  case PT_RENAME_TRIGGER:
3237  error = do_rename_trigger (parser, statement);
3238  break;
3239 
3240  case PT_ALTER_TRIGGER:
3241  error = do_alter_trigger (parser, statement);
3242  break;
3243 
3244  case PT_EXECUTE_TRIGGER:
3245  error = do_execute_trigger (parser, statement);
3246  break;
3247 
3248  case PT_REMOVE_TRIGGER:
3249  error = do_remove_trigger (parser, statement);
3250  break;
3251 
3252  case PT_CREATE_SERIAL:
3253  error = do_create_serial (parser, statement);
3254  break;
3255 
3256  case PT_ALTER_SERIAL:
3257  error = do_alter_serial (parser, statement);
3258  break;
3259 
3260  case PT_DROP_SERIAL:
3261  error = do_drop_serial (parser, statement);
3262  break;
3263 
3264  case PT_GET_OPT_LVL:
3265  error = do_get_optimization_param (parser, statement);
3266  break;
3267 
3268  case PT_SET_OPT_LVL:
3269  error = do_set_optimization_param (parser, statement);
3270  break;
3271 
3272  case PT_SET_SYS_PARAMS:
3273  error = do_set_sys_params (parser, statement);
3274  break;
3275 
3277  error = jsp_create_stored_procedure (parser, statement);
3278  break;
3279 
3281  error = jsp_alter_stored_procedure (parser, statement);
3282  break;
3283 
3285  error = jsp_drop_stored_procedure (parser, statement);
3286  break;
3287 
3288  case PT_SET_NAMES:
3289  error = do_set_names (parser, statement);
3290  break;
3291 
3292  case PT_QUERY_TRACE:
3293  error = do_set_query_trace (parser, statement);
3294  break;
3295 
3296  case PT_SET_TIMEZONE:
3297  error = do_set_timezone (parser, statement);
3298  break;
3299 
3300  default:
3302  break;
3303  }
3304 
3305  /* enable data replication log */
3306  if (need_stmt_replication)
3307  {
3308  int repl_error = NO_ERROR;
3309 
3310  /* before enable data replication log, we have to flush all dirty objects to server not to write redundant
3311  * data replication logs for DDLs */
3312  if (error >= 0)
3313  {
3314  repl_error = locator_all_flush ();
3315  }
3316 
3317  suppress_repl_error = db_set_suppress_repl_on_transaction (false);
3318 
3319  /* write schema replication log */
3320  if (error >= 0 && repl_error == NO_ERROR && suppress_repl_error == NO_ERROR)
3321  {
3322  repl_error = do_replicate_statement (parser, statement);
3323  }
3324 
3325  if (repl_error != NO_ERROR)
3326  {
3327  error = repl_error;
3328  }
3329  }
3330  }
3331 
3332 end:
3333  /* restore old read fetch instance version */
3334  db_set_read_fetch_instance_version (read_fetch_instance_version);
3335  /* There may be parse tree fragments that were collected during the execution of the statement that should be freed
3336  * now. */
3337  pt_free_orphans (parser);
3338 
3339  /* During query execution, if current transaction was rollbacked by the system, abort transaction on client side
3340  * also. */
3342  {
3344  }
3345 
3347  {
3348  (void) tran_abort_only_client (false);
3349  }
3350 
3352 
3353  if (error == ER_FAILED)
3354  {
3355  assert (er_errid () != NO_ERROR);
3356  error = er_errid ();
3357  if (error == NO_ERROR)
3358  {
3359  error = ER_GENERIC_ERROR;
3360  }
3361  }
3362  return error;
3363 }
3364 
3365 /*
3366  * do_prepare_statement() - Prepare a given statement for execution
3367  * return: Error code
3368  * parser(in): Parser context
3369  * statement(in): Parse tree of a statement
3370  *
3371  * Note:
3372  * PREPARE includes query optimization and plan generation (XASL) for the SQL
3373  * statement. EXECUTE means requesting the server to execute the given XASL.
3374  *
3375  * Some type of statement is not necessary or not able to do PREPARE stage.
3376  * They can or must be EXECUTEd directly without PREPARE. For those types of
3377  * statements, this function will return NO_ERROR.
3378  */
3379 int
3381 {
3382  int err = NO_ERROR;
3383 
3384  init_compile_context (parser);
3385 
3386  switch (statement->node_type)
3387  {
3388  case PT_DELETE:
3389  err = do_prepare_delete (parser, statement, NULL);
3390  break;
3391  case PT_INSERT:
3392  err = do_prepare_insert (parser, statement);
3393  break;
3394  case PT_UPDATE:
3395  err = do_prepare_update (parser, statement);
3396  break;
3397  case PT_MERGE:
3398  err = do_prepare_merge (parser, statement);
3399  break;
3400  case PT_SELECT:
3401  case PT_DIFFERENCE:
3402  case PT_INTERSECTION:
3403  case PT_UNION:
3404  err = do_prepare_select (parser, statement);
3405  break;
3406  case PT_EXECUTE_PREPARE:
3407  err = do_prepare_session_statement (parser, statement);
3408  break;
3409  default:
3410  /* there are no actions for other types of statements */
3411  break;
3412  }
3413 
3414  return ((err == ER_FAILED && (err = er_errid ()) == NO_ERROR) ? ER_GENERIC_ERROR : err);
3415 } /* do_prepare_statement() */
3416 
3417 /*
3418  * do_execute_statement() - Execute a prepared statement
3419  * return: Error code
3420  * parser(in): Parser context
3421  * statement(in): Parse tree of a statement
3422  *
3423  * Note:
3424  * The statement should be PREPAREd before to EXECUTE. But, some type of
3425  * statement will be EXECUTEd directly without PREPARE stage because we can
3426  * decide the fact that they should be executed using query plan (XASL)
3427  * at the time of execution stage.
3428  */
3429 int
3431 {
3432  int err = NO_ERROR;
3433  bool need_stmt_based_repl = false;
3434  int suppress_repl_error;
3435  LC_FETCH_VERSION_TYPE read_fetch_instance_version;
3436 
3437  assert (parser->query_id == NULL_QUERY_ID);
3438  /* save old read fetch instance version */
3439  read_fetch_instance_version = TM_TRAN_READ_FETCH_VERSION ();
3440 
3441  /* If it is an internally created statement, set its host variable info again to search host variables at parent
3442  * parser */
3444 
3445  /* skip ddl execution in case of parameter or opt. level */
3446  if (pt_is_ddl_statement (statement) != 0)
3447  {
3449  {
3450  const char *cp = statement->sql_user_text;
3451  if (cp == NULL)
3452  {
3453  cp = statement->alias_print;
3454  }
3455 
3456  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_BLOCK_DDL_STMT, 1, cp ? cp : "unknown");
3457  err = ER_BLOCK_DDL_STMT;
3458  goto end;
3459  }
3460 
3461  /* if QO_PARAM_LEVEL indicate no execution, just return */
3462  if (qo_need_skip_execution ())
3463  {
3464  err = NO_ERROR;
3465  goto end;
3466  }
3467  }
3468 
3469  /* for the subset of nodes which represent top level statements, process them; for any other node, return an error */
3470 
3471  /* disable data replication log for schema replication log types in HA mode */
3472  if (!HA_DISABLED () && is_stmt_based_repl_type (statement))
3473  {
3474  need_stmt_based_repl = true;
3475 
3476  /* since we are going to suppress writing replication logs, we need to flush all dirty objects to server not to
3477  * lose them */
3478  err = locator_all_flush ();
3479  if (err != NO_ERROR)
3480  {
3481  goto end;
3482  }
3483 
3484  suppress_repl_error = db_set_suppress_repl_on_transaction (true);
3485  if (suppress_repl_error != NO_ERROR)
3486  {
3487  goto end;
3488  }
3489  }
3490 
3491  switch (statement->node_type)
3492  {
3493  case PT_GET_TRIGGER:
3494  case PT_GET_XACTION:
3495  case PT_SAVEPOINT:
3496  case PT_PREPARE_TO_COMMIT:
3497  case PT_COMMIT_WORK:
3498  case PT_ROLLBACK_WORK:
3499  case PT_SCOPE:
3500  case PT_INSERT:
3501  case PT_SELECT:
3502  case PT_DIFFERENCE:
3503  case PT_INTERSECTION:
3504  case PT_UNION:
3505  case PT_EVALUATE:
3506  case PT_GET_STATS:
3507  case PT_GET_OPT_LVL:
3508  case PT_SET_OPT_LVL:
3509  case PT_SET_SYS_PARAMS:
3510  case PT_DO:
3511  case PT_EXECUTE_PREPARE:
3512  case PT_VACUUM:
3513  case PT_QUERY_TRACE:
3514  case PT_KILL_STMT:
3515 
3517  break;
3518 
3519  case PT_EXECUTE_TRIGGER:
3520  case PT_CREATE_ENTITY:
3521  case PT_CREATE_INDEX:
3522  case PT_CREATE_SERIAL:
3523  case PT_CREATE_TRIGGER:
3524  case PT_CREATE_USER:
3525  case PT_ALTER:
3526  case PT_ALTER_INDEX:
3527  case PT_ALTER_SERIAL:
3528  case PT_ALTER_TRIGGER:
3529  case PT_ALTER_USER:
3530  case PT_DROP:
3531  case PT_DROP_INDEX:
3532  case PT_DROP_SERIAL:
3533  case PT_DROP_TRIGGER:
3534  case PT_DROP_USER:
3535  case PT_DROP_VARIABLE:
3536  case PT_RENAME:
3537  case PT_RENAME_TRIGGER:
3538  case PT_SET_TRIGGER:
3539  case PT_REMOVE_TRIGGER:
3540  case PT_GRANT:
3541  case PT_REVOKE:
3542  case PT_2PC_ATTACH:
3543  case PT_SET_XACTION:
3544  case PT_DELETE:
3545  case PT_UPDATE:
3546  case PT_MERGE:
3547  case PT_METHOD_CALL:
3548  case PT_UPDATE_STATS:
3552  case PT_TRUNCATE:
3555  case PT_SET_NAMES:
3556  case PT_SET_TIMEZONE:
3557  /* Need to get dirty version when fetch the instance. That's because we are in an update command. */
3559  break;
3560 
3561  default:
3563  break;
3564  }
3565 
3566  switch (statement->node_type)
3567  {
3568  case PT_CREATE_ENTITY:
3569  /* err = do_create_entity(parser, statement); */
3570  /* execute internal statements before and after do_create_entity() */
3571  err = do_check_internal_statements (parser, statement,
3572  /* statement->info.create_entity. internal_stmts, */
3574  break;
3575  case PT_CREATE_INDEX:
3576  err = do_create_index (parser, statement);
3577  break;
3578  case PT_CREATE_SERIAL:
3579  err = do_create_serial (parser, statement);
3580  break;
3581  case PT_CREATE_TRIGGER:
3582  err = do_create_trigger (parser, statement);
3583  break;
3584  case PT_CREATE_USER:
3585  err = do_create_user (parser, statement);
3586  break;
3587  case PT_ALTER:
3588  /* err = do_alter(parser, statement); */
3589  /* execute internal statements before and after do_alter() */
3590  err = do_check_internal_statements (parser, statement,
3591  /* statement->info.alter. internal_stmts, */ do_alter);
3592  break;
3593  case PT_ALTER_INDEX:
3594  err = do_alter_index (parser, statement);
3595  break;
3596  case PT_ALTER_SERIAL:
3597  err = do_alter_serial (parser, statement);
3598  break;
3599  case PT_ALTER_TRIGGER:
3600  err = do_alter_trigger (parser, statement);
3601  break;
3602  case PT_ALTER_USER:
3603  err = do_alter_user (parser, statement);
3604  break;
3605  case PT_DROP:
3606  /* err = do_drop(parser, statement); */
3607  /* execute internal statements before and after do_drop() */
3608  err = do_check_internal_statements (parser, statement,
3609  /* statement->info.drop.internal_stmts, */
3610  do_drop);
3611  break;
3612  case PT_DROP_INDEX:
3613  err = do_drop_index (parser, statement);
3614  break;
3615  case PT_DROP_SERIAL:
3616  err = do_drop_serial (parser, statement);
3617  break;
3618  case PT_DROP_TRIGGER:
3619  err = do_drop_trigger (parser, statement);
3620  break;
3621  case PT_DROP_USER:
3622  err = do_drop_user (parser, statement);
3623  break;
3624  case PT_DROP_VARIABLE:
3625  err = do_drop_variable (parser, statement);
3626  break;
3627  case PT_RENAME:
3628  err = do_rename (parser, statement);
3629  break;
3630  case PT_RENAME_TRIGGER:
3631  err = do_rename_trigger (parser, statement);
3632  break;
3633  case PT_SET_TRIGGER:
3634  err = do_set_trigger (parser, statement);
3635  break;
3636  case PT_GET_TRIGGER:
3637  err = do_get_trigger (parser, statement);
3638  break;
3639  case PT_EXECUTE_TRIGGER:
3640  err = do_execute_trigger (parser, statement);
3641  break;
3642  case PT_REMOVE_TRIGGER:
3643  err = do_remove_trigger (parser, statement);
3644  break;
3645  case PT_GRANT:
3646  err = do_grant (parser, statement);
3647  break;
3648  case PT_REVOKE:
3649  err = do_revoke (parser, statement);
3650  break;
3651  case PT_2PC_ATTACH:
3652  err = do_attach (parser, statement);
3653  break;
3654  case PT_GET_XACTION:
3655  err = do_get_xaction (parser, statement);
3656  break;
3657  case PT_SET_XACTION:
3658  err = do_set_xaction (parser, statement);
3659  break;
3660  case PT_SAVEPOINT:
3661  err = do_savepoint (parser, statement);
3662  break;
3663  case PT_PREPARE_TO_COMMIT:
3664  err = do_prepare_to_commit (parser, statement);
3665  break;
3666  case PT_COMMIT_WORK:
3667  err = do_commit (parser, statement);
3668  break;
3669  case PT_ROLLBACK_WORK:
3670  err = do_rollback (parser, statement);
3671  break;
3672  case PT_SCOPE:
3673  err = do_scope (parser, statement);
3674  break;
3675  case PT_DELETE:
3676  err = do_check_delete_trigger (parser, statement, do_execute_delete);
3677  break;
3678  case PT_INSERT:
3679  err = do_check_insert_trigger (parser, statement, do_execute_insert);
3680  break;
3681  case PT_UPDATE:
3682  err = do_check_update_trigger (parser, statement, do_execute_update);
3683  break;
3684  case PT_MERGE:
3685  err = do_check_merge_trigger (parser, statement, do_execute_merge);
3686  break;
3687  case PT_SELECT:
3688  case PT_DIFFERENCE:
3689  case PT_INTERSECTION:
3690  case PT_UNION:
3691  err = do_execute_select (parser, statement);
3692  break;
3693  case PT_EVALUATE:
3694  err = do_evaluate (parser, statement);
3695  break;
3696  case PT_METHOD_CALL:
3697  err = do_call_method (parser, statement);
3698  break;
3699  case PT_GET_STATS:
3700  err = do_get_stats (parser, statement);
3701  break;
3702  case PT_UPDATE_STATS:
3703  err = do_update_stats (parser, statement);
3704  break;
3705  case PT_GET_OPT_LVL:
3706  err = do_get_optimization_param (parser, statement);
3707  break;
3708  case PT_SET_OPT_LVL:
3709  err = do_set_optimization_param (parser, statement);
3710  break;
3711  case PT_SET_SYS_PARAMS:
3712  err = do_set_sys_params (parser, statement);
3713  break;
3715  err = jsp_create_stored_procedure (parser, statement);
3716  break;
3718  err = jsp_alter_stored_procedure (parser, statement);
3719  break;
3721  err = jsp_drop_stored_procedure (parser, statement);
3722  break;
3723  case PT_TRUNCATE:
3724  err = do_truncate (parser, statement);
3725  break;
3726  case PT_DO:
3727  err = do_execute_do (parser, statement);
3728  break;
3729  case PT_EXECUTE_PREPARE:
3730  err = do_execute_session_statement (parser, statement);
3731  break;
3733  err = do_set_session_variables (parser, statement);
3734  break;
3736  err = do_drop_session_variables (parser, statement);
3737  break;
3738  case PT_SET_NAMES:
3739  err = do_set_names (parser, statement);
3740  break;
3741  case PT_VACUUM:
3742  err = do_vacuum (parser, statement);
3743  break;
3744  case PT_QUERY_TRACE:
3745  err = do_set_query_trace (parser, statement);
3746  break;
3747  case PT_KILL_STMT:
3748  err = do_kill (parser, statement);
3749  break;
3750  case PT_SET_TIMEZONE:
3751  err = do_set_timezone (parser, statement);
3752  break;
3753  default:
3755  break;
3756  }
3757 
3758  /* enable data replication log */
3759  if (need_stmt_based_repl)
3760  {
3761  int repl_error = NO_ERROR;
3762 
3763  /* before enable data replication log we have to flush all dirty objects to server not to write redundant data
3764  * replication logs for DDLs and SBR statements */
3765  if (err >= 0)
3766  {
3767  repl_error = locator_all_flush ();
3768  }
3769 
3770  suppress_repl_error = db_set_suppress_repl_on_transaction (false);
3771 
3772  /* write schema replication log */
3773  if (err >= 0 && repl_error == NO_ERROR && suppress_repl_error == NO_ERROR)
3774  {
3775  repl_error = do_replicate_statement (parser, statement);
3776  }
3777 
3778  if (repl_error != NO_ERROR)
3779  {
3780  err = repl_error;
3781  }
3782  }
3783 
3784 end:
3785 
3786  /* restore old read fetch instance version */
3787  db_set_read_fetch_instance_version (read_fetch_instance_version);
3788 
3789  /* There may be parse tree fragments that were collected during the execution of the statement that should be freed
3790  * now. */
3791  pt_free_orphans (parser);
3792 
3793  /* During query execution, if current transaction was rollbacked by the system, abort transaction on client side
3794  * also. */
3796  {
3798  }
3799 
3801  {
3802  (void) tran_abort_only_client (false);
3803  }
3804 
3806 
3807  return ((err == ER_FAILED && (err = er_errid ()) == NO_ERROR) ? ER_GENERIC_ERROR : err);
3808 } /* do_execute_statement() */
3809 
3810 #if defined(ENABLE_UNUSED_FUNCTION)
3811 /*
3812  * do_statements() - Execute a prepared statement
3813  * return: Error code
3814  * parser(in): Parser context
3815  * statement_list(in): Parse tree of a statement list
3816  *
3817  * Note: Side effects can exist at the statement list
3818  */
3819 int
3820 do_statements (PARSER_CONTEXT * parser, PT_NODE * statement_list)
3821 {
3822  int error = 0;
3823  PT_NODE *statement;
3824 
3825  /* for each of a list of statement nodes, process it. */
3826  for (statement = statement_list; statement != NULL; statement = statement->next)
3827  {
3828  do_Trigger_involved = false;
3829  error = do_statement (parser, statement);
3830  do_Trigger_involved = false;
3831  if (error)
3832  {
3833  break;
3834  }
3835  }
3836 
3837  return error;
3838 }
3839 #endif
3840 
3841 /*
3842  * do_check_internal_statements() -
3843  * return: Error code
3844  * parser(in): Parser context
3845  * statement_list(in): Parse tree of a statement
3846  * internal_stmt_list(in):
3847  * do_func(in):
3848  *
3849  * Note:
3850  * Do savepoint and execute statements before and after do_func()
3851  * if an error happens, rollback to the savepoint.
3852  */
3853 int
3855  /* PT_NODE * internal_stmt_list, */
3856  PT_DO_FUNC do_func)
3857 {
3858 #if 0 /* to disable TEXT */
3859  const char *savepoint_name = UNIQUE_SAVEPOINT_EXTERNAL_STATEMENT;
3860  int error = NO_ERROR, num_rows = NO_ERROR;
3861 
3862  if (internal_stmt_list == NULL)
3863  {
3864 #endif
3865  return do_func (parser, statement);
3866 #if 0 /* to disable TEXT */
3867  }
3868  else
3869  {
3870  error = tran_system_savepoint (savepoint_name);
3871  if (error != NO_ERROR)
3872  return error;
3873 
3874  error = do_internal_statements (parser, internal_stmt_list, 0);
3875  if (error >= NO_ERROR)
3876  {
3877  /* The main statement cas use out parameters from internal statements, and the internal statements generate
3878  * the parameters at execution time. So, it need to bind the parameters again */
3879  (void) parser_walk_tree (parser, statement, pt_bind_param_node, NULL, NULL, NULL);
3880  num_rows = error = do_func (parser, statement);
3881 #if defined(CUBRID_DEBUG)
3882  er_log_debug (ARG_FILE_LINE, "do_check_internal_statements : execute %s statement, %s\n", "main",
3883  parser_print_tree (parser, statement));
3884 #endif
3885  if (error >= NO_ERROR)
3886  {
3887  error = do_internal_statements (parser, internal_stmt_list, 1);
3888  }
3889  }
3890  if (error < NO_ERROR)
3891  {
3892  (void) tran_abort_upto_system_savepoint (savepoint_name);
3893  return error;
3894  }
3895  return num_rows;
3896  }
3897 #endif
3898 }
3899 
3900 #if defined(ENABLE_UNUSED_FUNCTION)
3901 /*
3902  * do_internal_statements() -
3903  * return: Error code
3904  * parser(in): Parser context
3905  * internal_stmt_list(in):
3906  * phase(in):
3907  *
3908  * Note:
3909  * For input statements, find the statements to do now and
3910  * using new parser, parse, check semantics and execute these.
3911  *
3912  */
3913 int
3914 do_internal_statements (PARSER_CONTEXT * parser, PT_NODE * internal_stmt_list, const int phase)
3915 {
3916  PT_NODE *stmt_str;
3917  DB_QUERY_RESULT *query_result;
3918  DB_QUERY_ERROR query_error;
3919  PARSER_CONTEXT *save_parser;
3920  DB_OBJECT *save_user;
3921  int au_save;
3922  int error = NO_ERROR;
3923 
3924  save_user = Au_user;
3925  Au_user = Au_dba_user;
3926  AU_DISABLE (au_save);
3927 
3928  for (stmt_str = internal_stmt_list; stmt_str != NULL; stmt_str = stmt_str->next)
3929  {
3930  if ((phase == 0 && stmt_str->etc == NULL) || (phase == 1 && stmt_str->etc != NULL))
3931  {
3932  /* To get host variable info from parent parser, set the parent parser */
3933  save_parser = parent_parser;
3935  error = db_compile_and_execute_local (stmt_str->info.value.text, &query_result, &query_error);
3936  /* restore the parent parser */
3937  parent_parser = save_parser;
3938  if (error < NO_ERROR)
3939  break;
3940  }
3941  }
3942 
3943  Au_user = save_user;
3944  AU_ENABLE (au_save);
3945 
3946  return error;
3947 }
3948 #endif
3949 
3950 /*
3951  * Function Group:
3952  * Parse tree to update statistics translation.
3953  *
3954  */
3955 
3956 typedef enum
3957 {
3960 #if 0
3961  CST_ATTR_MIN, CST_ATTR_MAX,
3962  CST_ATTR_NINDEXES, CST_BT_NLEAFS, CST_BT_HEIGHT,
3963 #endif
3965 } CST_ITEM_ENUM;
3966 
3967 typedef struct cst_item CST_ITEM;
3968 struct cst_item
3969 {
3971  const char *string;
3972  int att_id;
3973  int bt_idx;
3974 };
3975 
3977  {CST_NOBJECTS, "#objects", -1, -1},
3978  {CST_NPAGES, "#pages", -1, -1},
3979  {CST_NATTRIBUTES, "#attributes", -1, -1},
3980 #if 0
3981  {CST_ATTR_MIN, "min", 0, -1},
3982  {CST_ATTR_MAX, "max", 0, -1},
3983  {CST_ATTR_NINDEXES, "#indexes", 0, -1},
3984  {CST_BT_NLEAFS, "#leaf_pages", 0, 0},
3985  {CST_BT_NPAGES, "#index_pages", 0, 0},
3986  {CST_BT_HEIGHT, "index_height", 0, 0},
3987 #endif
3988  {CST_BT_NKEYS, "#keys", 0, 0},
3989  {CST_UNDEFINED, "", 0, 0}
3990 };
3991 
3992 static char *extract_att_name (const char *str);
3993 static int extract_bt_idx (const char *str);
3994 static int make_cst_item_value (DB_OBJECT * obj, const char *str, DB_VALUE * db_val);
3995 
3996 /*
3997  * do_update_stats() - Updates the statistics of a list of classes or ALL classes
3998  * return: Error code
3999  * parser(in): Parser context
4000  * statement(in/out): Parse tree of a update statistics statement
4001  */
4002 int
4003 do_update_stats (PARSER_CONTEXT * parser, PT_NODE * statement)
4004 {
4005  int error = NO_ERROR;
4006 
4008 
4009  if (statement->info.update_stats.all_classes > 0)
4010  {
4011  // ALL CLASSES
4013  {
4014  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_DBA_ONLY, 1, "update statistics on all classes");
4015  return ER_AU_DBA_ONLY;
4016  }
4017 
4020  return error;
4021  }
4022  else if (statement->info.update_stats.all_classes < 0)
4023  {
4024  // CATALOG CLASSES
4026  {
4027  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_DBA_ONLY, 1, "update statistics on catalog classes");
4028  return ER_AU_DBA_ONLY;
4029  }
4030 
4033  return error;
4034  }
4035  else
4036  {
4037  // CLASS LISTS
4038 
4039  PT_NODE *cls = NULL;
4040  DB_OBJECT *class_mop;
4041 
4042  // fetch classes and check authorization
4043  for (cls = statement->info.update_stats.class_list; cls != NULL && error == NO_ERROR; cls = cls->next)
4044  {
4045  class_mop = db_find_class (cls->info.name.original);
4046  if (class_mop != NULL)
4047  {
4048  cls->info.name.db_object = class_mop;
4049  pt_check_user_owns_class (parser, cls);
4050  }
4051  else
4052  {
4053  ASSERT_ERROR_AND_SET (error);
4054  return error;
4055  }
4056 
4057  error = au_check_authorization (class_mop, AU_ALTER);
4058  if (error != NO_ERROR)
4059  {
4060  // set an error since only warning was set.
4062  return error;
4063  }
4064  }
4065 
4066  // update stats
4067  for (cls = statement->info.update_stats.class_list; cls != NULL && error == NO_ERROR; cls = cls->next)
4068  {
4069  class_mop = cls->info.name.db_object;
4070 
4071  error = sm_update_statistics (class_mop, (statement->info.update_stats.with_fullscan
4073  }
4074 
4075  return error;
4076  }
4077 }
4078 
4079 /*
4080  * extract_att_name() -
4081  * return:
4082  * str(in):
4083  */
4084 static char *
4085 extract_att_name (const char *str)
4086 {
4087  char *s, *t, *att = NULL;
4088  int size;
4089 
4090  s = intl_mbs_chr (str, '(');
4091  if (s && *(++s))
4092  {
4093  t = intl_mbs_chr (s, ':');
4094  if (!t)
4095  {
4096  t = intl_mbs_chr (s, ')');
4097  }
4098  if (t && t != s)
4099  {
4100  size = CAST_STRLEN (t - s);
4101  att = (char *) malloc (size + 1);
4102  if (att)
4103  {
4104  if (intl_mbs_ncpy (att, s, size + 1) != NULL)
4105  {
4106  att[size] = '\0';
4107  }
4108  else
4109  {
4110  free_and_init (att);
4111  }
4112  }
4113  }
4114  }
4115  return att;
4116 }
4117 
4118 /*
4119  * extract_bt_idx() -
4120  * return:
4121  * str(in):
4122  */
4123 static int
4124 extract_bt_idx (const char *str)
4125 {
4126  char *s, *t;
4127  int idx = -1;
4128 
4129  t = intl_mbs_chr (str, '(');
4130  if (t && *(++t))
4131  {
4132  s = intl_mbs_chr (t, ':');
4133  if (s && s != t && *(++s))
4134  {
4135  t = intl_mbs_chr (s, ')');
4136  if (t && t != s)
4137  {
4138  idx = atoi (s);
4139  }
4140  }
4141  }
4142  return idx;
4143 }
4144 
4145 /*
4146  * make_cst_item_value() -
4147  * return: Error code
4148  * obj(in):
4149  * str(in):
4150  * db_val(in):
4151  */
4152 static int
4153 make_cst_item_value (DB_OBJECT * obj, const char *str, DB_VALUE * db_val)
4154 {
4155  CST_ITEM cst_item = { CST_UNDEFINED, "", -1, -1 };
4156  char *att_name = NULL;
4157  int bt_idx;
4158  CLASS_STATS *class_statsp = NULL;
4159  ATTR_STATS *attr_statsp = NULL;
4160  BTREE_STATS *bt_statsp = NULL;
4161  int i;
4162  int error;
4163 
4164  for (i = 0; i < (signed) DIM (cst_item_tbl); i++)
4165  {
4166  if (intl_mbs_ncasecmp (str, cst_item_tbl[i].string, strlen (cst_item_tbl[i].string)) == 0)
4167  {
4168  cst_item = cst_item_tbl[i];
4169  if (cst_item.att_id >= 0)
4170  {
4171  att_name = extract_att_name (str);
4172  if (att_name == NULL)
4173  {
4174  cst_item.item = CST_UNDEFINED;
4175  break;
4176  }
4177  cst_item.att_id = sm_att_id (obj, att_name);
4178  if (cst_item.att_id < 0)
4179  {
4180  cst_item.item = CST_UNDEFINED;
4181  break;
4182  }
4183  free_and_init (att_name);
4184  if (cst_item.bt_idx >= 0)
4185  {
4186  bt_idx = extract_bt_idx (str);
4187  if (bt_idx <= 0)
4188  {
4189  cst_item.item = CST_UNDEFINED;
4190  break;
4191  }
4192  cst_item.bt_idx = bt_idx;
4193  }
4194  }
4195  break;
4196  }
4197  }
4198  if (cst_item.item == CST_UNDEFINED)
4199  {
4200  db_make_null (db_val);
4201  error = ER_DO_UNDEFINED_CST_ITEM;
4203  return error;
4204  }
4205 
4206  class_statsp = sm_get_statistics_force (obj);
4207  if (class_statsp == NULL)
4208  {
4209  db_make_null (db_val);
4210 
4211  assert (er_errid () != NO_ERROR);
4212  return er_errid ();
4213  }
4214  if (cst_item.att_id >= 0)
4215  {
4216  for (i = 0; i < class_statsp->n_attrs; i++)
4217  {
4218  if (class_statsp->attr_stats[i].id == cst_item.att_id)
4219  {
4220  attr_statsp = &class_statsp->attr_stats[i];
4221  break;
4222  }
4223  }
4224  }
4225  if (attr_statsp && cst_item.bt_idx > 0 && cst_item.bt_idx <= attr_statsp->n_btstats)
4226  {
4227  for (i = 0; i < cst_item.bt_idx; i++)
4228  {
4229  ;
4230  }
4231  bt_statsp = &attr_statsp->bt_stats[i];
4232  }
4233 
4234  switch (cst_item.item)
4235  {
4236  case CST_NOBJECTS:
4237  db_make_int (db_val, class_statsp->heap_num_objects);
4238  break;
4239  case CST_NPAGES:
4240  db_make_int (db_val, class_statsp->heap_num_pages);
4241  break;
4242  case CST_NATTRIBUTES:
4243  db_make_int (db_val, class_statsp->n_attrs);
4244  break;
4245 #if 0
4246  case CST_ATTR_MIN:
4247  db_make_null (db_val); /* not support */
4248  break;
4249  case CST_ATTR_MAX:
4250  db_make_null (db_val); /* not support */
4251  break;
4252  case CST_ATTR_NINDEXES:
4253  if (!attr_statsp)
4254  {
4255  db_make_null (db_val);
4256  }
4257  else
4258  {
4259  db_make_int (db_val, attr_statsp->n_btstats);
4260  }
4261  break;
4262  case CST_BT_NLEAFS:
4263  if (!attr_statsp || !bt_statsp)
4264  {
4265  db_make_null (db_val);
4266  }
4267  else
4268  {
4269  db_make_int (db_val, bt_statsp->leafs);
4270  }
4271  break;
4272  case CST_BT_NPAGES:
4273  if (!attr_statsp || !bt_statsp)
4274  {
4275  db_make_null (db_val);
4276  }
4277  else
4278  {
4279  db_make_int (db_val, bt_statsp->pages);
4280  }
4281  break;
4282  case CST_BT_HEIGHT:
4283  if (!attr_statsp || !bt_statsp)
4284  {
4285  db_make_null (db_val);
4286  }
4287  else
4288  {
4289  db_make_int (db_val, bt_statsp->height);
4290  }
4291  break;
4292 #endif
4293  case CST_BT_NKEYS:
4294  if (!attr_statsp || !bt_statsp)
4295  {
4296  db_make_null (db_val);
4297  }
4298  else
4299  {
4300  db_make_int (db_val, bt_statsp->keys);
4301  }
4302  break;
4303  default:
4304  break;
4305  }
4306 
4307  return NO_ERROR;
4308 } /* make_cst_item_value() */
4309 
4310 /*
4311  * do_get_stats() -
4312  * return: Error code
4313  * parser(in): Parser context
4314  * statement(in/out): Parse tree of a get statistics statement
4315  */
4316 int
4317 do_get_stats (PARSER_CONTEXT * parser, PT_NODE * statement)
4318 {
4319  PT_NODE *cls, *arg, *into;
4320  DB_OBJECT *obj;
4321  DB_VALUE *ret_val, db_val;
4322  int error;
4323 
4324  db_make_null (&db_val);
4325 
4326  cls = statement->info.get_stats.class_;
4327  arg = statement->info.get_stats.args;
4328  into = statement->info.get_stats.into_var;
4329  if (!cls || !arg)
4330  {
4331  return ER_OBJ_INVALID_ARGUMENTS;
4332  }
4333 
4334  obj = db_find_class (cls->info.name.original);
4335  if (!obj)
4336  {
4337  return ER_OBJ_INVALID_ARGUMENTS;
4338  }
4339 
4340  cls->info.name.db_object = obj;
4341  (void) pt_check_user_owns_class (parser, cls);
4342 
4343  ret_val = db_value_create ();
4344  if (ret_val == NULL)
4345  {
4346  assert (er_errid () != NO_ERROR);
4347  return er_errid ();
4348  }
4349 
4350  pt_evaluate_tree (parser, arg, &db_val, 1);
4351  if (pt_has_error (parser) || DB_IS_NULL (&db_val))
4352  {
4353  return ER_OBJ_INVALID_ARGUMENTS;
4354  }
4355 
4356  error = make_cst_item_value (obj, db_get_string (&db_val), ret_val);
4357  pr_clear_value (&db_val);
4358  if (error != NO_ERROR)
4359  {
4360  return error;
4361  }
4362 
4363  statement->etc = (void *) ret_val;
4364 
4365  if (into && into->node_type == PT_NAME && into->info.name.original)
4366  {
4368  }
4369 
4370  return NO_ERROR;
4371 }
4372 
4373 
4374 /*
4375  * Function Group:
4376  * DO functions for transaction management
4377  *
4378  */
4379 
4380 static int map_iso_levels (PARSER_CONTEXT * parser, PT_NODE * statement, DB_TRAN_ISOLATION * tran_isolation,
4381  PT_NODE * node);
4382 static int set_iso_level (PARSER_CONTEXT * parser, DB_TRAN_ISOLATION * tran_isolation, bool * async_ws,
4383  PT_NODE * statement, const DB_VALUE * level);
4384 static int check_timeout_value (PARSER_CONTEXT * parser, PT_NODE * statement, DB_VALUE * val);
4385 static const char *get_savepoint_name_from_db_value (DB_VALUE * val);
4386 
4387 /*
4388  * do_attach() - Attaches to named (distributed 2pc) transaction
4389  * return: Error code if attach fails
4390  * parser(in): Parser context
4391  * statement(in): Parse tree of an attach statement
4392  *
4393  * Note:
4394  */
4395 int
4396 do_attach (PARSER_CONTEXT * parser, PT_NODE * statement)
4397 {
4398  if (!parser || pt_has_error (parser) || !statement || statement->node_type != PT_2PC_ATTACH)
4399  {
4400  return ER_GENERIC_ERROR;
4401  }
4402  else
4403  return db_2pc_attach_transaction (statement->info.attach.trans_id);
4404 }
4405 
4406 /*
4407  * do_prepare_to_commit() - Prepare to commit local participant of i
4408  * (distributed 2pc) transaction
4409  * return: Error code if prepare-to-commit fails
4410  * parser(in): Parser context
4411  * statement(in): Parse tree of a prepare-to-commit statement
4412  *
4413  * Note:
4414  */
4415 int
4417 {
4418  if (!parser || pt_has_error (parser) || !statement || statement->node_type != PT_PREPARE_TO_COMMIT)
4419  {
4420  return ER_GENERIC_ERROR;
4421  }
4422  else
4424 }
4425 
4426 /*
4427  * do_commit() - Commit a transaction
4428  * return: Error code
4429  * parser(in): Parser context
4430  * statement(in): Parse tree of a commit statement
4431  *
4432  * Note:
4433  */
4434 int
4435 do_commit (PARSER_CONTEXT * parser, PT_NODE * statement)
4436 {
4437  /* Row count should be reset to -1 for explicit commits (i.e: commit statements) but should not be reset in
4438  * AUTO_COMMIT mode. This is the best place to reset it for commit statements. */
4440  return tran_commit (statement->info.commit_work.retain_lock ? true : false);
4441 }
4442 
4443 /*
4444  * do_rollback() - Rollbacks a transaction
4445  * return: Error code
4446  * parser(in): Parser context
4447  * statement(in): Parse tree of a rollback statement (for regularity)
4448  *
4449  * Note: If a savepoint name is given, the transaction is rolled back to
4450  * the savepoint, otherwise the entire transaction is rolled back.
4451  */
4452 int
4453 do_rollback (PARSER_CONTEXT * parser, PT_NODE * statement)
4454 {
4455  int error = NO_ERROR;
4456  const char *save_name;
4457  PT_NODE *name;
4458  DB_VALUE val;
4459 
4460  db_make_null (&val);
4461 
4462  name = statement->info.rollback_work.save_name;
4463  if (name == NULL)
4464  {
4465  error = tran_abort ();
4466  }
4467  else
4468  {
4469  if (name->node_type == PT_NAME && name->info.name.meta_class != PT_PARAMETER)
4470  {
4471  save_name = name->info.name.original;
4472  error = db_abort_to_savepoint_internal (save_name);
4473  }
4474  else
4475  {
4476  pt_evaluate_tree (parser, name, &val, 1);
4477  if (pt_has_error (parser))
4478  {
4479  return ER_GENERIC_ERROR;
4480  }
4481  save_name = get_savepoint_name_from_db_value (&val);
4482  if (save_name == NULL)
4483  {
4484  assert (er_errid () != NO_ERROR);
4485  return er_errid ();
4486  }
4487  error = db_abort_to_savepoint_internal (save_name);
4488  db_value_clear (&val);
4489  }
4490  }
4491 
4492  return error;
4493 }
4494 
4495 /*
4496  * do_savepoint() - Creates a transaction savepoint
4497  * return: Error code if savepoint fails
4498  * parser(in): Parser context of a savepoint statement
4499  * statement(in): Parse tree of a rollback statement (for regularity)
4500  *
4501  * Note: If a savepoint name is given, the savepoint is created
4502  * with that name, if no savepoint name is given, we generate a unique one.
4503  */
4504 int
4505 do_savepoint (PARSER_CONTEXT * parser, PT_NODE * statement)
4506 {
4507  int error = NO_ERROR;
4508  const char *save_name;
4509  PT_NODE *name;
4510  DB_VALUE val;
4511 
4512  db_make_null (&val);
4513 
4514  name = statement->info.savepoint.save_name;
4515  if (name == NULL)
4516  {
4517  PT_INTERNAL_ERROR (parser, "transactions");
4518  }
4519  else
4520  {
4521  if (name->node_type == PT_NAME && name->info.name.meta_class != PT_PARAMETER)
4522  {
4523  save_name = name->info.name.original;
4524  error = db_savepoint_transaction_internal (save_name);
4525  }
4526  else
4527  {
4528  pt_evaluate_tree (parser, name, &val, 1);
4529  if (pt_has_error (parser))
4530  {
4531  return ER_GENERIC_ERROR;
4532  }
4533  save_name = get_savepoint_name_from_db_value (&val);
4534  if (save_name == NULL)
4535  {
4536  assert (er_errid () != NO_ERROR);
4537  return er_errid ();
4538  }
4539  error = db_savepoint_transaction_internal (save_name);
4540  db_value_clear (&val);
4541  }
4542  }
4543 
4544  return error;
4545 }
4546 
4547 /*
4548  * do_get_xaction() - Gets the isolation level and/or timeout value for
4549  * a transaction
4550  * return: Error code if it fails
4551  * parser(in): Parser context
4552  * statement(in/out): Parse tree of a get transaction statement
4553  *
4554  * Note:
4555  */
4556 int
4557 do_get_xaction (PARSER_CONTEXT * parser, PT_NODE * statement)
4558 {
4559  int lock_timeout_in_msecs = 0;
4560  DB_TRAN_ISOLATION tran_isolation = TRAN_UNKNOWN_ISOLATION;
4561  bool async_ws;
4562  int tran_num;
4563  const char *into_label;
4564  DB_VALUE *ins_val;
4565  PT_NODE *into_var;
4566  int error = NO_ERROR;
4567 
4568  (void) tran_get_tran_settings (&lock_timeout_in_msecs, &tran_isolation, &async_ws);
4569 
4570  /* create a DB_VALUE to hold the result */
4571  ins_val = db_value_create ();
4572  if (ins_val == NULL)
4573  {
4574  assert (er_errid () != NO_ERROR);
4575  return er_errid ();
4576  }
4577 
4578  db_make_int (ins_val, 0);
4579 
4580  switch (statement->info.get_xaction.option)
4581  {
4582  case PT_ISOLATION_LEVEL:
4583  tran_num = (int) tran_isolation;
4584  if (async_ws)
4585  {
4586  tran_num |= TRAN_ASYNC_WS_BIT;
4587  }
4588  db_make_int (ins_val, tran_num);
4589  break;
4590 
4591  case PT_LOCK_TIMEOUT:
4592  if (lock_timeout_in_msecs > 0)
4593  {
4594  db_make_float (ins_val, (float) lock_timeout_in_msecs / 1000);
4595  }
4596  else
4597  {
4598  db_make_float (ins_val, (float) lock_timeout_in_msecs);
4599  }
4600  break;
4601 
4602  default:
4603  break;
4604  }
4605 
4606  statement->etc = (void *) ins_val;
4607 
4608  into_var = statement->info.get_xaction.into_var;
4609  if (into_var != NULL && into_var->node_type == PT_NAME && (into_label = into_var->info.name.original) != NULL)
4610  {
4611  /*
4612  * create another DB_VALUE of the new instance for
4613  * the label_table
4614  */
4615  ins_val = db_value_create ();
4616  if (ins_val == NULL)
4617  {
4618  assert (er_errid () != NO_ERROR);
4619  return er_errid ();
4620  }
4621 
4622  db_make_int (ins_val, 0);
4623 
4624  switch (statement->info.get_xaction.option)
4625  {
4626  case PT_ISOLATION_LEVEL:
4627  tran_num = (int) tran_isolation;
4628  if (async_ws)
4629  {
4630  tran_num |= TRAN_ASYNC_WS_BIT;
4631  }
4632  db_make_int (ins_val, tran_num);
4633  break;
4634 
4635  case PT_LOCK_TIMEOUT:
4636  if (lock_timeout_in_msecs > 0)
4637  {
4638  db_make_float (ins_val, (float) (lock_timeout_in_msecs / 1000.0));
4639  }
4640  else
4641  {
4642  db_make_float (ins_val, (float) lock_timeout_in_msecs);
4643  }
4644  break;
4645 
4646  default:
4647  break;
4648  }
4649 
4650  /* enter {label, ins_val} pair into the label_table */
4651  error = pt_associate_label_with_value_check_reference (into_label, ins_val);
4652  }
4653 
4654  return error;
4655 }
4656 
4657 /*
4658  * do_set_xaction() - Sets the isolation level and/or timeout value for
4659  * a transaction
4660  * return: Error code if it fails
4661  * parser(in): Parser context
4662  * statement(in): Parse tree of a set transaction statement
4663  *
4664  * Note:
4665  */
4666 int
4667 do_set_xaction (PARSER_CONTEXT * parser, PT_NODE * statement)
4668 {
4669  DB_TRAN_ISOLATION tran_isolation;
4670  DB_VALUE val;
4671  PT_NODE *mode = statement->info.set_xaction.xaction_modes;
4672  int error = NO_ERROR;
4673  bool async_ws;
4674  float wait_secs;
4675 
4676  db_make_null (&val);
4677 
4678  while ((error == NO_ERROR) && (mode != NULL))
4679  {
4680  switch (mode->node_type)
4681  {
4682  case PT_ISOLATION_LVL:
4683  if (mode->info.isolation_lvl.level == NULL)
4684  {
4685  /* map schema/instance pair to level */
4686  error = map_iso_levels (parser, statement, &tran_isolation, mode);
4687  async_ws = mode->info.isolation_lvl.async_ws ? true : false;
4688  }
4689  else
4690  {
4691  pt_evaluate_tree (parser, mode->info.isolation_lvl.level, &val, 1);
4692 
4693  if (pt_has_error (parser))
4694  {
4695  return ER_GENERIC_ERROR;
4696  }
4697 
4698  if (DB_VALUE_TYPE (&val) != DB_TYPE_INTEGER)
4699  {
4701  return ER_GENERIC_ERROR;
4702  }
4703 
4704  error = set_iso_level (parser, &tran_isolation, &async_ws, statement, &val);
4705  }
4706 
4707  if (error == NO_ERROR)
4708  {
4709  error = tran_reset_isolation (tran_isolation, async_ws);
4710  }
4711  break;
4712  case PT_TIMEOUT:
4713  pt_evaluate_tree (parser, mode->info.timeout.val, &val, 1);
4714  if (pt_has_error (parser))
4715  {
4716  return ER_GENERIC_ERROR;
4717  }
4718 
4719  if (check_timeout_value (parser, statement, &val) != NO_ERROR)
4720  {
4721  return ER_GENERIC_ERROR;
4722  }
4723  else
4724  {
4725  wait_secs = db_get_float (&val);
4726  if (wait_secs > 0)
4727  {
4728  wait_secs *= 1000;
4729  }
4730  (void) tran_reset_wait_times ((int) wait_secs);
4731  }
4732  break;
4733  default:
4734  return ER_GENERIC_ERROR;
4735  }
4736 
4737  mode = mode->next;
4738  }
4739 
4740  return error;
4741 }
4742 
4743 /*
4744  * do_get_optimization_level() - Determine the current optimization and
4745  * return it through the statement parameter.
4746  * return: Error code if it fails
4747  * parser(in): Parser context
4748  * statement(in/out): Parse tree of a get transaction statement
4749  *
4750  * Note:
4751  */
4752 int
4754 {
4755  DB_VALUE *val;
4756  PT_NODE *into_var;
4757  const char *into_name;
4758  char *cost;
4759  int error = NO_ERROR;
4760 
4761  val = db_value_create ();
4762  if (val == NULL)
4763  {
4764  assert (er_errid () != NO_ERROR);
4765  return er_errid ();
4766  }
4767 
4768  switch (statement->info.get_opt_lvl.option)
4769  {
4770  case PT_OPT_LVL:
4771  {
4772  int i;
4774  db_make_int (val, i);
4775  break;
4776  }
4777  case PT_OPT_COST:
4778  {
4779  DB_VALUE plan;
4780 
4781  db_make_null (&plan);
4782 
4783  pt_evaluate_tree (parser, statement->info.get_opt_lvl.args, &plan, 1);
4784  if (pt_has_error (parser))
4785  {
4786  return ER_OBJ_INVALID_ARGUMENTS;
4787  }
4788 
4789  /* 'cost' is referenced by 'val', it should be allocated from heap, and will be freed when free 'val' if set
4790  * 'need_clear' to 'true' */
4791  cost = (char *) db_private_alloc (NULL, 2);
4792  if (cost == NULL)
4793  {
4794  return ER_OUT_OF_VIRTUAL_MEMORY;
4795  }
4796 
4798  pr_clear_value (&plan);
4799  db_make_string (val, cost);
4800  val->need_clear = true;
4801  }
4802  default:
4803  /*
4804  * Default ok; nothing else can get in here.
4805  */
4806  break;
4807  }
4808 
4809  statement->etc = (void *) val;
4810 
4811  into_var = statement->info.get_opt_lvl.into_var;
4812  if (into_var != NULL && into_var->node_type == PT_NAME && (into_name = into_var->info.name.original) != NULL)
4813  {
4815  }
4816 
4817  return error;
4818 }
4819 
4820 /*
4821  * do_set_optimization_param() - Set the optimization level to the indicated
4822  * value and return the old value through the
4823  * statement parameter.
4824  * return: Error code if it fails
4825  * parser(in): Parser context
4826  * statement(in): Parse tree of a set transaction statement
4827  *
4828  * Note:
4829  */
4830 int
4832 {
4833  PT_NODE *p1, *p2;
4834  DB_VALUE val1, val2;
4835  const char *plan, *cost;
4836 
4837  db_make_null (&val1);
4838  db_make_null (&val2);
4839 
4840  p1 = statement->info.set_opt_lvl.val;
4841 
4842  if (p1 == NULL)
4843  {
4844  er_set (ER_ERROR_SEVERITY, __FILE__, __LINE__, ER_OBJ_INVALID_ARGUMENTS, 0);
4845  return ER_OBJ_INVALID_ARGUMENTS;
4846  }
4847 
4848  pt_evaluate_tree (parser, p1, &val1, 1);
4849  if (pt_has_error (parser))
4850  {
4851  pr_clear_value (&val1);
4852  return NO_ERROR;
4853  }
4854 
4855  switch (statement->info.set_opt_lvl.option)
4856  {
4857  case PT_OPT_LVL:
4859  break;
4860  case PT_OPT_COST:
4861  plan = db_get_string (&val1);
4862  p2 = p1->next;
4863  pt_evaluate_tree (parser, p2, &val2, 1);
4864  if (pt_has_error (parser))
4865  {
4866  pr_clear_value (&val1);
4867  pr_clear_value (&val2);
4868  return ER_OBJ_INVALID_ARGUMENTS;
4869  }
4870  switch (DB_VALUE_TYPE (&val2))
4871  {
4872  case DB_TYPE_INTEGER:
4874  break;
4875  case DB_TYPE_CHAR:
4876  case DB_TYPE_NCHAR:
4877  case DB_TYPE_VARCHAR:
4878  case DB_TYPE_VARNCHAR:
4879  cost = db_get_string (&val2);
4880  qo_set_optimization_param (NULL, QO_PARAM_COST, plan, (int) cost[0]);
4881  break;
4882  default:
4883  er_set (ER_ERROR_SEVERITY, __FILE__, __LINE__, ER_OBJ_INVALID_ARGUMENTS, 0);
4884  pr_clear_value (&val1);
4885  pr_clear_value (&val2);
4886  return ER_OBJ_INVALID_ARGUMENTS;
4887  }
4888  break;
4889  default:
4890  /*
4891  * Default ok; no other options available.
4892  */
4893  break;
4894  }
4895 
4896  pr_clear_value (&val1);
4897  pr_clear_value (&val2);
4898  return NO_ERROR;
4899 }
4900 
4901 /*
4902  * do_set_sys_params() - Set the system parameters defined in 'cubrid.conf'.
4903  * return: Error code if it fails
4904  * parser(in): Parser context
4905  * statement(in): Parse tree of a set transaction statement
4906  *
4907  * Note:
4908  */
4909 int
4911 {
4912  PT_NODE *val;
4913  DB_VALUE db_val;
4914  int error = NO_ERROR;
4915 
4916  db_make_null (&db_val);
4917 
4918  val = statement->info.set_sys_params.val;
4919  if (val == NULL)
4920  {
4921  return ER_OBJ_INVALID_ARGUMENTS;
4922  }
4923 
4924  db_make_null (&db_val);
4925  while (val && error == NO_ERROR)
4926  {
4927  pt_evaluate_tree (parser, val, &db_val, 1);
4928 
4929  if (pt_has_error (parser))
4930  {
4931  error = ER_GENERIC_ERROR;
4932  }
4933  else
4934  {
4935  error = db_set_system_parameters (db_get_string (&db_val));
4936  }
4937 
4938  pr_clear_value (&db_val);
4939  val = val->next;
4940  }
4941 
4942  return error;
4943 }
4944 
4945 /*
4946  * map_iso_levels() - Maps the schema/instance isolation level to the
4947  * DB_TRAN_ISOLATION enumerated type.
4948  * return: Error code if it fails
4949  * parser(in): Parser context
4950  * tran_isolation(out):
4951  * node(in): Parse tree of a set transaction statement
4952  *
4953  * Note: Initializes isolation_levels array
4954  */
4955 static int
4956 map_iso_levels (PARSER_CONTEXT * parser, PT_NODE * statement, DB_TRAN_ISOLATION * tran_isolation, PT_NODE * node)
4957 {
4958  PT_MISC_TYPE instances = node->info.isolation_lvl.instances;
4959  PT_MISC_TYPE schema = node->info.isolation_lvl.schema;
4960 
4961  switch (schema)
4962  {
4963  case PT_SERIALIZABLE:
4964  if (instances == PT_SERIALIZABLE)
4965  {
4966  *tran_isolation = TRAN_SERIALIZABLE;
4967  }
4968  else
4969  {
4971  pt_show_misc_type (schema), pt_show_misc_type (instances));
4972  return ER_GENERIC_ERROR;
4973  }
4974  break;
4975  case PT_REPEATABLE_READ:
4976  if (instances == PT_READ_COMMITTED)
4977  {
4978  *tran_isolation = TRAN_READ_COMMITTED;
4979  }
4980  else if (instances == PT_REPEATABLE_READ)
4981  {
4982  *tran_isolation = TRAN_REPEATABLE_READ;
4983  }
4984  else
4985  {
4987  pt_show_misc_type (schema), pt_show_misc_type (instances));
4988  return ER_GENERIC_ERROR;
4989  }
4990  break;
4991  case PT_READ_COMMITTED:
4992  if (instances == PT_READ_COMMITTED)
4993  {
4994  *tran_isolation = TRAN_READ_COMMITTED;
4995  }
4996  else
4997  {
4999  pt_show_misc_type (schema), pt_show_misc_type (instances));
5000  return ER_GENERIC_ERROR;
5001  }
5002  break;
5003  default:
5004  return ER_GENERIC_ERROR;
5005  }
5006 
5007  return NO_ERROR;
5008 }
5009 
5010 /*
5011  * set_iso_level() -
5012  * return: Error code if it fails
5013  * parser(in): Parser context
5014  * tran_isolation(out): Isolation level set as a side effect
5015  * async_ws(out):
5016  * statement(in): Parse tree of a set transaction statement
5017  * level(in):
5018  *
5019  * Note: Translates the user entered isolation level (1,2,3,4,5) into
5020  * the enumerated type.
5021  */
5022 static int
5023 set_iso_level (PARSER_CONTEXT * parser, DB_TRAN_ISOLATION * tran_isolation, bool * async_ws, PT_NODE * statement,
5024  const DB_VALUE * level)
5025 {
5026  int error = NO_ERROR;
5027  int isolvl = db_get_int (level) & 0x0F;
5028  *async_ws = (db_get_int (level) & 0xF0) ? true : false;
5029 
5030  /* translate to the enumerated type */
5031  switch (isolvl)
5032  {
5033  case TRAN_READ_COMMITTED:
5034  *tran_isolation = TRAN_READ_COMMITTED;
5035  fprintf (stdout,
5037  fprintf (stdout,
5039  break;
5040  case TRAN_REPEATABLE_READ:
5041  *tran_isolation = TRAN_REPEATABLE_READ;
5042  fprintf (stdout,
5044  fprintf (stdout,
5046  break;
5047  case TRAN_SERIALIZABLE:
5048  *tran_isolation = TRAN_SERIALIZABLE;
5049  fprintf (stdout,
5051  fprintf (stdout,
5053  break;
5054  case 0:
5055  if (*async_ws == true)
5056  { /* only async workspace is given */
5057  int dummy_lktimeout;
5058  bool dummy_aws;
5059  tran_get_tran_settings (&dummy_lktimeout, tran_isolation, &dummy_aws);
5060  break;
5061  }
5062  /* fall through */
5063  case 1: /* unsupported ones */
5064  case 2:
5065  case 3:
5066  default:
5068  error = ER_GENERIC_ERROR;
5069  }
5070 
5071  return error;
5072 }
5073 
5074 /*
5075  * check_timeout_value() -
5076  * return: Error code if it fails
5077  * parser(in): Parser context
5078  * statement(in):
5079  * val(in): DB_VALUE with the value to set
5080  *
5081  * Note: Checks the user entered isolation level. Valid values are:
5082  * -1 : Infinite
5083  * 0 : Don't wait
5084  * >0 : Wait this number of seconds
5085  */
5086 static int
5087 check_timeout_value (PARSER_CONTEXT * parser, PT_NODE * statement, DB_VALUE * val)
5088 {
5089  float timeout;
5090 
5092  {
5093  timeout = db_get_float (val);
5094  if ((timeout == -1) || (timeout >= 0))
5095  {
5096  return NO_ERROR;
5097  }
5098  }
5100  return ER_GENERIC_ERROR;
5101 }
5102 
5103 /*
5104  * get_savepoint_name_from_db_value() -
5105  * return: a NULL if the value doesn't properly describe the name
5106  * of a savepoint.
5107  * val(in):
5108  *
5109  * Note: Mutates the contents of val to hold a NULL terminated string
5110  * holding a valid savepoint name. If the value is already of
5111  * type string, a NULL termination will be assumed since the
5112  * name came from a parse tree.
5113  */
5114 const static char *
5116 {
5117  if (DB_VALUE_TYPE (val) != DB_TYPE_CHAR && DB_VALUE_TYPE (val) != DB_TYPE_VARCHAR
5119  {
5121  {
5122  return (char *) NULL;
5123  }
5124  }
5125 
5126  return db_get_string (val);
5127 }
5128 
5129 
5130 
5131 
5132 
5133 /*
5134  * Function Group:
5135  * DO functions for trigger management
5136  *
5137  */
5138 
5139 
5140 /* Value supplied in statement has an invalid type */
5141 #define ER_TR_INVALID_VALUE_TYPE ER_GENERIC_ERROR
5142 
5143 #define MAX_DOMAIN_NAME_SIZE 150
5144 
5145 /*
5146  * PARSE TREE MACROS
5147  *
5148  * arguments:
5149  * statement: parser node
5150  *
5151  * returns/side-effects: non-zero
5152  *
5153  * description:
5154  * These are used as shorthand for parse tree access.
5155  * Given a statement node, they test for certain characteristics
5156  * and return a boolean.
5157  */
5158 
5159 #define IS_REJECT_ACTION_STATEMENT(statement) \
5160  ((statement)->node_type == PT_TRIGGER_ACTION \
5161  && (statement)->info.trigger_action.action_type == PT_REJECT)
5162 
5163 #define IS_INVALIDATE_ACTION_STATEMENT(statement) \
5164  ((statement)->node_type == PT_TRIGGER_ACTION \
5165  && (statement)->info.trigger_action.action_type == PT_INVALIDATE_XACTION)
5166 
5167 #define IS_PRINT_ACTION_STATEMENT(statement) \
5168  ((statement)->node_type == PT_TRIGGER_ACTION \
5169  && (statement)->info.trigger_action.action_type == PT_PRINT)
5170 
5171 #define PT_NODE_TR_NAME(node) \
5172  ((node)->info.create_trigger.trigger_name->info.name.original)
5173 #define PT_NODE_TR_STATUS(node) \
5174  (convert_misc_to_tr_status((node)->info.create_trigger.trigger_status))
5175 #define PT_NODE_TR_PRI(node) \
5176  ((node)->info.create_trigger.trigger_priority)
5177 #define PT_NODE_TR_EVENT_TYPE(node) \
5178  (convert_event_to_tr_event((node)->info.create_trigger.trigger_event->info.event_spec.event_type))
5179 
5180 #define PT_NODE_TR_TARGET(node) \
5181  ((node)->info.create_trigger.trigger_event->info.event_spec.event_target)
5182 #define PT_TR_TARGET_CLASS(target) \
5183  ((target)->info.event_target.class_name->info.name.original)
5184 #define PT_TR_TARGET_ATTR(target) \
5185  ((target)->info.event_target.attribute)
5186 #define PT_TR_ATTR_NAME(attr) \
5187  ((attr)->info.name.original)
5188 
5189 #define PT_NODE_COND(node) \
5190  ((node)->info.create_trigger.trigger_condition)
5191 #define PT_NODE_COND_TIME(node) \
5192  (convert_misc_to_tr_time((node)->info.create_trigger.condition_time))
5193 
5194 #define PT_NODE_ACTION(node) \
5195  ((node)->info.create_trigger.trigger_action)
5196 #define PT_NODE_ACTION_TIME(node) \
5197  (convert_misc_to_tr_time((node)->info.create_trigger.action_time))
5198 
5199 #define PT_NODE_TR_REF(node) \
5200  ((node)->info.create_trigger.trigger_reference)
5201 #define PT_TR_REF_REFERENCE(ref) \
5202  (&(ref)->info.event_object)
5203 
5204 static int tr_savepoint_number = 0;
5205 
5206 static int merge_mop_list_extension (DB_OBJLIST * new_objlist, DB_OBJLIST ** list);
5210 static int convert_speclist_to_objlist (DB_OBJLIST ** triglist, PT_NODE * specnode);
5211 static int check_trigger (DB_TRIGGER_EVENT event, PT_DO_FUNC * do_func, PARSER_CONTEXT * parser, PT_NODE * statement);
5212 static int check_merge_trigger (PT_DO_FUNC * do_func, PARSER_CONTEXT * parser, PT_NODE * statement);
5213 static char **find_update_columns (int *count_ptr, PT_NODE * statement);
5214 static void get_activity_info (PARSER_CONTEXT * parser, DB_TRIGGER_ACTION * type, const char **source,
5215  PT_NODE * statement);
5216 
5217 /*
5218  * merge_mop_list_extension() -
5219  * return: Number of MOPs to be added
5220  * new(in):
5221  * list(in):
5222  *
5223  * Note:
5224  */
5225 static int
5227 {
5228  DB_OBJLIST *obj, *next;
5229  int added = 0;
5230 
5231  for (obj = new_objlist, next = NULL; obj != NULL; obj = next)
5232  {
5233  next = obj->next;
5234  if (ml_find (*list, obj->op))
5235  {
5236  obj->next = NULL;
5237  ml_ext_free (obj);
5238  }
5239  else
5240  {
5241  obj->next = *list;
5242  *list = obj;
5243  added++;
5244  }
5245  }
5246 
5247  return added;
5248 }
5249 
5250 /*
5251  * These translate parse tree things into corresponding trigger things.
5252  */
5253 
5254 /*
5255  * convert_event_to_tr_event() - Converts a PT_EV type into the corresponding
5256  * TR_EVENT_ type.
5257  * return: DB_TRIGER_EVENT
5258  * ev(in): One of PT_EVENT_TYPE
5259  *
5260  * Note:
5261  */
5262 static DB_TRIGGER_EVENT
5264 {
5266 
5267  switch (ev)
5268  {
5269  case PT_EV_INSERT:
5270  event = TR_EVENT_INSERT;
5271  break;
5272  case PT_EV_STMT_INSERT:
5273  event = TR_EVENT_STATEMENT_INSERT;
5274  break;
5275  case PT_EV_DELETE:
5276  event = TR_EVENT_DELETE;
5277  break;
5278  case PT_EV_STMT_DELETE:
5279  event = TR_EVENT_STATEMENT_DELETE;
5280  break;
5281  case PT_EV_UPDATE:
5282  event = TR_EVENT_UPDATE;
5283  break;
5284  case PT_EV_STMT_UPDATE:
5285  event = TR_EVENT_STATEMENT_UPDATE;
5286  break;
5287  case PT_EV_ALTER:
5288  event = TR_EVENT_ALTER;
5289  break;
5290  case PT_EV_DROP:
5291  event = TR_EVENT_DROP;
5292  break;
5293  case PT_EV_COMMIT:
5294  event = TR_EVENT_COMMIT;
5295  break;
5296  case PT_EV_ROLLBACK:
5297  event = TR_EVENT_ROLLBACK;
5298  break;
5299  case PT_EV_ABORT:
5300  event = TR_EVENT_ABORT;
5301  break;
5302  case PT_EV_TIMEOUT:
5303  event = TR_EVENT_TIMEOUT;
5304  break;
5305  default:
5306  break;
5307  }
5308 
5309  return event;
5310 }
5311 
5312 /*
5313  * convert_misc_to_tr_time() - Converts a PT_MISC_TYPE into a corresponding
5314  * TR_TYPE_TYPE constant.
5315  * return: DB_TRIGGER_TIME
5316  * pt_time(in): One of PT_MISC_TYPE
5317  *
5318  * Note:
5319  */
5320 static DB_TRIGGER_TIME
5322 {
5323  DB_TRIGGER_TIME time;
5324 
5325  switch (pt_time)
5326  {
5327  case PT_AFTER:
5328  time = TR_TIME_AFTER;
5329  break;
5330  case PT_BEFORE:
5331  time = TR_TIME_BEFORE;
5332  break;
5333  case PT_DEFERRED:
5334  time = TR_TIME_DEFERRED;
5335  break;
5336  default:
5337  time = TR_TIME_NULL;
5338  break;
5339  }
5340 
5341  return time;
5342 }
5343 
5344 /*
5345  * convert_misc_to_tr_status() - Converts a PT_MISC_TYPE into the corresponding
5346  * TR_STATUE_TYPE.
5347  * return: DB_TRIGGER_STATUS
5348  * pt_status(in): One of PT_MISC_TYPE
5349  *
5350  * Note:
5351  */
5352 static DB_TRIGGER_STATUS
5354 {
5355  DB_TRIGGER_STATUS status;
5356 
5357  switch (pt_status)
5358  {
5359  case PT_ACTIVE:
5360  status = TR_STATUS_ACTIVE;
5361  break;
5362  case PT_INACTIVE:
5363  status = TR_STATUS_INACTIVE;
5364  break;
5365  default: /* if we get bogus input, should it be inactive ? */
5366  status = TR_STATUS_ACTIVE;
5367  break;
5368  }
5369 
5370  return status;
5371 }
5372 
5373 /*
5374  * convert_speclist_to_objlist() - Converts a PT_MISC_TYPE into the
5375  * corresponding TR_STATUE_TYPE.
5376  * return: Error code
5377  * triglist(out): Returned trigger object list
5378  * specnode(in): Node with PT_TRIGGER_SPEC_LIST_INFO
5379  *
5380  * Note:
5381  * This function converts a trigger specification list in PT format
5382  * into a list of the corresponding trigger objects.
5383  * This is used by a variety of the functions that accept trigger
5384  * specifications.
5385  * The list is an external MOP list and must be freed with ml_ext_free()
5386  * or db_objlist_free.
5387  * The alter flag is set for operations that alter triggers based
5388  * on the WITH EVENT and ALL TRIGGERS specification. In these cases
5389  * we need to automatically filter out the triggers in the list for
5390  * which we don't have authorization.
5391  */
5392 static int
5394 {
5395  int error = NO_ERROR;
5396  DB_OBJLIST *triggers, *etrigs;
5397  PT_NODE *names, *n, *events, *e;
5398  PT_EVENT_SPEC_INFO *espec;
5399  PT_EVENT_TARGET_INFO *target;
5400  const char *str, *attribute;
5401  DB_TRIGGER_EVENT tr_event;
5402  DB_OBJECT *trigger, *class_;
5403 
5404  triggers = NULL;
5405 
5406  if (specnode != NULL)
5407  {
5408  if (specnode->info.trigger_spec_list.all_triggers)
5409  {
5410  error = tr_find_all_triggers (&triggers);
5411  }
5412 
5413  else if ((names = specnode->info.trigger_spec_list.trigger_name_list) != NULL)
5414  {
5415  /* since this is an explicitly specified list, if we do not have alter authorization for any of the specified
5416  * triggers, we need to make sure the statement is not executed (no triggers are dropped). Use
5417  * tr_check_authorization to find out. */
5418  for (n = names; n != NULL && error == NO_ERROR; n = n->next)
5419  {
5420  str = n->info.name.original;
5421  trigger = tr_find_trigger (str);
5422  if (trigger == NULL)
5423  {
5424  assert (er_errid () != NO_ERROR);
5425  error = er_errid ();
5426  }
5427  else
5428  {
5429  error = ml_ext_add (&triggers, trigger, NULL);
5430  }
5431  }
5432  }
5433  else if ((events = specnode->info.trigger_spec_list.event_list) != NULL)
5434  {
5435  for (e = events; e != NULL && error == NO_ERROR; e = e->next)
5436  {
5437  class_ = NULL;
5438  attribute = NULL;
5439  espec = &(e->info.event_spec);
5440  tr_event = convert_event_to_tr_event (espec->event_type);
5441 
5442  if (espec->event_target != NULL)
5443  {
5444  target = &(espec->event_target->info.event_target);
5445  class_ = db_find_class (target->class_name->info.name.original);
5446  if (class_ == NULL)
5447  {
5448  assert (er_errid () != NO_ERROR);
5449  error = er_errid ();
5450  }
5451  else
5452  {
5453  if (target->attribute != NULL)
5454  {
5455  attribute = target->attribute->info.name.original;
5456  }
5457 
5458  error = tr_find_event_triggers (tr_event, class_, attribute, true, &etrigs);
5459  if (error == NO_ERROR)
5460  {
5461  merge_mop_list_extension (etrigs, &triggers);
5462  }
5463  }
5464  }
5465  }
5466  }
5467  }
5468 
5469  if (error)
5470  {
5471  ml_ext_free (triggers);
5472  }
5473  else
5474  {
5475  *triglist = triggers;
5476  }
5477 
5478  return error;
5479 }
5480 
5481 /*
5482  * get_priority() -
5483  * return: Double value
5484  * parser(in): Parser context
5485  * node(in): Priority value node
5486  *
5487  * Note:
5488  * Shorthand function for getting the priority value out of the parse
5489  * tree. Formerly, we just assumed that this would be represented
5490  * with a double value. Now we use coersion.
5491  */
5492 static double
5494 {
5495  DB_VALUE *src, value;
5496  double priority;
5497 
5498  priority = TR_LOWEST_PRIORITY;
5499 
5500  src = pt_value_to_db (parser, node);
5501  if (src != NULL && (tp_value_coerce (src, &value, &tp_Double_domain) == DOMAIN_COMPATIBLE))
5502  {
5503  priority = db_get_double (&value);
5504  }
5505  /* else, should be setting some kind of error */
5506 
5507  return priority;
5508 }
5509 
5510 /*
5511  * INSERT, UPDATE, & DELETE STATEMENTS
5512  */
5513 
5514 /*
5515  * check_trigger() -
5516  * return: Error code
5517  * event(in): Trigger event type
5518  * do_func(in): Function to do
5519  * parser(in): Parser context used by do_func
5520  * statement(in): Parse tree of a statement used by do_func
5521  *
5522  * Note: The function checks if there is any active trigger defined on
5523  * the targets. If there is one, raise the trigger. Otherwise,
5524  * perform the given do_ function.
5525  */
5526 static int
5527 check_trigger (DB_TRIGGER_EVENT event, PT_DO_FUNC * do_func, PARSER_CONTEXT * parser, PT_NODE * statement)
5528 {
5529  int err, result = NO_ERROR;
5530  TR_STATE *state;
5531  const char *savepoint_name = NULL;
5532  PT_NODE *node = NULL, *flat = NULL;
5533  DB_OBJECT *class_ = NULL;
5534 
5535  /* Prepare a trigger state for any triggers that must be raised in this statement */
5536 
5537  state = NULL;
5538 
5539  switch (event)
5540  {
5542  node = statement->info.delete_.spec;
5543  while (node != NULL)
5544  {
5545  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
5546  {
5547  flat = node->info.spec.flat_entity_list;
5548  class_ = (flat ? flat->info.name.db_object : NULL);
5549  if (class_ == NULL)
5550  {
5551  PT_INTERNAL_ERROR (parser, "invalid spec id");
5552  result = ER_FAILED;
5553  goto exit;
5554  }
5555  result = tr_prepare_statement (&state, event, class_, 0, NULL);
5556  if (result != NO_ERROR)
5557  {
5558  goto exit;
5559  }
5560  }
5561  node = node->next;
5562  }
5563  break;
5564 
5566  flat = (statement->info.insert.spec) ? statement->info.insert.spec->info.spec.flat_entity_list : NULL;
5567  class_ = (flat) ? flat->info.name.db_object : NULL;
5568  result = tr_prepare_statement (&state, event, class_, 0, NULL);
5569  break;
5570 
5572  {
5573  /* If this is an "update object" statement, we may not have a spec list yet. This may have been fixed due to
5574  * the recent changes in pt_exec_trigger_stmt to do name resolution each time. */
5575  char **columns = NULL;
5576  int count = pt_count_assignments (parser, statement->info.update.assignment);
5577  int idx;
5579  PT_NODE *assign = NULL;
5581 
5582  columns = (char **) (malloc (count * sizeof (char *)));
5583  if (columns == NULL)
5584  {
5585  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, count * sizeof (char *));
5586  result = ER_FAILED;
5587  goto exit;
5588  }
5589 
5590  /* prepare trigger state structures */
5591  node = statement->info.update.spec;
5592  do
5593  {
5594  /* flag is set to UPDATE to make sure triggers are checked for statement->info.update.object_parameter too */
5595  flag = PT_SPEC_FLAG_UPDATE;
5596 
5597  if (node != NULL)
5598  {
5599  flat = node->info.spec.flat_entity_list;
5600  flag = node->info.spec.flag;
5601  node = node->next;
5602  }
5603  else
5604  {
5605  flat = statement->info.update.object_parameter;
5606  }
5607 
5608  if (flag & PT_SPEC_FLAG_UPDATE)
5609  {
5610  idx = 0;
5611  pt_init_assignments_helper (parser, &ea, statement->info.update.assignment);
5612  while ((assign = pt_get_next_assignment (&ea)) != NULL)
5613  {
5614  if (assign->info.name.spec_id == flat->info.name.spec_id)
5615  {
5616  columns[idx++] = (char *) assign->info.name.original;
5617  }
5618  }
5619 
5620  class_ = flat ? flat->info.name.db_object : NULL;
5621  if (class_ == NULL)
5622  {
5623  PT_INTERNAL_ERROR (parser, "invalid spec id");
5624  result = ER_FAILED;
5625  goto exit;
5626  }
5627 
5628  result = tr_prepare_statement (&state, event, class_, idx, (const char **) columns);
5629  }
5630  }
5631  while (node);
5632  if (columns)
5633  {
5634  free_and_init (columns);
5635  }
5636  break;
5637  }
5638  default:
5639  break;
5640  }
5641 
5642  if (result == NO_ERROR)
5643  {
5644  if (state == NULL)
5645  {
5646  /* no triggers, just do it */
5647  /* result = do_func(parser, statement); */
5648  /* execute internal statements before and after do_func() */
5649  result = do_check_internal_statements (parser, statement, do_func);
5650  }
5651  else
5652  {
5653  /* the operations performed in 'tr_before', 'do_check_internal_statements' and 'tr_after' should be all
5654  * contained in one transaction */
5655  if (tr_Current_depth <= 1)
5656  {
5657  savepoint_name = mq_generate_name (parser, "UtrP", &tr_savepoint_number);
5658  if (savepoint_name == NULL)
5659  {
5660  result = ER_GENERIC_ERROR;
5661  goto exit;
5662  }
5663  result = tran_system_savepoint (savepoint_name);
5664  if (result != NO_ERROR)
5665  {
5666  goto exit;
5667  }
5668  }
5669 
5670  /* fire BEFORE STATEMENT triggers */
5671  result = tr_before (state);
5672  if (result == NO_ERROR)
5673  {
5674  /* note, do_insert, do_update, & do_delete don't return just errors, they can also return positive result
5675  * counts. Need to specifically check for result < 0 */
5676  /* result = do_func(parser, statement); */
5677  /* execute internal statements before and after do_func() */
5678  result = do_check_internal_statements (parser, statement, do_func);
5679  if (result < NO_ERROR)
5680  {
5681  tr_abort (state);
5682  state = NULL; /* state was freed */
5683  }
5684  else
5685  {
5686  /* try to preserve the usual result value */
5687  err = tr_after (state);
5688  if (err)
5689  {
5690  result = err;
5691  }
5692  if (tr_get_execution_state ())
5693  {
5694  state = NULL; /* state was freed */
5695  }
5696 
5697  }
5698  }
5699  else
5700  {
5701  state = NULL;
5702  }
5703  }
5704  }
5705 
5706 exit:
5707  if (state)
5708  {
5709  /* We need to free state and decrease the tr_Current_depth. */
5710  tr_abort (state);
5711  }
5712 
5713  if (result < NO_ERROR && savepoint_name != NULL && (result != ER_LK_UNILATERALLY_ABORTED))
5714  {
5715  /* savepoint from tran_savepoint() */
5716  (void) tran_abort_upto_system_savepoint (savepoint_name);
5717  }
5718  return result;
5719 }
5720 
5721 /*
5722  * do_check_for_empty_classes_in_delete() - check empty tables
5723  * return: Error code, NO_ERROR or 1 if there is at least one empty class
5724  * parser(in): Parser context
5725  * statement(in): Delete statement
5726  *
5727  * Note: The function checks if the original join, which was splitted, would
5728  * have returned 0 elements. If so then the original DELETE statement
5729  * would have deleted no records. After split this behaviour will change.
5730  * So we check that there is at least one splitted table with no records.
5731  * For compatibility reasons we must preserve the behaviour of the
5732  * original DELETE statement.
5733  */
5734 static int
5736 {
5737  int error = NO_ERROR, num_classes = 0, idx, partition_type = 0;
5738  PT_NODE *node = statement->info.delete_.del_stmt_list, *flat = NULL;
5739  char **classes_names = NULL;
5740  LOCK *locks = NULL;
5741  int *need_subclasses = NULL, au_save = 0;
5742  MOP *partitions = NULL;
5743  HFID *hfid = NULL;
5744  bool has_rows = false;
5745  LC_PREFETCH_FLAGS *flags = NULL;
5746 
5747  /* count the number of new DELETE statements */
5748  while (node != NULL)
5749  {
5750  num_classes++;
5751  node = node->next;
5752  }
5753 
5754  /* allocate classes_names array */
5755  classes_names = (char **) db_private_alloc (NULL, num_classes * sizeof (char *));
5756  if (classes_names == NULL)
5757  {
5758  error = ER_OUT_OF_VIRTUAL_MEMORY;
5759  goto cleanup;
5760  }
5761 
5762  /* allocate locks array */
5763  locks = (LOCK *) db_private_alloc (NULL, num_classes * sizeof (LOCK));
5764  if (locks == NULL)
5765  {
5766  error = ER_OUT_OF_VIRTUAL_MEMORY;
5767  goto cleanup;
5768  }
5769 
5770  /* allocate need_subclasses array */
5771  need_subclasses = (int *) db_private_alloc (NULL, num_classes * sizeof (int));
5772  if (need_subclasses == NULL)
5773  {
5774  error = ER_OUT_OF_VIRTUAL_MEMORY;
5775  goto cleanup;
5776  }
5777 
5778  flags = (LC_PREFETCH_FLAGS *) db_private_alloc (NULL, num_classes * sizeof (LC_PREFETCH_FLAGS));
5779  if (flags == NULL)
5780  {
5781  error = ER_OUT_OF_VIRTUAL_MEMORY;
5782  goto cleanup;
5783  }
5784 
5785  /* prepare information for locking */
5786  node = statement->info.delete_.del_stmt_list;
5787  for (idx = 0; idx < num_classes && node != NULL; idx++, node = node->next)
5788  {
5789  if (node->info.delete_.spec == NULL || node->info.delete_.spec->info.spec.entity_name == NULL
5790  || node->info.delete_.spec->info.spec.entity_name->info.name.original == NULL)
5791  {
5792  error = ER_GENERIC_ERROR;
5793  goto cleanup;
5794  }
5795  classes_names[idx] = (char *) node->info.delete_.spec->info.spec.entity_name->info.name.original;
5796  locks[idx] = X_LOCK;
5797  if (node->info.delete_.spec->info.spec.only_all == PT_ALL)
5798  {
5799  need_subclasses[idx] = true;
5800  }
5801  else
5802  {
5803  need_subclasses[idx] = false;
5804  }
5805  flags[idx] = LC_PREF_FLAG_LOCK;
5806  }
5807 
5808  /* lock splitted classes with X_LOCK */
5809  if (locator_lockhint_classes (num_classes, (const char **) classes_names, locks, need_subclasses, flags, 1, NULL_LOCK)
5810  != LC_CLASSNAME_EXIST)
5811  {
5812  assert (er_errid () != NO_ERROR);
5813  error = er_errid ();
5814  goto cleanup;
5815  }
5816 
5817  AU_DISABLE (au_save);
5818  /* Check if we have a splitted spec that has no records */
5819  for (node = statement->info.delete_.del_stmt_list; node != NULL; node = node->next)
5820  {
5821  flat = node->info.delete_.spec->info.spec.flat_entity_list;
5822  if (flat == NULL)
5823  {
5824  error = ER_GENERIC_ERROR;
5825  goto cleanup;
5826  }
5827 
5828  has_rows = false;
5829  /* we check subclasses and partitions including the class itself */
5830  do
5831  {
5832  error = locator_flush_all_instances (flat->info.name.db_object, DONT_DECACHE);
5833  if (error != NO_ERROR)
5834  {
5835  goto cleanup;
5836  }
5837 
5838  error = sm_partitioned_class_type (flat->info.name.db_object, &partition_type, NULL, &partitions);
5839  if (error != NO_ERROR)
5840  {
5841  goto cleanup;
5842  }
5843  if (partition_type == DB_PARTITIONED_CLASS && partitions != NULL)
5844  {
5845  for (idx = 0; partitions[idx] != NULL && !has_rows; idx++)
5846  {
5847  hfid = sm_get_ch_heap (partitions[idx]);
5848  if (hfid == NULL)
5849  {
5850  free_and_init (partitions);
5851  goto cleanup;
5852  }
5853  error = heap_has_instance (hfid, ws_oid (partitions[idx]), 1);
5854  if (error < NO_ERROR)
5855  {
5856  free_and_init (partitions);
5857  goto cleanup;
5858  }
5859  if (error > 0)
5860  {
5861  has_rows = true;
5862  }
5863  }
5864  }
5865  else
5866  {
5867  hfid = sm_get_ch_heap (flat->info.name.db_object);
5868  if (hfid == NULL)
5869  {
5870  goto cleanup;
5871  }
5872  error = heap_has_instance (hfid, ws_oid (flat->info.name.db_object), 1);
5873  if (error < NO_ERROR)
5874  {
5875  goto cleanup;
5876  }
5877  if (error > 0)
5878  {
5879  has_rows = true;
5880  }
5881  }
5882  if (partitions != NULL)
5883  {
5884  free_and_init (partitions);
5885  }
5886  flat = flat->next;
5887  }
5888  while (flat != NULL && !has_rows);
5889  if (!has_rows)
5890  {
5891  break;
5892  }
5893  }
5894 
5895  /* if we have a splitted class from wich all records will be deleted and it has no records then the join will have no
5896  * records so we can abort the deletion. */
5897  error = (node == NULL ? NO_ERROR : 1);
5898 
5899 cleanup:
5900 
5901  AU_ENABLE (au_save);
5902 
5903  /* free allocated resources */
5904  if (classes_names != NULL)
5905  {
5906  db_private_free (NULL, classes_names);
5907  }
5908 
5909  if (locks != NULL)
5910  {
5911  db_private_free (NULL, locks);
5912  }
5913 
5914  if (need_subclasses != NULL)
5915  {
5916  db_private_free (NULL, need_subclasses);
5917  }
5918 
5919  if (flags != NULL)
5920  {
5921  db_private_free (NULL, flags);
5922  }
5923 
5924  return error;
5925 }
5926 
5927 /*
5928  * do_check_delete_trigger() -
5929  * return: Error code
5930  * parser(in): Parser context
5931  * statement(in): Parse tree of a statement
5932  * do_func(in): Function to do
5933  *
5934  * Note: The function checks if there is any active trigger with event
5935  * TR_EVENT_STATEMENT_DELETE defined on the target.
5936  * If there is one, raise the trigger. Otherwise, perform the
5937  * given do_ function.
5938  */
5939 int
5940 do_check_delete_trigger (PARSER_CONTEXT * parser, PT_NODE * statement, PT_DO_FUNC * do_func)
5941 {
5942  PT_NODE *node = NULL;
5943  int affected_count, error = 0;
5944  PT_NODE *next = NULL;
5945 
5947  {
5949  return ER_BLOCK_NOWHERE_STMT;
5950  }
5951 
5952  if (statement->info.delete_.del_stmt_list != NULL)
5953  {
5954  error = do_check_for_empty_classes_in_delete (parser, statement);
5955  if (error < 0)
5956  {
5957  return error;
5958  }
5959  if (error > 0)
5960  {
5961  return 0;
5962  }
5963  }
5964 
5965  if (statement->flag.use_auto_commit)
5966  {
5967  /* No active trigger is involved. Avoid lock and fetch request. */
5968  error = do_func (parser, statement);
5969  }
5970  else
5971  {
5972  error = check_trigger (TR_EVENT_STATEMENT_DELETE, do_func, parser, statement);
5973  }
5974 
5975  /* if the statement that contains joins with conditions deletes no record then we skip the deletion in the subsequent
5976  * classes beacuse the original join would have deleted no record */
5977  if (error <= NO_ERROR)
5978  {
5979  return error;
5980  }
5981 
5982  affected_count = error;
5983 
5984  if (!statement->flag.use_auto_commit)
5985  {
5986  node = statement->info.delete_.del_stmt_list;
5987  while (node != NULL)
5988  {
5989  next = node->next;
5990  node->next = NULL;
5991  error = check_trigger (TR_EVENT_STATEMENT_DELETE, do_func, parser, node);
5992  node->next = next;
5993  if (error < NO_ERROR)
5994  {
5995  return error;
5996  }
5997  affected_count += error;
5998 
5999  node = node->next;
6000  }
6001  }
6002 
6003  return affected_count;
6004 }
6005 
6006 /*
6007  * do_check_insert_trigger() -
6008  * return: Error code
6009  * parser(in): Parser context
6010  * statement(in): Parse tree of a statement
6011  * do_func(in): Function to do
6012  *
6013  * Note: The function checks if there is any active trigger with event
6014  * TR_EVENT_STATEMENT_INSERT defined on the target.
6015  * If there is one, raise the trigger. Otherwise, perform the
6016  * given do_ function.
6017  */
6018 int
6019 do_check_insert_trigger (PARSER_CONTEXT * parser, PT_NODE * statement, PT_DO_FUNC * do_func)
6020 {
6021  if (statement->flag.use_auto_commit)
6022  {
6023  /* no active trigger is involved. Avoid lock and fetch request. */
6024  return do_func (parser, statement);
6025  }
6026  else
6027  {
6028  return check_trigger (TR_EVENT_STATEMENT_INSERT, do_func, parser, statement);
6029  }
6030 }
6031 
6032 /*
6033  * find_update_columns() -
6034  * return: Attribute (column) name array
6035  * count_ptr(out): Returned name count
6036  * statement(in): Parse tree of a statement to examine
6037  *
6038  * Note:
6039  * This is used to to find the attribute/column names referenced in
6040  * the statement. It builds a array of strings and returns the length of
6041  * the array.
6042  */
6043 static char **
6044 find_update_columns (int *count_ptr, PT_NODE * statement)
6045 {
6046  PT_NODE *assign;
6047  char **columns;
6048  int count, size, i;
6049  PT_NODE *lhs, *att;
6050 
6051  assign = statement->info.update.assignment;
6052  for (count = 0; assign; assign = assign->next)
6053  {
6054  lhs = assign->info.expr.arg1;
6055  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
6056  {
6057  /* multicolumn update */
6058  count += pt_length_of_list (lhs->info.expr.arg1);
6059  }
6060  else
6061  {
6062  count++;
6063  }
6064  }
6065  size = sizeof (char *) * count;
6066 
6067  columns = (char **) (malloc (size));
6068  if (columns == NULL)
6069  {
6070  return NULL;
6071  }
6072 
6073  assign = statement->info.update.assignment;
6074  for (i = 0; i < count; assign = assign->next)
6075  {
6076  lhs = assign->info.expr.arg1;
6077  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
6078  {
6079  for (att = lhs->info.expr.arg1; att; att = att->next)
6080  {
6081  columns[i++] = (char *) att->info.name.original;
6082  }
6083  }
6084  else
6085  {
6086  columns[i++] = (char *) lhs->info.name.original;
6087  }
6088  }
6089 
6090  *count_ptr = count;
6091  return columns;
6092 }
6093 
6094 /*
6095  * do_check_update_trigger() -
6096  * return: Error code
6097  * parser(in): Parser context
6098  * statement(in): Parse tree of a statement
6099  *
6100  * Note: The function checks if there is any active trigger with event
6101  * TR_EVENT_STATEMENT_UPDATE defined on the target.
6102  * If there is one, raise the trigger. Otherwise, perform the
6103  * given do_ function.
6104  */
6105 int
6106 do_check_update_trigger (PARSER_CONTEXT * parser, PT_NODE * statement, PT_DO_FUNC * do_func)
6107 {
6108  int err;
6109 
6111  {
6113  return ER_BLOCK_NOWHERE_STMT;
6114  }
6115 
6116  if (statement->flag.use_auto_commit)
6117  {
6118  /* no active trigger is involved. Avoid lock and fetch request. */
6119  err = do_func (parser, statement);
6120  }
6121  else
6122  {
6123  err = check_trigger (TR_EVENT_STATEMENT_UPDATE, do_func, parser, statement);
6124  }
6125 
6126  return err;
6127 }
6128 
6129 /*
6130  * CREATE TRIGGER STATEMENT
6131  */
6132 
6133 /*
6134  * get_activity_info() - Works for do_create_trigger
6135  * return: None
6136  * parser(in): Parse context for the create trigger statement
6137  * type(out): Returned type of the activity
6138  * source(out) : Returned source of the activity (sometimes NULL)
6139  * statement(in): Sub-tree for the condition or action expression
6140  *
6141  * Note:
6142  * This is used to convert a parser sub-tree into the corresponding
6143  * pair of DB_TRIGGER_ACTIVITY and source string suitable for use
6144  * with tr_create_trigger.
6145  * Since we can't use this parsed representation of the expressions
6146  * anyway (they aren't inside the proper scope), we just convert
6147  * them back into strings with parser_print_tree and let the trigger manager
6148  * call pt_compile_trigger_stmt when necessary.
6149  */
6150 static void
6151 get_activity_info (PARSER_CONTEXT * parser, DB_TRIGGER_ACTION * type, const char **source, PT_NODE * statement)
6152 {
6153  PT_NODE *str;
6154 
6155  *type = TR_ACT_NULL;
6156  *source = NULL;
6157 
6158  if (statement != NULL)
6159  {
6160  if (IS_REJECT_ACTION_STATEMENT (statement))
6161  {
6162  *type = TR_ACT_REJECT;
6163  }
6164  else if (IS_INVALIDATE_ACTION_STATEMENT (statement))
6165  {
6166  *type = TR_ACT_INVALIDATE;
6167  }
6168  else if (IS_PRINT_ACTION_STATEMENT (statement))
6169  {
6170  *type = TR_ACT_PRINT;
6171 
6172  /* extract the print string from the parser node, not sure if I should be looking at the "data_value.s" field
6173  * or the "text" field, they seem to be the same always. */
6174  str = statement->info.trigger_action.string;
6175  if (str->node_type == PT_VALUE)
6176  {
6177  *source = (char *) str->info.value.data_value.str->bytes;
6178  }
6179  }
6180  else
6181  {
6182  /* complex expression */
6183  *type = TR_ACT_EXPRESSION;
6184  *source = parser_print_tree_with_quotes (parser, statement);
6185  }
6186  }
6187 }
6188 
6189 /*
6190  * do_create_trigger() -
6191  * return: Error code
6192  * parser(in): Parse context
6193  * statement(in): Parse tree of a statement
6194  *
6195  * Note: The function creates a trigger object by calling the trigger
6196  * create function.
6197  */
6198 int
6200 {
6201  PT_NODE *cond, *action, *target, *attr, *pri, *comment_node;
6202  const char *name, *comment;
6203  DB_TRIGGER_STATUS status;
6204  double priority;
6205  DB_TRIGGER_EVENT event;
6206  DB_OBJECT *class_;
6207  const char *attribute;
6208  DB_TRIGGER_ACTION cond_type, action_type;
6209  DB_TRIGGER_TIME cond_time, action_time;
6210  const char *cond_source, *action_source;
6211  DB_OBJECT *trigger;
6212  SM_CLASS *smclass = NULL;
6213  int error = NO_ERROR;
6215 
6216  name = PT_NODE_TR_NAME (statement);
6217  status = PT_NODE_TR_STATUS (statement);
6218 
6219  comment_node = statement->info.create_trigger.comment;
6220  if (comment_node != NULL)
6221  {
6222  assert (comment_node->node_type == PT_VALUE);
6223  comment = (char *) comment_node->info.value.data_value.str->bytes;
6224  }
6225  else
6226  {
6227  comment = NULL;
6228  }
6229 
6230  pri = PT_NODE_TR_PRI (statement);
6231  if (pri != NULL)
6232  {
6233  priority = get_priority (parser, pri);
6234  }
6235  else
6236  {
6237  priority = TR_LOWEST_PRIORITY;
6238  }
6239 
6240  event = PT_NODE_TR_EVENT_TYPE (statement);
6241  class_ = NULL;
6242  attribute = NULL;
6243  target = PT_NODE_TR_TARGET (statement);
6244  if (target)
6245  {
6246  class_ = db_find_class (PT_TR_TARGET_CLASS (target));
6247  if (class_ == NULL)
6248  {
6249  assert (er_errid () != NO_ERROR);
6250  return er_errid ();
6251  }
6252 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
6253  if (sm_has_text_domain (db_get_attributes (class_), 1))
6254  {
6255  /* prevent to create a trigger at the class to contain TEXT */
6257  return er_errid ();
6258  }
6259 #endif /* ENABLE_UNUSED_FUNCTION */
6260  attr = PT_TR_TARGET_ATTR (target);
6261  if (attr)
6262  {
6263  attribute = PT_TR_ATTR_NAME (attr);
6264  }
6265  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
6266  if (error != NO_ERROR)
6267  {
6268  return error;
6269  }
6270  if (smclass->partition != NULL && smclass->users == NULL)
6271  {
6272  /* Triggers must be created on the partitioned table, not on a specific partition */
6275  }
6276  }
6277  cond = PT_NODE_COND (statement);
6278  cond_time = PT_NODE_COND_TIME (statement);
6279  /* note that cond_type can only be TR_ACT_EXPRESSION, if there is no conditino node, cond_source will be left NULL */
6280  get_activity_info (parser, &cond_type, &cond_source, cond);
6281 
6282  action = PT_NODE_ACTION (statement);
6283  action_time = PT_NODE_ACTION_TIME (statement);
6284  get_activity_info (parser, &action_type, &action_source, action);
6285 
6286  trigger =
6287  tr_create_trigger (name, status, priority, event, class_, attribute, cond_time, cond_source, action_time,
6288  action_type, action_source, comment);
6289 
6290  if (trigger == NULL)
6291  {
6292  assert (er_errid () != NO_ERROR);
6293  return er_errid ();
6294  }
6295 
6296  /* Save the new trigger object in the parse tree. Actually, we probably should also allow INTO variable sub-clause to
6297  * be compatible with INSERT statement. In that case, the portion of code in do_insert() for saving the new object and
6298  * creating a label table entry needs to be made a extern function. */
6299 
6300  /* This should be treated like a "create class" statement not like an "insert" statement. The trigger object that
6301  * gets created can't be assigned with an INTO clause so there's no need to return it. Assuming this doesn't host
6302  * anything, delete the commented out lines below. */
6303 #if 0
6304  if ((value = db_value_create ()) == NULL)
6305  {
6306  assert (er_errid () != NO_ERROR);
6307  return er_errid ();
6308  }
6309  db_make_object (value, trigger);
6310  statement->etc = (void *) value;
6311 #endif
6312 
6313  if (smclass != NULL && smclass->users != NULL && TM_TRAN_ISOLATION () < TRAN_REP_READ)
6314  {
6315  /* We have to flush the newly created trigger if the class it belongs to has subclasses. This is because the same
6316  * trigger is assigned to the whole hierarchy and we have to make sure it does not remain a temporary object when
6317  * it is first compiled. Since the class that this trigger belongs to might also be a temporary object, we
6318  * actually have to flush the whole workspace. No need to flush in isolation levels >= repeatable read since
6319  * already flushed in tr_create_trigger */
6320  error = locator_all_flush ();
6321  }
6322 
6323  return error;
6324 }
6325 
6326 /*
6327  * MISC TRIGGER OPERATIONS
6328  */
6329 
6330 /*
6331  * do_drop_trigger() - Drop one or more triggers based on a trigger spec list.
6332  * return: Error code
6333  * parser(in): Parse context
6334  * statement(in): Parse tree of a statement
6335  *
6336  * Note:
6337  */
6338 int
6339 do_drop_trigger (PARSER_CONTEXT * parser, PT_NODE * statement)
6340 {
6341  int error = NO_ERROR;
6342  PT_NODE *speclist;
6343  DB_OBJLIST *triggers, *t;
6344 
6346 
6347  /* The grammar has beem define such that DROP TRIGGER can only be used with an explicit list of named triggers.
6348  * Although convert_speclist_to_objlist will handle the WITH EVENT and ALL TRIGGERS cases we shouldn't see those
6349  * here. If for some reason they do sneak in, we may get errors when we call tr_drop_triggger() on triggers we don't
6350  * own. */
6351 
6352  speclist = statement->info.drop_trigger.trigger_spec_list;
6353  if (convert_speclist_to_objlist (&triggers, speclist))
6354  {
6355  assert (er_errid () != NO_ERROR);
6356  return er_errid ();
6357  }
6358 
6359  if (triggers != NULL)
6360  {
6361  /* make sure we have ALTER authorization on all the triggers before proceeding */
6362 
6363  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6364  {
6365  error = tr_check_authorization (t->op, true);
6366  }
6367 
6368  if (error == NO_ERROR)
6369  {
6370  /* shouldn't encounter errors in this loop, if we do, may have to abort the transaction */
6371  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6372  {
6373  error = tr_drop_trigger (t->op, false);
6374  if (error == ER_TR_TRIGGER_NOT_FOUND)
6375  {
6376  /* another transaction has drop the trigger before me */
6377  break;
6378  }
6379  }
6380  }
6381 
6382  /* always free this */
6383  ml_ext_free (triggers);
6384  }
6385 
6386  return error;
6387 }
6388 
6389 /*
6390  * do_alter_trigger() - Alter the priority or status of one or more triggers.
6391  * return: Error code
6392  * parser(in): Parse context
6393  * statement(in): Parse tree with alter trigger node
6394  *
6395  * Note:
6396  */
6397 int
6398 do_alter_trigger (PARSER_CONTEXT * parser, PT_NODE * statement)
6399 {
6400  int error = NO_ERROR;
6401  PT_NODE *speclist = NULL, *p_node = NULL, *comment_node = NULL;
6402  DB_OBJLIST *triggers = NULL, *t = NULL;
6403  double priority = TR_LOWEST_PRIORITY;
6404  DB_TRIGGER_STATUS status;
6405  PT_NODE *trigger_owner = NULL, *trigger_name = NULL;
6406  const char *trigger_owner_name = NULL, *trigger_comment = NULL;
6407  DB_VALUE returnval, trigger_name_val, user_val;
6408  bool has_trigger_comment = false;
6409  TR_TRIGGER *trigger = NULL;
6410  int count;
6411  bool has_savepoint = false;
6412 
6414 
6415  triggers = NULL;
6416  p_node = statement->info.alter_trigger.trigger_priority;
6417  trigger_owner = statement->info.alter_trigger.trigger_owner;
6418  speclist = statement->info.alter_trigger.trigger_spec_list;
6419  if (convert_speclist_to_objlist (&triggers, speclist))
6420  {
6421  assert (er_errid () != NO_ERROR);
6422  return er_errid ();
6423  }
6424 
6425  comment_node = statement->info.alter_trigger.comment;
6426  if (comment_node != NULL)
6427  {
6428  has_trigger_comment = true;
6429  assert (comment_node->node_type == PT_VALUE);
6430  trigger_comment = (char *) comment_node->info.value.data_value.str->bytes;
6431  }
6432 
6433  /* currently, we can' set the status and priority at the same time. The existance of p_node determines which type of
6434  * alter statement this is. */
6435  status = TR_STATUS_INVALID;
6436 
6437  if (trigger_owner != NULL)
6438  {
6439  trigger_owner_name = trigger_owner->info.name.original;
6440  trigger_name = speclist->info.trigger_spec_list.trigger_name_list;
6441  }
6442  else if (p_node != NULL)
6443  {
6444  priority = get_priority (parser, p_node);
6445  }
6446  else if (statement->info.alter_trigger.trigger_status == PT_ACTIVE
6447  || statement->info.alter_trigger.trigger_status == PT_INACTIVE)
6448  {
6450  }
6451  else
6452  {
6453  /* here, means user intends to alter comment only, which must exist */
6454  assert (has_trigger_comment);
6455  }
6456 
6457  if (error == NO_ERROR)
6458  {
6459  /* make sure we have ALTER authorization on all the triggers before proceeding */
6460  count = 0;
6461  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6462  {
6463  error = tr_check_authorization (t->op, true);
6464  count++;
6465  }
6466 
6467  if (error == NO_ERROR)
6468  {
6469  if (count > 0 || TM_TRAN_ISOLATION () >= TRAN_REP_READ)
6470  {
6471  /* need atomic operation */
6473  if (error != NO_ERROR)
6474  {
6475  goto cleanup;
6476  }
6477  has_savepoint = true;
6478  }
6479 
6480  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6481  {
6482  if (status != TR_STATUS_INVALID)
6483  {
6484  error = tr_set_status (t->op, status, false);
6485  if (error != NO_ERROR)
6486  {
6487  ASSERT_ERROR ();
6488  break;
6489  }
6490  }
6491 
6492  if (p_node != NULL)
6493  {
6494  error = tr_set_priority (t->op, priority, false);
6495  if (error != NO_ERROR)
6496  {
6497  ASSERT_ERROR ();
6498  break;
6499  }
6500  }
6501 
6502  if (trigger_owner != NULL)
6503  {
6504  assert (trigger_name != NULL);
6505 
6506  db_make_null (&returnval);
6507 
6508  db_make_string (&trigger_name_val, trigger_name->info.name.original);
6509  db_make_string (&user_val, trigger_owner_name);
6510 
6511  au_change_trigger_owner_method (t->op, &returnval, &trigger_name_val, &user_val);
6512 
6513  pr_clear_value (&trigger_name_val);
6514  pr_clear_value (&user_val);
6515 
6516  if (DB_VALUE_TYPE (&returnval) == DB_TYPE_ERROR)
6517  {
6518  error = db_get_error (&returnval);
6519  break;
6520  }
6521 
6522  trigger_name = trigger_name->next;
6523  }
6524 
6525  if (has_trigger_comment)
6526  {
6527  error = tr_set_comment (t->op, trigger_comment, false);
6528  if (error != NO_ERROR)
6529  {
6530  ASSERT_ERROR ();
6531  break;
6532  }
6533  }
6534 
6535  error = locator_flush_instance (t->op);
6536  if (error != NO_ERROR)
6537  {
6538  ASSERT_ERROR ();
6539  break;
6540  }
6541 
6542  /* If trigger is on a class, lock it (S_LOCK) to block concurrent DML statements. */
6543  trigger = tr_map_trigger (t->op, false);
6544  if (trigger->class_mop != NULL)
6545  {
6546  if (locator_fetch_class (trigger->class_mop, DB_FETCH_SCAN) == NULL)
6547  {
6548  ASSERT_ERROR_AND_SET (error);
6549  break;
6550  }
6551  }
6552  }
6553  }
6554  }
6555 
6556  if (has_savepoint && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
6557  {
6559  }
6560 
6561 cleanup:
6562  if (triggers != NULL)
6563  {
6564  ml_ext_free (triggers);
6565  }
6566 
6567  return error;
6568 }
6569 
6570 /*
6571  * do_execute_trigger() - Execute the deferred activities for one or more
6572  * triggers.
6573  * return: Error code
6574  * parser(in): Parse context
6575  * statement(in): Parse tree of a execute trigger statement
6576  *
6577  * Note:
6578  */
6579 int
6581 {
6582  int error = NO_ERROR;
6583  PT_NODE *speclist;
6584  DB_OBJLIST *triggers, *t;
6585 
6587 
6588  speclist = statement->info.execute_trigger.trigger_spec_list;
6589  error = convert_speclist_to_objlist (&triggers, speclist);
6590 
6591  if (error == NO_ERROR && triggers != NULL)
6592  {
6593  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6594  {
6595  error = tr_execute_deferred_activities (t->op, NULL);
6596  }
6597  ml_ext_free (triggers);
6598  }
6599 
6600  return error;
6601 }
6602 
6603 /*
6604  * do_remove_trigger() - Remove the deferred activities for one or more triggers
6605  * return: Error code
6606  * parser(in): Parse context
6607  * statement(in): Parse tree of a remove trigger statement
6608  *
6609  * Note:
6610  */
6611 int
6613 {
6614  int error = NO_ERROR;
6615  PT_NODE *speclist;
6616  DB_OBJLIST *triggers, *t;
6617 
6619 
6620  speclist = statement->info.remove_trigger.trigger_spec_list;
6621  error = convert_speclist_to_objlist (&triggers, speclist);
6622 
6623  if (error == NO_ERROR && triggers != NULL)
6624  {
6625  for (t = triggers; t != NULL && error == NO_ERROR; t = t->next)
6626  {
6627  error = tr_drop_deferred_activities (t->op, NULL);
6628  }
6629 
6630  ml_ext_free (triggers);
6631  }
6632 
6633  return error;
6634 }
6635 
6636 /*
6637  * do_rename_trigger() - Rename a trigger
6638  * return: Error code
6639  * parser(in): Parse context
6640  * statement(in): Parse tree of a rename trigger statement
6641  *
6642  * Note:
6643  */
6644 int
6646 {
6647  int error = NO_ERROR;
6648  const char *old_name, *new_name;
6649  DB_OBJECT *trigger;
6650 
6652 
6653  old_name = statement->info.rename_trigger.old_name->info.name.original;
6654  new_name = statement->info.rename_trigger.new_name->info.name.original;
6655 
6656  trigger = tr_find_trigger (old_name);
6657  if (trigger == NULL)
6658  {
6659  assert (er_errid () != NO_ERROR);
6660  error = er_errid ();
6661  }
6662  else
6663  {
6664  error = tr_rename_trigger (trigger, new_name, false);
6665  }
6666 
6667  return error;
6668 }
6669 
6670 /*
6671  * do_set_trigger() - Set one of the trigger options
6672  * return: Error code
6673  * parser(in): Parse context
6674  * statement(in): Parse tree of a set trigger statement
6675  *
6676  * Note:
6677  */
6678 int
6679 do_set_trigger (PARSER_CONTEXT * parser, PT_NODE * statement)
6680 {
6681  int error = NO_ERROR;
6682  DB_VALUE src, dst;
6683  TP_DOMAIN_STATUS dom_status;
6684 
6685  db_make_null (&src);
6686  db_make_null (&dst);
6687 
6688  pt_evaluate_tree (parser, statement->info.set_trigger.val, &src, 1);
6689  if (pt_has_error (parser))
6690  {
6691  pt_report_to_ersys (parser, PT_SEMANTIC);
6692  error = er_errid ();
6693  if (error == ER_TP_CANT_COERCE || error == ER_IT_DATA_OVERFLOW)
6694  {
6695  char buf1[MAX_DOMAIN_NAME_SIZE];
6696  char buf2[MAX_DOMAIN_NAME_SIZE];
6697  (void) tp_value_domain_name (&src, buf1, sizeof (buf1));
6698  (void) tp_domain_name (&tp_Integer_domain, buf2, sizeof (buf2));
6699  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, buf1, buf2);
6700  }
6701  }
6702  else
6703  {
6704  dom_status = tp_value_coerce (&src, &dst, &tp_Integer_domain);
6705  if (dom_status != DOMAIN_COMPATIBLE)
6706  {
6707  error = tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &src, &tp_Integer_domain);
6708  /* already set error */
6709  }
6710  }
6711 
6712  if (error == NO_ERROR)
6713  {
6715  int v;
6716 
6717  option = statement->info.set_trigger.option;
6718  v = db_get_int (&dst);
6719 
6720  if (option == PT_TRIGGER_TRACE)
6721  {
6722  error = tr_set_trace ((bool) v);
6723  }
6724  else if (option == PT_TRIGGER_DEPTH)
6725  {
6726  error = tr_set_depth (v);
6727  }
6728  }
6729 
6730  /*
6731  * No need to clear dst, because it's either NULL or an integer at
6732  * this point. src could be arbitrarily complex, and it was created
6733  * by pt_evaluate_tree, so we need to clear it before we leave.
6734  */
6735  db_value_clear (&src);
6736 
6737  return error;
6738 }
6739 
6740 /*
6741  * do_get_trigger() - Get one of the trigger option values.
6742  * return: Error code
6743  * parser(in): Parse context
6744  * statement(in/out): Parse tree of a get trigger statement
6745  *
6746  * Note:
6747  */
6748 int
6749 do_get_trigger (PARSER_CONTEXT * parser, PT_NODE * statement)
6750 {
6751  int error = NO_ERROR;
6752  const char *into_label;
6753  DB_VALUE *ins_val;
6754  PT_NODE *into;
6756 
6757  /* create a value to hold the result */
6758  ins_val = db_value_create ();
6759  if (ins_val == NULL)
6760  {
6761  assert (er_errid () != NO_ERROR);
6762  return er_errid ();
6763  }
6764 
6765  option = statement->info.set_trigger.option;
6766  switch (option)
6767  {
6768  case PT_TRIGGER_DEPTH:
6769  db_make_int (ins_val, tr_get_depth ());
6770  break;
6771  case PT_TRIGGER_TRACE:
6772  db_make_int (ins_val, tr_get_trace ());
6773  break;
6774  default:
6775  db_make_null (ins_val); /* can't happen */
6776  break;
6777  }
6778 
6779  statement->etc = (void *) ins_val;
6780 
6781  into = statement->info.get_trigger.into_var;
6782  if (into != NULL && into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL)
6783  {
6784  /* create another DB_VALUE for the label table */
6785  ins_val = db_value_copy (ins_val);
6786 
6787  /* enter the value into the table */
6788  error = pt_associate_label_with_value_check_reference (into_label, ins_val);
6789  }
6790 
6791  return error;
6792 }
6793 
6794 
6795 
6796 
6797 
6798 
6799 
6800 /*
6801  * Function Group:
6802  * DO functions for update statements
6803  *
6804  */
6805 
6806 typedef enum
6808 
6809 #define DB_VALUE_STACK_MAX 40
6810 
6811 /* It is used to generate unique savepoint names */
6813 
6814 static void unlink_list (PT_NODE * list);
6815 
6816 static QFILE_LIST_ID *get_select_list_to_update (PARSER_CONTEXT * parser, PT_NODE * from, PT_NODE * column_names,
6817  PT_NODE * column_values, PT_NODE * with, PT_NODE * where,
6818  PT_NODE * order_by, PT_NODE * orderby_for, PT_NODE * using_index,
6819  PT_NODE * class_specs, PT_NODE * update_stmt);
6820 static int update_object_attribute (PARSER_CONTEXT * parser, DB_OTMPL * otemplate, PT_NODE * name,
6821  DB_ATTDESC * attr_desc, DB_VALUE * value);
6822 static int update_object_tuple (PARSER_CONTEXT * parser, CLIENT_UPDATE_INFO * assigns, int assigns_count,
6823  CLIENT_UPDATE_CLASS_INFO * upd_classes_info, int classes_cnt,
6824  const int turn_off_unique_check, const int turn_off_serializable_conflict_check,
6825  UPDATE_TYPE update_type, bool should_delete);
6826 static int update_object_by_oid (PARSER_CONTEXT * parser, PT_NODE * statement, UPDATE_TYPE update_type);
6827 static int init_update_data (PARSER_CONTEXT * parser, PT_NODE * statement, CLIENT_UPDATE_INFO ** assigns_data,
6828  int *assigns_count, CLIENT_UPDATE_CLASS_INFO ** cls_data, int *cls_count,
6829  DB_VALUE ** values, int *values_cnt, bool has_delete);
6830 static int do_set_pruning_type (PARSER_CONTEXT * parser, PT_NODE * spec, CLIENT_UPDATE_CLASS_INFO * cls);
6831 static int update_objs_for_list_file (PARSER_CONTEXT * parser, QFILE_LIST_ID * list_id, PT_NODE * statement,
6832  bool savepoint_started);
6833 static int update_class_attributes (PARSER_CONTEXT * parser, PT_NODE * statement);
6834 static int update_at_server (PARSER_CONTEXT * parser, PT_NODE * from, PT_NODE * statement, PT_NODE ** non_null_attrs,
6835  int has_uniques);
6836 static int update_check_for_constraints (PARSER_CONTEXT * parser, int *has_unique, PT_NODE ** not_nulls,
6837  const PT_NODE * statement);
6838 static bool update_check_having_meta_attr (PARSER_CONTEXT * parser, PT_NODE * assignment);
6839 static int update_real_class (PARSER_CONTEXT * parser, PT_NODE * statement, bool savepoint_started);
6840 static XASL_NODE *statement_to_update_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_attrs);
6841 static int is_server_update_allowed (PARSER_CONTEXT * parser, PT_NODE ** non_null_attrs, int *has_uniques,
6842  int *const server_allowed, const PT_NODE * statement);
6843 static int delete_object_tuple (DB_OBJECT * obj);
6844 static int has_unique_constraint (DB_OBJECT * mop);
6845 
6846 /*
6847  * unlink_list - Unlinks next pointer shortcut of lhs, rhs assignments
6848  * return: None
6849  * list(in): Node list to cut
6850  *
6851  * Note:
6852  */
6853 static void
6855 {
6856  PT_NODE *next;
6857 
6858  while (list)
6859  {
6860  next = list->next;
6861  list->next = NULL;
6862  list = next;
6863  }
6864 }
6865 
6866 /*
6867  * get_select_list_to_update -
6868  * return: List file if success, otherwise NULL
6869  * parser(in): Parser context
6870  * from(in): Parse tree of an FROM class
6871  * column_values(in): Column list in SELECT clause
6872  * with(in): WITH clause
6873  * where(in): WHERE clause
6874  * order_by(in): ORDER BY clause
6875  * orderby_num(in): converted from ORDER BY with LIMIT
6876  * using_index(in): USING INDEX clause
6877  * class_specs(in): Another class specs in FROM clause
6878  *
6879  * Note:
6880  */
6881 static QFILE_LIST_ID *
6882 get_select_list_to_update (PARSER_CONTEXT * parser, PT_NODE * from, PT_NODE * column_names, PT_NODE * column_values,
6883  PT_NODE * with, PT_NODE * where, PT_NODE * order_by, PT_NODE * orderby_for,
6884  PT_NODE * using_index, PT_NODE * class_specs, PT_NODE * update_stmt)
6885 {
6886  PT_NODE *statement = NULL;
6887  QFILE_LIST_ID *result = NULL;
6888  int err = NO_ERROR;
6889 
6890  assert (parser->query_id == NULL_QUERY_ID);
6891 
6892  if (from && (from->node_type == PT_SPEC) && from->info.spec.range_var
6893  && ((statement =
6894  pt_to_upd_del_query (parser, column_names, column_values, from, with, class_specs, where, using_index,
6895  order_by, orderby_for, 0 /* not server update */ , S_UPDATE)) != NULL))
6896  {
6897  err = pt_copy_upddel_hints_to_select (parser, update_stmt, statement);
6898  if (err != NO_ERROR)
6899  {
6900  parser_free_tree (parser, statement);
6901  return NULL;
6902  }
6903 
6904  /* If we are updating a proxy, the select is not yet fully translated. If we are updating anything else, this is
6905  * a no-op. */
6906  statement = mq_translate (parser, statement);
6907 
6908  if (statement)
6909  {
6910  /* This enables authorization checking during methods in queries */
6911  AU_ENABLE (parser->au_save);
6912 
6913  assert (parser->query_id == NULL_QUERY_ID);
6914  if (do_select_for_ins_upd (parser, statement) < NO_ERROR)
6915  {
6916  /* query failed, an error has already been set */
6917  statement = NULL;
6918  }
6919 
6920  AU_DISABLE (parser->au_save);
6921  }
6922  }
6923 
6924  if (statement)
6925  {
6926  result = (QFILE_LIST_ID *) statement->etc;
6927  parser_free_tree (parser, statement);
6928  }
6929 
6930  return result;
6931 }
6932 
6933 /*
6934  * update_object_attribute -
6935  * return: Error code
6936  * parser(in): Parser context
6937  * otemplate(in/out): Class template to be edited
6938  * name(in): Parse tree of a attribute name
6939  * attr_desc(in): Descriptor of attribute to update
6940  * value(in): New attribute value
6941  *
6942  * Note: If db_put fails, return an error
6943  */
6944 static int
6945 update_object_attribute (PARSER_CONTEXT * parser, DB_OTMPL * otemplate, PT_NODE * name, DB_ATTDESC * attr_desc,
6946  DB_VALUE * value)
6947 {
6948  int error = NO_ERROR;
6949 
6950  if (name->info.name.db_object)
6951  {
6952  error = db_is_vclass (name->info.name.db_object);
6953  if (error < 0)
6954  {
6955  return error;
6956  }
6957  if (error > 0)
6958  {
6959  /* this is a shared attribute of a view. this means this cannot be updated in the template for this real
6960  * class. Its simply done separately by a db_put. */
6961  error = obj_set_shared (name->info.name.db_object, name->info.name.original, value);
6962  return error;
6963  }
6964  }
6965 
6966  /* the normal case */
6967  error = dbt_dput_internal (otemplate, attr_desc, value);
6968 
6969  return error;
6970 }
6971 
6972 /*
6973  * update_object_tuple - Updates object attributes with db_values
6974  * return: Error code
6975  * assigns(in): array of assignments
6976  * assigns_count(in): no of assignments
6977  * upd_classes_info(in): array of classes info
6978  * classes_cnt(in): no of classes
6979  * turn_off_unique_check(in):
6980  * turn_off_serializable_conflict_check(in): true, if turn off SERIALIZABLE
6981  * conflict checking
6982  * update_type(in):
6983  * should_delete(in):
6984  *
6985  * Note:
6986  */
6987 static int
6988 update_object_tuple (PARSER_CONTEXT * parser, CLIENT_UPDATE_INFO * assigns, int assigns_count,
6989  CLIENT_UPDATE_CLASS_INFO * upd_classes_info, int classes_cnt, const int turn_off_unique_check,
6990  const int turn_off_serializable_conflict_check, UPDATE_TYPE update_type, bool should_delete)
6991 {
6992  int error = NO_ERROR;
6993  DB_OTMPL *otemplate = NULL;
6994  int idx = 0, upd_tpl_cnt = 0;
6995  DB_OBJECT *real_object = NULL, *object = NULL;
6996  SM_CLASS *smclass = NULL;
6997  CLIENT_UPDATE_INFO *assign = NULL;
6999  bool flush_del = false;
7000  MOP object_class_mop;
7001 
7002  for (idx = 0; idx < classes_cnt && error == NO_ERROR; idx++)
7003  {
7004  cls_info = &upd_classes_info[idx];
7005 
7006  if (DB_IS_NULL (cls_info->oid))
7007  {
7008  continue;
7009  }
7010 
7011  object = db_get_object (cls_info->oid);
7012  error = db_is_deleted (object);
7013  if (error < 0)
7014  {
7015  return error;
7016  }
7017  if (error > 0)
7018  {
7019  error = NO_ERROR;
7020  continue;
7021  }
7022 
7023  real_object = db_real_instance (object);
7024  if (real_object == NULL)
7025  { /* real_object's fail */
7026  assert (er_errid () != NO_ERROR);
7027  error = er_errid ();
7028  if (error == NO_ERROR)
7029  {
7030  error = ER_GENERIC_ERROR;
7031  }
7032  return error;
7033  }
7034 
7035  /* if this is the first tuple or the class has changed to a new subclass then fetch new class */
7036  object_class_mop = ws_class_mop (object);
7037  if (cls_info->class_mop == NULL
7038  || (object_class_mop != NULL && ws_mop_compare (object_class_mop, cls_info->class_mop) != 0))
7039  {
7040  cls_info->class_mop = object_class_mop;
7041 
7042  if (object_class_mop != NULL)
7043  {
7044  error = au_fetch_class (object_class_mop, &smclass, AU_FETCH_READ, AU_SELECT);
7045  if (error != NO_ERROR)
7046  {
7047  return error;
7048  }
7049  cls_info->smclass = smclass;
7050  }
7051  }
7052  else
7053  {
7054  /* otherwise use old class */
7055  smclass = cls_info->smclass;
7056  }
7057 
7058  otemplate = dbt_edit_object (real_object);
7059  if (otemplate == NULL)
7060  {
7061  assert (er_errid () != NO_ERROR);
7062  return er_errid ();
7063  }
7064 
7065  if (turn_off_unique_check)
7066  {
7067  obt_disable_unique_checking (otemplate);
7068  }
7069 
7070  if (turn_off_serializable_conflict_check)
7071  {
7073  }
7074 
7075  /* this is an update - force NOT NULL constraint check */
7076  otemplate->force_check_not_null = 1;
7077 
7078  otemplate->pruning_type = cls_info->pruning_type;
7079 
7080  /* If this update came from INSERT ON DUPLICATE KEY UPDATE, flush the object on updating it. */
7081  if (update_type == ON_DUPLICATE_KEY_UPDATE || otemplate->pruning_type != DB_NOT_PARTITIONED_CLASS)
7082  {
7083  obt_set_force_flush (otemplate);
7084  }
7085 
7086  /* iterate through class assignments and update template with new values */
7087  for (assign = cls_info->first_assign; assign != NULL && error == NO_ERROR; assign = assign->next)
7088  {
7089  /* if this is the first update, get the attribute descriptor */
7090  if (assign->attr_desc == NULL)
7091  {
7092  int is_vclass = 0;
7093 
7094  /* don't get descriptors for shared attrs of views */
7095  if (assign->upd_col_name->info.name.db_object != NULL)
7096  {
7097  is_vclass = db_is_vclass (assign->upd_col_name->info.name.db_object);
7098 
7099  if (is_vclass < 0)
7100  {
7101  error = is_vclass;
7102  }
7103  }
7104  if (!is_vclass)
7105  {
7106  error =
7107  db_get_attribute_descriptor (real_object, assign->upd_col_name->info.name.original, 0, 1,
7108  &assign->attr_desc);
7109  }
7110  }
7111 
7112  if (error == NO_ERROR)
7113  {
7114  /* update tuple's template */
7115  error =
7116  update_object_attribute (parser, otemplate, assign->upd_col_name, assign->attr_desc, assign->db_val);
7117 
7118  /* clear not constant values */
7119  if (!assign->is_const)
7120  {
7121  db_value_clear (assign->db_val);
7122  }
7123  }
7124  }
7125 
7126  if (error != NO_ERROR)
7127  {
7128  /* abort if an error has occurred */
7129  (void) dbt_abort_object (otemplate);
7130  }
7131  else
7132  {
7133  /* update tuple with new values */
7134  object = dbt_finish_object (otemplate);
7135  if (object == NULL)
7136  {
7137  assert (er_errid () != NO_ERROR);
7138  error = er_errid ();
7139  (void) dbt_abort_object (otemplate);
7140  return error;
7141  }
7142  else
7143  {
7144  /* check condition for 'with check option' */
7145  error = mq_evaluate_check_option (parser,
7146  (cls_info->check_where != NULL
7147  ? cls_info->check_where->info.check_option.expr : NULL), object,
7148  cls_info->spec->info.spec.flat_entity_list);
7149  }
7150  }
7151 
7152  /* handle delete only after update to give a chance to triggers */
7153  if (should_delete && error == NO_ERROR)
7154  {
7155  error = locator_flush_instance (object);
7156  if (error != NO_ERROR)
7157  {
7158  continue;
7159  }
7160  flush_del = has_unique_constraint (object);
7161  error = delete_object_tuple (object);
7163  {
7164  er_clear ();
7165  error = NO_ERROR;
7166  continue;
7167  }
7168  if (flush_del && error == NO_ERROR)
7169  {
7170  error = locator_flush_instance (object);
7171  }
7172  }
7173  upd_tpl_cnt++;
7174  }
7175 
7176  return error == NO_ERROR ? upd_tpl_cnt : error;
7177 }
7178 
7179 /*
7180  * update_object_by_oid - Updates attributes of object by oid
7181  * return: 1 if success, otherwise returns error code
7182  * parser(in): Parser context
7183  * statement(in): Parse tree of a update statement
7184  * update_type(in): denote whether the update comes from normal update stmt,
7185  * update object stmt or insert on duplicate key update stmt.
7186  *
7187  * Note:
7188  */
7189 static int
7190 update_object_by_oid (PARSER_CONTEXT * parser, PT_NODE * statement, UPDATE_TYPE update_type)
7191 {
7192  int error = NO_ERROR;
7193  DB_OBJECT *oid = statement->info.update.object;
7194  int i = 0;
7195  PT_NODE *node = NULL;
7196  int vals_cnt = 0;
7197  PT_NODE *class_;
7198  PT_NODE *lhs;
7199 
7200  if (!statement->info.update.spec || !(class_ = statement->info.update.spec->info.spec.flat_entity_list)
7201  || !(class_->info.name.db_object) || statement->info.update.spec->next != NULL)
7202  {
7203  PT_INTERNAL_ERROR (parser, "update");
7204  return ER_GENERIC_ERROR;
7205  }
7206 
7207  /* fetch classes that will be updated */
7208  node = statement->info.update.spec;
7209  while (node)
7210  {
7211  if (node->info.spec.flag & PT_SPEC_FLAG_UPDATE)
7212  {
7214  {
7215  assert (er_errid () != NO_ERROR);
7216  return er_errid ();
7217  }
7218  }
7219 
7220  node = node->next;
7221  }
7222 
7223  /* get first argument of first assignment */
7224  lhs = statement->info.update.assignment->info.expr.arg1;
7225  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
7226  {
7227  lhs = lhs->info.expr.arg1;
7228  }
7229 
7230  if (lhs->info.name.meta_class == PT_META_ATTR)
7231  {
7232  /* if left argument of first assignment is an attribute then all other assignments are to class attributes */
7233  error = update_class_attributes (parser, statement);
7234  }
7235  else
7236  {
7237  /* update object */
7238  int assigns_count = 0, upd_cls_cnt = 0, multi_assign_cnt = 0;
7239  CLIENT_UPDATE_INFO *assigns = NULL;
7241  DB_VALUE *dbvals = NULL;
7243  PT_NODE *rhs = NULL, *lhs = NULL;
7244 
7245  /* Before we start evaluating assignments, we need to first lock the object. Assignments may depend on current
7246  * object values which cannot be modified by others. */
7247  error = obj_inst_lock (oid, 1);
7248  if (error != NO_ERROR)
7249  {
7250  PT_INTERNAL_ERROR (parser, "update_object_by_oid failed to lock object.");
7251  return error;
7252  }
7253 
7254  /* load structures for update */
7255  error =
7256  init_update_data (parser, statement, &assigns, &assigns_count, &cls_info, &upd_cls_cnt, &dbvals, &vals_cnt,
7257  false);
7258 
7259  if (error == NO_ERROR)
7260  {
7261  db_make_object (&dbvals[0], oid);
7262 
7263  /* iterate through assignments and evaluate right side of each assignment */
7264  i = 0;
7265  pt_init_assignments_helper (parser, &ea, statement->info.update.assignment);
7266  while (pt_get_next_assignment (&ea) && error == NO_ERROR)
7267  {
7268  rhs = ea.rhs;
7269  lhs = ea.lhs;
7270  multi_assign_cnt = 1;
7271  /* for multi-column assignments with common right side count number of attributes to assign to */
7272  if (ea.is_n_column)
7273  {
7274  while (pt_get_next_assignment (&ea) && rhs == ea.rhs)
7275  {
7276  multi_assign_cnt++;
7277  }
7278  }
7279 
7280  error =
7281  mq_evaluate_expression_having_serial (parser, rhs, assigns[i].db_val, multi_assign_cnt, oid,
7282  lhs->info.name.spec_id);
7283  i += multi_assign_cnt;
7284  }
7285 
7286  /* update tuple */
7287  if (error >= NO_ERROR)
7288  {
7289  error =
7290  update_object_tuple (parser, assigns, assigns_count, cls_info, upd_cls_cnt, 0, 0, update_type, false);
7291  }
7292 
7293  }
7294 
7295  /* free assignments array */
7296  if (assigns != NULL)
7297  {
7298  /* free attribute descriptors */
7299  for (i = assigns_count - 1; i >= 0; i--)
7300  {
7301  if (assigns[i].attr_desc)
7302  {
7303  db_free_attribute_descriptor (assigns[i].attr_desc);
7304  }
7305  }
7306  db_private_free (NULL, assigns);
7307  }
7308 
7309  /* free classes information */
7310  if (cls_info != NULL)
7311  {
7312  db_private_free (NULL, cls_info);
7313  }
7314 
7315  /* free dbvals array */
7316  if (dbvals != NULL)
7317  {
7318  db_private_free (NULL, dbvals);
7319  }
7320  }
7321 
7322  if (error < NO_ERROR)
7323  return error;
7324  else
7325  return 1; /* we successfully updated 1 object */
7326 }
7327 
7328 /*
7329  * do_set_pruning_type () - set pruning type for a spec
7330  * return : error code or NO_ERROR
7331  * parser (in) : parser context
7332  * spec (in) : spec
7333  * cls (in) : update class info
7334  */
7335 static int
7337 {
7338  int error = NO_ERROR;
7339  MOP class_mop = NULL;
7340  PT_NODE *derived = NULL;
7341  if (cls == NULL || spec == NULL)
7342  {
7343  return NO_ERROR;
7344  }
7345  if (spec->node_type != PT_SPEC)
7346  {
7347  return NO_ERROR;
7348  }
7349  if (PT_SPEC_IS_ENTITY (spec))
7350  {
7351  if (spec->info.spec.entity_name->node_type == PT_NAME)
7352  {
7353  class_mop = spec->info.spec.entity_name->info.name.db_object;
7354  if (class_mop == NULL)
7355  {
7356  PT_ERROR (parser, spec, "Generic error");
7357  return ER_FAILED;
7358  }
7359  error = sm_partitioned_class_type (class_mop, &cls->pruning_type, NULL, NULL);
7360  return error;
7361  }
7362  else if (spec->info.spec.entity_name->node_type == PT_SPEC)
7363  {
7364  /* (classA, classB) specification. We do not allow partitions in this context */
7365  PT_NODE *node = spec->info.spec.entity_name;
7366  while (node)
7367  {
7368  error = do_set_pruning_type (parser, node, cls);
7369  if (cls->pruning_type == DB_PARTITION_CLASS)
7370  {
7373  return ER_FAILED;
7374  }
7375  node = node->next;
7376  }
7377  return NO_ERROR;
7378  }
7379  }
7380 
7381  if (PT_SPEC_IS_CTE (spec))
7382  {
7383  PT_ERROR (parser, spec, "CTE not handled");
7384  return ER_FAILED;
7385  }
7386 
7387  /* We're in the context of a table update/insert etc. This is possible only if the derived table is a SELECT and has
7388  * only one updated class */
7389  derived = spec->info.spec.derived_table;
7390  error = NO_ERROR;
7391  if (derived->node_type == PT_SELECT)
7392  {
7393  for (spec = derived->info.query.q.select.from; spec != NULL; spec = spec->next)
7394  {
7395  if (error == NO_ERROR && (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE))
7396  {
7397  error = do_set_pruning_type (parser, spec, cls);
7398  }
7399  }
7400  }
7401  else if (derived->node_type == PT_UNION)
7402  {
7403  if (derived->info.query.q.union_.arg1 != NULL && derived->info.query.q.union_.arg1->node_type == PT_SELECT)
7404  {
7405  for (spec = derived->info.query.q.union_.arg1->info.query.q.select.from; spec != NULL; spec = spec->next)
7406  {
7407  if (error == NO_ERROR && (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE))
7408  {
7409  error = do_set_pruning_type (parser, spec, cls);
7410  }
7411  }
7412  }
7413 
7414  if (derived->info.query.q.union_.arg2 != NULL && derived->info.query.q.union_.arg2->node_type == PT_SELECT)
7415  {
7416  for (spec = derived->info.query.q.union_.arg2->info.query.q.select.from; spec != NULL; spec = spec->next)
7417  {
7418  if (error == NO_ERROR && (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE))
7419  {
7420  error = do_set_pruning_type (parser, spec, cls);
7421  }
7422  }
7423  }
7424  }
7425  else
7426  {
7427  PT_ERROR (parser, spec, "Generic error");
7428  return ER_FAILED;
7429  }
7430 
7431  return error;
7432 }
7433 
7434 /*
7435  * init_update_data () - init update data structures
7436  * return: NO_ERROR or error code
7437  * parser(in): Parser context
7438  * assigns_data(out): address of a pointer variable that will receive the
7439  * array for assignments info. This array must be
7440  * released by the caller
7441  * assigns_no(out): address of a int variable that will receive number of
7442  * assignments
7443  * cls_data(out): address of a pointer that will receive information about
7444  * classes that will be updated
7445  * cls_count(out): address of a integer variable that will receive number of
7446  * classes that will be updated
7447  * values(out): address of a pointer that will receive an array of DB_VALUE
7448  * that represents runtime computed values and constants.
7449  * This array is referenced by elements of assigns_data.
7450  * values_cnt(out): number of classes OIDs + values computed at
7451  * runtime for assignments.
7452  * has_delete(in): update/delete
7453  *
7454  * Note:
7455  */
7456 static int
7457 init_update_data (PARSER_CONTEXT * parser, PT_NODE * statement, CLIENT_UPDATE_INFO ** assigns_data, int *assigns_count,
7458  CLIENT_UPDATE_CLASS_INFO ** cls_data, int *cls_count, DB_VALUE ** values, int *values_cnt,
7459  bool has_delete)
7460 {
7461  int error = NO_ERROR;
7462  int assign_cnt = 0, upd_cls_cnt = 0, vals_cnt = 0, idx, idx2, idx3, i;
7464  PT_NODE *node = NULL, *assignments, *spec, *class_spec, *check_where;
7465  DB_VALUE *dbvals = NULL;
7466  CLIENT_UPDATE_CLASS_INFO *cls_info = NULL, *cls_info_tmp = NULL;
7467  CLIENT_UPDATE_INFO *assigns = NULL, *assign = NULL, *assign2 = NULL;
7468 
7469  assign_cnt = vals_cnt = 0;
7470  assignments =
7471  statement->node_type == PT_MERGE ? statement->info.merge.update.assignment : statement->info.update.assignment;
7472  spec = statement->node_type == PT_MERGE ? statement->info.merge.into : statement->info.update.spec;
7473  class_spec = statement->node_type == PT_MERGE ? NULL : statement->info.update.class_specs;
7474  check_where =
7475  statement->node_type == PT_MERGE ? statement->info.merge.check_where : statement->info.update.check_where;
7476 
7477  pt_init_assignments_helper (parser, &ea, assignments);
7478  while (pt_get_next_assignment (&ea))
7479  {
7480  if (!ea.is_rhs_const)
7481  {
7482  /* count values that are not constants */
7483  vals_cnt++;
7484  }
7485  /* count number of assignments */
7486  assign_cnt++;
7487  }
7488 
7489  /* allocate memory for assignment structures */
7490  assigns = (CLIENT_UPDATE_INFO *) db_private_alloc (NULL, assign_cnt * sizeof (CLIENT_UPDATE_INFO));
7491  if (assigns == NULL)
7492  {
7493  error = ER_REGU_NO_SPACE;
7494  goto error_return;
7495  }
7496  memset (assigns, 0, assign_cnt * sizeof (CLIENT_UPDATE_INFO));
7497 
7498  node = spec;
7499  while (node)
7500  {
7501  if (node->info.spec.flag & PT_SPEC_FLAG_UPDATE)
7502  {
7503  /* count classes that will be updated */
7504  upd_cls_cnt++;
7505  }
7506 
7507  node = node->next;
7508  }
7509 
7510  node = class_spec;
7511  while (node)
7512  {
7513  if (node->info.spec.flag & PT_SPEC_FLAG_UPDATE)
7514  {
7515  /* count classes that will be updated */
7516  upd_cls_cnt++;
7517  }
7518  node = node->next;
7519  }
7520 
7521  /* allocate array of classes information structures */
7522  cls_info = (CLIENT_UPDATE_CLASS_INFO *) db_private_alloc (NULL, upd_cls_cnt * sizeof (CLIENT_UPDATE_CLASS_INFO));
7523  if (cls_info == NULL)
7524  {
7525  error = ER_REGU_NO_SPACE;
7526  goto error_return;
7527  }
7528  memset (cls_info, 0, upd_cls_cnt * sizeof (CLIENT_UPDATE_CLASS_INFO));
7529 
7530  /* add number of class oid's */
7531  vals_cnt += upd_cls_cnt;
7532  vals_cnt += has_delete;
7533  /* allocate array of DB_VALUE's. The length of the array must be equal to that of select statement's list */
7534  dbvals = (DB_VALUE *) db_private_alloc (NULL, (assign_cnt + upd_cls_cnt + has_delete) * sizeof (DB_VALUE));
7535  if (dbvals == NULL)
7536  {
7537  error = ER_REGU_NO_SPACE;
7538  goto error_return;
7539  }
7540 
7541  for (i = 0; i < assign_cnt + upd_cls_cnt + has_delete; i++)
7542  {
7543  db_make_null (&dbvals[i]);
7544  }
7545 
7546  /* initialize classes info array */
7547  idx = 0;
7548  node = spec;
7549  while (node)
7550  {
7551  if (node->info.spec.flag & PT_SPEC_FLAG_UPDATE)
7552  {
7553  PT_NODE *save = check_where;
7554 
7555  cls_info_tmp = &cls_info[idx++];
7556  cls_info_tmp->spec = node;
7557  cls_info_tmp->first_assign = NULL;
7558  cls_info_tmp->class_mop = NULL;
7559  cls_info_tmp->pruning_type = DB_NOT_PARTITIONED_CLASS;
7560  error = do_set_pruning_type (parser, node, cls_info_tmp);
7561  if (error != NO_ERROR)
7562  {
7563  goto error_return;
7564  }
7565  /* condition to check for 'with check option' option */
7566  while (check_where != NULL && check_where->info.check_option.spec_id != node->info.spec.id)
7567  {
7568  check_where = check_where->next;
7569  }
7570  cls_info_tmp->check_where = check_where;
7571 
7572  check_where = save;
7573  }
7574 
7575  node = node->next;
7576  }
7577 
7578  /* initialize classes info array */
7579  node = class_spec;
7580  while (node)
7581  {
7582  if (node->info.spec.flag & PT_SPEC_FLAG_UPDATE)
7583  {
7584  PT_NODE *save = check_where;
7585 
7586  cls_info_tmp = &cls_info[idx++];
7587  cls_info_tmp->spec = node;
7588  cls_info_tmp->first_assign = NULL;
7589  cls_info_tmp->class_mop = NULL;
7590  cls_info_tmp->pruning_type = DB_NOT_PARTITIONED_CLASS;
7591  error = do_set_pruning_type (parser, node, cls_info_tmp);
7592  if (error != NO_ERROR)
7593  {
7594  goto error_return;
7595  }
7596 
7597  /* condition to check for 'with check option' option */
7598  while (check_where != NULL && check_where->info.check_option.spec_id != node->info.spec.id)
7599  {
7600  check_where = check_where->next;
7601  }
7602  cls_info_tmp->check_where = check_where;
7603 
7604  check_where = save;
7605  }
7606 
7607  node = node->next;
7608  }
7609 
7610  /* Fill assignment structures */
7611  idx = 0;
7612  pt_init_assignments_helper (parser, &ea, assignments);
7613  for (idx3 = 1, assign = assigns; pt_get_next_assignment (&ea); assign++)
7614  {
7615  assign->attr_desc = NULL;
7616  assign->upd_col_name = ea.lhs;
7617  /* Distribution of dbvals array. The array must match the select list of the generated select statement: first
7618  * upd_cls_cnt elements must be associated with OID representing tuple from a class, followed by values that must
7619  * be calculated at runtime for assignment and then by constants */
7620  if (ea.is_rhs_const)
7621  {
7622  /* constants */
7623  assign->db_val = &dbvals[assign_cnt + upd_cls_cnt + has_delete - idx3++];
7624  *assign->db_val = *pt_value_to_db (parser, ea.rhs);
7625  assign->is_const = true;
7626  }
7627  else
7628  {
7629  /* not constants */
7630  assign->db_val = &dbvals[upd_cls_cnt + has_delete + idx++];
7631  assign->is_const = false;
7632  }
7633 
7634  for (idx2 = 0; idx2 < upd_cls_cnt; idx2++)
7635  {
7636  if (cls_info[idx2].spec->info.spec.id == ea.lhs->info.name.spec_id)
7637  {
7638  /* OIDs are in reverse order */
7639  cls_info[idx2].oid = &dbvals[upd_cls_cnt - idx2 - 1];
7640  /* attach class information to assignment */
7641  assign->cls_info = &cls_info[idx2];
7642  /* link assignment to its class info */
7643  if (cls_info[idx2].first_assign)
7644  {
7645  assign2 = cls_info[idx2].first_assign;
7646  while (assign2->next)
7647  {
7648  assign2 = assign2->next;
7649  }
7650  assign2->next = assign;
7651  }
7652  else
7653  {
7654  cls_info[idx2].first_assign = assign;
7655  }
7656  assign->next = NULL;
7657  break;
7658  }
7659  }
7660  }
7661 
7662  /* output computed data */
7663  *assigns_data = assigns;
7664  *assigns_count = assign_cnt;
7665  *cls_data = cls_info;
7666  *cls_count = upd_cls_cnt;
7667  *values = dbvals;
7668  *values_cnt = vals_cnt;
7669 
7670  return error;
7671 
7672 error_return:
7673  /* free class information array */
7674  if (cls_info)
7675  {
7676  db_private_free (NULL, cls_info);
7677  }
7678 
7679  /* free assignments information */
7680  if (assigns != NULL)
7681  {
7682  /* free attribute descriptors */
7683  for (idx = 0; idx < assign_cnt; idx++)
7684  {
7685  assign = &assigns[idx];
7686  if (assign->attr_desc)
7687  {
7688  db_free_attribute_descriptor (assign->attr_desc);
7689  }
7690  }
7691  db_private_free (NULL, assigns);
7692  }
7693 
7694  /* free dbvals array */
7695  if (dbvals != NULL)
7696  {
7697  db_private_free (NULL, dbvals);
7698  }
7699 
7700  return error;
7701 }
7702 
7703 /*
7704  * update_objs_for_list_file - Updates oid attributes for every oid
7705  * in a list file
7706  * return: Number of affected objects if success, otherwise an error code
7707  * parser(in): Parser context
7708  * list_id(in): A list file of oid's and values
7709  * statement(in): update statement
7710  * savepoint_started(in): true, if savepoint started
7711  *
7712  * Note:
7713  */
7714 static int
7716  bool savepoint_started)
7717 {
7718  int error = NO_ERROR;
7719  int idx = 0, count = 0, assign_count = 0;
7720  int upd_cls_cnt = 0, vals_cnt = 0;
7721  CLIENT_UPDATE_INFO *assigns = NULL, *assign = NULL;
7723  int turn_off_unique_check;
7724  int turn_off_server_serializable_conflict_check;
7726  DB_VALUE *dbvals = NULL;
7727  const char *savepoint_name = NULL;
7728  int cursor_status;
7729  PT_NODE *check_where;
7730  bool has_unique, has_trigger;
7731  bool has_delete, should_delete = false;
7732  bool client_check_serializable_conflict = false;
7733 
7734  if (list_id == NULL || statement == NULL)
7735  {
7736  er_set (ER_ERROR_SEVERITY, __FILE__, __LINE__, ER_REGU_SYSTEM, 0);
7737  error = ER_REGU_SYSTEM;
7738  goto done;
7739  }
7740 
7741  check_where =
7742  statement->node_type == PT_MERGE ? statement->info.merge.check_where : statement->info.update.check_where;
7743  has_unique =
7744  statement->node_type ==
7745  PT_MERGE ? (statement->info.merge.flags & PT_MERGE_INFO_HAS_UNIQUE) : statement->info.update.has_unique;
7746  /* For merge stmt, the savepoint has already been added in do_merge() or do_execute_merge(). we do not need to check
7747  * the trigger any more. */
7748  has_trigger = (statement->node_type == PT_UPDATE && statement->info.update.has_trigger);
7749  has_delete = (statement->node_type == PT_MERGE && statement->info.merge.update.has_delete);
7750 
7751  /* load data in update structures */
7752  error =
7753  init_update_data (parser, statement, &assigns, &assign_count, &cls_info, &upd_cls_cnt, &dbvals, &vals_cnt,
7754  has_delete);
7755  if (error != NO_ERROR)
7756  {
7757  goto done;
7758  }
7759 
7760  /* if the list file contains more than 1 object we need to savepoint the statement to guarantee statement atomicity. */
7761  if (list_id->tuple_cnt > 1 || check_where || has_unique || has_trigger || TM_TRAN_ISOLATION () >= TRAN_REP_READ)
7762  {
7763  if (savepoint_started == false)
7764  {
7765  savepoint_name = mq_generate_name (parser, "UusP", &update_savepoint_number);
7766  error = tran_system_savepoint (savepoint_name);
7767  if (error != NO_ERROR)
7768  {
7769  goto done;
7770  }
7771  }
7772  }
7773 
7774  /* 'turn_off_unique_check' is used when call update_object_tuple(). */
7775  if (list_id->tuple_cnt == 1 && upd_cls_cnt == 1)
7776  {
7777  /* Instance level uniqueness and SERIALIZABLE conflict checking is performed on the server when a new single row
7778  * is inserted. */
7779  turn_off_unique_check = 0;
7780  turn_off_server_serializable_conflict_check = 0;
7781  }
7782  else
7783  {
7784  /* list_id->tuple_cnt > 1 : multiple row update Statement level uniqueness checking and SERIALIZABLE conflict is
7785  * performed on the client */
7786  turn_off_unique_check = 1;
7787  turn_off_server_serializable_conflict_check = 1;
7788  }
7789 
7790  /* open cursor */
7791  if (!cursor_open (&cursor_id, list_id, false, false))
7792  {
7793  error = ER_GENERIC_ERROR;
7794  if (savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
7795  {
7796  (void) tran_abort_upto_system_savepoint (savepoint_name);
7797  }
7798  goto done;
7799  }
7800  cursor_id.query_id = parser->query_id;
7801 
7802  /* set prefetching lock mode to WRITE access since we'll be updating all the objects in the list file. */
7803  (void) cursor_set_prefetch_lock_mode (&cursor_id, DB_FETCH_WRITE);
7804 
7805  cursor_status = cursor_next_tuple (&cursor_id);
7806 
7807  while (cursor_status == DB_CURSOR_SUCCESS)
7808  {
7809  /* read OIDs and runtime computed values */
7810  if (cursor_get_tuple_value_list (&cursor_id, vals_cnt, dbvals) != NO_ERROR)
7811  {
7812  assert (er_errid () != NO_ERROR);
7813  error = er_errid ();
7814  cursor_close (&cursor_id);
7815  if (savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
7816  {
7817  (void) tran_abort_upto_system_savepoint (savepoint_name);
7818  }
7819  goto done;
7820  }
7821 
7822  if (has_delete)
7823  {
7824  /* We may get NULL as an expr value. See pt_to_merge_update_query(...). */
7825  if (DB_IS_NULL (&dbvals[upd_cls_cnt]))
7826  {
7827  should_delete = false;
7828  }
7829  else
7830  {
7831  should_delete = db_get_int (&dbvals[upd_cls_cnt]);
7832  }
7833  }
7834 
7835  /* perform update for current tuples */
7836  error =
7837  update_object_tuple (parser, assigns, assign_count, cls_info, upd_cls_cnt, turn_off_unique_check,
7838  turn_off_server_serializable_conflict_check, NORMAL_UPDATE, should_delete);
7839 
7840  /* close cursor and restore to savepoint in case of error */
7841  if (error < NO_ERROR)
7842  {
7843 #if 0 /* TODO */
7844  /* mq_evaluate_check_option () do not er_set () */
7845  assert (er_errid () != NO_ERROR);
7846 #endif
7847  error = er_errid ();
7848  cursor_close (&cursor_id);
7849  if (savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
7850  {
7851  (void) tran_abort_upto_system_savepoint (savepoint_name);
7852  }
7853  goto done;
7854  }
7855 
7856  count += error; /* number of objects affected. Incorrect for multi-table update !!! */
7857  cursor_status = cursor_next_tuple (&cursor_id);
7858  }
7859 
7860  /* close cursor and restore to savepoint in case of error */
7861  if (cursor_status != DB_CURSOR_END)
7862  {
7863  error = ER_GENERIC_ERROR;
7864  cursor_close (&cursor_id);
7865  if (savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
7866  {
7867  (void) tran_abort_upto_system_savepoint (savepoint_name);
7868  }
7869  goto done;
7870  }
7871  cursor_close (&cursor_id);
7872 
7873  if (TM_TRAN_ISOLATION () >= TRAN_REP_READ && turn_off_server_serializable_conflict_check)
7874  {
7875  /* activate SERIALIZABLE conflict checks */
7876  client_check_serializable_conflict = true;
7877  }
7878 
7879  /* check uniques or SERIALIZABLE conflicts if not already checked */
7880  if (has_unique || client_check_serializable_conflict)
7881  {
7882  /* need to check unique or SERIALIZABLE conflicts */
7883  for (idx = upd_cls_cnt - 1; idx >= 0; idx--)
7884  {
7885  if (!(cls_info[idx].spec->info.spec.flag & PT_SPEC_FLAG_HAS_UNIQUE) && !client_check_serializable_conflict)
7886  {
7887  /* if not unique and don't want to check SERIALIZABLE conflict */
7888  continue;
7889  }
7890  error = sm_flush_for_multi_update (cls_info[idx].spec->info.spec.flat_entity_list->info.name.db_object);
7891  /* if error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
7892  * transaction itself. */
7893  if ((error < NO_ERROR) && savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
7894  {
7895  (void) tran_abort_upto_system_savepoint (savepoint_name);
7896  break;
7897  }
7898  }
7899  }
7900 
7901 done:
7902  /* free classes information array */
7903  if (cls_info)
7904  {
7905  db_private_free (NULL, cls_info);
7906  }
7907 
7908  /* free assignments information */
7909  if (assigns != NULL)
7910  {
7911  /* free attributes descriptors */
7912  for (idx = 0; idx < assign_count; idx++)
7913  {
7914  assign = &assigns[idx];
7915  if (assign->attr_desc)
7916  {
7917  db_free_attribute_descriptor (assign->attr_desc);
7918  }
7919  }
7920  db_private_free (NULL, assigns);
7921  }
7922 
7923  /* free values array */
7924  if (dbvals != NULL)
7925  {
7926  db_private_free (NULL, dbvals);
7927  }
7928 
7929  if (error >= NO_ERROR)
7930  {
7931  return count;
7932  }
7933  else
7934  {
7935  return error;
7936  }
7937 }
7938 
7939 /*
7940  * update_class_attributes - Returns corresponding lists of names and expressions
7941  * return: Error code
7942  * parser(in): Parser context
7943  * statement(in): update statement
7944  *
7945  * Note:
7946  */
7947 static int
7949 {
7950  int error = NO_ERROR;
7951  DB_OTMPL *otemplate = NULL;
7952  PT_NODE *rhs = NULL, *assignments = NULL;
7954  int idx = 0, assigns_count = 0;
7955  int upd_cls_cnt = 0, vals_cnt = 0, multi_assign_cnt = 0;
7956  CLIENT_UPDATE_INFO *assigns = NULL, *assign = NULL;
7958  DB_VALUE *dbvals = NULL;
7959 
7960  assignments =
7961  statement->node_type == PT_MERGE ? statement->info.merge.update.assignment : statement->info.update.assignment;
7962 
7963  /* load data for update */
7964  error =
7965  init_update_data (parser, statement, &assigns, &assigns_count, &cls_info, &upd_cls_cnt, &dbvals, &vals_cnt, false);
7966  if (error == NO_ERROR)
7967  {
7968  /* evaluate values for assignment */
7969  pt_init_assignments_helper (parser, &ea, assignments);
7970  for (idx = 0; idx < assigns_count && error == NO_ERROR; idx += multi_assign_cnt)
7971  {
7972  assign = &assigns[idx];
7973  cls = assign->cls_info;
7974 
7975  pt_get_next_assignment (&ea);
7976  rhs = ea.rhs;
7977  multi_assign_cnt = 1;
7978  if (ea.is_n_column)
7979  {
7980  while (pt_get_next_assignment (&ea) && rhs == ea.rhs)
7981  {
7982  multi_assign_cnt++;
7983  }
7984  }
7985 
7986  pt_evaluate_tree (parser, rhs, assign->db_val, multi_assign_cnt);
7987  if (pt_has_error (parser))
7988  {
7989  error = ER_GENERIC_ERROR;
7990  }
7991  }
7992  }
7993 
7994  /* execute assignments */
7995  if (error == NO_ERROR)
7996  {
7997  for (idx = 0; idx < upd_cls_cnt && error == NO_ERROR; idx++)
7998  {
7999  cls = &cls_info[idx];
8000 
8001  otemplate = dbt_edit_object (cls->spec->info.spec.flat_entity_list->info.name.db_object);
8002  for (assign = cls->first_assign; assign != NULL && error == NO_ERROR; assign = assign->next)
8003  {
8004  error = dbt_put_internal (otemplate, assign->upd_col_name->info.name.original, assign->db_val);
8005  }
8006  if (error == NO_ERROR && dbt_finish_object (otemplate) == NULL)
8007  {
8008  assert (er_errid () != NO_ERROR);
8009  error = er_errid ();
8010  (void) dbt_abort_object (otemplate);
8011  }
8012  }
8013  }
8014 
8015  /* free assignments array */
8016  if (assigns != NULL)
8017  {
8018  /* free attributes descriptors */
8019  for (idx = assigns_count - 1; idx >= 0; idx--)
8020  {
8021  if (assigns[idx].attr_desc)
8022  {
8023  db_free_attribute_descriptor (assigns[idx].attr_desc);
8024  }
8025  }
8026  db_private_free (NULL, assigns);
8027  }
8028 
8029  /* free classes info array */
8030  if (cls_info != NULL)
8031  {
8032  db_private_free (NULL, cls_info);
8033  }
8034 
8035  /* free values array */
8036  if (dbvals != NULL)
8037  {
8038  db_private_free (NULL, dbvals);
8039  }
8040 
8041  return error;
8042 }
8043 
8044 /*
8045  * statement_to_update_xasl - Converts an update parse tree to
8046  * an XASL graph for an update
8047  * parser(in): Parser context
8048  * statement(in): Parse tree of a update statement
8049  * non_null_attrs(in):
8050  *
8051  * Note:
8052  */
8053 static XASL_NODE *
8054 statement_to_update_xasl (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** non_null_attrs)
8055 {
8056  return pt_to_update_xasl (parser, statement, non_null_attrs);
8057 }
8058 
8059 /*
8060  * init_compile_context() -
8061  *
8062  * parser (in/out):
8063  *
8064  */
8065 static void
8067 {
8068  memset (&parser->context, 0x00, sizeof (COMPILE_CONTEXT));
8070  parser->context.recompile_xasl_pinned = (bool) parser->flag.recompile_xasl_pinned;
8071 }
8072 
8073 /*
8074  * init_xasl_stream() - init XASL_STREAM
8075  *
8076  * stream (in): initialized parameter
8077  *
8078  */
8079 static void
8081 {
8082  memset (stream, 0x00, sizeof (XASL_STREAM));
8083 }
8084 
8085 /*
8086  * update_at_server - Build an xasl tree for a server update and execute it
8087  * return: Tuple count if success, otherwise an error code
8088  * parser(in): Parser context
8089  * from(in): Class spec to update
8090  * statement(in): Parse tree of a update statement
8091  * non_null_attrs(in):
8092  * has_uniques(in):
8093  *
8094  * Note:
8095  * The xasl tree has an UPDATE_PROC node as the top node and
8096  * a BUILDLIST_PROC as its aptr. The BUILDLIST_PROC selects the
8097  * instance OID and any update attribute expression values.
8098  * The UPDATE_PROC node scans the BUILDLIST_PROC results.
8099  * The UPDATE_PROC node contains the attribute ID's and values
8100  * for update constants. The server executes the aptr and then
8101  * for each instance selected, updates it with the attribute expression
8102  * values and constants. The result information is sent back to the
8103  * client as a list file without any pages. The list file tuple count
8104  * is used as the return value from this routine.
8105  *
8106  * The instances for the class are flushed from the client before the
8107  * update is executed. If any instances are updated, the instances are
8108  * decached from the client after the update is executed.
8109  *
8110  * It is assumed that class attributes and regular attributes
8111  * are not mixed in the same update statement.
8112  */
8113 static int
8114 update_at_server (PARSER_CONTEXT * parser, PT_NODE * from, PT_NODE * statement, PT_NODE ** non_null_attrs,
8115  int has_uniques)
8116 {
8117  int error = NO_ERROR;
8118  int i;
8119  XASL_NODE *xasl = NULL;
8120  int count = 0;
8121  QUERY_ID query_id_self = parser->query_id;
8122  QFILE_LIST_ID *list_id = NULL;
8123  PT_NODE *cl_name_node = NULL, *spec = NULL;
8124 
8125  XASL_STREAM stream;
8126 
8127  assert (parser->query_id == NULL_QUERY_ID);
8128 
8129  init_xasl_stream (&stream);
8130 
8131  /* mark the beginning of another level of xasl packing */
8133 
8134  xasl = statement_to_update_xasl (parser, statement, non_null_attrs);
8135  if (xasl)
8136  {
8137  UPDATE_PROC_NODE *update = &xasl->proc.update;
8138 
8139  error = xts_map_xasl_to_stream (xasl, &stream);
8140  if (error != NO_ERROR)
8141  {
8143  }
8144 
8145  for (i = 0; i < update->num_assigns; i++)
8146  {
8147  if (update->assigns[i].constant)
8148  {
8149  pr_clear_value (update->assigns[i].constant);
8150  }
8151  }
8152  }
8153  else
8154  {
8155  assert (er_errid () != NO_ERROR);
8156  error = er_errid ();
8157  }
8158 
8159  if (error == NO_ERROR)
8160  {
8161  int au_save;
8162  QUERY_FLAG query_flag;
8163 
8164  query_flag = DEFAULT_EXEC_MODE;
8165 
8166  if (parser->flag.is_auto_commit)
8167  {
8168  query_flag |= TRAN_AUTO_COMMIT;
8169  }
8170 
8171  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
8172 
8173  error =
8174  prepare_and_execute_query (stream.buffer, stream.buffer_size, &parser->query_id,
8175  parser->host_var_count + parser->auto_param_count, parser->host_variables, &list_id,
8176  query_flag);
8177  AU_RESTORE (au_save);
8178  }
8179 
8180  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
8181  if (stream.buffer)
8182  {
8183  free_and_init (stream.buffer);
8184  }
8185 
8186  if (list_id)
8187  {
8188  count = list_id->tuple_cnt;
8189  if (count > 0)
8190  {
8191  spec = statement->info.update.spec;
8192  while (spec)
8193  {
8194  for (cl_name_node = spec->info.spec.flat_entity_list; cl_name_node && error == NO_ERROR;
8195  cl_name_node = cl_name_node->next)
8196  {
8198  {
8199  /* Nothing to flush. Avoids flush, since may fetch the class. */
8201  }
8202  else
8203  {
8204  error = sm_flush_and_decache_objects (cl_name_node->info.name.db_object, true);
8205  }
8206 
8207  }
8208  spec = spec->next;
8209  }
8210  }
8211  cursor_free_self_list_id (list_id);
8212  }
8213  pt_end_query (parser, query_id_self);
8214 
8215  /* mark the end of another level of xasl packing */
8217 
8218  if (error >= NO_ERROR)
8219  {
8220  return count;
8221  }
8222  else
8223  {
8224  return error;
8225  }
8226 }
8227 
8228 /*
8229  * update_check_for_constraints - Determine whether attributes of the target
8230  * classes have UNIQUE and/or NOT NULL
8231  * constraints, and return a list of NOT NULL
8232  * attributes if exist
8233  * return: Error code
8234  * parser(in): Parser context
8235  * has_unique(out): Indicator representing there is UNIQUE constraint, 1 or 0
8236  * not_nulls(out): A list of pointers to NOT NULL attributes, or NULL
8237  * statement(in): Parse tree of an UPDATE or MERGE statement
8238  *
8239  * Note:
8240  */
8241 static int
8242 update_check_for_constraints (PARSER_CONTEXT * parser, int *has_unique, PT_NODE ** not_nulls, const PT_NODE * statement)
8243 {
8244  int error = NO_ERROR;
8245  PT_NODE *lhs = NULL, *att = NULL, *pointer = NULL, *spec = NULL;
8246  PT_NODE *assignment = NULL;
8247  DB_OBJECT *class_obj = NULL;
8248 
8249  assignment =
8250  statement->node_type == PT_MERGE ? statement->info.merge.update.assignment : statement->info.update.assignment;
8251 
8252  *has_unique = 0;
8253  *not_nulls = NULL;
8254 
8255  for (; assignment; assignment = assignment->next)
8256  {
8257  lhs = assignment->info.expr.arg1;
8258  if (lhs->node_type == PT_NAME)
8259  {
8260  att = lhs;
8261  }
8262  else if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
8263  {
8264  att = lhs->info.expr.arg1;
8265  }
8266  else
8267  {
8268  /* bullet proofing, should not get here */
8269 #if defined(CUBRID_DEBUG)
8270  fprintf (stdout, "system error detected in %s, line %d.\n", __FILE__, __LINE__);
8271 #endif
8272  error = ER_GENERIC_ERROR;
8273  goto exit_on_error;
8274  }
8275 
8276  for (; att; att = att->next)
8277  {
8278  if (att->node_type != PT_NAME)
8279  {
8280  /* bullet proofing, should not get here */
8281 #if defined(CUBRID_DEBUG)
8282  fprintf (stdout, "system error detected in %s, line %d.\n", __FILE__, __LINE__);
8283 #endif
8284  error = ER_GENERIC_ERROR;
8285  goto exit_on_error;
8286  }
8287 
8288  spec = pt_find_spec_in_statement (parser, statement, att);
8289  if (spec == NULL || (class_obj = spec->info.spec.flat_entity_list->info.name.db_object) == NULL)
8290  {
8291  error = ER_GENERIC_ERROR;
8292  goto exit_on_error;
8293  }
8294 
8295  if ((spec->info.spec.flag & (PT_SPEC_FLAG_HAS_UNIQUE | PT_SPEC_FLAG_DOESNT_HAVE_UNIQUE)) == 0)
8296  {
8297  bool has_unique_temp = false;
8298  bool check_subclasses = (spec->info.spec.only_all == PT_ALL);
8299 
8300  error = sm_class_has_unique_constraint (NULL, class_obj, check_subclasses, &has_unique_temp);
8301  if (error == NO_ERROR)
8302  {
8303  if (has_unique_temp)
8304  {
8305  *has_unique = 1;
8306  spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_HAS_UNIQUE);
8307  }
8308  else
8309  {
8310  spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_DOESNT_HAVE_UNIQUE);
8311  }
8312  }
8313  else
8314  {
8315  goto exit_on_error;
8316  }
8317 
8318  }
8319  if (sm_att_constrained (class_obj, att->info.name.original, SM_ATTFLAG_NON_NULL))
8320  {
8321  pointer = pt_point (parser, att);
8322  if (pointer == NULL)
8323  {
8326  goto exit_on_error;
8327  }
8328  *not_nulls = parser_append_node (pointer, *not_nulls);
8329  }
8330  } /* for ( ; attr; ...) */
8331  } /* for ( ; assignment; ...) */
8332 
8333  return NO_ERROR;
8334 
8335 exit_on_error:
8336  if (*not_nulls)
8337  {
8338  parser_free_tree (parser, *not_nulls);
8339  *not_nulls = NULL;
8340  }
8341  return error;
8342 }
8343 
8344 /*
8345  * update_check_for_meta_attr () -
8346  * return: true if update assignment clause has class or shared attribute
8347  * parser(in): Parser context
8348  * assignment(in): Parse tree of an assignment clause
8349  *
8350  * Note:
8351  */
8352 static bool
8354 {
8355  PT_NODE *lhs, *att;
8356 
8357  for (; assignment; assignment = assignment->next)
8358  {
8359  lhs = assignment->info.expr.arg1;
8360  if (lhs->node_type == PT_NAME)
8361  {
8362  att = lhs;
8363  }
8364  else if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
8365  {
8366  att = lhs->info.expr.arg1;
8367  }
8368  else
8369  {
8370  att = NULL;
8371  }
8372 
8373  for (; att; att = att->next)
8374  {
8375  if (att->node_type == PT_NAME && att->info.name.meta_class != PT_NORMAL)
8376  {
8377  return true;
8378  }
8379  }
8380  }
8381 
8382  return false;
8383 }
8384 
8385 /*
8386  * update_real_class() -
8387  * return: Error code if update fails
8388  * parser(in): Parser context
8389  * statement(in): Parse tree of a update statement
8390  * savepoint_started(in): true, if savepoint started
8391  *
8392  * Note: If the statement is of type "update class foo ...", this
8393  * routine updates class attributes of foo. If the statement is of
8394  * type "update foo ...", this routine updates objects or rows in foo.
8395  * It is assumed that class attributes and regular attributes
8396  * are not mixed in the same update statement.
8397  */
8398 static int
8399 update_real_class (PARSER_CONTEXT * parser, PT_NODE * statement, bool savepoint_started)
8400 {
8401  int error = NO_ERROR;
8402  PT_NODE *non_null_attrs = NULL, *spec = statement->info.update.spec;
8403  DB_OBJECT *class_obj = NULL;
8404  int server_allowed = 0;
8405  int has_uniques = 0;
8406  PT_NODE **links = NULL;
8407 
8408  /* update a "real" class in this database */
8409 
8410  while (spec)
8411  {
8412  /* Safety check: make sure that we have access to the class. We're only setting a weak lock here which guarantees
8413  * that the schema for the classes which are updated in this query is not changed. The correct lock for this
8414  * operation will be set server side when the SELECT part of the operation is being performed. */
8415  if (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE)
8416  {
8417  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
8418  if (!locator_fetch_class (class_obj, DB_FETCH_READ))
8419  {
8420  goto exit_on_error;
8421  }
8422  }
8423  spec = spec->next;
8424  }
8425 
8426  if (is_server_update_allowed (parser, &non_null_attrs, &has_uniques, &server_allowed, statement) != NO_ERROR)
8427  {
8428  goto exit_on_error;
8429  }
8430 
8431  if (server_allowed)
8432  {
8433  /* do update on server */
8434  error = update_at_server (parser, spec, statement, &non_null_attrs, has_uniques);
8435  }
8436  else
8437  {
8438  PT_NODE *lhs = NULL;
8439  PT_NODE *select_names = NULL;
8440  PT_NODE *select_values = NULL;
8441  PT_NODE *const_names = NULL;
8442  PT_NODE *const_values = NULL;
8443  QFILE_LIST_ID *oid_list = NULL;
8444  int no_vals = 0;
8445  int no_consts = 0;
8446  int wait_msecs = -2;
8447  int old_wait_msecs = -2;
8448  float hint_waitsecs;
8449 
8450  /* do update on client */
8451  lhs = statement->info.update.assignment->info.expr.arg1;
8452  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
8453  {
8454  lhs = lhs->info.expr.arg1;
8455  }
8456  if (lhs->info.name.meta_class != PT_META_ATTR)
8457  {
8458  QUERY_ID query_id_self;
8459  PT_NODE *hint_arg;
8460 
8461  query_id_self = parser->query_id;
8462  parser->query_id = NULL_QUERY_ID;
8463 
8464  hint_arg = statement->info.update.waitsecs_hint;
8465  if (statement->info.update.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
8466  {
8467  hint_waitsecs = (float) atof (hint_arg->info.name.original);
8468  if (hint_waitsecs > 0)
8469  {
8470  wait_msecs = (int) (hint_waitsecs * 1000);
8471  }
8472  else
8473  {
8474  wait_msecs = (int) hint_waitsecs;
8475  }
8476  if (wait_msecs >= -1)
8477  {
8478  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
8479  (void) tran_reset_wait_times (wait_msecs);
8480  }
8481  }
8482  if (error == NO_ERROR)
8483  {
8484  error =
8485  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &no_vals,
8486  &no_consts, statement->info.update.assignment, &links);
8487  if (error != NO_ERROR)
8488  {
8489  goto exit_on_error;
8490  }
8491  /* get the oid's and new values */
8492  oid_list =
8493  get_select_list_to_update (parser, statement->info.update.spec, select_names, select_values,
8494  statement->info.update.with, statement->info.update.search_cond,
8495  statement->info.update.order_by, statement->info.update.orderby_for,
8496  statement->info.update.using_index, statement->info.update.class_specs,
8497  statement);
8498 
8499  /* restore tree structure */
8500  pt_restore_assignment_links (statement->info.update.assignment, links, -1);
8501  }
8502  if (old_wait_msecs >= -1)
8503  {
8504  (void) tran_reset_wait_times (old_wait_msecs);
8505  }
8506 
8507  if (!oid_list)
8508  {
8509  parser->query_id = query_id_self;
8510  /* an error should be set already, don't lose it */
8511  error = ER_GENERIC_ERROR;
8512  goto exit_on_error;
8513  }
8514 
8515  /* update each oid */
8516  error = update_objs_for_list_file (parser, oid_list, statement, savepoint_started);
8517 
8518  cursor_free_self_list_id (oid_list);
8519  pt_end_query (parser, query_id_self);
8520  }
8521  else
8522  {
8523  /* we are updating class attributes */
8524  error = update_class_attributes (parser, statement);
8525  }
8526  }
8527 
8528  if (non_null_attrs != NULL)
8529  {
8530  parser_free_tree (parser, non_null_attrs);
8531  non_null_attrs = NULL;
8532  }
8533 
8534  return error;
8535 
8536 exit_on_error:
8537 
8538  if (error == NO_ERROR)
8539  {
8540  assert (er_errid () != NO_ERROR);
8541  error = er_errid ();
8542  }
8543  if (non_null_attrs != NULL)
8544  {
8545  parser_free_tree (parser, non_null_attrs);
8546  non_null_attrs = NULL;
8547  }
8548  return error;
8549 }
8550 
8551 /*
8552  * is_server_update_allowed() - Checks to see if a server-side update is
8553  * allowed
8554  * return: NO_ERROR or error code on failure
8555  * parser(in): Parser context
8556  * non_null_attrs(in/out): Parse tree for attributes with the NOT NULL
8557  * constraint
8558  * has_uniques(in/out): whether unique indexes are affected by the update
8559  * server_allowed(in/out): whether the update can be executed on the server
8560  * statement(in): Parse tree of an update statement
8561  */
8562 static int
8563 is_server_update_allowed (PARSER_CONTEXT * parser, PT_NODE ** non_null_attrs, int *has_uniques,
8564  int *const server_allowed, const PT_NODE * statement)
8565 {
8566  int error = NO_ERROR;
8567  int is_partition = 0;
8568  int trigger_involved = 0, ti = 0, is_virt = 0;
8569  PT_NODE *spec = statement->info.update.spec;
8570  DB_OBJECT *class_obj = NULL;
8571  int save_au;
8572 
8573  *has_uniques = 0;
8574  *server_allowed = 0;
8575 
8576  AU_DISABLE (save_au);
8577 
8578  /* check if at least one spec that will be updated is virtual or has triggers */
8579  while (spec && !trigger_involved && !is_virt)
8580  {
8581  if (!(spec->info.spec.flag & PT_SPEC_FLAG_UPDATE))
8582  {
8583  spec = spec->next;
8584  continue;
8585  }
8586  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
8587  error = sm_partitioned_class_type (class_obj, &is_partition, NULL, NULL);
8588  if (error != NO_ERROR)
8589  {
8590  goto error_exit;
8591  }
8592 
8593  /* If the class is partitioned and has any type of trigger, the update must be executed on the client. */
8594  error = sm_class_has_triggers (class_obj, &ti, (is_partition ? TR_EVENT_ALL : TR_EVENT_UPDATE));
8595  if (error != NO_ERROR)
8596  {
8597  goto error_exit;
8598  }
8599 
8600  if (ti)
8601  {
8602  trigger_involved = ti;
8603  }
8604 
8605  is_virt = (spec->info.spec.flat_entity_list->info.name.virt_object != NULL);
8606 
8607  spec = spec->next;
8608  }
8609 
8610  error = update_check_for_constraints (parser, has_uniques, non_null_attrs, statement);
8611  if (error < NO_ERROR)
8612  {
8613  goto error_exit;
8614  }
8615 
8616  /* Check to see if the update can be done on the server */
8617  *server_allowed = ((!trigger_involved && !is_virt)
8618  && !update_check_having_meta_attr (parser, statement->info.update.assignment));
8619 
8620  AU_ENABLE (save_au);
8621  return error;
8622 
8623 error_exit:
8624  if (non_null_attrs != NULL && *non_null_attrs != NULL)
8625  {
8626  parser_free_tree (parser, *non_null_attrs);
8627  *non_null_attrs = NULL;
8628  }
8629  AU_ENABLE (save_au);
8630  return error;
8631 }
8632 
8633 /*
8634  * do_update() - Updates objects or rows
8635  * return: Error code if update fails
8636  * parser(in): Parser context
8637  * statement(in): Parse tree of a update statement
8638  *
8639  * Note:
8640  */
8641 int
8642 do_update (PARSER_CONTEXT * parser, PT_NODE * statement)
8643 {
8644  int error = NO_ERROR;
8645  int result = NO_ERROR;
8646  const char *savepoint_name = NULL;
8647  bool savepoint_started = false;
8648 
8650 
8651  /* DON'T REMOVE this, correct authorization validation of views depends on this. DON'T return from the body of this
8652  * function. Break out of the loop if necessary. */
8653  AU_DISABLE (parser->au_save);
8654 
8655  /* savepoint for statement atomicity */
8656  if ((statement != NULL && statement->next != NULL)
8658  && (statement->info.update.object != NULL || !statement->info.update.server_update)))
8659  {
8660  savepoint_name = mq_generate_name (parser, "UmusP", &update_savepoint_number);
8661  if (savepoint_name == NULL)
8662  {
8663  error = ER_GENERIC_ERROR;
8664  goto end;
8665  }
8666  error = tran_system_savepoint (savepoint_name);
8667  if (error != NO_ERROR)
8668  {
8669  goto end;
8670  }
8671 
8672  savepoint_started = true;
8673  }
8674 
8675  while (statement && (error >= 0))
8676  {
8677  if (statement->node_type != PT_UPDATE || statement->info.update.assignment == NULL)
8678  {
8679  /* bullet proofing, should not get here */
8680  PT_INTERNAL_ERROR (parser, "update");
8681  error = ER_GENERIC_ERROR;
8682  break;
8683  }
8684 
8685  if (pt_false_where (parser, statement))
8686  {
8687  /* nothing to update, where part is false */
8688  }
8689  else if (statement->info.update.object != NULL)
8690  {
8691  /* this is a update object if it has an object */
8692  error = update_object_by_oid (parser, statement, UPDATE_OBJECT);
8693  }
8694  else
8695  {
8696  /* the following is the "normal" sql type execution */
8697  error = update_real_class (parser, statement, savepoint_started);
8698  }
8699 
8700  if (error < NO_ERROR && er_errid () != NO_ERROR)
8701  {
8702  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number,
8703  er_msg (), NULL);
8704  }
8705 
8706  result += error;
8707  statement = statement->next;
8708  }
8709 
8710  /* if error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
8711  * transaction. */
8712  if (error < NO_ERROR && savepoint_name && error != ER_LK_UNILATERALLY_ABORTED)
8713  {
8714  db_abort_to_savepoint (savepoint_name);
8715  }
8716 
8717 end:
8718  if (error < 0)
8719  {
8720  result = error;
8721  }
8722 
8723  /* DON'T REMOVE this, correct authorization validation of views depends on this. */
8724  AU_ENABLE (parser->au_save);
8725 
8726  return result;
8727 }
8728 
8729 /*
8730  * do_prepare_update() - Prepare the UPDATE statement
8731  * return: Error code
8732  * parser(in): Parser context
8733  * statement(in/out): Parse tree of a update statement
8734  *
8735  * Note:
8736  */
8737 int
8739 {
8740  int err;
8741  PT_NODE *flat, *not_nulls, *lhs, *spec = NULL;
8742  DB_OBJECT *class_obj;
8743  int has_trigger, has_unique, has_any_update_trigger, au_save, has_virt = 0;
8744  bool server_update;
8745 
8746  if (parser == NULL || statement == NULL)
8747  {
8749  return ER_OBJ_INVALID_ARGUMENTS;
8750  }
8751 
8752  for (err = NO_ERROR; statement && (err >= NO_ERROR); statement = statement->next)
8753  {
8754  COMPILE_CONTEXT *contextp;
8755  XASL_STREAM stream;
8756 
8757  contextp = &parser->context;
8758 
8759  init_xasl_stream (&stream);
8760 
8761  contextp->sql_user_text = statement->sql_user_text;
8762  contextp->sql_user_text_len = statement->sql_user_text_len;
8763 
8764  /* there can be no results, this is a compile time false where clause */
8765  if (pt_false_where (parser, statement))
8766  {
8767  /* tell to the execute routine that there's no XASL to execute */
8768  statement->xasl_id = NULL;
8769  err = NO_ERROR;
8770  continue; /* continue to next UPDATE statement */
8771  }
8772 
8773  /*
8774  * Update object case:
8775  * this is a update object if it has an object
8776  */
8777  if (statement->info.update.object)
8778  {
8779  statement->etc = NULL;
8780  err = NO_ERROR;
8781  continue; /* continue to next UPDATE statement */
8782  }
8783 
8784  /* if already prepared */
8785  if (statement->xasl_id)
8786  {
8787  continue; /* continue to next UPDATE statement */
8788  }
8789 
8790  AU_SAVE_AND_DISABLE (au_save); /* because sm_class_has_trigger() calls au_fetch_class() */
8791 
8792  /* check if at least one spec to be updated has triggers. If none has triggers then see if at least one is
8793  * virtual */
8794  spec = statement->info.update.spec;
8795  has_trigger = 0;
8796  has_any_update_trigger = 0;
8797  while (spec && !has_trigger && err == NO_ERROR)
8798  {
8799  if (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE)
8800  {
8801  flat = spec->info.spec.flat_entity_list;
8802  class_obj = (flat) ? flat->info.name.db_object : NULL;
8803  assert (class_obj); /* safeguard */
8804  /* the presence of a proxy trigger should force the update to be performed through the workspace */
8805  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_UPDATE);
8806 
8807  if (err == NO_ERROR)
8808  {
8809  if (has_trigger)
8810  {
8811  has_any_update_trigger = has_trigger;
8812  }
8813  else if (!has_any_update_trigger)
8814  {
8815  /* Check for statement delete triggerrs. */
8816  err = sm_class_has_triggers (class_obj, &has_any_update_trigger, TR_EVENT_STATEMENT_UPDATE);
8817  }
8818  }
8819 
8820  if (!has_virt)
8821  {
8822  has_virt = (flat->info.name.virt_object != NULL);
8823  }
8824  }
8825 
8826  spec = spec->next;
8827  }
8828  AU_RESTORE (au_save);
8829 
8830  /* err = has_proxy_trigger(flat, &has_trigger); */
8831  if (err != NO_ERROR)
8832  {
8833  PT_INTERNAL_ERROR (parser, "update");
8834  break; /* stop while loop if error */
8835  }
8836  /* sm_class_has_triggers() checked if the class has active triggers */
8837  statement->info.update.has_trigger = (bool) has_trigger;
8838 
8839  /* check if the target class has UNIQUE constraint and get attributes that has NOT NULL constraint */
8840  err = update_check_for_constraints (parser, &has_unique, &not_nulls, statement);
8841  if (err < NO_ERROR)
8842  {
8843  PT_INTERNAL_ERROR (parser, "update");
8844  break; /* stop while loop if error */
8845  }
8846 
8847  statement->info.update.has_unique = (bool) has_unique;
8848 
8849  /* determine whether it can be server-side or OID list update */
8850  server_update = (!has_trigger && !has_virt
8851  && !update_check_having_meta_attr (parser, statement->info.update.assignment));
8852 
8853  lhs = statement->info.update.assignment->info.expr.arg1;
8854  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
8855  {
8856  lhs = lhs->info.expr.arg1;
8857  }
8858  statement->info.update.server_update = server_update;
8859  if (server_update && !has_any_update_trigger && !(statement->info.update.hint & PT_HINT_USE_SBR))
8860  {
8861  statement->info.update.execute_with_commit_allowed = 1;
8862  }
8863 
8864  /* if we are updating class attributes, not need to prepare */
8865  if (lhs->info.name.meta_class == PT_META_ATTR)
8866  {
8867  statement->info.update.do_class_attrs = true;
8868  continue; /* continue to next UPDATE statement */
8869  }
8870 
8871  if (server_update)
8872  {
8873  /*
8874  * Server-side update case: (by requesting server to execute XASL)
8875  * build UPDATE_PROC XASL
8876  */
8877 
8878  /* make query string */
8879  parser->flag.dont_prt_long_string = 1;
8880  parser->flag.long_string_skipped = 0;
8881  parser->flag.print_type_ambiguity = 0;
8883  contextp->sql_hash_text = (char *) statement->alias_print;
8884  err =
8885  SHA1Compute ((unsigned char *) contextp->sql_hash_text, (unsigned) strlen (contextp->sql_hash_text),
8886  &contextp->sha1);
8887  if (err != NO_ERROR)
8888  {
8889  ASSERT_ERROR ();
8890  return err;
8891  }
8892  parser->flag.dont_prt_long_string = 0;
8893  if (parser->flag.long_string_skipped || parser->flag.print_type_ambiguity)
8894  {
8895  statement->flag.cannot_prepare = 1;
8896  return NO_ERROR;
8897  }
8898  }
8899 
8900  stream.xasl_id = NULL;
8901  if (server_update)
8902  {
8903  /*
8904  * Server-side update case: (by requesting server to execute XASL)
8905  * build UPDATE_PROC XASL
8906  */
8907 
8908  /* look up server's XASL cache for this query string and get XASL file id (XASL_ID) returned if found */
8909  contextp->recompile_xasl = statement->flag.recompile;
8910  if (statement->flag.recompile == 0)
8911  {
8912  err = prepare_query (contextp, &stream);
8913 
8914  if (err != NO_ERROR)
8915  {
8916  ASSERT_ERROR_AND_SET (err);
8917  }
8918  else if (contextp->recompile_xasl == true)
8919  {
8920  /* recompile requested by server */
8921  if (stream.xasl_id != NULL)
8922  {
8923  free_and_init (stream.xasl_id);
8924  }
8925  }
8926  }
8927 
8928  if (stream.xasl_id == NULL && err == NO_ERROR)
8929  {
8930  /* cache not found; make XASL from the parse tree including query optimization and plan generation */
8931 
8932  /* mark the beginning of another level of xasl packing */
8934 
8935  /* this prevents authorization checking during generating XASL */
8936  AU_SAVE_AND_DISABLE (au_save);
8937 
8938  /* pt_to_update_xasl() will build XASL tree from parse tree */
8939  contextp->xasl = pt_to_update_xasl (parser, statement, &not_nulls);
8940  AU_RESTORE (au_save);
8941 
8942  if (contextp->xasl && (err >= NO_ERROR))
8943  {
8944  int i;
8945  UPDATE_PROC_NODE *update = &contextp->xasl->proc.update;
8946 
8947  /* convert the created XASL tree to the byte stream for transmission to the server */
8948  err = xts_map_xasl_to_stream (contextp->xasl, &stream);
8949  if (err != NO_ERROR)
8950  {
8952  }
8953  for (i = update->num_assigns - 1; i >= 0; i--)
8954  {
8955  if (update->assigns[i].constant)
8956  {
8957  pr_clear_value (update->assigns[i].constant);
8958  }
8959  }
8960  }
8961  else
8962  {
8963  assert (er_errid () != NO_ERROR);
8964  err = er_errid ();
8965  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number,
8966  er_msg (), NULL);
8967  }
8968 
8969  /* request the server to prepare the query; give XASL stream generated from the parse tree and get XASL
8970  * file id returned */
8971  if (stream.buffer && (err >= NO_ERROR))
8972  {
8973  err = prepare_query (contextp, &stream);
8974 
8975  if (err != NO_ERROR)
8976  {
8977  assert (er_errid () != NO_ERROR);
8978  err = er_errid ();
8979  }
8980  }
8981 
8982  /* mark the end of another level of xasl packing */
8984 
8985  /* As a result of query preparation of the server, the XASL cache for this query will be created or
8986  * updated. */
8987 
8988  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
8989  if (stream.buffer)
8990  {
8991  free_and_init (stream.buffer);
8992  }
8993  statement->flag.use_plan_cache = 0;
8994  }
8995  else
8996  { /* if (!xasl_id) */
8997  spec = statement->info.update.spec;
8998  while (spec && err == NO_ERROR)
8999  {
9000  flat = spec->info.spec.flat_entity_list;
9001  while (flat)
9002  {
9004  {
9005  stream.xasl_id = NULL;
9006  assert (er_errid () != NO_ERROR);
9007  err = er_errid ();
9008  break;
9009  }
9010  flat = flat->next;
9011  }
9012  spec = spec->next;
9013  }
9014  if (err == NO_ERROR)
9015  {
9016  statement->flag.use_plan_cache = 1;
9017  }
9018  else
9019  {
9020  statement->flag.use_plan_cache = 0;
9021  }
9022  }
9023  }
9024  else
9025  { /* if (server_update) */
9026  /*
9027  * OID list update case: (by selecting OIDs to update)
9028  * make SELECT statement for this UPDATE statement
9029  */
9030  PT_NODE *select_statement = NULL;
9031  PT_NODE *select_names = NULL, *select_values = NULL;
9032  PT_NODE *const_names = NULL, *const_values = NULL;
9033  PT_NODE **links = NULL;
9034  int no_vals = 0, no_consts = 0;
9035 
9036  PT_NODE *assigns = statement->info.update.assignment;
9037  PT_NODE *from = statement->info.update.spec;
9038 
9039  err = pt_append_omitted_on_update_expr_assignments (parser, assigns, from);
9040  if (err != NO_ERROR)
9041  {
9042  PT_INTERNAL_ERROR (parser, "update");
9043  break; /* stop while loop if error */
9044  }
9045 
9046  err = pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &no_vals,
9047  &no_consts, statement->info.update.assignment, &links);
9048  if (err != NO_ERROR)
9049  {
9050  PT_INTERNAL_ERROR (parser, "update");
9051  break; /* stop while loop if error */
9052  }
9053 
9054  /* make sure that lhs->info.name.meta_class != PT_META_ATTR */
9055  select_statement =
9056  pt_to_upd_del_query (parser, select_names, select_values, statement->info.update.spec,
9057  statement->info.update.with, statement->info.update.class_specs,
9058  statement->info.update.search_cond, statement->info.update.using_index,
9059  statement->info.update.order_by, statement->info.update.orderby_for, 0, S_UPDATE);
9060 
9061  /* restore tree structure; pt_get_assignment_lists() */
9062  pt_restore_assignment_links (statement->info.update.assignment, links, -1);
9063 
9064  /* translate views or virtual classes into base classes; If we are updating a proxy, the SELECT is not yet
9065  * fully translated. If we are updating anything else, this is a no-op. */
9066 
9067  /* this prevents authorization checking during view transformation */
9068  AU_SAVE_AND_DISABLE (au_save);
9069 
9070  if (select_statement != NULL)
9071  {
9072  err = pt_copy_upddel_hints_to_select (parser, statement, select_statement);
9073  if (err != NO_ERROR)
9074  {
9075  parser_free_tree (parser, select_statement);
9076  break;
9077  }
9078  }
9079  select_statement = mq_translate (parser, select_statement);
9080  AU_RESTORE (au_save);
9081  if (select_statement)
9082  {
9083  /* get XASL_ID by calling do_prepare_select() */
9084  err = do_prepare_select (parser, select_statement);
9085  stream.xasl_id = select_statement->xasl_id;
9086  select_statement->xasl_id = NULL;
9087  parser_free_tree (parser, select_statement);
9088  }
9089  else
9090  {
9092  err = er_errid ();
9093  }
9094 
9095  } /* else (server_update) */
9096 
9097  /* save the XASL_ID that is allocated and returned by prepare_query() into 'statement->xasl_id' to be used by
9098  * do_execute_update() */
9099  statement->xasl_id = stream.xasl_id;
9100 
9101  if (not_nulls)
9102  {
9103  parser_free_tree (parser, not_nulls);
9104  }
9105  }
9106 
9107  return err;
9108 }
9109 
9110 /*
9111  * do_execute_update() - Execute the prepared UPDATE statement
9112  * return: Error code
9113  * parser(in): Parser context
9114  * statement(in): Parse tree of a update statement
9115  *
9116  * Note:
9117  */
9118 int
9120 {
9121  int err, result = 0;
9122  PT_NODE *flat, *spec = NULL;
9123  const char *savepoint_name = NULL;
9124  DB_OBJECT *class_obj;
9125  QFILE_LIST_ID *list_id;
9126  int au_save;
9127  int wait_msecs = -2, old_wait_msecs = -2;
9128  float hint_waitsecs;
9129  PT_NODE *hint_arg;
9130  QUERY_ID query_id_self = parser->query_id;
9131  bool savepoint_started = false;
9132 
9133  assert (parser->query_id == NULL_QUERY_ID);
9134 
9136 
9137  /* savepoint for statement atomicity */
9138  if ((statement != NULL && statement->next != NULL)
9140  && (statement->info.update.object != NULL || !statement->info.update.server_update)))
9141  {
9142  savepoint_name = mq_generate_name (parser, "UmusP", &update_savepoint_number);
9143  if (savepoint_name == NULL)
9144  {
9145  return ER_GENERIC_ERROR;
9146  }
9147  err = tran_system_savepoint (savepoint_name);
9148  if (err != NO_ERROR)
9149  {
9150  return err;
9151  }
9152  savepoint_started = true;
9153  }
9154 
9155  for (err = NO_ERROR, result = 0; statement && (err >= NO_ERROR); statement = statement->next)
9156  {
9157  /*
9158  * Update object case:
9159  * update object by OID
9160  */
9161  if (statement->info.update.object)
9162  {
9163  err = update_object_by_oid (parser, statement, UPDATE_OBJECT);
9164  continue; /* continue to next UPDATE statement */
9165  }
9166 
9167  /* check if it is not necessary to execute this statement, e.g. false where or not prepared correctly */
9168  if (!statement->info.update.do_class_attrs && !statement->xasl_id)
9169  {
9170  statement->etc = NULL;
9171  err = NO_ERROR;
9172  continue; /* continue to next UPDATE statement */
9173  }
9174 
9175  /*
9176  * Server-side update or OID list update case:
9177  * execute the prepared(stored) XASL (UPDATE_PROC or SELECT statement)
9178  */
9179  if (statement->info.update.server_update || !statement->info.update.do_class_attrs)
9180  {
9181  /* Request that the server executes the stored XASL, which is the execution plan of the prepared query, with
9182  * the host variables given by users as parameter values for the query. As a result, query id and result file
9183  * id (QFILE_LIST_ID) will be returned. do_prepare_update() has saved the XASL file id (XASL_ID) in
9184  * 'statement->xasl_id' */
9185 
9186  int query_flag = DEFAULT_EXEC_MODE;
9187 
9188  query_flag |= NOT_FROM_RESULT_CACHE;
9189  query_flag |= RESULT_CACHE_INHIBITED;
9190 
9191  if (parser->flag.is_xasl_pinned_reference)
9192  {
9193  query_flag |= XASL_CACHE_PINNED_REFERENCE;
9194  }
9195 
9196  if (statement->flag.use_auto_commit)
9197  {
9198  query_flag |= EXECUTE_QUERY_WITH_COMMIT;
9199  }
9200 
9201  if (parser->flag.is_auto_commit)
9202  {
9203  query_flag |= TRAN_AUTO_COMMIT;
9204  }
9205 
9206  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
9207  {
9208  do_set_trace_to_query_flag (&query_flag);
9210  }
9211 
9212  // When a transaction is under auto-commit mode, flush all dirty objects to server.
9213  // Otherwise, flush associated objects.
9214  if (statement->flag.use_auto_commit)
9215  {
9216  err = tran_flush_to_commit ();
9217  }
9218  else
9219  {
9220  /* flush necessary objects before execute */
9221  for (spec = statement->info.update.spec; spec != NULL && err == NO_ERROR; spec = spec->next)
9222  {
9223  if (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE)
9224  {
9226  }
9227  }
9228  }
9229 
9230  if (err != NO_ERROR)
9231  {
9232  // flush error
9233  break;
9234  }
9235 
9236  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
9237 
9238  assert (parser->query_id == NULL_QUERY_ID);
9239  list_id = NULL;
9240 
9241  /* check host variables are filled : values from orderby_for may not have been auto-parameterized as host
9242  * variables; if that is the case, do it now */
9243  if (statement->info.update.orderby_for != NULL && parser->auto_param_count == 0)
9244  {
9245  assert ((parser->host_variables == NULL && parser->host_var_count == 0)
9246  || (parser->host_variables != NULL && parser->host_var_count > 0));
9247 
9248  qo_do_auto_parameterize (parser, statement->info.update.orderby_for);
9249  }
9250 
9251  err = execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
9252  parser->host_variables, &list_id, query_flag, NULL, NULL);
9253 
9254  AU_RESTORE (au_save);
9255  if (err != NO_ERROR)
9256  {
9257  break; /* stop while loop if error */
9258  }
9259  }
9260 
9261  if (!statement->info.update.server_update)
9262  {
9263  hint_arg = statement->info.update.waitsecs_hint;
9264  if (statement->info.update.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
9265  {
9266  hint_waitsecs = (float) atof (hint_arg->info.name.original);
9267  if (hint_waitsecs > 0)
9268  {
9269  wait_msecs = (int) (hint_waitsecs * 1000);
9270  }
9271  else
9272  {
9273  wait_msecs = (int) hint_waitsecs;
9274  }
9275  if (wait_msecs >= -1)
9276  {
9277  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
9278  (void) tran_reset_wait_times (wait_msecs);
9279  }
9280  }
9281  AU_SAVE_AND_DISABLE (au_save); /* this prevents authorization checking during execution */
9282  if (statement->info.update.do_class_attrs)
9283  {
9284  /* in case of update class attributes, */
9285  err = update_class_attributes (parser, statement);
9286  }
9287  else
9288  {
9289  /* in the case of OID list update, now update the selected OIDs */
9290  err = update_objs_for_list_file (parser, list_id, statement, savepoint_started);
9291  }
9292 
9293  AU_RESTORE (au_save);
9294  if (old_wait_msecs >= -1)
9295  {
9296  (void) tran_reset_wait_times (old_wait_msecs);
9297  }
9298  }
9299 
9300  if (statement->info.update.server_update || !statement->info.update.do_class_attrs)
9301  {
9302  /* free returned QFILE_LIST_ID */
9303  if (list_id)
9304  {
9305  if (list_id->tuple_cnt > 0 && statement->info.update.server_update)
9306  {
9307  spec = statement->info.update.spec;
9308  while (spec && err == NO_ERROR)
9309  {
9310  if (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE)
9311  {
9312  flat = spec->info.spec.flat_entity_list;
9313  class_obj = (flat) ? flat->info.name.db_object : NULL;
9314  if (statement->flag.use_auto_commit && tran_was_latest_query_committed ())
9315  {
9316  /* Nothing to flush. Avoids flush, since may fetch the class. */
9318  }
9319  else
9320  {
9321  err = sm_flush_and_decache_objects (class_obj, true);
9322  }
9323  }
9324 
9325  spec = spec->next;
9326  }
9327  }
9328  if (err >= NO_ERROR && statement->info.update.server_update)
9329  {
9330  err = list_id->tuple_cnt; /* as a result */
9331  }
9332  cursor_free_self_list_id (list_id);
9333  }
9334  /* end the query; reset query_id and call qmgr_end_query() */
9335  pt_end_query (parser, query_id_self);
9336  }
9337 
9338  /* accumulate intermediate results */
9339  if (err >= NO_ERROR)
9340  {
9341  result += err;
9342  }
9343 
9344  spec = statement->info.update.spec;
9345  while (spec && err == NO_ERROR)
9346  {
9347  if (spec->info.spec.flag & PT_SPEC_FLAG_UPDATE)
9348  {
9349  flat = spec->info.spec.flat_entity_list;
9350  class_obj = (flat) ? flat->info.name.db_object : NULL;
9351 
9352  if (class_obj && (statement->flag.use_auto_commit == false || !tran_was_latest_query_committed ()))
9353  {
9354  err = db_is_vclass (class_obj);
9355  if (err > 0)
9356  {
9357  err = sm_flush_objects (class_obj);
9358  }
9359  }
9360 
9361  }
9362 
9363  spec = spec->next;
9364  }
9365 
9366  if ((err < NO_ERROR) && er_errid () != NO_ERROR)
9367  {
9368  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number,
9369  er_msg (), NULL);
9370  }
9371  }
9372 
9373  /* If error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
9374  * transaction. */
9375  if (err < NO_ERROR && savepoint_name && err != ER_LK_UNILATERALLY_ABORTED)
9376  {
9377  db_abort_to_savepoint (savepoint_name);
9378  }
9379 
9380  return (err < NO_ERROR) ? err : result;
9381 }
9382 
9383 
9384 /*
9385  * Function Group:
9386  * DO functions for delete statements
9387  *
9388  */
9389 
9390 /* used to generate unique savepoint names */
9392 
9393 static int select_delete_list (PARSER_CONTEXT * parser, QFILE_LIST_ID ** result_p, PT_NODE * delete_stmt);
9394 #if defined(ENABLE_UNUSED_FUNCTION)
9395 static int delete_object_by_oid (const PARSER_CONTEXT * parser, const PT_NODE * statement);
9396 #endif /* ENABLE_UNUSED_FUNCTION */
9397 static int delete_list_by_oids (PARSER_CONTEXT * parser, PT_NODE * statement, QFILE_LIST_ID * list_id,
9398  bool savepoint_started);
9399 static int build_xasl_for_server_delete (PARSER_CONTEXT * parser, PT_NODE * statement);
9400 static int delete_real_class (PARSER_CONTEXT * parser, PT_NODE * statement);
9401 
9402 /*
9403  * select_delete_list() -
9404  * return: Error code
9405  * parser(in/out): Parser context
9406  * result(out): QFILE_LIST_ID for query result
9407  * delete_stmt(in): delete statement
9408  *
9409  * Note : The list_id is allocated during query execution
9410  */
9411 static int
9412 select_delete_list (PARSER_CONTEXT * parser, QFILE_LIST_ID ** result_p, PT_NODE * delete_stmt)
9413 {
9414  PT_NODE *statement = NULL;
9415  QFILE_LIST_ID *result = NULL;
9416  int ret = NO_ERROR;
9417 
9418  assert (parser->query_id == NULL_QUERY_ID);
9419  assert (delete_stmt->info.delete_.with == NULL);
9420 
9421  statement = pt_to_upd_del_query (parser, NULL, NULL, delete_stmt->info.delete_.spec, delete_stmt->info.delete_.with,
9422  delete_stmt->info.delete_.class_specs, delete_stmt->info.delete_.search_cond,
9423  delete_stmt->info.delete_.using_index, NULL, NULL,
9424  0 /* not server update */ , S_DELETE);
9425  if (statement != NULL)
9426  {
9427  ret = pt_copy_upddel_hints_to_select (parser, delete_stmt, statement);
9428  if (ret != NO_ERROR)
9429  {
9430  parser_free_tree (parser, statement);
9431  return ret;
9432  }
9433  /* If we are updating a proxy, the select is not yet fully translated. if we are updating anything else, this is
9434  * a no-op. */
9435  statement = mq_translate (parser, statement);
9436 
9437  if (statement)
9438  {
9439  /* This enables authorization checking during methods in queries */
9440  AU_ENABLE (parser->au_save);
9441 
9442  assert (parser->query_id == NULL_QUERY_ID);
9443  if (do_select (parser, statement) < NO_ERROR)
9444  {
9445  /* query failed, an error has already been set */
9446  statement = NULL;
9447  }
9448 
9449  AU_DISABLE (parser->au_save);
9450  }
9451  }
9452 
9453  if (statement)
9454  {
9455  result = (QFILE_LIST_ID *) statement->etc;
9456  parser_free_tree (parser, statement);
9457  }
9458 
9459  *result_p = result;
9460 
9461  if (ret == NO_ERROR)
9462  {
9463  if (er_errid () != NO_ERROR)
9464  {
9465  ret = er_errid ();
9466  }
9467  }
9468 
9469  return ret;
9470 }
9471 
9472 /*
9473  * delete_object_tuple() - Deletes object attributes with db_values
9474  * return: Error code if db_put fails
9475  * object(in): object to delete
9476  */
9477 static int
9479 {
9480  int error = NO_ERROR;
9481  DB_OBJECT *class_obj;
9482  DB_ATTRIBUTE *attr;
9483  if (object == NULL)
9484  {
9485  error = ER_OBJ_INVALID_ARGUMENTS;
9487  }
9488 
9489  /* authorizations checked in compiler--turn off but remember in parser so we can re-enable in case we run out of
9490  * memory and longjmp to the cleanup routine. */
9491 
9492  /* delete blob or clob data files if exist */
9493  class_obj = db_get_class (object);
9494  attr = db_get_attributes (class_obj);
9495  while (attr)
9496  {
9497  if (attr->type->id == DB_TYPE_BLOB || attr->type->id == DB_TYPE_CLOB)
9498  {
9499  DB_VALUE dbvalue;
9500  error = db_get (object, attr->header.name, &dbvalue);
9501  if (error == NO_ERROR && !DB_IS_NULL (&dbvalue))
9502  {
9503  DB_ELO *elo;
9504 
9505  assert (db_value_type (&dbvalue) == DB_TYPE_BLOB || db_value_type (&dbvalue) == DB_TYPE_CLOB);
9506  elo = db_get_elo (&dbvalue);
9507  if (elo)
9508  {
9509  error = db_elo_delete (elo);
9510  }
9511  db_value_clear (&dbvalue);
9512  error = (error >= 0 ? NO_ERROR : error);
9513  }
9514  if (error != NO_ERROR)
9515  {
9517  return error;
9518  }
9519  }
9520  attr = db_attribute_next (attr);
9521  }
9522  /* TODO: to delete blob or clob at db api call */
9523  error = db_drop (object);
9524 
9525  return error;
9526 }
9527 
9528 #if defined(ENABLE_UNUSED_FUNCTION)
9529 /*
9530  * delete_object_by_oid() - Deletes db object by oid.
9531  * return: Error code if delete fails
9532  * parser(in): Parser context
9533  * statement(in): Parse tree representing object to delete
9534  */
9535 static int
9536 delete_object_by_oid (const PARSER_CONTEXT * parser, const PT_NODE * statement)
9537 {
9538  int error = NO_ERROR;
9539 
9540  error = ER_GENERIC_ERROR; /* unimplemented */
9541 
9542  return error;
9543 }
9544 #endif /* ENABLE_UNUSED_FUNCTION */
9545 
9546 /*
9547  * delete_list_by_oids() - Deletes every oid in a list file
9548  * return: Error code if delete fails
9549  * parser(in): Parser context
9550  * statement(in): Delete statement
9551  * list_id(in): A list file of oid's
9552  * savepoint_started(in): true, if savepoint already started
9553  */
9554 static int
9555 delete_list_by_oids (PARSER_CONTEXT * parser, PT_NODE * statement, QFILE_LIST_ID * list_id, bool savepoint_started)
9556 {
9557  int error = NO_ERROR;
9558  int cursor_status;
9559  DB_VALUE *oids = NULL;
9561  int count = 0, attrs_cnt = 0, idx; /* how many objects were deleted? */
9562  const char *savepoint_name = NULL;
9563  int *flush_to_server = NULL;
9564  DB_OBJECT *mop = NULL, *class_obj = NULL;
9565  bool has_savepoint = false, is_cursor_open = false;
9566  PT_NODE *spec;
9567 
9568  if (list_id == NULL)
9569  {
9570  return NO_ERROR;
9571  }
9572 
9573  assert (parser->query_id != NULL_QUERY_ID);
9574  assert (parser->query_id == list_id->query_id);
9575 
9576  spec = statement->info.delete_.spec;
9577  while (spec)
9578  {
9579  if (spec->info.spec.flag & PT_SPEC_FLAG_DELETE)
9580  {
9581  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
9582  /* place IX lock on the class. This should have been done already when the list_id was produced but this is
9583  * the last opportunity we have before actually deleting objects. */
9585  {
9586  assert (er_errid () != NO_ERROR);
9587  return er_errid ();
9588  }
9589  }
9590  spec = spec->next;
9591  }
9592 
9593  /* if the list file contains more than 1 object we need to savepoint the statement to guarantee statement atomicity. */
9594  if (list_id->tuple_cnt >= 1 || TM_TRAN_ISOLATION () >= TRAN_REP_READ)
9595  {
9596  if (savepoint_started == false)
9597  {
9598  savepoint_name = mq_generate_name (parser, "UdsP", &delete_savepoint_number);
9599 
9600  error = tran_system_savepoint (savepoint_name);
9601  if (error != NO_ERROR)
9602  {
9603  goto cleanup;
9604  }
9605  has_savepoint = true;
9606  }
9607  }
9608 
9609  if (!cursor_open (&cursor_id, list_id, false, false))
9610  {
9611  error = ER_GENERIC_ERROR;
9612  goto cleanup;
9613  }
9614  is_cursor_open = true;
9615  attrs_cnt = list_id->type_list.type_cnt;
9616 
9617  oids = (DB_VALUE *) db_private_alloc (NULL, attrs_cnt * sizeof (DB_VALUE));
9618  if (oids == NULL)
9619  {
9620  error = ER_OUT_OF_VIRTUAL_MEMORY;
9621  goto cleanup;
9622  }
9623  flush_to_server = (int *) db_private_alloc (NULL, attrs_cnt * sizeof (int));
9624  if (flush_to_server == NULL)
9625  {
9626  error = ER_OUT_OF_VIRTUAL_MEMORY;
9627  goto cleanup;
9628  }
9629  for (idx = 0; idx < attrs_cnt; idx++)
9630  {
9631  flush_to_server[idx] = -1;
9632  }
9633 
9634  cursor_id.query_id = parser->query_id;
9635  cursor_status = cursor_next_tuple (&cursor_id);
9636 
9637  while ((error >= NO_ERROR) && cursor_status == DB_CURSOR_SUCCESS)
9638  {
9639  error = cursor_get_tuple_value_list (&cursor_id, attrs_cnt, oids);
9640  /* The select list contains instance OID - class OID pairs */
9641  for (idx = 0; idx < attrs_cnt && error >= NO_ERROR; idx++)
9642  {
9643  if (DB_IS_NULL (&oids[idx]))
9644  {
9645  continue;
9646  }
9647 
9648  mop = db_get_object (&oids[idx]);
9649 
9650  error = db_is_deleted (mop);
9651  if (error < 0)
9652  {
9653  return error;
9654  }
9655  if (error > 0)
9656  {
9657  /* if the object is an invalid object (was already deleted) then skip the delete, instance flush and
9658  * count steps */
9659  error = NO_ERROR;
9660  continue;
9661  }
9662 
9663  if (flush_to_server[idx] == -1)
9664  {
9665  /* the following code may be improved to not flush every time */
9667  {
9668  flush_to_server[idx] = 1;
9669  }
9670  else
9671  {
9672  flush_to_server[idx] = 0;
9673  }
9674  }
9675  error = delete_object_tuple (mop);
9677  {
9678  er_clear ();
9679  error = NO_ERROR;
9680  continue;
9681  }
9682 
9683  if ((error >= NO_ERROR) && flush_to_server[idx])
9684  {
9685  error = (locator_flush_instance (mop) == NO_ERROR) ? 0 : (er_errid () != NO_ERROR ? er_errid () : -1);
9686  }
9687 
9688  if (error >= NO_ERROR)
9689  {
9690  count++; /* another object has been deleted */
9691  }
9692  }
9693 
9694  if (error >= NO_ERROR)
9695  {
9696  cursor_status = cursor_next_tuple (&cursor_id);
9697  }
9698  }
9699 
9700  if ((error >= NO_ERROR) && cursor_status != DB_CURSOR_END)
9701  {
9702  error = ER_GENERIC_ERROR;
9703  }
9704 
9705 cleanup:
9706  if (is_cursor_open)
9707  {
9708  cursor_close (&cursor_id);
9709  }
9710 
9711  /* if error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the transaction
9712  * itself. */
9713  if (has_savepoint && (error < NO_ERROR) && savepoint_name && error != ER_LK_UNILATERALLY_ABORTED)
9714  {
9715  (void) tran_abort_upto_system_savepoint (savepoint_name);
9716  }
9717 
9718  if (oids != NULL)
9719  {
9720  db_private_free (NULL, oids);
9721  }
9722 
9723  if (flush_to_server != NULL)
9724  {
9725  db_private_free (NULL, flush_to_server);
9726  }
9727 
9728  if (error >= NO_ERROR)
9729  {
9730  return count;
9731  }
9732  else
9733  {
9734  return error;
9735  }
9736 }
9737 
9738 /*
9739  * build_xasl_for_server_delete() - Build an xasl tree for a server delete
9740  * and execute it.
9741  * return: Error code if delete fails
9742  * parser(in/out): Parser context
9743  * statement(in): Parse tree of a delete statement.
9744  *
9745  * Note:
9746  * The xasl tree has an DELETE_PROC node as the top node and
9747  * a BUILDLIST_PROC as its aptr. The BUILDLIST_PROC selects the
9748  * instance OID. The DELETE_PROC node scans the BUILDLIST_PROC results.
9749  * The server executes the aptr and then for each instance selected,
9750  * deletes it. The result information is sent back to the
9751  * client as a list file without any pages. The list file tuple count
9752  * is used as the return value from this routine.
9753  *
9754  * The instances for the class are flushed from the client before the
9755  * delete is executed. If any instances are deleted, the instances are
9756  * decached from the client after the delete is executed.
9757  */
9758 static int
9760 {
9761  int error = NO_ERROR;
9762  XASL_NODE *xasl = NULL;
9763  DB_OBJECT *class_obj;
9764  int count = 0;
9765  QUERY_ID query_id_self = parser->query_id;
9766  QFILE_LIST_ID *list_id = NULL;
9767  const PT_NODE *node;
9768 
9769  XASL_STREAM stream;
9770 
9771  assert (parser->query_id == NULL_QUERY_ID);
9772 
9773  init_xasl_stream (&stream);
9774 
9775  /* mark the beginning of another level of xasl packing */
9777 
9778  xasl = pt_to_delete_xasl (parser, statement);
9779 
9780  if (xasl)
9781  {
9782  error = xts_map_xasl_to_stream (xasl, &stream);
9783  if (error != NO_ERROR)
9784  {
9786  }
9787  }
9788  else
9789  {
9790  assert (er_errid () != NO_ERROR);
9791  error = er_errid ();
9792  }
9793 
9794  if (error == NO_ERROR)
9795  {
9796  int au_save;
9797  QUERY_FLAG query_flag;
9798 
9799  query_flag = DEFAULT_EXEC_MODE;
9800 
9801  if (parser->flag.is_auto_commit)
9802  {
9803  query_flag |= TRAN_AUTO_COMMIT;
9804  }
9805 
9806  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
9807 
9808  error =
9809  prepare_and_execute_query (stream.buffer, stream.buffer_size, &parser->query_id,
9810  parser->host_var_count + parser->auto_param_count, parser->host_variables, &list_id,
9811  query_flag);
9812  AU_RESTORE (au_save);
9813  }
9814 
9815  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
9816  if (stream.buffer)
9817  {
9818  free_and_init (stream.buffer);
9819  }
9820 
9821  if (list_id)
9822  {
9823  count = list_id->tuple_cnt;
9824  if (count > 0)
9825  {
9826  node = statement->info.delete_.spec;
9827  while (node && error == NO_ERROR)
9828  {
9829  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
9830  {
9831  class_obj = node->info.spec.flat_entity_list->info.name.db_object;
9833  {
9834  /* Nothing to flush. Avoids flush, since may fetch the class. */
9836  }
9837  else
9838  {
9839  error = sm_flush_and_decache_objects (class_obj, true);
9840  }
9841  }
9842 
9843  node = node->next;
9844  }
9845  }
9846  cursor_free_self_list_id (list_id);
9847  }
9848 
9849  pt_end_query (parser, query_id_self);
9850 
9851  /* mark the end of another level of xasl packing */
9853 
9854  if (error >= NO_ERROR)
9855  {
9856  return count;
9857  }
9858  else
9859  {
9860  return error;
9861  }
9862 }
9863 
9864 /*
9865  * has_unique_constraint() - Check if class has an unique constraint
9866  * return: 1 if the class has an unique constraint, otherwise 0
9867  * mop(in/out): Class object to be checked
9868  */
9869 static int
9871 {
9872  DB_CONSTRAINT *constraint_list, *c;
9873  SM_CONSTRAINT_TYPE ctype;
9874 
9875  if (mop == NULL)
9876  {
9877  return 0;
9878  }
9879 
9880  constraint_list = db_get_constraints (mop);
9881  for (c = constraint_list; c; c = c->next)
9882  {
9883  ctype = c->type;
9884  if (SM_IS_CONSTRAINT_UNIQUE_FAMILY (ctype))
9885  {
9886  return 1;
9887  }
9888  }
9889 
9890  return 0;
9891 }
9892 
9893 /*
9894  * delete_real_class() - Deletes objects or rows
9895  * return: Error code if delete fails
9896  * parser(in/out): Parser context
9897  * statement(in): Delete statement
9898  */
9899 static int
9901 {
9902  int error = NO_ERROR;
9903  QFILE_LIST_ID *oid_list = NULL;
9904  int trigger_involved = 0;
9905  MOBJ class_;
9906  DB_OBJECT *class_obj;
9907  int wait_msecs = -2, old_wait_msecs = -2;
9908  float hint_waitsecs;
9909  PT_NODE *hint_arg = NULL, *spec = NULL;
9910  bool has_virt_object = false;
9911 
9912  /* delete a "real" class in this database */
9913 
9914  spec = statement->info.delete_.spec;
9915  while (spec)
9916  {
9917  if (spec->info.spec.flag & PT_SPEC_FLAG_DELETE)
9918  {
9919  class_obj = spec->info.spec.flat_entity_list->info.name.db_object;
9920 
9921  if (spec->info.spec.flat_entity_list->info.name.virt_object)
9922  {
9923  has_virt_object = true;
9924  }
9925  /* place weak lock here, we will upgrade it once the actual DELETE operation starts */
9926  class_ = locator_fetch_class (class_obj, DB_FETCH_READ);
9927  if (class_ == NULL)
9928  {
9929  assert (er_errid () != NO_ERROR);
9930  return er_errid ();
9931  }
9932 
9933  if (!trigger_involved)
9934  {
9935  error = sm_class_has_triggers (class_obj, &trigger_involved, TR_EVENT_DELETE);
9936  if (error != NO_ERROR)
9937  {
9938  return error;
9939  }
9940  }
9941  }
9942 
9943  spec = spec->next;
9944  }
9945 
9946  /* do delete on server if there is no trigger involved and the class is a real class */
9947  if (!trigger_involved && !has_virt_object)
9948  {
9949  error = build_xasl_for_server_delete (parser, statement);
9950  }
9951  else
9952  {
9953  QUERY_ID query_id_self;
9954 
9955  query_id_self = parser->query_id;
9956  parser->query_id = NULL_QUERY_ID;
9957 
9958  hint_arg = statement->info.delete_.waitsecs_hint;
9959  if (statement->info.delete_.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
9960  {
9961  hint_waitsecs = (float) atof (hint_arg->info.name.original);
9962  if (hint_waitsecs > 0)
9963  {
9964  wait_msecs = (int) (hint_waitsecs * 1000);
9965  }
9966  else
9967  {
9968  wait_msecs = (int) hint_waitsecs;
9969  }
9970  if (wait_msecs >= -1)
9971  {
9972  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
9973  (void) tran_reset_wait_times (wait_msecs);
9974  }
9975  }
9976  if (error >= NO_ERROR)
9977  {
9978  /* get the oid's and new values */
9979  error = select_delete_list (parser, &oid_list, statement);
9980  }
9981  if (old_wait_msecs >= -1)
9982  {
9983  (void) tran_reset_wait_times (old_wait_msecs);
9984  }
9985 
9986  if (!oid_list)
9987  {
9988  parser->query_id = query_id_self;
9989  /* an error should be set already, don't lose it */
9990  return error;
9991  }
9992 
9993  /* delete each oid */
9994  error = delete_list_by_oids (parser, statement, oid_list, false);
9995  cursor_free_self_list_id (oid_list);
9996  pt_end_query (parser, query_id_self);
9997  }
9998 
9999  return error;
10000 }
10001 
10002 /*
10003  * do_delete() - Deletes objects or rows
10004  * return: Error code if delete fails
10005  * parser(in/out): Parser context
10006  * statement(in): Delete statement
10007  *
10008  * Note: Returning the number of deleted object on success is a bug fix!
10009  * uci_static expects do_execute_statement to return the number of
10010  * affected objects for a successful DELETE, UPDATE, INSERT, SELECT.
10011  */
10012 int
10013 do_delete (PARSER_CONTEXT * parser, PT_NODE * statement)
10014 {
10015  int error = NO_ERROR;
10016  int result = NO_ERROR;
10017  PT_NODE *spec;
10018  const char *savepoint_name = NULL;
10019 
10021 
10022  /* DON'T REMOVE this, correct authorization validation of views depends on this.
10023  *
10024  * DON'T return from the body of this function. Break out of the loop if necessary. */
10025 
10026  AU_DISABLE (parser->au_save);
10027 
10028  /* savepoint for statement atomicity */
10029  if (statement != NULL && statement->next != NULL)
10030  {
10031  savepoint_name = mq_generate_name (parser, "UmdsP", &delete_savepoint_number);
10032  if (savepoint_name == NULL)
10033  {
10034  error = ER_GENERIC_ERROR;
10035  goto end;
10036  }
10037  error = tran_system_savepoint (savepoint_name);
10038  if (error != NO_ERROR)
10039  {
10040  goto end;
10041  }
10042  }
10043 
10044  while (statement && error >= 0)
10045  {
10046  if (statement->node_type != PT_DELETE)
10047  {
10048  /* bullet proofing, should not get here */
10049  PT_INTERNAL_ERROR (parser, "delete");
10050  error = ER_GENERIC_ERROR;
10051  break;
10052  }
10053 
10054  spec = statement->info.delete_.spec;
10055 
10056  if (pt_false_where (parser, statement))
10057  {
10058  /* nothing to delete, where part is false */
10059  }
10060 #if defined(ENABLE_UNUSED_FUNCTION)
10061  else if (!spec)
10062  {
10063  /* this is an delete object if it has no spec */
10064  error = delete_object_by_oid (parser, statement);
10065  }
10066 #endif /* ENABLE_UNUSED_FUNCTION */
10067  else
10068  {
10069  /* the following is the "normal" sql type execution */
10070  error = delete_real_class (parser, statement);
10071  }
10072 
10073  result += error;
10074  statement = statement->next;
10075  }
10076 
10077  /* if error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
10078  * transaction. */
10079 
10080  if (error < NO_ERROR && savepoint_name && error != ER_LK_UNILATERALLY_ABORTED)
10081  {
10082  db_abort_to_savepoint (savepoint_name);
10083  }
10084 
10085 end:
10086  if (error < 0)
10087  {
10088  result = error;
10089  }
10090 
10091  /* DON'T REMOVE this, correct authorization validation of views depends on this. */
10092 
10093  AU_ENABLE (parser->au_save);
10094 
10095  return result;
10096 }
10097 
10098 /*
10099  * do_prepare_delete() - Prepare the DELETE statement
10100  * return: Error code
10101  * parser(in/out): Parser context
10102  * statement(in/out): Delete statement
10103  * parent(in): Parent statement if using multi-delete list
10104  */
10105 int
10106 do_prepare_delete (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * parent)
10107 {
10108  int err;
10109  PT_NODE *flat;
10110  DB_OBJECT *class_obj;
10111  int has_trigger, au_save, has_any_delete_trigger;
10112  bool server_delete, has_virt_obj;
10113  PT_NODE *node = NULL;
10114  PT_NODE *save_stmt = statement;
10115 
10116  if (parser == NULL)
10117  {
10119  return ER_OBJ_INVALID_ARGUMENTS;
10120  }
10121 
10122  for (err = NO_ERROR; statement && (err >= NO_ERROR); statement = statement->next)
10123  {
10124  COMPILE_CONTEXT *contextp;
10125  XASL_STREAM stream;
10126 
10127  contextp = &parser->context;
10128 
10129  init_xasl_stream (&stream);
10130 
10131  contextp->sql_user_text = statement->sql_user_text;
10132  contextp->sql_user_text_len = statement->sql_user_text_len;
10133 
10134  /* there can be no results, this is a compile time false where clause */
10135  if (pt_false_where (parser, statement))
10136  {
10137  /* tell to the execute routine that there's no XASL to execute */
10138  statement->xasl_id = NULL;
10139  err = NO_ERROR;
10140  continue; /* continue to next DELETE statement */
10141  }
10142 
10143  /* Delete object case: this is an delete object if it has no spec */
10144  if (!statement->info.delete_.spec)
10145  {
10146  statement->etc = NULL;
10147  err = NO_ERROR;
10148  continue; /* continue to next DELETE statement */
10149  }
10150 
10151  /* if already prepared */
10152  if (statement->xasl_id)
10153  {
10154  continue; /* continue to next DELETE statement */
10155  }
10156 
10157  err = pt_split_delete_stmt (parser, statement);
10158  if (err != NO_ERROR)
10159  {
10160  break;
10161  }
10162 
10163  /* the presence of a proxy trigger should force the delete to be performed through the workspace */
10164  AU_SAVE_AND_DISABLE (au_save); /* because sm_class_has_trigger() calls au_fetch_class() */
10165  has_virt_obj = false;
10166  has_trigger = 0;
10167  has_any_delete_trigger = 0;
10168  node = (PT_NODE *) statement->info.delete_.spec;
10169  while (node && err == NO_ERROR && !has_trigger)
10170  {
10171  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
10172  {
10173  flat = node->info.spec.flat_entity_list;
10174  if (flat)
10175  {
10176  if (flat->info.name.virt_object)
10177  {
10178  has_virt_obj = true;
10179  }
10180  class_obj = flat->info.name.db_object;
10181  }
10182  else
10183  {
10184  class_obj = NULL;
10185  }
10186  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_DELETE);
10187 
10188  if (err == NO_ERROR)
10189  {
10190  if (has_trigger)
10191  {
10192  has_any_delete_trigger = has_trigger;
10193  }
10194  else if (!has_any_delete_trigger)
10195  {
10196  /* Check for statement delete triggerrs. */
10197  err = sm_class_has_triggers (class_obj, &has_any_delete_trigger, TR_EVENT_STATEMENT_DELETE);
10198  }
10199  }
10200  }
10201 
10202  node = node->next;
10203  }
10204 
10205  AU_RESTORE (au_save);
10206  /* err = has_proxy_trigger(flat, &has_trigger); */
10207  if (err != NO_ERROR)
10208  {
10209  PT_INTERNAL_ERROR (parser, "delete");
10210  break; /* stop while loop if error */
10211  }
10212  /* sm_class_has_triggers() checked if the class has active triggers */
10213  statement->info.delete_.has_trigger = has_trigger;
10214 
10215  /* determine whether it can be server-side or OID list deletion */
10216  server_delete = (!has_trigger && !has_virt_obj);
10217 
10218  statement->info.delete_.server_delete = server_delete;
10219  if (server_delete && !has_any_delete_trigger && !(statement->info.delete_.hint & PT_HINT_USE_SBR))
10220  {
10221  statement->info.delete_.execute_with_commit_allowed = 1;
10222  }
10223 
10224  stream.xasl_id = NULL;
10225  if (server_delete)
10226  {
10227  /* Server-side deletion case: (by requesting server to execute XASL) build DELETE_PROC XASL */
10228 
10229  /* make query string */
10230  parser->flag.dont_prt_long_string = 1;
10231  parser->flag.long_string_skipped = 0;
10232  parser->flag.print_type_ambiguity = 0;
10234  contextp->sql_hash_text = (char *) statement->alias_print;
10235  err =
10236  SHA1Compute ((unsigned char *) contextp->sql_hash_text, (unsigned) strlen (contextp->sql_hash_text),
10237  &contextp->sha1);
10238  if (err != NO_ERROR)
10239  {
10240  ASSERT_ERROR ();
10241  return err;
10242  }
10243  parser->flag.dont_prt_long_string = 0;
10244  if (parser->flag.long_string_skipped || parser->flag.print_type_ambiguity)
10245  {
10246  statement->flag.cannot_prepare = 1;
10247  err = NO_ERROR;
10248  break;
10249  }
10250 
10251  /* look up server's XASL cache for this query string and get XASL file id (XASL_ID) returned if found */
10252  contextp->recompile_xasl = statement->flag.recompile;
10253  if (statement->flag.recompile == 0)
10254  {
10255  err = prepare_query (contextp, &stream);
10256  if (err != NO_ERROR)
10257  {
10258  ASSERT_ERROR_AND_SET (err);
10259  }
10260  else if (contextp->recompile_xasl == true)
10261  {
10262  /* recompile requested by server */
10263  if (stream.xasl_id != NULL)
10264  {
10265  free_and_init (stream.xasl_id);
10266  }
10267  }
10268  }
10269  if (stream.xasl_id == NULL && err == NO_ERROR)
10270  {
10271  /* cache not found; make XASL from the parse tree including query optimization and plan generation */
10272 
10273  /* mark the beginning of another level of xasl packing */
10275 
10276  /* this prevents authorization checking during generating XASL */
10277  AU_SAVE_AND_DISABLE (au_save);
10278 
10279  /* pt_to_delete_xasl() will build XASL tree from parse tree */
10280  contextp->xasl = pt_to_delete_xasl (parser, statement);
10281  AU_RESTORE (au_save);
10282 
10283  if (contextp->xasl && (err >= NO_ERROR))
10284  {
10285  /* convert the created XASL tree to the byte stream for transmission to the server */
10286  err = xts_map_xasl_to_stream (contextp->xasl, &stream);
10287  if (err != NO_ERROR)
10288  {
10290  }
10291  }
10292  else
10293  {
10294  assert (er_errid () != NO_ERROR);
10295  err = er_errid ();
10296  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number,
10297  er_msg (), NULL);
10298  }
10299 
10300  /* request the server to prepare the query; give XASL stream generated from the parse tree and get XASL
10301  * file id returned */
10302  if (stream.buffer && (err >= NO_ERROR))
10303  {
10304  err = prepare_query (contextp, &stream);
10305  if (err != NO_ERROR)
10306  {
10307  assert (er_errid () != NO_ERROR);
10308  err = er_errid ();
10309  }
10310  }
10311 
10312  /* mark the end of another level of xasl packing */
10314 
10315  /* As a result of query preparation of the server, the XASL cache for this query will be created or
10316  * updated. */
10317 
10318  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
10319  if (stream.buffer)
10320  {
10321  free_and_init (stream.buffer);
10322  }
10323  statement->flag.use_plan_cache = 0;
10324  }
10325  else
10326  {
10327  if (err == NO_ERROR)
10328  {
10329  statement->flag.use_plan_cache = 1;
10330  }
10331  else
10332  {
10333  statement->flag.use_plan_cache = 0;
10334  }
10335  }
10336  }
10337  else
10338  {
10339  /* OID list deletion case: (by selecting OIDs to delete) make SELECT statement for this DELETE statement */
10340 
10341  PT_NODE *select_statement;
10342  PT_DELETE_INFO *delete_info;
10343 
10344  delete_info = &statement->info.delete_;
10345 
10346  select_statement =
10347  pt_to_upd_del_query (parser, NULL, NULL, delete_info->spec, delete_info->with, delete_info->class_specs,
10348  delete_info->search_cond, delete_info->using_index, NULL, NULL, 0, S_DELETE);
10349  err = pt_copy_upddel_hints_to_select (parser, statement, select_statement);
10350  if (err != NO_ERROR)
10351  {
10352  parser_free_tree (parser, select_statement);
10353  break;
10354  }
10355  /* translate views or virtual classes into base classes; If we are updating a proxy, the SELECT is not yet
10356  * fully translated. If we are updating anything else, this is a no-op. */
10357 
10358  /* this prevents authorization checking during view transformation */
10359  AU_SAVE_AND_DISABLE (au_save);
10360 
10361  select_statement = mq_translate (parser, select_statement);
10362  AU_RESTORE (au_save);
10363  if (select_statement)
10364  {
10365  /* get XASL_ID by calling do_prepare_select() */
10366  err = do_prepare_select (parser, select_statement);
10367  stream.xasl_id = select_statement->xasl_id;
10368  select_statement->xasl_id = NULL;
10369  parser_free_tree (parser, select_statement);
10370  }
10371  else
10372  {
10374  err = er_errid ();
10375  }
10376  }
10377 
10378  if (statement->info.delete_.del_stmt_list != NULL)
10379  {
10380  err = do_prepare_delete (parser, statement->info.delete_.del_stmt_list, statement);
10381  if (err != NO_ERROR)
10382  {
10383  break;
10384  }
10385  }
10386 
10387  /* save the XASL_ID that is allocated and returned by prepare_query() into 'statement->xasl_id' to be used by
10388  * do_execute_delete() */
10389  statement->xasl_id = stream.xasl_id;
10390  }
10391 
10392  /* if something failed or cannot be prepared in in del_stmt_list clear all statement->xasl_id */
10393  if (err != NO_ERROR || (statement != NULL && statement->flag.cannot_prepare == 1))
10394  {
10395  for (node = save_stmt; node != statement; node = node->next)
10396  {
10398  }
10399  if (err == NO_ERROR && parent != NULL)
10400  {
10401  /* set cannot_prepare to parent */
10402  parent->flag.cannot_prepare = 1;
10403  }
10404  }
10405 
10406  return err;
10407 }
10408 
10409 /*
10410  * do_execute_delete() - Execute the prepared DELETE statement
10411  * return: Tuple count if success, otherwise an error code
10412  * parser(in): Parser context
10413  * statement(in): Delete statement
10414  */
10415 int
10417 {
10418  int err, result = 0;
10419  PT_NODE *flat, *node;
10420  const char *savepoint_name = NULL;
10421  DB_OBJECT *class_obj;
10422  QFILE_LIST_ID *list_id;
10423  int au_save;
10424  int wait_msecs = -2, old_wait_msecs = -2;
10425  float hint_waitsecs;
10426  PT_NODE *hint_arg;
10427  int query_flag;
10428  QUERY_ID query_id_self = parser->query_id;
10429  bool savepoint_started = false;
10430 
10431  assert (parser->query_id == NULL_QUERY_ID);
10432 
10434 
10435  /* savepoint for statement atomicity */
10436  if ((statement != NULL && statement->next != NULL)
10437  || (TM_TRAN_ISOLATION () >= TRAN_REP_READ && !statement->info.delete_.server_delete))
10438  {
10439  savepoint_name = mq_generate_name (parser, "UmdsP", &delete_savepoint_number);
10440  if (savepoint_name == NULL)
10441  {
10442  return ER_GENERIC_ERROR;
10443  }
10444  err = tran_system_savepoint (savepoint_name);
10445  if (err != NO_ERROR)
10446  {
10447  return err;
10448  }
10449 
10450  savepoint_started = true;
10451  }
10452 
10453  for (err = NO_ERROR, result = 0; statement && (err >= NO_ERROR); statement = statement->next)
10454  {
10455 #if defined(ENABLE_UNUSED_FUNCTION)
10456  /* Delete object case: delete object by OID */
10457 
10458  if (!statement->info.delete_.spec)
10459  {
10460  err = delete_object_by_oid (parser, statement);
10461  continue; /* continue to next DELETE statement */
10462  }
10463 #endif /* ENABLE_UNUSED_FUNCTION */
10464 
10465  /* check if it is not necessary to execute this statement, e.g. false where or not prepared correctly */
10466  if (!statement->xasl_id)
10467  {
10468  statement->etc = NULL;
10469  err = NO_ERROR;
10470  continue; /* continue to next DELETE statement */
10471  }
10472 
10473  /* Server-side deletion or OID list deletion case: execute the prepared(stored) XASL (DELETE_PROC or SELECT
10474  * statement) */
10475 
10476  /* Request that the server executes the stored XASL, which is the execution plan of the prepared query, with the
10477  * host variables given by users as parameter values for the query. As a result, query id and result file id
10478  * (QFILE_LIST_ID) will be returned. do_prepare_delete() has saved the XASL file id (XASL_ID) in
10479  * 'statement->xasl_id' */
10480 
10481  query_flag = DEFAULT_EXEC_MODE;
10482  query_flag |= NOT_FROM_RESULT_CACHE;
10483  query_flag |= RESULT_CACHE_INHIBITED;
10484 
10485  if (parser->flag.is_xasl_pinned_reference)
10486  {
10487  query_flag |= XASL_CACHE_PINNED_REFERENCE;
10488  }
10489 
10490  if (statement->flag.use_auto_commit)
10491  {
10492  query_flag |= EXECUTE_QUERY_WITH_COMMIT;
10493  }
10494 
10495  if (parser->flag.is_auto_commit)
10496  {
10497  query_flag |= TRAN_AUTO_COMMIT;
10498  }
10499 
10500  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
10501  {
10502  do_set_trace_to_query_flag (&query_flag);
10504  }
10505 
10506  // When a transaction is under auto-commit mode, flush all dirty objects to server.
10507  // Otherwise, flush associated objects.
10508  if (statement->flag.use_auto_commit)
10509  {
10510  err = tran_flush_to_commit ();
10511  }
10512  else
10513  {
10514  for (node = statement->info.delete_.spec; node && err == NO_ERROR; node = node->next)
10515  {
10516  flat = node->info.spec.flat_entity_list;
10517  if (flat != NULL)
10518  {
10519  /* flush necessary objects before execute */
10520  err = sm_flush_objects (flat->info.name.db_object);
10521  }
10522  }
10523  }
10524 
10525  if (err != NO_ERROR)
10526  {
10527  // flush error
10528  break;
10529  }
10530 
10531  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
10532 
10533  assert (parser->query_id == NULL_QUERY_ID);
10534  list_id = NULL;
10535  err = execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
10536  parser->host_variables, &list_id, query_flag, NULL, NULL);
10537 
10538  AU_RESTORE (au_save);
10539 
10540  /* in the case of OID list deletion, now delete the selected OIDs */
10541  if ((err >= NO_ERROR) && list_id)
10542  {
10543  if (statement->info.delete_.server_delete)
10544  {
10545  err = list_id->tuple_cnt;
10546  }
10547  else
10548  {
10549  hint_arg = statement->info.delete_.waitsecs_hint;
10550  if (statement->info.delete_.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
10551  {
10552  hint_waitsecs = (float) atof (hint_arg->info.name.original);
10553  if (hint_waitsecs > 0)
10554  {
10555  wait_msecs = (int) (hint_waitsecs * 1000);
10556  }
10557  else
10558  {
10559  wait_msecs = (int) hint_waitsecs;
10560  }
10561  if (wait_msecs >= -1)
10562  {
10563  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
10564  (void) tran_reset_wait_times (wait_msecs);
10565  }
10566  }
10567  AU_SAVE_AND_DISABLE (au_save); /* this prevents authorization checking during execution */
10568  /* delete each oid */
10569  err = delete_list_by_oids (parser, statement, list_id, savepoint_started);
10570  AU_RESTORE (au_save);
10571  if (old_wait_msecs >= -1)
10572  {
10573  (void) tran_reset_wait_times (old_wait_msecs);
10574  }
10575  }
10576  }
10577 
10578  /* free returned QFILE_LIST_ID */
10579  if (list_id)
10580  {
10581  if (list_id->tuple_cnt > 0 && statement->info.delete_.server_delete)
10582  {
10583  int err2 = NO_ERROR;
10584  node = statement->info.delete_.spec;
10585 
10586  while (node && err2 >= NO_ERROR)
10587  {
10588  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
10589  {
10590  flat = node->info.spec.flat_entity_list;
10591  class_obj = (flat) ? flat->info.name.db_object : NULL;
10592 
10593  if (statement->flag.use_auto_commit && tran_was_latest_query_committed ())
10594  {
10595  /* Nothing to flush. Avoids flush, since may fetch the class. */
10597  }
10598  else
10599  {
10600  err2 = sm_flush_and_decache_objects (class_obj, true);
10601  }
10602  }
10603 
10604  node = node->next;
10605  }
10606  if (err2 != NO_ERROR)
10607  {
10608  err = err2;
10609  }
10610  }
10611  cursor_free_self_list_id (list_id);
10612  }
10613 
10614  /* end the query; reset query_id and call qmgr_end_query() */
10615  pt_end_query (parser, query_id_self);
10616 
10617  /* accumulate intermediate results */
10618  if (err >= NO_ERROR)
10619  {
10620  result += err;
10621  }
10622 
10623  node = statement->info.delete_.spec;
10624 
10625  while (node && err >= NO_ERROR)
10626  {
10627  if (node->info.spec.flag & PT_SPEC_FLAG_DELETE)
10628  {
10629  flat = node->info.spec.flat_entity_list;
10630  class_obj = (flat) ? flat->info.name.db_object : NULL;
10631 
10632  if (class_obj && (statement->flag.use_auto_commit == false || !tran_was_latest_query_committed ()))
10633  {
10634  err = db_is_vclass (class_obj);
10635  if (err > 0)
10636  {
10637  err = sm_flush_objects (class_obj);
10638  }
10639  }
10640  }
10641 
10642  node = node->next;
10643  }
10644  }
10645 
10646  /* If error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
10647  * transaction. */
10648  if (err < NO_ERROR && savepoint_name && err != ER_LK_UNILATERALLY_ABORTED)
10649  {
10650  db_abort_to_savepoint (savepoint_name);
10651  }
10652 
10653  return (err < NO_ERROR) ? err : result;
10654 }
10655 
10656 
10657 /*
10658  * Function Group:
10659  * Implements the evaluate statement.
10660  *
10661  */
10662 
10663 
10664 /*
10665  * do_evaluate() - Evaluates an expression
10666  * return: Error code
10667  * parser(in): Parser context
10668  * statement(in/out): Parse tree of a insert statement
10669  */
10670 int
10671 do_evaluate (PARSER_CONTEXT * parser, PT_NODE * statement)
10672 {
10673  int error = NO_ERROR;
10674  DB_VALUE expr_value, *into_val;
10675  PT_NODE *expr, *into_var;
10676  const char *into_label;
10677 
10678  db_make_null (&expr_value);
10679 
10680  if (!statement || !((expr = statement->info.evaluate.expression)))
10681  {
10682  return ER_GENERIC_ERROR;
10683  }
10684 
10685  pt_evaluate_tree (parser, expr, &expr_value, 1);
10686  if (pt_has_error (parser))
10687  {
10688  pt_report_to_ersys (parser, PT_SEMANTIC);
10689  return ER_PT_SEMANTIC;
10690  }
10691 
10692  statement->etc = (void *) db_value_copy (&expr_value);
10693  into_var = statement->info.evaluate.into_var;
10694 
10695  if (into_var && into_var->node_type == PT_NAME && (into_label = into_var->info.name.original) != NULL)
10696  {
10697  /* create another DB_VALUE of the new instance for the label_table */
10698  into_val = db_value_copy (&expr_value);
10699 
10700  /* enter {label, ins_val} pair into the label_table */
10701  error = pt_associate_label_with_value_check_reference (into_label, into_val);
10702  }
10703 
10704  pr_clear_value (&expr_value);
10705  return error;
10706 }
10707 
10708 
10709 
10710 
10711 
10712 /*
10713  * Function Group:
10714  * DO functions for insert statements
10715  *
10716  */
10717 
10718 
10719 typedef enum
10720 {
10723 #if defined(ENABLE_UNUSED_FUNCTION)
10724  /*
10725  * NOT USED ANY MORE.
10726  * prm_insert_mode_upper is still left as 31 for backward compatibility.
10727  *
10728  */
10729  INSERT_DEFAULT = 4,
10730  INSERT_REPLACE = 8,
10731  INSERT_ON_DUP_KEY_UPDATE = 16
10732 #endif /* ENABLE_UNUSED_FUNCTION */
10734 
10737 {
10738  PT_NODE *insert_stmt; /* insert statement */
10739  CURSOR_ID *cursor_p; /* select cursor id */
10740 };
10741 
10742 /* used to generate unique savepoint names */
10744 
10745 static int insert_object_attr (const PARSER_CONTEXT * parser, DB_OTMPL * otemplate, DB_VALUE * value, PT_NODE * name,
10746  DB_ATTDESC * attr_desc);
10747 static int check_for_cons (PARSER_CONTEXT * parser, int *has_unique, PT_NODE ** non_null_attrs,
10748  const PT_NODE * attr_list, DB_OBJECT * class_obj);
10749 static int is_server_insert_allowed (PARSER_CONTEXT * parser, PT_NODE * statement);
10750 static int do_insert_at_server (PARSER_CONTEXT * parser, PT_NODE * statement);
10751 static int insert_subquery_results (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * values_list,
10752  PT_NODE * class_, const char **savepoint_name);
10753 static int is_attr_not_in_insert_list (const PARSER_CONTEXT * parser, PT_NODE * name_list, const char *name);
10754 static int check_missing_non_null_attrs (const PARSER_CONTEXT * parser, const PT_NODE * spec, PT_NODE * attr_list,
10755  const bool has_default_values_list);
10756 static PT_NODE *make_vmops (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
10757 static PT_NODE *test_check_option (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
10758 static int insert_local (PARSER_CONTEXT * parser, PT_NODE * statement);
10759 static PT_NODE *do_create_odku_stmt (PARSER_CONTEXT * parser, PT_NODE * insert);
10760 static int do_find_unique_constraint_violations (DB_OTMPL * tmpl, bool for_update, OID ** oids, int *oids_count);
10761 static int do_create_midxkey_for_constraint (DB_OTMPL * tmpl, SM_CLASS_CONSTRAINT * constraint, DB_VALUE * key);
10762 static int do_on_duplicate_key_update (PARSER_CONTEXT * parser, DB_OTMPL * tpl, PT_NODE * update_stmt);
10763 static int do_replace_into (PARSER_CONTEXT * parser, DB_OTMPL * tmpl, PT_NODE * spec, PT_NODE * class_specs);
10764 static int is_replace_or_odku_allowed (DB_OBJECT * obj, int *allowed);
10765 static PT_NODE *pt_append_odku_references (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
10766 static PT_NODE *do_check_insert_server_allowed (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk);
10767 static PT_NODE *do_set_insert_server_not_allowed (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg,
10768  int *continue_walk);
10769 /*
10770  * insert_object_attr()
10771  * return: Error code if db_put fails
10772  * parser(in): Short description of the param1
10773  * otemplate(in/out): Short description of the param2
10774  * value(in/out): New attr value
10775  * name(in): Name to update
10776  * attr_desc(in): Attr descriptor of attribute to update
10777  */
10778 static int
10779 insert_object_attr (const PARSER_CONTEXT * parser, DB_OTMPL * otemplate, DB_VALUE * value, PT_NODE * name,
10780  DB_ATTDESC * attr_desc)
10781 {
10782  int error = NO_ERROR;
10783 
10784  if (DB_VALUE_TYPE (value) == DB_TYPE_OBJECT && !DB_IS_NULL (value))
10785  {
10786  /* we may need to check for value coming in from a parameter or host variable as a
10787  * not-yet-translated-to-real-class value. This must be done at run time in general. */
10788  db_make_object (value, db_real_instance (db_get_object (value)));
10789  }
10790 
10791  if (name->info.name.db_object)
10792  {
10793  error = db_is_vclass (name->info.name.db_object);
10794  }
10795  if (error > 0)
10796  {
10797  /* this is a shared attribute of a view. this means this cannot be updated in the template for this real class.
10798  * Its simply done separately by a db_put. */
10799  error = obj_set_shared (name->info.name.db_object, name->info.name.original, value);
10800  }
10801  else if (!error)
10802  {
10803  /* the normal case */
10804  SM_ATTRIBUTE *att;
10805 
10806  att = db_get_attribute (otemplate->classobj, name->info.name.original);
10807  error = dbt_dput_internal (otemplate, attr_desc, value);
10808  }
10809 
10810  return error;
10811 }
10812 
10813 
10814 /*
10815  * do_prepare_insert_internal () - Prepares insert statement for server
10816  * execution.
10817  *
10818  * return : Error code.
10819  * parser (in) : Parser context.
10820  * statement (in) : Parse tree node for insert statement.
10821  */
10822 static int
10824 {
10825  int error = NO_ERROR;
10826  PT_NODE *val = NULL, *head = NULL, *prev = NULL;
10827  PT_NODE *value_list = NULL;
10828 
10829  COMPILE_CONTEXT *contextp;
10830  XASL_STREAM stream;
10831 
10832  contextp = &parser->context;
10833 
10834  init_xasl_stream (&stream);
10835 
10836  if (!parser || !statement || statement->node_type != PT_INSERT)
10837  {
10838  assert (false);
10839  return ER_GENERIC_ERROR;
10840  }
10841 
10842  contextp->sql_user_text = statement->sql_user_text;
10843  contextp->sql_user_text_len = statement->sql_user_text_len;
10844 
10845  /* insert value auto parameterize */
10846  for (value_list = statement->info.insert.value_clauses; value_list != NULL; value_list = value_list->next)
10847  {
10848  head = NULL;
10849  prev = NULL;
10850  for (val = value_list->info.node_list.list; val != NULL; val = val->next)
10851  {
10852  if (pt_is_const_not_hostvar (val) && !PT_IS_NULL_NODE (val))
10853  {
10854  val = pt_rewrite_to_auto_param (parser, val);
10855  if (prev != NULL)
10856  {
10857  prev->next = val;
10858  }
10859 
10860  if (val == NULL)
10861  {
10862  break;
10863  }
10864  }
10865 
10866  if (head == NULL)
10867  {
10868  head = val;
10869  }
10870 
10871  prev = val;
10872  }
10873  value_list->info.node_list.list = head;
10874  }
10875 
10876  /* make query string */
10877  parser->flag.dont_prt_long_string = 1;
10878  parser->flag.long_string_skipped = 0;
10879  parser->flag.print_type_ambiguity = 0;
10881  contextp->sql_hash_text = (char *) statement->alias_print;
10882  error =
10883  SHA1Compute ((unsigned char *) contextp->sql_hash_text, (unsigned) strlen (contextp->sql_hash_text),
10884  &contextp->sha1);
10885  if (error != NO_ERROR)
10886  {
10887  ASSERT_ERROR ();
10888  return error;
10889  }
10890  parser->flag.dont_prt_long_string = 0;
10891  if (parser->flag.long_string_skipped || parser->flag.print_type_ambiguity)
10892  {
10893  statement->flag.cannot_prepare = 1;
10894  return NO_ERROR;
10895  }
10896 
10897  /* look up server's XASL cache for this query string and get XASL file id (XASL_ID) returned if found */
10898  contextp->recompile_xasl = statement->flag.recompile;
10899  if (statement->flag.recompile == 0)
10900  {
10901  error = prepare_query (contextp, &stream);
10902  if (error != NO_ERROR)
10903  {
10904  ASSERT_ERROR_AND_SET (error);
10905  }
10906  else if (contextp->recompile_xasl == true)
10907  {
10908  /* recompile requested by server */
10909  if (stream.xasl_id != NULL)
10910  {
10911  free_and_init (stream.xasl_id);
10912  }
10913  }
10914  }
10915 
10916  if (stream.xasl_id == NULL && error == NO_ERROR)
10917  {
10918  /* mark the beginning of another level of xasl packing */
10920  contextp->xasl = pt_to_insert_xasl (parser, statement);
10921 
10922  if (contextp->xasl)
10923  {
10924  assert (contextp->xasl->dptr_list == NULL);
10925 
10926  if (error == NO_ERROR)
10927  {
10928  error = xts_map_xasl_to_stream (contextp->xasl, &stream);
10929  if (error != NO_ERROR)
10930  {
10932  }
10933  }
10934  }
10935  else
10936  {
10937  assert (er_errid () != NO_ERROR);
10938  error = er_errid ();
10939  }
10940 
10941  if (stream.buffer && (error >= NO_ERROR))
10942  {
10943  error = prepare_query (contextp, &stream);
10944  if (error != NO_ERROR)
10945  {
10946  assert (er_errid () != NO_ERROR);
10947  error = er_errid ();
10948  }
10949  }
10950 
10951  /* mark the end of another level of xasl packing */
10953 
10954  /* As a result of query preparation of the server, the XASL cache for this query will be created or updated. */
10955 
10956  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
10957  if (stream.buffer)
10958  {
10959  free_and_init (stream.buffer);
10960  }
10961 
10962  statement->flag.use_plan_cache = 0;
10963  }
10964  else
10965  {
10966  if (error == NO_ERROR)
10967  {
10968  statement->flag.use_plan_cache = 1;
10969  }
10970  else
10971  {
10972  statement->flag.use_plan_cache = 0;
10973  }
10974  }
10975 
10976  /* save the XASL_ID that is allocated and returned by prepare_query() into 'statement->xasl_id' to be used by
10977  * do_execute_update() */
10978  statement->xasl_id = stream.xasl_id;
10979 
10980  return NO_ERROR;
10981 }
10982 
10983 /*
10984  * do_insert_at_server () - Builds an xasl tree for a server insert and
10985  * executes it.
10986  *
10987  * return : Error code.
10988  * parser (in) : Parser context.
10989  * statement (in) : Parse tree node for insert statement.
10990  *
10991  * NOTE:
10992  * The xasl tree has an INSERT_PROC node as the top node and
10993  * a BUILDLIST_PROC as its aptr. The BUILDLIST_PROC selects the
10994  * insert values. The INSERT_PROC node scans the BUILDLIST_PROC results.
10995  * The server executes the aptr and then for each instance selected,
10996  * inserts it. The result information is sent back to the
10997  * client as a list file without any pages. The list file tuple count
10998  * is used as the return value from this routine.
10999 
11000  * The instances for the class are flushed from the client before the
11001  * insert is executed.
11002  */
11003 static int
11005 {
11006  int error = NO_ERROR;
11007  XASL_NODE *xasl = NULL;
11008  int count = 0;
11009  QUERY_ID query_id_self = parser->query_id;
11010  QFILE_LIST_ID *list_id = NULL;
11011 
11012  XASL_STREAM stream;
11013 
11014  assert (parser->query_id == NULL_QUERY_ID);
11015 
11016  init_xasl_stream (&stream);
11017 
11018  if (parser == NULL || statement == NULL || statement->node_type != PT_INSERT)
11019  {
11020  return ER_GENERIC_ERROR;
11021  }
11022 
11023  /* mark the beginning of another level of xasl packing */
11025  xasl = pt_to_insert_xasl (parser, statement);
11026 
11027  if (xasl)
11028  {
11029  error = xts_map_xasl_to_stream (xasl, &stream);
11030  if (error != NO_ERROR)
11031  {
11033  }
11034  }
11035  else
11036  {
11037  assert (er_errid () != NO_ERROR);
11038  error = er_errid ();
11039  }
11040 
11041  if (error == NO_ERROR && stream.buffer != NULL)
11042  {
11043  int au_save;
11044  QUERY_FLAG query_flag;
11045 
11046  query_flag = DEFAULT_EXEC_MODE;
11047  /* Do not update LAST_INSERT_ID during executing a trigger. */
11048  if (do_Trigger_involved == true)
11049  {
11050  query_flag |= TRIGGER_IS_INVOLVED;
11051  }
11052 
11053  if (parser->flag.is_auto_commit)
11054  {
11055  query_flag |= TRAN_AUTO_COMMIT;
11056  }
11057 
11058  assert (stream.buffer_size > 0);
11059 
11060  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
11061 
11062  error =
11063  prepare_and_execute_query (stream.buffer, stream.buffer_size, &parser->query_id,
11064  (parser->host_var_count + parser->auto_param_count), parser->host_variables,
11065  &list_id, query_flag);
11066  AU_RESTORE (au_save);
11067  }
11068 
11069  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
11070  if (stream.buffer)
11071  {
11072  free_and_init (stream.buffer);
11073  }
11074 
11075  if (list_id)
11076  {
11077  count = list_id->tuple_cnt;
11078  if (count > 0 && (statement->info.insert.odku_assignments != NULL || statement->info.insert.do_replace))
11079  {
11080  MOP class_obj = statement->info.insert.spec->info.spec.flat_entity_list->info.name.db_object;
11081 
11083  {
11084  /* Nothing to flush. Avoids flush, since may fetch the class. */
11086  }
11087  else
11088  {
11089  error = sm_flush_and_decache_objects (class_obj, true);
11090  }
11091  }
11092 
11093  if (parser->flag.return_generated_keys)
11094  {
11095  statement->etc = (void *) list_id;
11096  }
11097  else
11098  {
11099  cursor_free_self_list_id (list_id);
11100  }
11101  }
11102 
11103  pt_end_query (parser, query_id_self);
11104 
11105  /* mark the end of another level of xasl packing */
11107 
11108  if (error >= NO_ERROR)
11109  {
11110  return count;
11111  }
11112  else
11113  {
11114  return error;
11115  }
11116 }
11117 
11118 /*
11119  * check_for_cons() - Determines whether an attribute has not null or unique
11120  * constraints.
11121  *
11122  * return: Error code
11123  * parser(in): Parser context
11124  * has_unique(in/out):
11125  * non_null_attrs(in/out): all the "NOT NULL" attributes except for the
11126  * AUTO_INCREMENT ones
11127  * attr_list(in): Parse tree of an insert statement attribute list
11128  * class_obj(in): Class object
11129 
11130  */
11131 static int
11132 check_for_cons (PARSER_CONTEXT * parser, int *has_unique, PT_NODE ** non_null_attrs, const PT_NODE * attr_list,
11133  DB_OBJECT * class_obj)
11134 {
11135  PT_NODE *pointer;
11136 
11137  assert (non_null_attrs != NULL);
11138  if (*non_null_attrs != NULL)
11139  {
11140  /* non_null_attrs already checked */
11141  return NO_ERROR;
11142  }
11143  *has_unique = 0;
11144 
11145  while (attr_list)
11146  {
11147  if (attr_list->node_type != PT_NAME)
11148  {
11149  /* bullet proofing, should not get here */
11150  return ER_GENERIC_ERROR;
11151  }
11152 
11153  if (*has_unique == 0 && sm_att_unique_constrained (class_obj, attr_list->info.name.original))
11154  {
11155  *has_unique = 1;
11156  }
11157 
11158  if (sm_att_constrained (class_obj, attr_list->info.name.original, SM_ATTFLAG_NON_NULL))
11159  {
11160  /* NULL values are allowed for auto_increment columns. It means that the next auto_increment value will be
11161  * inserted. */
11162  if (sm_att_auto_increment (class_obj, attr_list->info.name.original) == false)
11163  {
11164  pointer = pt_point (parser, attr_list);
11165  if (pointer == NULL)
11166  {
11168 
11169  if (*non_null_attrs)
11170  {
11171  parser_free_tree (parser, *non_null_attrs);
11172  }
11173  *non_null_attrs = NULL;
11174 
11176  }
11177  *non_null_attrs = parser_append_node (pointer, *non_null_attrs);
11178  }
11179  }
11180 
11181  attr_list = attr_list->next;
11182  }
11183 
11184  if (*has_unique == 0)
11185  {
11186  /* check if the class has an auto-increment attribute which has unique constraint */
11187 
11188  SM_CLASS *class_;
11189  SM_ATTRIBUTE *att;
11190 
11191  if (au_fetch_class_force (class_obj, &class_, AU_FETCH_READ) == NO_ERROR)
11192  {
11193  for (att = class_->ordered_attributes; att; att = att->order_link)
11194  {
11196  {
11197  *has_unique = 1;
11198  break;
11199  }
11200  }
11201  }
11202  }
11203 
11204  return NO_ERROR;
11205 }
11206 
11207 /*
11208  * is_server_insert_allowed () - Checks to see if a server-side insert is
11209  * allowed
11210  *
11211  * return : Error code.
11212  * parser (in) : Parser context.
11213  * statement (in) : Parse tree node for insert statement.
11214  */
11215 static int
11217 {
11218  int error = NO_ERROR;
11219  int trigger_involved;
11220  PT_NODE *attrs = NULL, *attr = NULL;
11221  PT_NODE *value_clauses = NULL, *class_ = NULL;
11222  /* set lock timeout hint if specified */
11223  int server_preference;
11224  int save_au;
11225 
11226  assert (statement != NULL && statement->node_type == PT_INSERT);
11227  if (statement == NULL || statement->node_type != PT_INSERT)
11228  {
11229  return ER_FAILED;
11230  }
11231 
11233  {
11234  /* already checked */
11235  return NO_ERROR;
11236  }
11238 
11239  AU_DISABLE (save_au);
11240 
11241  class_ = statement->info.insert.spec->info.spec.flat_entity_list;
11242 
11243  value_clauses = statement->info.insert.value_clauses;
11244  attrs = statement->info.insert.attr_list;
11245  /* server insert cannot handle insert into a shared attribute */
11246  attr = attrs;
11247  while (attr)
11248  {
11249  if (attr->node_type != PT_NAME)
11250  {
11251  /* this can occur when inserting into a view with default values. The name list may not be inverted, and may
11252  * contain expressions, such as (x+2). */
11253  goto end;
11254  }
11255  if (attr->info.name.meta_class != PT_NORMAL)
11256  {
11257  /* We found a shared attribute, bail out */
11258  goto end;
11259  }
11260  attr = attr->next;
11261  }
11262 
11263  error =
11264  check_for_cons (parser, &statement->info.insert.has_uniques, &statement->info.insert.non_null_attrs, attrs,
11265  class_->info.name.db_object);
11266  if (error != NO_ERROR)
11267  {
11268  goto end;
11269  }
11270 
11271  server_preference = prm_get_integer_value (PRM_ID_INSERT_MODE);
11272 
11273  if (statement->info.insert.hint & PT_HINT_INSERT_MODE)
11274  {
11275  PT_NODE *mode = statement->info.insert.insert_mode;
11276  if (mode && mode->node_type == PT_NAME)
11277  {
11278  server_preference = atoi (mode->info.name.original);
11279  }
11280  }
11281 
11282  if (value_clauses->info.node_list.list_type == PT_IS_SUBQUERY)
11283  {
11284  if (!(server_preference & INSERT_SELECT))
11285  {
11286  goto end;
11287  }
11288  }
11289  else if (value_clauses->info.node_list.list_type == PT_IS_VALUE)
11290  {
11291  int server_allowed = 1;
11292  if (!(server_preference & INSERT_VALUES))
11293  {
11294  goto end;
11295  }
11296  (void) parser_walk_tree (parser, value_clauses, do_check_insert_server_allowed, &server_allowed, NULL, NULL);
11297  if (pt_has_error (parser))
11298  {
11299  error = ER_FAILED;
11300  goto end;
11301  }
11302  if (!server_allowed)
11303  {
11304  goto end;
11305  }
11306  }
11307  else
11308  {
11309  assert (false);
11310  }
11311 
11312  if (statement->info.insert.into_var != NULL)
11313  {
11314  goto end;
11315  }
11316 
11317  /* check option could be done on the server by adding another predicate to the insert_info block. However, one must
11318  * also take care that subqueries in this predicate have their xasl blocks properly attached to the insert xasl
11319  * block. Currently, pt_to_pred will do that only if being called from parser_generate_xasl. This may mean that
11320  * do_server_insert should call parser_generate_xasl, and have a portion of its code put. */
11321  if (statement->info.insert.where != NULL)
11322  {
11323  goto end;
11324  }
11325 
11326  if (statement->info.insert.do_replace && statement->info.insert.has_uniques)
11327  {
11328  error = sm_class_has_triggers (class_->info.name.db_object, &trigger_involved, TR_EVENT_DELETE);
11329  if (error != NO_ERROR)
11330  {
11331  goto end;
11332  }
11333 
11334  if (trigger_involved)
11335  {
11336  goto end;
11337  }
11338  }
11339 
11340  if (statement->info.insert.odku_assignments != NULL && statement->info.insert.has_uniques)
11341  {
11342  error = sm_class_has_triggers (class_->info.name.db_object, &trigger_involved, TR_EVENT_UPDATE);
11343  if (error != NO_ERROR)
11344  {
11345  goto end;
11346  }
11347 
11348  if (trigger_involved)
11349  {
11350  goto end;
11351  }
11352  }
11353 
11354  error = sm_class_has_triggers (class_->info.name.db_object, &trigger_involved, TR_EVENT_INSERT);
11355  if (error != NO_ERROR)
11356  {
11357  goto end;
11358  }
11359 
11360  /* Even if unique indexes are defined on the class, the operation could be performed on server. */
11361  if (!trigger_involved && !do_Trigger_involved)
11362  {
11364  }
11365 
11366 end:
11367  /* the entire insert statement must be executed on client or on server. if any sub-insert is not allowed on server,
11368  * or if the root is not allowed on server, all inserts must be executed on client */
11369  if (error == NO_ERROR && statement->info.insert.server_allowed == SERVER_INSERT_IS_NOT_ALLOWED
11370  && value_clauses->info.node_list.list_type == PT_IS_VALUE)
11371  {
11372  (void) parser_walk_tree (parser, value_clauses, do_set_insert_server_not_allowed, NULL, NULL, NULL);
11373  if (pt_has_error (parser))
11374  {
11375  error = ER_FAILED;
11376  }
11377  }
11378  AU_ENABLE (save_au);
11379  return error;
11380 }
11381 
11382 /*
11383  * do_check_insert_server_allowed () - Parser walk function that checks all
11384  * sub-inserts are allowed on server.
11385  *
11386  * return : Unchanged node argument.
11387  * parser (in) : Parser context.
11388  * node (in) : Parse tree node.
11389  * arg (out) : int * argument that stores server_allowed.
11390  * continue_walk (in) : Continue walk.
11391  */
11392 static PT_NODE *
11393 do_check_insert_server_allowed (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
11394 {
11395  int *server_allowed = (int *) arg;
11396  int error = NO_ERROR;
11397 
11398  if (node == NULL || node->node_type != PT_INSERT)
11399  {
11400  /* stop check */
11401  return node;
11402  }
11403 
11404  *server_allowed = 1;
11405  error = is_server_insert_allowed (parser, node);
11406  if (error != NO_ERROR || node->info.insert.server_allowed != SERVER_INSERT_IS_ALLOWED)
11407  {
11408  *server_allowed = 0;
11409  *continue_walk = PT_STOP_WALK;
11410  }
11411  return node;
11412 }
11413 
11414 /*
11415  * do_set_insert_server_not_allowed () - Parser walk function that should be
11416  * called when top insert is not allowed
11417  * on server. This will force all sub
11418  * inserts to run on client.
11419  *
11420  * return : Unchanged node argument.
11421  * parser (in) : Parser context.
11422  * node (in) : Parse tree node.
11423  * void_arg (in) : Void argument.
11424  * continue_walk (in) : Continue walk.
11425  */
11426 static PT_NODE *
11427 do_set_insert_server_not_allowed (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk)
11428 {
11429  int error = NO_ERROR;
11430 
11431  if (node == NULL || node->node_type != PT_INSERT)
11432  {
11433  return node;
11434  }
11435 
11437  {
11438  /* is_server_insert_allowed was no called for this insert node, must call check_for_cons (). */
11440  error =
11442  node->info.insert.attr_list, class_obj);
11443  if (error != NO_ERROR)
11444  {
11445  *continue_walk = PT_STOP_WALK;
11446  return node;
11447  }
11448  }
11450  return node;
11451 }
11452 
11453 /*
11454  * do_create_midxkey_for_constraint () - create a MIDX_KEY db_value for the
11455  * specified constraint using the values
11456  * assigned in an object template
11457  * return : error code or NO_ERROR;
11458  * tmpl (in) : object template
11459  * constraint (in) : constraint
11460  * key (in/out) : the MIDX key
11461  */
11462 static int
11464 {
11465  DB_MIDXKEY midxkey;
11466  SM_ATTRIBUTE **attr = NULL;
11467  int buf_size = 0, bitmap_size = 0, i, error = NO_ERROR, attr_count = 0;
11468  unsigned char *bits;
11469  char *bound_bits = NULL, *key_ptr = NULL;
11470  OR_BUF buf;
11471  DB_VALUE *val = NULL;
11472  TP_DOMAIN *attr_dom = NULL, *dom = NULL, *setdomain = NULL;
11473  const int *asc_desc = NULL;
11474 
11475  midxkey.buf = NULL;
11476  midxkey.min_max_val.position = -1;
11477  asc_desc = db_constraint_asc_desc (constraint);
11478 
11479  /* compute key size */
11480  for (attr_count = 0, attr = constraint->attributes; *attr != NULL; attr_count++, attr++)
11481  {
11482  val = NULL;
11483  if (tmpl->assignments[(*attr)->order] != NULL)
11484  {
11485  val = tmpl->assignments[(*attr)->order]->variable;
11486  }
11487 
11488  attr_dom = tp_domain_copy ((*attr)->domain, false);
11489  if (attr_dom == NULL)
11490  {
11491  error = ER_FAILED;
11492  goto error_return;
11493  }
11494 
11495  if (asc_desc != NULL && asc_desc[attr_count] == 1)
11496  {
11497  attr_dom->is_desc = 1;
11498  }
11499 
11500  if (val != NULL && !DB_IS_NULL (val))
11501  {
11502  buf_size += attr_dom->type->get_index_size_of_value (val);
11503  }
11504 
11505  if (setdomain == NULL)
11506  {
11507  setdomain = attr_dom;
11508  }
11509  else
11510  {
11511  dom->next = attr_dom;
11512  }
11513  dom = attr_dom;
11514  }
11515 
11516  bitmap_size = OR_MULTI_BOUND_BIT_BYTES (attr_count);
11517  buf_size += bitmap_size;
11518 
11519  midxkey.buf = (char *) db_private_alloc (NULL, buf_size);
11520  if (midxkey.buf == NULL)
11521  {
11522  error = ER_FAILED;
11523  goto error_return;
11524  }
11525 
11526  bound_bits = midxkey.buf;
11527  key_ptr = bound_bits + bitmap_size;
11528 
11529  OR_BUF_INIT (buf, key_ptr, buf_size - bitmap_size);
11530  if (bitmap_size > 0)
11531  {
11532  bits = (unsigned char *) bound_bits;
11533  for (i = 0; i < bitmap_size; i++)
11534  {
11535  bits[i] = (unsigned char) 0;
11536  }
11537  }
11538 
11539  for (i = 0, attr = constraint->attributes; *attr != NULL; attr++, i++)
11540  {
11541  val = NULL;
11542  if (tmpl->assignments[(*attr)->order] != NULL)
11543  {
11544  val = tmpl->assignments[(*attr)->order]->variable;
11545  }
11546  dom = (*attr)->domain;
11547 
11548  if (val != NULL && !DB_IS_NULL (val))
11549  {
11550  dom->type->index_writeval (&buf, val);
11551  OR_ENABLE_BOUND_BIT (bound_bits, i);
11552  }
11553  else
11554  {
11555  OR_CLEAR_BOUND_BIT (bound_bits, i);
11556  }
11557  }
11558 
11559  midxkey.size = buf_size;
11560  midxkey.ncolumns = attr_count;
11561  midxkey.domain = tp_domain_construct (DB_TYPE_MIDXKEY, NULL, attr_count, 0, setdomain);
11562  if (midxkey.domain == NULL)
11563  {
11564  error = ER_FAILED;
11565  goto error_return;
11566  }
11567  midxkey.domain = tp_domain_cache (midxkey.domain);
11568  midxkey.min_max_val.position = -1;
11569  midxkey.min_max_val.type = MIN_COLUMN;
11570 
11571  error = db_make_midxkey (key, &midxkey);
11572  if (error != NO_ERROR)
11573  {
11574  goto error_return;
11575  }
11576  key->need_clear = true;
11577  return NO_ERROR;
11578 
11579 error_return:
11580  if (midxkey.buf != NULL)
11581  {
11582  db_private_free (NULL, midxkey.buf);
11583  }
11584  dom = setdomain;
11585  while (dom != NULL)
11586  {
11587  attr_dom = dom->next;
11588  dom->next = NULL;
11589  tp_domain_free (dom);
11590  dom = attr_dom;
11591  }
11592  return error;
11593 }
11594 
11595 /*
11596  * do_create_odku_stmt () - create an UPDATE statement for ON DUPLICATE KEY
11597  * UPDATE node
11598  * return : update node or NULL
11599  * parser (in) : parser context
11600  * insert (in) : INSERT statement node
11601  *
11602  * Note: this function alters the flag set on the SPEC node of the INSERT
11603  * statement. Callers should backup the value of the flag and restore it
11604  * when they're finished with the UPDATE statement.
11605  */
11606 static PT_NODE *
11608 {
11609  PT_NODE *update = NULL;
11610 
11611  if (insert == NULL || insert->node_type != PT_INSERT)
11612  {
11613  assert (false);
11614  PT_INTERNAL_ERROR (parser, "invalid arguments");
11615  return NULL;
11616  }
11617 
11618  insert->info.insert.spec->info.spec.flag =
11620 
11621  update = parser_new_node (parser, PT_UPDATE);
11622  if (update == NULL)
11623  {
11624  PT_INTERNAL_ERROR (parser, "allocate new node");
11625  goto error_return;
11626  }
11627  update->info.update.assignment = insert->info.insert.odku_assignments;
11628  update->info.update.spec = insert->info.insert.spec;
11629 
11630  if (insert->info.insert.where != NULL)
11631  {
11632  PT_NODE *check_where = parser_new_node (parser, PT_CHECK_OPTION);
11633  if (check_where == NULL)
11634  {
11635  PT_INTERNAL_ERROR (parser, "allocate new node");
11636  goto error_return;
11637  }
11638 
11639  check_where->info.check_option.expr = insert->info.insert.where;
11640  check_where->info.check_option.spec_id = insert->info.insert.spec->info.spec.id;
11641 
11642  update->info.update.check_where = check_where;
11643  }
11644 
11645  return update;
11646 
11647 error_return:
11648  if (update != NULL)
11649  {
11650  update->info.update.assignment = NULL;
11651  update->info.update.spec = NULL;
11652  if (update->info.update.check_where != NULL)
11653  {
11655  }
11656  parser_free_tree (parser, update);
11657  }
11658 
11659  return NULL;
11660 }
11661 
11662 /*
11663  * do_find_unique_constraint_violations () - find oids for which unique
11664  * constraints would be violated by
11665  * inserting an object template
11666  * return : error code or NO_ERROR
11667  * tmpl (in) : object template
11668  * for_update (in) : if true, offending OIDs will be updated
11669  * oids (in/out) : array of offending OIDs
11670  * oids_count (in) : number of OIDs in array
11671  */
11672 static int
11673 do_find_unique_constraint_violations (DB_OTMPL * tmpl, bool for_update, OID ** oids, int *oids_count)
11674 {
11675  int error = NO_ERROR;
11676  SM_CLASS_CONSTRAINT *constraint = NULL;
11677  SM_CLASS *class_ = NULL;
11678  int unique_count = 0, key_cnt, i, level, attr_count = 0;
11679  BTID *unique_btids = NULL;
11680  DB_VALUE *unique_keys = NULL;
11681  SM_ATTRIBUTE **attr;
11682  OBJ_TEMPASSIGN *assignment = NULL;
11683  bool should_verify = false;
11684  BTREE_SEARCH result;
11685  SCAN_OPERATION_TYPE op_type = S_UPDATE;
11686 
11688  if (level & 0x02)
11689  {
11690  /* User is only interested in query plan. Query will not be executed and we have no plan to show. */
11691  *oids = NULL;
11692  *oids_count = 0;
11693  return NO_ERROR;
11694  }
11695  /* Populate the defaults and auto_increment values here because we need them when building the WHERE clause for the
11696  * SELECT statement. These values will not be reassigned if the template will eventually be inserted as they are
11697  * already populated. */
11698  error = obt_populate_known_arguments (tmpl);
11699  if (error != NO_ERROR)
11700  {
11701  return error;
11702  }
11703 
11704  class_ = tmpl->class_;
11705  for (constraint = class_->constraints; constraint != NULL; constraint = constraint->next)
11706  {
11707  if (!SM_IS_CONSTRAINT_UNIQUE_FAMILY (constraint->type))
11708  {
11709  continue;
11710  }
11711  unique_count++;
11712  }
11713 
11714  if (unique_count == 0)
11715  {
11716  /* class does not have unique constraints */
11717  *oids = NULL;
11718  oids_count = 0;
11719  return NO_ERROR;
11720  }
11721 
11722  unique_btids = (BTID *) db_private_alloc (NULL, unique_count * sizeof (BTID));
11723  if (unique_btids == NULL)
11724  {
11725  error = ER_FAILED;
11726  goto cleanup;
11727  }
11728  unique_keys = (DB_VALUE *) db_private_alloc (NULL, unique_count * sizeof (DB_VALUE));
11729  if (unique_keys == NULL)
11730  {
11731  error = ER_FAILED;
11732  goto cleanup;
11733  }
11734  key_cnt = 0;
11735  for (constraint = class_->constraints; constraint != NULL; constraint = constraint->next)
11736  {
11737  if (!SM_IS_CONSTRAINT_UNIQUE_FAMILY (constraint->type))
11738  {
11739  continue;
11740  }
11741  BTID_COPY (&unique_btids[key_cnt], &constraint->index_btid);
11742  db_make_null (&unique_keys[key_cnt]);
11743  attr_count = 0;
11744  for (attr = constraint->attributes; *attr != NULL; attr++)
11745  {
11746  assignment = tmpl->assignments[(*attr)->order];
11747  if (assignment != NULL && assignment->variable != NULL)
11748  {
11749  /* this constraint may be violated */
11750  should_verify = true;
11751  }
11752  attr_count++;
11753  }
11754 
11755  if (!should_verify || attr_count == 0)
11756  {
11757  continue;
11758  }
11759 
11760  if (attr_count == 1)
11761  {
11762  /* single key handling */
11763  attr = constraint->attributes;
11764  assignment = tmpl->assignments[(*attr)->order];
11765  if (assignment == NULL)
11766  {
11767  /* value not set */
11768  continue;
11769  }
11770  pr_clone_value (assignment->variable, &unique_keys[key_cnt]);
11771  key_cnt++;
11772  continue;
11773  }
11774 
11775  /* multiple key, need to create a MIDXKEY */
11776  error = do_create_midxkey_for_constraint (tmpl, constraint, &unique_keys[key_cnt]);
11777  if (error != NO_ERROR)
11778  {
11779  goto cleanup;
11780  }
11781  key_cnt++;
11782  }
11783 
11784  if (key_cnt == 0)
11785  {
11786  goto cleanup;
11787  }
11788 
11789  if (for_update)
11790  {
11791  op_type = S_UPDATE;
11792  }
11793  else
11794  {
11795  op_type = S_DELETE;
11796  }
11797 
11798  result =
11799  btree_find_multi_uniques (ws_oid (tmpl->classobj), tmpl->pruning_type, unique_btids, unique_keys, key_cnt, op_type,
11800  oids, oids_count);
11801  if (result == BTREE_ERROR_OCCURRED)
11802  {
11803  error = ER_FAILED;
11804  }
11805 
11806 cleanup:
11807  if (unique_keys != NULL)
11808  {
11809  for (i = 0; i < key_cnt; i++)
11810  {
11811  pr_clear_value (&unique_keys[i]);
11812  }
11813  db_private_free (NULL, unique_keys);
11814  }
11815  if (unique_btids != NULL)
11816  {
11817  db_private_free (NULL, unique_btids);
11818  }
11819  return error;
11820 }
11821 
11822 /*
11823  * do_on_duplicate_key_update() - runs an update statement instead of an
11824  * insert statement for the cases in which
11825  * the insert would cause a unique constraint
11826  * violation
11827  * return: The number of affected rows if successful, error code otherwise
11828  *
11829  * parser(in) : Parser context
11830  * tmpl(in) : object template to be inserted
11831  * update_stmt(in) : the update statement to run if there are unique
11832  * constraint violations
11833  *
11834  * Notes: This function creates a SELECT statement based on the values
11835  * supplied in the template object and runs update_stmt for one
11836  * of the OIDs with which tmpl would generate unique key conflicts.
11837  * If this function returns 0 then no rows were updated and the caller
11838  * should proceed with the insert.
11839  */
11840 static int
11842 {
11843  int retval = NO_ERROR;
11844  int ret_code = 0;
11845  OID *oids = NULL;
11846  int oids_count = 0;
11847 
11848  retval = do_find_unique_constraint_violations (tmpl, true, &oids, &oids_count);
11849  if (retval != NO_ERROR)
11850  {
11851  goto cleanup;
11852  }
11853  assert_release (oids_count <= 1);
11854  if (oids_count == 0)
11855  {
11856  assert (oids == NULL);
11857  return NO_ERROR;
11858  }
11859 
11860  update_stmt->info.update.object = ws_mop (oids, NULL);
11861 
11862  ret_code = update_object_by_oid (parser, update_stmt, ON_DUPLICATE_KEY_UPDATE);
11863  update_stmt->info.update.object = NULL;
11864  if (ret_code < NO_ERROR)
11865  {
11866  retval = ret_code;
11867  goto cleanup;
11868  }
11869 
11870  /* one updated row */
11871  retval = 1;
11872 
11873 cleanup:
11874  if (oids != NULL)
11875  {
11876  free_and_init (oids);
11877  }
11878  return retval;
11879 }
11880 
11881 /*
11882  * do_replace_into() - runs an delete statement for the cases in
11883  * which INSERT would cause a unique constraint violation
11884  *
11885  * return: The number of affected rows if successful, error code otherwise
11886  *
11887  * parser(in) : Parser context
11888  * tmpl(in) : object template to be inserted
11889  * spec(in) : the spec used for insert
11890  * class_specs(in) :
11891  *
11892  * Notes: This function creates a SELECT statement based on the values
11893  * supplied in the template object and runs delete for the
11894  * OIDs with which tmpl would generate unique key violations
11895  */
11896 static int
11897 do_replace_into (PARSER_CONTEXT * parser, DB_OTMPL * tmpl, PT_NODE * spec, PT_NODE * class_specs)
11898 {
11899  int retval = 0, error = NO_ERROR;
11900  OID *oids = NULL;
11901  int oids_count = 0, i;
11902  MOP obj = NULL;
11903 
11904  error = do_find_unique_constraint_violations (tmpl, false, &oids, &oids_count);
11905  if (error != NO_ERROR)
11906  {
11907  retval = error;
11908  goto cleanup;
11909  }
11910  if (oids_count == 0)
11911  {
11912  retval = 0;
11913  goto cleanup;
11914  }
11915 
11916  retval = 0;
11917  for (i = 0; i < oids_count; i++)
11918  {
11919  obj = ws_mop (&oids[i], NULL);
11920  error = db_is_deleted (obj);
11921  if (error < 0)
11922  {
11923  goto cleanup;
11924  retval = error;
11925  }
11926  if (error > 0)
11927  {
11928  error = NO_ERROR;
11929  continue;
11930  }
11931 
11932  error = delete_object_tuple (obj);
11933  if (error != NO_ERROR)
11934  {
11935  retval = error;
11936  goto cleanup;
11937  }
11938  retval++;
11939  }
11940 
11941 cleanup:
11942  if (oids != NULL)
11943  {
11944  free_and_init (oids);
11945  }
11946  return retval;
11947 }
11948 
11949 /*
11950  * is_replace_or_odku_allowed() - checks to see if the class is partitioned or
11951  * part of an inheritance chain
11952  *
11953  * return: error code if unsuccessful, NO_ERROR otherwise
11954  *
11955  * obj(in) : object to be checked
11956  * allowed(out) : 0 if not allowed, 1 if allowed
11957  *
11958  */
11959 static int
11961 {
11962  int error = NO_ERROR;
11963  SM_CLASS *smclass = NULL;
11964 
11965  *allowed = 1;
11966  error = sm_is_partitioned_class (obj);
11967  if (error < 0)
11968  {
11969  return error;
11970  }
11971  if (error > 0)
11972  {
11973  return NO_ERROR;
11974  }
11975 
11976  error = au_fetch_class (obj, &smclass, AU_FETCH_READ, AU_SELECT);
11977  if (error != NO_ERROR)
11978  {
11979  return error;
11980  }
11981 
11982  if (smclass->inheritance != NULL || smclass->users != NULL)
11983  {
11984  *allowed = 0;
11985  }
11986 
11987  return error;
11988 }
11989 
11990 /*
11991  * do_insert_template () - Final step of insert execution on client.
11992  * 1. Checks if insert is allowed on server. If it is,
11993  * calls do_insert_at_server ().
11994  * 2. If INSERT ... SELECT is not allowed on server,
11995  * calls insert_subquery_results ().
11996  * 3. If INSERT ... VALUES is not allowed on server,
11997  * it is handled here.
11998  *
11999  * return : NO_ERROR or error code.
12000  * parser (in) : Parser context.
12001  * otemplate (out) : Class template to be inserted.
12002  * statement (in) : Parse tree of insert statement.
12003  * savepoint_name (in/out) : Name of savepoint (no savepoint if null).
12004  * row_count_ptr (in/out) : Pointer to row counter.
12005  */
12006 int
12007 do_insert_template (PARSER_CONTEXT * parser, DB_OTMPL ** otemplate, PT_NODE * statement, const char **savepoint_name,
12008  int *row_count_ptr)
12009 {
12010  const char *into_label = NULL;
12011  DB_VALUE *ins_val = NULL, *val = NULL, db_value;
12012  int error = NO_ERROR, flag = 0;
12013  PT_NODE *attr = NULL, *vc = NULL;
12014  PT_NODE *into = NULL;
12015  PT_NODE *class_ = NULL;
12016  PT_NODE *update = NULL;
12017  DB_ATTDESC **attr_descs = NULL;
12018  int i, degree, row_count = 0;
12019  int wait_msecs = -2, old_wait_msecs = -2;
12020  float hint_waitsecs;
12021  PT_NODE *hint_arg;
12022  int pruning_type = DB_NOT_PARTITIONED_CLASS;
12023  PT_NODE *value_clauses = statement->info.insert.value_clauses;
12024  PT_NODE *value_list = NULL;
12025  DB_OBJECT *obj = NULL, *vobj = NULL;
12026  unsigned int save_custom;
12027  DB_VALUE *value = NULL;
12028  DB_SEQ *seq = NULL;
12029  int obj_count = 0;
12030 
12031  assert (otemplate != NULL);
12032  if (otemplate == NULL)
12033  {
12034  return ER_FAILED;
12035  }
12036  *otemplate = NULL;
12037 
12038  db_make_null (&db_value);
12039 
12040  if (row_count_ptr != NULL)
12041  {
12042  *row_count_ptr = 0;
12043  }
12044 
12045  degree = 0;
12046  class_ = statement->info.insert.spec->info.spec.flat_entity_list;
12047  flag = statement->info.insert.spec->info.spec.flag;
12048  /* clear any previous error indicator because the rest of do_insert is sensitive to er_errid(). */
12049  er_clear ();
12050 
12051  error = do_insert_checks (parser, statement, &class_, &update, value_clauses);
12052  if (error != NO_ERROR)
12053  {
12054  ASSERT_ERROR ();
12055  goto cleanup;
12056  }
12057 
12058  into = statement->info.insert.into_var;
12059  if (into != NULL && PT_IS_NAME_NODE (into) && into->info.name.meta_class == PT_PARAMETER)
12060  {
12061  assert (into->info.name.original != NULL);
12062  into_label = into->info.name.original;
12063  }
12064  else
12065  {
12066  into_label = NULL;
12067  }
12068  if (into_label)
12069  {
12070  ins_val = db_value_create ();
12071  if (ins_val == NULL)
12072  {
12073  assert (er_errid () != NO_ERROR);
12074  error = er_errid ();
12075  goto cleanup;
12076  }
12077  db_make_object (ins_val, (DB_OBJECT *) NULL);
12078  }
12079 
12081  {
12082  /* We need to make sure snapshot is generated for this execution. */
12083  error = log_get_mvcc_snapshot ();
12084  if (error != NO_ERROR)
12085  {
12086  ASSERT_ERROR ();
12087  goto cleanup;
12088  }
12089  }
12090 
12092  {
12093  if (error != NO_ERROR)
12094  {
12095  goto cleanup;
12096  }
12097  error = do_insert_at_server (parser, statement);
12098  if (error >= 0)
12099  {
12100  row_count = error;
12101  }
12102  }
12103  else if (value_clauses->info.node_list.list_type == PT_IS_SUBQUERY
12104  && (vc = value_clauses->info.node_list.list) != NULL)
12105  {
12106  /* execute sub-query & insert its results into target class */
12107  row_count = insert_subquery_results (parser, statement, value_clauses, class_, savepoint_name);
12108  error = (row_count < 0) ? row_count : NO_ERROR;
12109  if (error == NO_ERROR)
12110  {
12111  if (ins_val != NULL)
12112  {
12113  if (row_count > 1)
12114  {
12115  error = ER_DO_INSERT_TOO_MANY;
12116  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
12117  goto cleanup;
12118  }
12119  val = (DB_VALUE *) statement->etc;
12120  if (val != NULL)
12121  {
12122  db_make_object (ins_val, db_get_object (val));
12123  }
12124  if (into_label != NULL)
12125  {
12126  error = pt_associate_label_with_value_check_reference (into_label, ins_val);
12127  }
12128  }
12129  }
12130  }
12131  else if (value_clauses->info.node_list.list_type == PT_IS_VALUE
12132  || value_clauses->info.node_list.list_type == PT_IS_DEFAULT_VALUE)
12133  {
12134  if (qo_need_skip_execution ())
12135  {
12136  return NO_ERROR;
12137  }
12138 
12139  error = sm_partitioned_class_type (class_->info.name.db_object, &pruning_type, NULL, NULL);
12140  if (error != NO_ERROR)
12141  {
12142  assert (er_errid () != NO_ERROR);
12143  error = er_errid ();
12144  goto cleanup;
12145  }
12146 
12147  if (parser->flag.return_generated_keys)
12148  {
12149  seq = set_create_sequence (0);
12150  if (seq == NULL)
12151  {
12152  error = ER_FAILED;
12153  goto cleanup;
12154  }
12155  }
12156 
12157  error = do_evaluate_insert_values (parser, statement);
12158  if (error != NO_ERROR)
12159  {
12160  goto cleanup;
12161  }
12162 
12163  for (value_list = value_clauses; value_list != NULL; value_list = value_list->next)
12164  {
12165  /* now create the object using templates, and then dbt_put each value for each corresponding attribute. Of
12166  * course, it is presumed that the order in which attributes are defined in the class as well as in the
12167  * actual insert statement is preserved. */
12168  *otemplate = dbt_create_object_internal (class_->info.name.db_object);
12169  if (*otemplate == NULL)
12170  {
12171  assert (er_errid () != NO_ERROR);
12172  error = er_errid ();
12173  goto cleanup;
12174  }
12175  (*otemplate)->pruning_type = pruning_type;
12176  if (pruning_type != DB_NOT_PARTITIONED_CLASS)
12177  {
12178  /* The reason we're forcing a flush here is to throw an error if the object does belong to any partition.
12179  * If we don't do it here, the error will be thrown when the object is flushed either by the next
12180  * statement or by a commit/rollback call. However, there cases when we don't need to do this. Hash
12181  * partitioning algorithm guarantees that there always is a partition for each record and range
12182  * partitioning using max value/min value does the same. This flushing should be refined. */
12183  obt_set_force_flush (*otemplate);
12184  }
12185 
12186  vc = value_list->info.node_list.list;
12187  attr = statement->info.insert.attr_list;
12188  degree = pt_length_of_list (attr);
12189 
12190  /* allocate attribute descriptors */
12191  if (attr != NULL && attr_descs == NULL)
12192  {
12193  attr_descs = (DB_ATTDESC **) calloc (degree, sizeof (DB_ATTDESC *));
12194  if (attr_descs == NULL)
12195  {
12197  (degree * sizeof (DB_ATTDESC *)));
12198  error = ER_OUT_OF_VIRTUAL_MEMORY;
12199  goto cleanup;
12200  }
12201  }
12202 
12203  hint_arg = statement->info.insert.waitsecs_hint;
12204  if (statement->info.insert.hint & PT_HINT_LK_TIMEOUT && PT_IS_HINT_NODE (hint_arg))
12205  {
12206  hint_waitsecs = (float) atof (hint_arg->info.name.original);
12207  if (hint_waitsecs > 0)
12208  {
12209  wait_msecs = (int) (hint_waitsecs * 1000);
12210  }
12211  else
12212  {
12213  wait_msecs = (int) hint_waitsecs;
12214  }
12215  if (wait_msecs >= -1)
12216  {
12217  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
12218 
12219  (void) tran_reset_wait_times (wait_msecs);
12220  }
12221  }
12222  i = 0;
12223  while (attr && vc)
12224  {
12225  assert (vc->node_type == PT_INSERT_VALUE && vc->info.insert_value.is_evaluated);
12226  if (vc->node_type != PT_INSERT_VALUE || !vc->info.insert_value.is_evaluated)
12227  {
12228  error = ER_FAILED;
12229  goto cleanup;
12230  }
12231 
12232  /* don't get descriptors for shared attrs of views */
12233  if (attr_descs[i] == NULL)
12234  {
12235  int is_vclass = 0;
12236 
12237  if (attr->info.name.db_object)
12238  {
12239  is_vclass = db_is_vclass (attr->info.name.db_object);
12240  if (is_vclass < 0)
12241  {
12242  error = is_vclass;
12243  }
12244  }
12245  if (!is_vclass)
12246  {
12247  error =
12249  &attr_descs[i]);
12250  }
12251  }
12252  if (error >= NO_ERROR)
12253  {
12254  error = insert_object_attr (parser, *otemplate, &vc->info.insert_value.value, attr, attr_descs[i]);
12255  }
12256 
12257  if (!pt_has_error (parser))
12258  {
12259  if (error < NO_ERROR)
12260  {
12261  save_custom = parser->custom_print;
12262  parser->custom_print = parser->custom_print | PT_PRINT_DB_VALUE;
12263 
12265  pt_short_print (parser, vc), attr->info.name.original,
12266  pt_chop_trailing_dots (parser, db_error_string (3)));
12267 
12268  parser->custom_print = save_custom;
12269 
12270  goto cleanup;
12271  }
12272  }
12273  else
12274  {
12275  goto cleanup;
12276  }
12277 
12278  attr = attr->next;
12279  vc = vc->next;
12280  i++;
12281  }
12282 
12283  /* inserted one more row */
12284  row_count++;
12285 
12286  if ((*otemplate) != NULL && statement->info.insert.odku_assignments)
12287  {
12288  assert (update != NULL);
12289  error = do_on_duplicate_key_update (parser, *otemplate, update);
12290  if (error < 0)
12291  {
12292  dbt_abort_object (*otemplate);
12293  *otemplate = NULL;
12294  goto cleanup;
12295  }
12296  else if (error > 0)
12297  {
12298  /* a successful update, go to finish */
12299  row_count += error;
12300  dbt_abort_object (*otemplate);
12301  *otemplate = NULL;
12302  error = NO_ERROR;
12303  }
12304  else
12305  { /* error == 0 */
12306  int level;
12308  if (level & 0x02)
12309  {
12310  /* do not execute, go to finish */
12311  row_count = 0;
12312  dbt_abort_object (*otemplate);
12313  *otemplate = NULL;
12314  error = NO_ERROR;
12315  }
12316  }
12317  }
12318  if ((*otemplate) != NULL && statement->info.insert.do_replace)
12319  {
12320  error =
12321  do_replace_into (parser, *otemplate, statement->info.insert.spec, statement->info.insert.class_specs);
12322  if (error > 0)
12323  {
12324  row_count += error;
12325  error = NO_ERROR;
12326  }
12327  }
12328 
12329  if (error < NO_ERROR)
12330  {
12331  goto cleanup;
12332  }
12333 
12334  if (ins_val != NULL && *otemplate != NULL)
12335  {
12336  if (row_count > 1)
12337  {
12338  error = ER_DO_INSERT_TOO_MANY;
12339  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
12340  goto cleanup;
12341  }
12342  error = dbt_set_label (*otemplate, ins_val);
12343  if (error == NO_ERROR)
12344  {
12345  if (into_label != NULL)
12346  {
12347  error = pt_associate_label_with_value_check_reference (into_label, ins_val);
12348  }
12349  }
12350  if (error != NO_ERROR)
12351  {
12352  goto cleanup;
12353  }
12354  }
12355 
12356  if (*otemplate != NULL)
12357  {
12358  obt_retain_after_finish (*otemplate);
12359 
12360  obj = dbt_finish_object (*otemplate);
12361  if (obj == NULL)
12362  {
12363  ASSERT_ERROR_AND_SET (error);
12364 
12365  dbt_abort_object (*otemplate);
12366  *otemplate = NULL;
12367  }
12368  else
12369  {
12370  bool include_new_obj;
12371 
12372  include_new_obj = (parser->flag.return_generated_keys && (*otemplate)->is_autoincrement_set);
12373 
12374  obt_quit (*otemplate); /* free template */
12375 
12376  if (include_new_obj == true)
12377  {
12378  db_make_object (&db_value, obj);
12379  error = set_put_element (seq, obj_count, &db_value);
12380  if (error != NO_ERROR)
12381  {
12382  goto cleanup;
12383  }
12384  obj_count++;
12385  }
12386  }
12387 
12388  if (error >= NO_ERROR)
12389  {
12390  error = mq_evaluate_check_option (parser, statement->info.insert.where, obj, class_);
12391  }
12392  }
12393 
12394  if (parser->flag.abort)
12395  {
12396  assert (er_errid () != NO_ERROR);
12397  error = er_errid ();
12398  }
12399  if (error < NO_ERROR)
12400  {
12401  break;
12402  }
12403 
12404  if (old_wait_msecs >= -1)
12405  {
12406  (void) tran_reset_wait_times (old_wait_msecs);
12407  }
12408  }
12409  }
12410 
12411  if (error < NO_ERROR)
12412  {
12413  goto cleanup;
12414  }
12415 
12416  if (*otemplate != NULL && parser->flag.return_generated_keys)
12417  {
12418  /* a client side insert with template, with requested generated keys */
12419  value = db_value_create ();
12420  if (value == NULL)
12421  {
12422  assert (er_errid () != NO_ERROR);
12423  error = er_errid ();
12424  goto cleanup;
12425  }
12426  error = db_make_sequence (value, seq);
12427  if (error != NO_ERROR)
12428  {
12429  goto cleanup;
12430  }
12431  statement->etc = (void *) value;
12432 
12433  goto cleanup;
12434  }
12435  else
12436  {
12437  if (!parser->flag.return_generated_keys && (*otemplate == NULL || value_clauses->next != NULL))
12438  {
12439  /* a client side insert with subquery and no template, a client side insert with multiple insert values or a
12440  * server side insert for which the generated keys have not been requested */
12441  value = db_value_create ();
12442  if (value == NULL)
12443  {
12444  assert (er_errid () != NO_ERROR);
12445  error = er_errid ();
12446  goto cleanup;
12447  }
12448  db_make_object (value, NULL);
12449  statement->etc = (void *) value;
12450 
12451  goto cleanup;
12452  }
12453  }
12454 
12455  if (*otemplate != NULL && value_clauses->next == NULL)
12456  {
12457  /* If any of the (nested) inserts were view objects we need to find them and create VMOPS for them. Use a post
12458  * walk so that vobj will point to the vmop for the outer insert if one is needed. */
12459  vobj = NULL;
12460  statement = parser_walk_tree (parser, statement, NULL, NULL, make_vmops, &vobj);
12461  /* create a DB_VALUE to hold the newly inserted instance */
12462  ins_val = db_value_create ();
12463  if (ins_val == NULL)
12464  {
12465  assert (er_errid () != NO_ERROR);
12466  error = er_errid ();
12467  }
12468  else
12469  {
12470  if (vobj != NULL)
12471  {
12472  /* use the virtual mop */
12473  db_make_object (ins_val, vobj);
12474  }
12475  else
12476  {
12477  db_make_object (ins_val, obj);
12478  }
12479  statement->etc = (void *) ins_val;
12480  }
12481  }
12482 
12483 cleanup:
12484  /* free attribute descriptors */
12485  if (attr_descs)
12486  {
12487  for (i = 0; i < degree; i++)
12488  {
12489  if (attr_descs[i])
12490  {
12491  db_free_attribute_descriptor (attr_descs[i]);
12492  }
12493  }
12494  free_and_init (attr_descs);
12495  }
12496 
12497  if (update != NULL)
12498  {
12499  update->info.update.assignment = NULL;
12500  update->info.update.spec = NULL;
12501  if (update->info.update.check_where != NULL)
12502  {
12504  }
12505  parser_free_tree (parser, update);
12506  }
12507 
12508  if (statement->info.insert.odku_non_null_attrs != NULL)
12509  {
12510  parser_free_tree (parser, statement->info.insert.odku_non_null_attrs);
12511  statement->info.insert.odku_non_null_attrs = NULL;
12512  }
12513 
12514  do_clear_insert_values (parser, statement);
12515 
12516  /* set NULL on labeled value */
12517  if (into_label != NULL && error != NO_ERROR)
12518  {
12519  DB_VALUE *db_val = pt_find_value_of_label (into_label);
12520 
12521  if (db_val != NULL)
12522  {
12523  db_make_object (db_val, (DB_OBJECT *) NULL);
12524  }
12525  }
12526 
12527  /* restore flags */
12528  statement->info.insert.spec->info.spec.flag = (PT_SPEC_FLAG) flag;
12529 
12530  if (*otemplate != NULL && error != NO_ERROR)
12531  {
12532  dbt_abort_object (*otemplate);
12533  *otemplate = NULL;
12534  }
12535 
12536  if (seq != NULL && error != NO_ERROR)
12537  {
12538  set_free (seq);
12539  }
12540 
12541  if (row_count_ptr != NULL)
12542  {
12543  *row_count_ptr = row_count;
12544  }
12545  return error;
12546 }
12547 
12548 /*
12549  * insert_subquery_results() - Execute sub-query & insert its results into
12550  * a target class
12551  * return: Error code
12552  * parser(in): Handle to the parser used to process & derive sub-query qry
12553  * statement(in/out):
12554  * values_list(in): The list of values to insert.
12555  * class(in):
12556  * savepoint_name(in):
12557  *
12558  * Note:
12559  * The function requires parser is the handle to the parser used to derive qry
12560  * qry is an error-free abstract syntax tree derived from a CUBRID
12561  * nested SELECT, UNION, DIFFERENCE, INTERSECTION subquery.
12562  * qry's select_list attributes have been expanded & type-checked.
12563  * qry's select_list and attrs have the same number of elements.
12564  * It modifies database state of target class and
12565  * effects that executes subquery and inserts its results as new instances of
12566  * target class.
12567  */
12568 static int
12569 insert_subquery_results (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE * values_list, PT_NODE * class_,
12570  const char **savepoint_name)
12571 {
12572  int error = NO_ERROR;
12574  DB_OTMPL *otemplate = NULL;
12575  DB_OBJECT *obj = NULL;
12576  PT_NODE *attr, *qry, *attrs, *update = NULL;
12577  DB_VALUE *vals = NULL, *val = NULL;
12578  int degree, k, cnt, i, flag = 0;
12579  DB_ATTDESC **attr_descs = NULL;
12580  ODKU_TUPLE_VALUE_ARG odku_arg;
12581  int pruning_type = DB_NOT_PARTITIONED_CLASS;
12582  QUERY_ID query_id_self = parser->query_id;
12583  int obj_count = 0;
12584  DB_SEQ *seq = NULL;
12586  DB_VALUE *value = NULL;
12587 
12588  assert (parser != NULL);
12589 
12590  if (values_list == NULL || values_list->node_type != PT_NODE_LIST
12591  || values_list->info.node_list.list_type != PT_IS_SUBQUERY || (qry = values_list->info.node_list.list) == NULL
12592  || (statement->node_type != PT_INSERT && statement->node_type != PT_MERGE))
12593  {
12594  return ER_GENERIC_ERROR;
12595  }
12596  attrs = statement->node_type == PT_MERGE ? statement->info.merge.insert.attr_list : statement->info.insert.attr_list;
12597  if (attrs == NULL)
12598  {
12599  return ER_GENERIC_ERROR;
12600  }
12601  error = sm_partitioned_class_type (class_->info.name.db_object, &pruning_type, NULL, NULL);
12602  if (error != NO_ERROR)
12603  {
12604  return error;
12605  }
12606 
12607  cnt = 0;
12608 
12609  if (parser->flag.return_generated_keys)
12610  {
12611  seq = set_create_sequence (0);
12612  if (seq == NULL)
12613  {
12614  error = ER_GENERIC_ERROR;
12615  return error;
12616  }
12617  }
12618 
12619  switch (qry->node_type)
12620  {
12621  default: /* preconditions not met */
12622  return ER_GENERIC_ERROR; /* so, nothing doing. */
12623 
12624  case PT_SELECT:
12625  case PT_UNION:
12626  case PT_DIFFERENCE:
12627  case PT_INTERSECTION:
12628  /* count elements in the select list before we modify it for ON DUPLICATE KEY UPDATE statements */
12630  if (degree <= 0)
12631  {
12633  return ER_DO_INSERT_TOO_MANY;
12634  }
12635  if (qry->etc == NULL)
12636  {
12637  if (statement->info.insert.odku_assignments != NULL)
12638  {
12639  /* Add nodes referenced in odku_assignments to the select list because we need those values when
12640  * evaluating values for update. */
12641  odku_arg.insert_stmt = statement;
12642  odku_arg.cursor_p = &cursor_id;
12643 
12644  statement->info.insert.odku_assignments =
12646  (void *) (&odku_arg), NULL, NULL);
12647  if (statement->info.insert.odku_assignments == NULL || pt_has_error (parser))
12648  {
12649  assert (er_errid () != NO_ERROR);
12650  error = er_errid ();
12651  if (error == NO_ERROR)
12652  {
12653  error = ER_FAILED;
12654  }
12655  return error;
12656  }
12657  }
12658 
12659  /* execute the subquery */
12660  query_id_self = parser->query_id;
12661  parser->query_id = NULL_QUERY_ID;
12662  error = do_select (parser, qry);
12663  if (error < NO_ERROR || qry->etc == NULL)
12664  {
12665  parser->query_id = query_id_self;
12666  return error;
12667  }
12668  }
12669 
12670  /* insert subquery results into target class */
12671  if (cursor_open (&cursor_id, (QFILE_LIST_ID *) qry->etc, false, false))
12672  {
12673  cursor_id.query_id = parser->query_id;
12674 
12675  vals = (DB_VALUE *) malloc (degree * sizeof (DB_VALUE));
12676  if (vals == NULL)
12677  {
12680  goto cleanup;
12681  }
12682 
12683  for (i = 0; i < degree; i++)
12684  {
12685  db_make_null (&vals[i]);
12686  }
12687 
12688  /* allocate attribute descriptor array */
12689  if (degree)
12690  {
12691  attr_descs = (DB_ATTDESC **) malloc ((degree) * sizeof (DB_ATTDESC *));
12692  if (attr_descs == NULL)
12693  {
12695  degree * sizeof (DB_ATTDESC *));
12697  goto cleanup;
12698  }
12699  for (i = 0; i < degree; i++)
12700  {
12701  attr_descs[i] = NULL;
12702  }
12703  }
12704 
12705  /* if the list file contains more than 1 object we need to savepoint the statement to guarantee statement
12706  * atomicity. */
12707  if ((((QFILE_LIST_ID *) qry->etc)->tuple_cnt > 1 && !*savepoint_name)
12708  || (TM_TRAN_ISOLATION () >= TRAN_REP_READ && statement->node_type == PT_INSERT
12709  && statement->info.insert.odku_assignments))
12710  {
12711  *savepoint_name = mq_generate_name (parser, "UisP", &insert_savepoint_number);
12712  error = tran_system_savepoint (*savepoint_name);
12713  }
12714 
12715  if (error >= NO_ERROR)
12716  {
12717  /* for each tuple in subquery result do */
12718  while (cursor_next_tuple (&cursor_id) == DB_CURSOR_SUCCESS)
12719  {
12720  /* get current tuple of subquery result */
12721  if (cursor_get_tuple_value_list (&cursor_id, degree, vals) != NO_ERROR)
12722  {
12723  break;
12724  }
12725 
12726  /* create an instance of the target class using templates */
12727  otemplate = dbt_create_object_internal (class_->info.name.db_object);
12728  if (otemplate == NULL)
12729  {
12730  break;
12731  }
12732  otemplate->pruning_type = pruning_type;
12733  if (pruning_type != DB_NOT_PARTITIONED_CLASS)
12734  {
12735  obt_set_force_flush (otemplate);
12736  }
12737  /* update new instance with current tuple of subquery result */
12738  for (attr = attrs, val = vals, k = 0; attr != NULL && k < degree; attr = attr->next, val++, k++)
12739  {
12740  /* if this is the first tuple, get the attr descriptor */
12741  if (attr_descs != NULL)
12742  {
12743  if (attr_descs[k] == NULL)
12744  {
12745  int is_vclass = 0;
12746 
12747  /* don't get descriptors for shared attrs of views */
12748  if (attr->info.name.db_object)
12749  {
12750  is_vclass = db_is_vclass (attr->info.name.db_object);
12751 
12752  if (is_vclass < 0)
12753  {
12754  error = is_vclass;
12755  }
12756  }
12757  if (!is_vclass)
12758  {
12759  error =
12761  0, 1, &attr_descs[k]);
12762  }
12763  }
12764  }
12765 
12766  if (error >= NO_ERROR)
12767  {
12768  error = insert_object_attr (parser, otemplate, val, attr, attr_descs[k]);
12769  }
12770 
12771  if (error < NO_ERROR)
12772  {
12773  dbt_abort_object (otemplate);
12774  cursor_close (&cursor_id);
12775  assert (er_errid () != NO_ERROR);
12776  cnt = er_errid ();
12777  goto cleanup;
12778  }
12779  }
12780 
12781  if (statement->node_type == PT_INSERT && statement->info.insert.odku_assignments)
12782  {
12783  if (update == NULL)
12784  {
12785  flag = statement->info.insert.spec->info.spec.flag;
12786  update = do_create_odku_stmt (parser, statement);
12787  if (update == NULL)
12788  {
12789  error = ER_FAILED;
12790  goto cleanup;
12791  }
12792  }
12793  error = do_on_duplicate_key_update (parser, otemplate, update);
12794  if (error < 0)
12795  {
12796  /* there was an error, cleanup and return */
12797  cursor_close (&cursor_id);
12798  if (obj == NULL)
12799  {
12800  dbt_abort_object (otemplate);
12801  }
12802  cnt = error;
12803  goto cleanup;
12804  }
12805  if (error > 0)
12806  {
12807  /* a successful update, go to finish */
12808  cnt += error;
12809  dbt_abort_object (otemplate);
12810  otemplate = NULL;
12811  error = NO_ERROR;
12812  }
12813  }
12814 
12815  if (statement->node_type == PT_INSERT && statement->info.insert.do_replace)
12816  {
12817  error =
12818  do_replace_into (parser, otemplate, statement->info.insert.spec,
12819  statement->info.insert.class_specs);
12820  if (error < 0)
12821  {
12822  cursor_close (&cursor_id);
12823  if (obj == NULL)
12824  {
12825  dbt_abort_object (otemplate);
12826  }
12827  cnt = error;
12828  goto cleanup;
12829  }
12830 
12831  cnt += error;
12832  }
12833 
12834  if (otemplate != NULL)
12835  {
12836  /* apply the object template */
12837  bool include_new_obj;
12838 
12839  obt_retain_after_finish (otemplate);
12840 
12841  obj = dbt_finish_object (otemplate); /* flush template */
12842 
12843  include_new_obj = (obj && parser->flag.return_generated_keys && otemplate->is_autoincrement_set);
12844 
12845  obt_quit (otemplate); /* free template */
12846 
12847  if (include_new_obj == true)
12848  {
12849  db_make_object (&db_value, obj);
12850  error = set_put_element (seq, obj_count, &db_value);
12851  if (error != NO_ERROR)
12852  {
12853  cnt = error;
12854  goto cleanup;
12855  }
12856  obj_count++;
12857  }
12858 
12859  if (obj && error >= NO_ERROR)
12860  {
12861  if (statement->node_type == PT_INSERT)
12862  {
12863  error = mq_evaluate_check_option (parser, statement->info.insert.where, obj, class_);
12864  }
12865  else if (statement->node_type == PT_MERGE && statement->info.merge.check_where)
12866  {
12867  error =
12868  mq_evaluate_check_option (parser,
12870  obj, class_);
12871  }
12872  }
12873 
12874  if (obj == NULL || error < NO_ERROR)
12875  {
12876  cursor_close (&cursor_id);
12877  if (obj == NULL)
12878  {
12879  dbt_abort_object (otemplate);
12880  assert (er_errid () != NO_ERROR);
12881  cnt = er_errid ();
12882  }
12883  else
12884  {
12885  cnt = error;
12886  }
12887  goto cleanup;
12888  }
12889 
12890  }
12891 
12892  /* keep track of how many we have inserted */
12893  cnt++;
12894  }
12895  }
12896 
12897  cursor_close (&cursor_id);
12898  }
12899  }
12900 
12901  if (parser->flag.return_generated_keys && seq != NULL)
12902  {
12903  value = db_value_create ();
12904  if (value == NULL)
12905  {
12906  assert (er_errid () != NO_ERROR);
12907  error = er_errid ();
12908  goto cleanup;
12909  }
12910  error = db_make_sequence (value, seq);
12911  if (error != NO_ERROR)
12912  {
12913  goto cleanup;
12914  }
12915  statement->etc = (void *) value;
12916  }
12917 
12918 cleanup:
12919  if (update != NULL)
12920  {
12921  /* restore flags */
12922  statement->info.insert.spec->info.spec.flag = (PT_SPEC_FLAG) flag;
12923  update->info.update.assignment = NULL;
12924  update->info.update.spec = NULL;
12925  if (update->info.update.check_where != NULL)
12926  {
12928  }
12929  parser_free_tree (parser, update);
12930  }
12931  if (vals != NULL)
12932  {
12933  for (val = vals, k = 0; k < degree; val++, k++)
12934  {
12935  db_value_clear (val);
12936  }
12937  free_and_init (vals);
12938  }
12939 
12940  if (attr_descs != NULL)
12941  {
12942  for (i = 0; i < degree; i++)
12943  {
12944  if (attr_descs[i] != NULL)
12945  {
12946  db_free_attribute_descriptor (attr_descs[i]);
12947  }
12948  }
12949  free_and_init (attr_descs);
12950  }
12951 
12952  if (cnt < 0 && seq != NULL)
12953  {
12954  set_free (seq);
12955  }
12956 
12958  pt_end_query (parser, query_id_self);
12959 
12960  return cnt;
12961 }
12962 
12963 /*
12964  * is_attr_not_in_insert_list() - Returns 1 if the name is not on the name_list,
12965  * 0 otherwise. name_list is assumed to be a list of PT_NAME nodes.
12966  * return: Error code
12967  * param1(out): Short description of the param1
12968  * param2(in/out): Short description of the param2
12969  * param2(in): Short description of the param3
12970  *
12971  * Note: If you feel the need
12972  */
12973 static int
12974 is_attr_not_in_insert_list (const PARSER_CONTEXT * parser, PT_NODE * name_list, const char *name)
12975 {
12976  PT_NODE *tmp;
12977  int not_on_list = 1;
12978 
12979  for (tmp = name_list; tmp != NULL; tmp = tmp->next)
12980  {
12981  if (intl_identifier_casecmp (tmp->info.name.original, name) == 0)
12982  {
12983  not_on_list = 0;
12984  break;
12985  }
12986  }
12987 
12988  return not_on_list;
12989 
12990 } /* is_attr_not_in_insert_list */
12991 
12992 /*
12993  * check_missing_non_null_attrs() - Check to see that all attributes of
12994  * the class that have a NOT NULL constraint AND have no default
12995  * value are present in the inserts assign list.
12996  * return: Error code
12997  * parser(in):
12998  * spec(in):
12999  * attr_list(in):
13000  * has_default_values_list(in): whether this statement is used to insert
13001  * default values
13002  */
13003 static int
13004 check_missing_non_null_attrs (const PARSER_CONTEXT * parser, const PT_NODE * spec, PT_NODE * attr_list,
13005  const bool has_default_values_list)
13006 {
13007  DB_ATTRIBUTE *attr;
13008  DB_OBJECT *class_;
13009  int error = NO_ERROR;
13010  int save_au;
13011 
13012  if (!spec || !spec->info.spec.entity_name || !(class_ = spec->info.spec.entity_name->info.name.db_object))
13013  {
13014  return ER_GENERIC_ERROR;
13015  }
13016 
13017  AU_DISABLE (save_au);
13018  attr = db_get_attributes (class_);
13019  while (attr)
13020  {
13023  && (is_attr_not_in_insert_list (parser, attr_list, db_attribute_name (attr)) || has_default_values_list)
13024  && !(attr->flags & SM_ATTFLAG_AUTO_INCREMENT))
13025  {
13028  }
13029  attr = db_attribute_next (attr);
13030  }
13031  AU_ENABLE (save_au);
13032 
13033  return error;
13034 }
13035 
13036 /*
13037  * make_vmops() -
13038  * return: Error code
13039  * parser(in): Short description of the param1
13040  * node(in):
13041  * arg(in/out):
13042  * continue_walk(in/out):
13043  */
13044 static PT_NODE *
13045 make_vmops (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13046 {
13047  DB_OBJECT **vobj = ((DB_OBJECT **) arg);
13048  DB_OBJECT *vclass_mop, *obj;
13049  const char *into_label;
13050  DB_VALUE *val;
13051 
13052  if (node->node_type != PT_INSERT)
13053  {
13054  return node;
13055  }
13056 
13057  /* make a virtual obj if it is a virtual class and has an into label */
13058  if (node->info.insert.into_var
13059  && ((vclass_mop = node->info.insert.spec->info.spec.flat_entity_list->info.name.virt_object) != NULL))
13060  {
13061  into_label = node->info.insert.into_var->info.name.original;
13062  val = pt_find_value_of_label (into_label);
13063  if (val != NULL)
13064  {
13065  obj = db_get_object (val);
13066  *vobj = vid_build_virtual_mop (obj, vclass_mop);
13067  /* change the label to point to the newly created vmop, we don't need to call pt_associate_label_with_value
13068  * here because we've directly modified the value that has been installed in the table. */
13069  db_make_object (val, *vobj);
13070  }
13071  }
13072  else
13073  {
13074  *vobj = NULL;
13075  }
13076 
13077  return node;
13078 
13079 }
13080 
13081 /*
13082  * test_check_option() - Tests if we are inserting to a class through a view
13083  * with a check option.
13084  * return: Error code
13085  * parser(in): Parser context
13086  * node(in): The PT_NAME node of a potential insert
13087  * arg(in/out): Nonzero iff insert statement has a check option
13088  * continue_walk(in/out):
13089  */
13090 static PT_NODE *
13091 test_check_option (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
13092 {
13093  int *found = (int *) arg;
13094  PT_NODE *class_;
13095  DB_OBJECT *view;
13096 
13097  if (node->node_type != PT_INSERT || !node->info.insert.spec)
13098  {
13099  return node;
13100  }
13101 
13102  /* make a virtual obj if it is a virtual class and has an into label */
13103  class_ = node->info.insert.spec->info.spec.flat_entity_list;
13104  view = class_->info.name.virt_object;
13105  if (view)
13106  {
13109  {
13110  *found = 1;
13111  *continue_walk = PT_STOP_WALK;
13112  }
13113  }
13114 
13115  return node;
13116 
13117 }
13118 
13119 /*
13120  * insert_local () - Insert execution checks:
13121  * 1. Updates attribute default expressions.
13122  * 2. Checks for missing attributes that have not null
13123  * constraints.
13124  * 3. Check if inserting a false sub-query.
13125  * 4. Check if a savepoint is needed.
13126  * 5. Calls do_insert_template.
13127  * 6. Revert to savepoint is an error occurred.
13128  *
13129  * return : Error code or row count if no error has occurred.
13130  * parser (in) : Parser context.
13131  * statement (in) : Parse tree node for insert statement.
13132  */
13133 static int
13134 insert_local (PARSER_CONTEXT * parser, PT_NODE * statement)
13135 {
13136  int error = NO_ERROR;
13137  int row_count_total = 0;
13138  PT_NODE *class_ = NULL, *vc = NULL;
13139  int save;
13140  int has_check_option = 0;
13141  const char *savepoint_name = NULL;
13142  PT_NODE *crt_list = NULL;
13143  bool has_default_values_list = false;
13144  bool is_multiple_tuples_insert = false;
13145  bool need_savepoint = false;
13146  int has_trigger = 0;
13147  bool is_trigger_involved = false;
13148  DB_OTMPL *otemplate = NULL;
13149 
13150  if (!statement || statement->node_type != PT_INSERT || !statement->info.insert.spec
13151  || !statement->info.insert.spec->info.spec.flat_entity_list)
13152  {
13153  return ER_GENERIC_ERROR;
13154  }
13155 
13156  class_ = statement->info.insert.spec->info.spec.flat_entity_list;
13157 
13158  statement->etc = NULL;
13159 
13160  for (crt_list = statement->info.insert.value_clauses, has_default_values_list = false; crt_list != NULL;
13161  crt_list = crt_list->next)
13162  {
13163  if (crt_list->info.node_list.list_type == PT_IS_DEFAULT_VALUE)
13164  {
13165  has_default_values_list = true;
13166  break;
13167  }
13168  }
13169 
13170  error = do_evaluate_default_expr (parser, class_);
13171  if (error != NO_ERROR)
13172  {
13173  return error;
13174  }
13175 
13176  error =
13177  check_missing_non_null_attrs (parser, statement->info.insert.spec, statement->info.insert.attr_list,
13178  has_default_values_list);
13179  if (error != NO_ERROR)
13180  {
13181  return error;
13182  }
13183 
13184  crt_list = statement->info.insert.value_clauses;
13185  if (crt_list->next != NULL)
13186  {
13187  is_multiple_tuples_insert = true;
13188  }
13189 
13190  if (crt_list->info.node_list.list_type == PT_IS_SUBQUERY && (vc = crt_list->info.node_list.list)
13191  && pt_false_where (parser, vc))
13192  {
13193  /* 0 tuples inserted. */
13194  return 0;
13195  }
13196 
13197  /*
13198  * It is necessary to add savepoint in the cases as below.
13199  *
13200  * 1. when multiple tuples were inserted (ex: insert into ... values(), (), ();)
13201  * 2. the REPLACE statement (ex: replace into ... values ..;)
13202  * 3. view having 'with check option'
13203  * 4. class/view having trigger
13204  * 5. when there is another insert statement among values.
13205  */
13206 
13207  if (is_multiple_tuples_insert == true || statement->info.insert.do_replace == true)
13208  {
13209  need_savepoint = true;
13210  }
13211 
13212  if (need_savepoint == false)
13213  {
13214  statement = parser_walk_tree (parser, statement, NULL, NULL, test_check_option, &has_check_option);
13215  if (has_check_option)
13216  {
13217  need_savepoint = true;
13218  }
13219  }
13220 
13221  /* DO NOT RETURN UNTIL AFTER AU_ENABLE! */
13222  AU_DISABLE (save);
13223  parser->au_save = save;
13224 
13225  if (need_savepoint == false && statement->info.insert.odku_assignments != NULL)
13226  {
13227  has_trigger = 0;
13228  error = sm_class_has_triggers (class_->info.name.db_object, &has_trigger, TR_EVENT_UPDATE);
13229  if (error != NO_ERROR)
13230  {
13231  AU_ENABLE (save);
13232  return error;
13233  }
13234  if (has_trigger != 0)
13235  {
13236  need_savepoint = true;
13237  }
13238  else if (TM_TRAN_ISOLATION () >= TRAN_REP_READ && !statement->info.insert.server_allowed)
13239  {
13240  need_savepoint = true;
13241  }
13242  }
13243 
13244  if (need_savepoint == false)
13245  {
13246  has_trigger = 0;
13247  error = sm_class_has_triggers (class_->info.name.db_object, &has_trigger, TR_EVENT_INSERT);
13248  if (error != NO_ERROR)
13249  {
13250  AU_ENABLE (save);
13251  return error;
13252  }
13253  if (has_trigger != 0)
13254  {
13255  need_savepoint = true;
13256  }
13257  }
13258 
13259  if (need_savepoint == false)
13260  {
13261  int arg[2]; /* argument for pt_find_node_type_pre */
13262  arg[0] = PT_INSERT; /* node type */
13263  arg[1] = 0; /* found */
13264  (void) parser_walk_tree (parser, statement->info.insert.value_clauses, pt_find_node_type_pre, arg, NULL, NULL);
13265  if (arg[1] == 1)
13266  {
13267  /* sub insert was found */
13268  need_savepoint = true;
13269  }
13270  }
13271 
13272  /*
13273  * if the insert statement contains more than one insert component,
13274  * we savepoint the insert components to try to guarantee insert
13275  * statement atomicity.
13276  */
13277  if (need_savepoint == true)
13278  {
13279  savepoint_name = mq_generate_name (parser, "UisP", &insert_savepoint_number);
13280  if (savepoint_name == NULL)
13281  {
13282  AU_ENABLE (save);
13283  return ER_GENERIC_ERROR;
13284  }
13285  error = tran_system_savepoint (savepoint_name);
13286  if (error != NO_ERROR)
13287  {
13288  AU_ENABLE (save);
13289  return error;
13290  }
13291  }
13292 
13293  /* the do_Trigger_involved will be set as true when execute trigger statement. it will not be set back. we need to
13294  * keep its value to update last insert id. */
13295  is_trigger_involved = do_Trigger_involved;
13296  if (!do_Trigger_involved)
13297  {
13299  }
13300 
13301  row_count_total = 0;
13302 
13303 
13304 
13305  error = do_insert_template (parser, &otemplate, statement, &savepoint_name, &row_count_total);
13306 
13307  AU_ENABLE (save);
13308 
13309  /* restore the obt_Last_insert_id_generated flag after insert. */
13310  if (!is_trigger_involved && obt_Last_insert_id_generated)
13311  {
13313  if (error != NO_ERROR)
13314  {
13315  (void) csession_reset_cur_insert_id ();
13316  }
13317  }
13318 
13319  /* if error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
13320  * transaction. */
13321  if (error < NO_ERROR && savepoint_name && (error != ER_LK_UNILATERALLY_ABORTED))
13322  {
13323  /* savepoint from tran_savepoint() */
13324  (void) tran_internal_abort_upto_savepoint (savepoint_name, SYSTEM_SAVEPOINT, true);
13325  /* Use a special version of rollback which will not clobber cached views. We can do this because we know insert
13326  * can not have created any views. This is instead of the extern function: db_abort_to_savepoint(savepoint_name); */
13327  }
13328 
13329  return error < 0 ? error : row_count_total;
13330 }
13331 
13332 /*
13333  * do_insert() - Checks if insert is already prepared and execute it. If it
13334  * is not prepared, calls insert_local.
13335  *
13336  * return : Error code if insert fails, the row count otherwise.
13337  * parser (in) : Parser context.
13338  * statement(in): Parse tree of a insert statement.
13339  */
13340 int
13341 do_insert (PARSER_CONTEXT * parser, PT_NODE * root_statement)
13342 {
13343  PT_NODE *statement = root_statement;
13344  int error;
13345 
13347 
13348  error = insert_local (parser, statement);
13349  if (pt_has_error (parser))
13350  {
13351  pt_report_to_ersys (parser, PT_EXECUTION);
13352  }
13353 
13354  while (error < NO_ERROR && statement->next)
13355  {
13356  /* assume error was from mismatch of multiple possible translated inserts. Try the next statement in the list.
13357  * Only report the last error. */
13358  parser_free_tree (parser, parser->error_msgs);
13359  parser->error_msgs = NULL;
13360 
13361  statement = statement->next;
13362  error = insert_local (parser, statement);
13363 
13364  /* check whether this transaction is a victim of deadlock during */
13365  /* request to the driver */
13366  if (parser->flag.abort)
13367  {
13368  assert (er_errid () != NO_ERROR);
13369  return (er_errid ());
13370  }
13371 
13372  if (pt_has_error (parser))
13373  {
13374  pt_report_to_ersys (parser, PT_EXECUTION);
13375  }
13376 
13377  /* This is to allow the row "counting" to be done in db_execute_and_keep_statement, and also correctly returns
13378  * the "result" of the last insert statement. Only the first insert statement in the list is examined for
13379  * results. */
13380  root_statement->etc = statement->etc;
13381  statement->etc = NULL;
13382  }
13383 
13384  return error;
13385 }
13386 
13387 /*
13388  * do_prepare_insert () - Prepare the INSERT statement
13389  * return: Error code
13390  * parser(in): Parser context
13391  * statement(in):
13392  */
13393 int
13395 {
13396  int error = NO_ERROR;
13397  PT_NODE *class_;
13398  PT_NODE *values = NULL;
13399  PT_NODE *attr_list;
13400  PT_NODE *update = NULL;
13401  PT_NODE *with = NULL;
13402  int save_au;
13403 
13404  if (statement == NULL || statement->node_type != PT_INSERT || statement->info.insert.spec == NULL
13405  || statement->info.insert.spec->info.spec.flat_entity_list == NULL)
13406  {
13407  assert (false);
13408  return ER_GENERIC_ERROR;
13409  }
13410 
13411  AU_DISABLE (save_au);
13412 
13413  /* We do not allow multi statements. To be checked! */
13414  if (pt_length_of_list (statement) > 1)
13415  {
13416  assert (false);
13417  goto cleanup;
13418  }
13419 
13420  statement->etc = NULL;
13421  class_ = statement->info.insert.spec->info.spec.flat_entity_list;
13422  values = statement->info.insert.value_clauses;
13423 
13424  error = do_insert_checks (parser, statement, &class_, &update, values);
13425  if (error != NO_ERROR)
13426  {
13427  ASSERT_ERROR ();
13428  goto cleanup;
13429  }
13430 
13432  {
13433  goto cleanup;
13434  }
13435 
13436  error = do_prepare_insert_internal (parser, statement);
13437 
13438 cleanup:
13439  /* Free update attribute. */
13440  if (update != NULL)
13441  {
13442  update->info.update.assignment = NULL;
13443  update->info.update.spec = NULL;
13444  if (update->info.update.check_where != NULL)
13445  {
13447  }
13448  parser_free_tree (parser, update);
13449  }
13450 
13451  AU_ENABLE (save_au);
13452 
13453  return error;
13454 }
13455 
13456 /*
13457  * do_execute_insert () - Execute the prepared INSERT statement
13458  * return: Error code
13459  * parser(in): Parser context
13460  * statement(in):
13461  */
13462 int
13464 {
13465  int err;
13466  PT_NODE *flat;
13467  DB_OBJECT *class_obj;
13468  QFILE_LIST_ID *list_id;
13469  QUERY_FLAG query_flag;
13470  QUERY_ID query_id_self = parser->query_id;
13471 
13472  assert (parser->query_id == NULL_QUERY_ID);
13473 
13475 
13476  if (statement->xasl_id == NULL)
13477  {
13478  /* check if it is not necessary to execute this statement */
13479  if (qo_need_skip_execution ())
13480  {
13481  statement->etc = NULL;
13482  return NO_ERROR;
13483  }
13484  return do_insert (parser, statement);
13485  }
13486 
13487  flat = statement->info.insert.spec->info.spec.flat_entity_list;
13488  class_obj = (flat) ? flat->info.name.db_object : NULL;
13489 
13490  query_flag = DEFAULT_EXEC_MODE;
13491 
13492  query_flag |= NOT_FROM_RESULT_CACHE;
13493  query_flag |= RESULT_CACHE_INHIBITED;
13494 
13495  if (parser->flag.return_generated_keys)
13496  {
13497  query_flag |= RETURN_GENERATED_KEYS;
13498  }
13499 
13500  if (parser->flag.is_xasl_pinned_reference)
13501  {
13502  query_flag |= XASL_CACHE_PINNED_REFERENCE;
13503  }
13504 
13505  if (statement->flag.use_auto_commit)
13506  {
13507  query_flag |= EXECUTE_QUERY_WITH_COMMIT;
13508  }
13509 
13510  if (parser->flag.is_auto_commit)
13511  {
13512  query_flag |= TRAN_AUTO_COMMIT;
13513  }
13514 
13515  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
13516  {
13517  do_set_trace_to_query_flag (&query_flag);
13519  }
13520 
13521  if (ws_need_flush ())
13522  {
13523  if (statement->flag.use_auto_commit)
13524  {
13525  // When a transaction is under auto-commit mode, flush all dirty objects to server.
13526  err = tran_flush_to_commit ();
13527  if (err != NO_ERROR)
13528  {
13529  return err;
13530  }
13531  /* Nothing to flush. However ws_Num_dirty_mop is not 0 sometimes. We may reset ws_Num_dirty_mop to 0,
13532  * if flushed without errors, but is not necessary. Before sending data to the server, we check that
13533  * the transaction was not finalized, in case of execution with commit.
13534  */
13535  }
13536  }
13537 
13538  assert (parser->query_id == NULL_QUERY_ID);
13539  list_id = NULL;
13540 
13541  err = execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
13542  parser->host_variables, &list_id, query_flag, NULL, NULL);
13543 
13544  /* free returned QFILE_LIST_ID */
13545  if (list_id)
13546  {
13547  /* set as result */
13548  err = list_id->tuple_cnt;
13549  if (parser->flag.return_generated_keys)
13550  {
13551  statement->etc = (void *) list_id;
13552  }
13553  else
13554  {
13555  cursor_free_self_list_id (list_id);
13556  }
13557  }
13558 
13559  /* end the query; reset query_id and call qmgr_end_query() */
13560  pt_end_query (parser, query_id_self);
13561 
13562  return err;
13563 }
13564 
13565 /*
13566  * Function Group:
13567  * Implement method calls
13568  *
13569  */
13570 
13571 static int call_method (PARSER_CONTEXT * parser, PT_NODE * statement);
13572 
13573 /*
13574  * call_method() -
13575  * return: Value returned by method if success, otherwise an error code
13576  * parser(in): Parser context
13577  * node(in): Parse tree of a call statement
13578  *
13579  * Note:
13580  */
13581 static int
13582 call_method (PARSER_CONTEXT * parser, PT_NODE * statement)
13583 {
13584  const char *into_label, *proc;
13585  int error = NO_ERROR;
13586  DB_OBJECT *obj = NULL;
13587  DB_VALUE target_value, *ins_val, ret_val, db_value;
13588  DB_VALUE_LIST *val_list = 0, *vl, **next_val_list;
13589  PT_NODE *vc, *into, *target, *method;
13590 
13591  db_make_null (&ret_val);
13592  db_make_null (&target_value);
13593 
13594  /*
13595  * The method name and ON name are required.
13596  */
13597  if (!statement || !(method = statement->info.method_call.method_name) || method->node_type != PT_NAME
13598  || !(proc = method->info.name.original) || !(target = statement->info.method_call.on_call_target))
13599  {
13601  return er_errid ();
13602  }
13603 
13604  /*
13605  * Determine whether the object is a class or instance.
13606  */
13607 
13608  pt_evaluate_tree (parser, target, &target_value, 1);
13609  if (pt_has_error (parser))
13610  {
13611  pt_report_to_ersys (parser, PT_SEMANTIC);
13612  return er_errid ();
13613  }
13614 
13615  if (DB_VALUE_TYPE (&target_value) == DB_TYPE_NULL)
13616  {
13617  /*
13618  * Don't understand the rationale behind this case. What's the
13619  * point here? MRS 4/30/96
13620  */
13621  error = NO_ERROR;
13622  }
13623  else
13624  {
13625  if (DB_VALUE_TYPE (&target_value) == DB_TYPE_OBJECT)
13626  {
13627  obj = db_get_object ((&target_value));
13628  }
13629 
13630  if (obj == NULL || pt_has_error (parser))
13631  {
13633  return er_errid ();
13634  }
13635 
13636  /*
13637  * Build an argument list.
13638  */
13639  next_val_list = &val_list;
13640  vc = statement->info.method_call.arg_list;
13641  for (; vc != NULL; vc = vc->next)
13642  {
13643  DB_VALUE *db_val;
13644  bool to_break = false;
13645 
13646  *next_val_list = (DB_VALUE_LIST *) calloc (1, sizeof (DB_VALUE_LIST));
13647  if (*next_val_list == NULL)
13648  {
13650  return er_errid ();
13651  }
13652  (*next_val_list)->next = (DB_VALUE_LIST *) 0;
13653 
13654  /*
13655  * Don't clone host vars; they may actually be acting as output
13656  * variables (e.g., a character array that is intended to receive
13657  * bytes from the method), and cloning will ensure that the
13658  * results never make it to the expected area. Since
13659  * pt_evaluate_tree() always clones its db_values we must not
13660  * use pt_evaluate_tree() to extract the db_value from a host
13661  * variable; instead extract it ourselves.
13662  */
13663  if (PT_IS_CONST (vc))
13664  {
13665  db_val = pt_value_to_db (parser, vc);
13666  }
13667  else
13668  {
13669  pt_evaluate_tree (parser, vc, &db_value, 1);
13670  if (pt_has_error (parser))
13671  {
13672  /* to maintain the list to free all the allocated */
13673  to_break = true;
13674  }
13675  db_val = &db_value;
13676  }
13677 
13678  if (db_val != NULL)
13679  {
13680  (*next_val_list)->val = *db_val;
13681 
13682  next_val_list = &(*next_val_list)->next;
13683  }
13684 
13685  if (to_break)
13686  {
13687  break;
13688  }
13689  }
13690 
13691  /*
13692  * Call the method.
13693  */
13694  if (pt_has_error (parser))
13695  {
13696  pt_report_to_ersys (parser, PT_SEMANTIC);
13697  error = er_errid ();
13698  }
13699  else
13700  {
13701  error = db_send_arglist (obj, proc, &ret_val, val_list);
13702  }
13703 
13704  /*
13705  * Free the argument list. Again, it is important to be careful
13706  * with host variables. Since we didn't clone them, we shouldn't
13707  * free or clear them.
13708  */
13709  vc = statement->info.method_call.arg_list;
13710  for (; val_list && vc; vc = vc->next)
13711  {
13712  vl = val_list->next;
13713  if (!PT_IS_CONST (vc))
13714  {
13715  db_value_clear (&val_list->val);
13716  }
13717  free_and_init (val_list);
13718  val_list = vl;
13719  }
13720 
13721  if (error == NO_ERROR)
13722  {
13723  /*
13724  * Save the method result.
13725  */
13726  statement->etc = (void *) db_value_copy (&ret_val);
13727 
13728  if ((into = statement->info.method_call.to_return_var) != NULL && into->node_type == PT_NAME
13729  && (into_label = into->info.name.original) != NULL)
13730  {
13731  /* create another DB_VALUE of the new instance for the label_table */
13732  ins_val = db_value_copy (&ret_val);
13733 
13734  /* enter {label, ins_val} pair into the label_table */
13735  error = pt_associate_label_with_value_check_reference (into_label, ins_val);
13736  }
13737  }
13738  }
13739 
13740  db_value_clear (&ret_val);
13741  return error;
13742 }
13743 
13744 /*
13745  * do_call_method() -
13746  * return: Value returned by method if success, otherwise an error code
13747  * parser(in): Parser context
13748  * node(in): Parse tree of a call statement
13749  *
13750  * Note:
13751  */
13752 int
13753 do_call_method (PARSER_CONTEXT * parser, PT_NODE * statement)
13754 {
13755  PT_NODE *method;
13756 
13757  if (!statement || !(method = statement->info.method_call.method_name) || method->node_type != PT_NAME
13758  || !(method->info.name.original))
13759  {
13761  return er_errid ();
13762  }
13763 
13764  if (statement->info.method_call.on_call_target)
13765  {
13766  return call_method (parser, statement);
13767  }
13768  else
13769  {
13770  return jsp_call_stored_procedure (parser, statement);
13771  }
13772 }
13773 
13774 /*
13775  * These functions are provided just so we have some builtin gadgets that we can
13776  * use for quick and dirty method testing. To get at them, alter your
13777  * favorite class like this:
13778  *
13779  * alter class foo
13780  * add method pickaname() string
13781  * function dbmeth_class_name;
13782  *
13783  * or
13784  *
13785  * alter class foo
13786  * add method pickaname(string) string
13787  * function dbmeth_print;
13788  *
13789  * After that you should be able to invoke "pickaname" on "foo" instances
13790  * to your heart's content. dbmeth_class_name() will retrieve the class
13791  * name of the target instance and return it as a string; dbmeth_print()
13792  * will print the supplied value on stdout every time it is invoked.
13793  */
13794 
13795 /*
13796  * TODO: The following function names need to be fixed.
13797  * Renaming can affects user interface.
13798  */
13799 
13800 /*
13801  * dbmeth_class_name() -
13802  * return: None
13803  * self(in): Class object
13804  * result(out): DB_VALUE for a class name
13805  *
13806  * Note: Position of function arguments must be kept
13807  * for pre-defined function pointers(au_static_links)
13808  */
13809 void
13811 {
13812  const char *cname;
13813 
13814  cname = db_get_class_name (self);
13815 
13816  /*
13817  * Make a string and clone it so that it won't become invalid if the
13818  * underlying class object that gave us the string goes away. Of
13819  * course, this gives the responsibility for freeing the cloned
13820  * string to someone else; is anybody accepting it?
13821  */
13822  db_make_string (result, cname);
13823 }
13824 
13825 /*
13826  * TODO: The functin name need to be fixed.
13827  * it is known system method so must fix corresponding qa first
13828  */
13829 
13830 /*
13831  * dbmeth_print() -
13832  * return: None
13833  * self(in): Class object
13834  * result(out): NULL value
13835  * msg(in): DB_VALUE for a message
13836  *
13837  * Note: Position of function arguments must be kept
13838  * for pre-defined function pointers(au_static_links)
13839  */
13840 void
13841 dbmeth_print (DB_OBJECT * self, DB_VALUE * result, DB_VALUE * msg)
13842 {
13843  db_value_print (msg);
13844  printf ("\n");
13845  db_make_null (result);
13846 }
13847 
13848 
13849 
13850 
13851 
13852 
13853 /*
13854  * Function Group:
13855  * Functions for the implementation of virtual queries.
13856  *
13857  */
13858 
13859 /*
13860  * do_select() -
13861  * return: Error code
13862  * parser(in/out): Parser context
13863  * statement(in/out): A statement to do
13864  *
13865  * Note: Side effects can exist at returned result through application extern
13866  */
13867 
13868 int
13869 do_select (PARSER_CONTEXT * parser, PT_NODE * statement)
13870 {
13871  return do_select_internal (parser, statement, false);
13872 }
13873 
13874 /*
13875  * do_select_for_ins_upd() -
13876  * return: Error code
13877  * parser(in/out): Parser context
13878  * statement(in/out): A statement to do
13879  *
13880  * Note: Side effects can exist at returned result through application extern
13881  */
13882 int
13884 {
13885  return do_select_internal (parser, statement, true);
13886 }
13887 
13888 /*
13889  * do_select_internal() - do_insert internal routine
13890  * return: Error code
13891  * parser(in/out): Parser context
13892  * statement(in/out): A statement to do
13893  * for_inst_upd: check insert/update statement
13894  *
13895  * Note: Side effects can exist at returned result through application extern
13896  */
13897 static int
13898 do_select_internal (PARSER_CONTEXT * parser, PT_NODE * statement, bool for_ins_upd)
13899 {
13900  int error;
13901  XASL_NODE *xasl = NULL;
13902  QFILE_LIST_ID *list_id = NULL;
13903  int into_cnt, i;
13904  PT_NODE *into;
13905  const char *into_label;
13906  DB_VALUE *vals, *v;
13907  int save;
13908  QUERY_FLAG query_flag;
13909  XASL_STREAM stream;
13910  bool query_trace = false;
13911 
13912  assert (parser->query_id == NULL_QUERY_ID);
13913 
13914  init_xasl_stream (&stream);
13915 
13916  error = NO_ERROR;
13917 
13918  /* click counter check */
13919  if (statement->flag.is_click_counter)
13920  {
13922  }
13923 
13924  AU_DISABLE (save);
13925  parser->au_save = save;
13926 
13927  /* mark the beginning of another level of xasl packing */
13929 
13930  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
13931  {
13932  query_trace = true;
13933  }
13934 
13935  query_flag = DEFAULT_EXEC_MODE;
13936 
13937  if (parser->flag.dont_collect_exec_stats)
13938  {
13939  query_flag |= DONT_COLLECT_EXEC_STATS;
13940  }
13941 
13942  if (parser->flag.is_auto_commit)
13943  {
13944  query_flag |= TRAN_AUTO_COMMIT;
13945  }
13946 
13947 #if defined(CUBRID_DEBUG)
13948  PT_NODE_PRINT_TO_ALIAS (parser, statement, PT_CONVERT_RANGE);
13949 #endif
13950 
13951  pt_null_etc (statement);
13952 
13953  xasl = parser_generate_xasl (parser, statement);
13954 
13955  if (xasl && !pt_has_error (parser))
13956  {
13957  if (for_ins_upd)
13958  {
13959  if (xasl->outptr_list)
13960  {
13961  for (REGU_VARIABLE_LIST regu_var_list = xasl->outptr_list->valptrp; regu_var_list;
13962  regu_var_list = regu_var_list->next)
13963  {
13964  regu_var_list->value.flags |= REGU_VARIABLE_UPD_INS_LIST;
13965  }
13966  }
13967  }
13968 
13969  if (pt_false_where (parser, statement))
13970  {
13971  /* there is no results, this is a compile time false where clause */
13972  }
13973  else
13974  {
13975  if (query_trace == true)
13976  {
13977  do_set_trace_to_query_flag (&query_flag);
13979  }
13980 
13981  if (error >= NO_ERROR)
13982  {
13983  error = xts_map_xasl_to_stream (xasl, &stream);
13984  if (error != NO_ERROR)
13985  {
13987  }
13988  }
13989 
13990  if (error >= NO_ERROR)
13991  {
13992  error =
13993  prepare_and_execute_query (stream.buffer, stream.buffer_size, &parser->query_id,
13994  parser->host_var_count + parser->auto_param_count, parser->host_variables,
13995  &list_id, query_flag);
13996  }
13997  statement->etc = list_id;
13998 
13999  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
14000  if (stream.buffer)
14001  {
14002  free_and_init (stream.buffer);
14003  }
14004 
14005  if (error >= NO_ERROR)
14006  {
14007  /* if select ... into label ... has some result val then enter {label,val} pair into the label_table */
14008  into = statement->info.query.into_list;
14009 
14010  into_cnt = pt_length_of_list (into);
14011  if (into_cnt > 0 && (vals = (DB_VALUE *) malloc (into_cnt * sizeof (DB_VALUE))) != NULL)
14012  {
14013  if (pt_get_one_tuple_from_list_id (parser, statement, vals, into_cnt))
14014  {
14015  for (i = 0, v = vals; i < into_cnt && into; i++, v++, into = into->next)
14016  {
14017  if (into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL)
14018  {
14020  }
14021  db_value_clear (v);
14022  }
14023  }
14024  else if (into->node_type == PT_NAME)
14025  {
14027  into->info.name.original);
14028  }
14029  free_and_init (vals);
14030  }
14031  }
14032  else
14033  {
14034  assert (er_errid () != NO_ERROR);
14035  error = er_errid ();
14036  if (error == NO_ERROR)
14037  {
14038  error = ER_REGU_SYSTEM;
14039  }
14040  }
14041  } /* else */
14042  }
14043  else
14044  {
14045  error = er_errid ();
14046  if (error == NO_ERROR && pt_has_error (parser))
14047  {
14048  pt_report_to_ersys (parser, PT_SEMANTIC);
14049  pt_reset_error (parser);
14050 
14051  error = er_errid ();
14052  }
14053 
14054  assert (er_errid () != NO_ERROR);
14055  if (error == NO_ERROR)
14056  {
14057  error = ER_FAILED;
14058  }
14059  }
14060 
14061  /* mark the end of another level of xasl packing */
14063 
14064  AU_ENABLE (save);
14065  return error;
14066 }
14067 
14068 /*
14069  * do_prepare_select() - Prepare the SELECT statement including optimization and
14070  * plan generation, and creating XASL as the result
14071  * return: Error code
14072  * parser(in/out): Parser context
14073  * statement(in/out): A statement to do
14074  *
14075  * Note:
14076  */
14077 int
14079 {
14080  int err = NO_ERROR;
14081  int au_save;
14082 
14083  COMPILE_CONTEXT *contextp;
14084  XASL_STREAM stream;
14085 
14086  contextp = &parser->context;
14087 
14088  init_xasl_stream (&stream);
14089 
14090  if (parser == NULL || statement == NULL)
14091  {
14093  return ER_OBJ_INVALID_ARGUMENTS;
14094  }
14095 
14096  contextp->sql_user_text = statement->sql_user_text;
14097  contextp->sql_user_text_len = statement->sql_user_text_len;
14098 
14099  /* click counter check */
14100  if (statement->flag.is_click_counter)
14101  {
14103  }
14104 
14105  /* there can be no results, this is a compile time false where clause */
14106  if (pt_false_where (parser, statement))
14107  {
14108  /* tell to the execute routine that there's no XASL to execute */
14109  statement->xasl_id = NULL;
14110  return NO_ERROR;
14111  }
14112 
14113  /* if already prepared */
14114  if (statement->xasl_id)
14115  {
14116  return NO_ERROR;
14117  }
14118 
14119  /* make query string */
14120  parser->flag.dont_prt_long_string = 1;
14121  parser->flag.long_string_skipped = 0;
14122  parser->flag.print_type_ambiguity = 0;
14123  PT_NODE_PRINT_TO_ALIAS (parser, statement,
14125  contextp->sql_hash_text = (char *) statement->alias_print;
14126  err =
14127  SHA1Compute ((unsigned char *) contextp->sql_hash_text, (unsigned) strlen (contextp->sql_hash_text),
14128  &contextp->sha1);
14129  if (err != NO_ERROR)
14130  {
14131  ASSERT_ERROR ();
14132  return err;
14133  }
14134  parser->flag.dont_prt_long_string = 0;
14135  if (parser->flag.long_string_skipped || parser->flag.print_type_ambiguity)
14136  {
14137  statement->flag.cannot_prepare = 1;
14138  return NO_ERROR;
14139  }
14140 
14141  /* look up server's XASL cache for this query string and get XASL file id (XASL_ID) returned if found */
14142  contextp->recompile_xasl = statement->flag.recompile;
14143  if (statement->flag.recompile == 0)
14144  {
14145  XASL_NODE_HEADER xasl_header;
14146  stream.xasl_header = &xasl_header;
14147 
14148  err = prepare_query (contextp, &stream);
14149  if (err != NO_ERROR)
14150  {
14151  ASSERT_ERROR_AND_SET (err);
14152  }
14153  else if (contextp->recompile_xasl == true)
14154  {
14155  /* recompile flag was returned by server */
14156  if (stream.xasl_id != NULL)
14157  {
14158  free_and_init (stream.xasl_id);
14159  }
14160  }
14161  else if (stream.xasl_id != NULL)
14162  {
14163  /* check xasl header */
14164  /* TODO: we can treat the different cases of MRO by hacking query string. */
14165  if (pt_recompile_for_limit_optimizations (parser, statement, stream.xasl_header->xasl_flag))
14166  {
14167  contextp->recompile_xasl = true;
14168  if (stream.xasl_id != NULL)
14169  {
14170  free_and_init (stream.xasl_id);
14171  }
14172  }
14173  }
14174  }
14175  if (stream.xasl_id == NULL && err == NO_ERROR)
14176  {
14177  /* cache not found; make XASL from the parse tree including query optimization and plan generation */
14178 
14179  /* mark the beginning of another level of xasl packing */
14181 
14182  AU_SAVE_AND_DISABLE (au_save); /* this prevents authorization checking during generating XASL */
14183  /* parser_generate_xasl() will build XASL tree from parse tree */
14184  contextp->xasl = parser_generate_xasl (parser, statement);
14185  if (contextp->xasl && statement->info.query.oids_included)
14186  {
14188  }
14189  AU_RESTORE (au_save);
14190 
14191  if (contextp->xasl && (err == NO_ERROR) && !pt_has_error (parser))
14192  {
14193  /* convert the created XASL tree to the byte stream for transmission to the server */
14194  err = xts_map_xasl_to_stream (contextp->xasl, &stream);
14195  if (err != NO_ERROR)
14196  {
14198  }
14199  }
14200  else
14201  {
14202  err = er_errid ();
14203  if (err == NO_ERROR && pt_has_error (parser))
14204  {
14205  pt_report_to_ersys (parser, PT_SEMANTIC);
14206  pt_reset_error (parser);
14207 
14208  err = er_errid ();
14209  }
14210 
14211  assert (er_errid () != NO_ERROR);
14212  if (err == NO_ERROR)
14213  {
14214  err = ER_FAILED;
14215  }
14216  }
14217 
14218  /* request the server to prepare the query; give XASL stream generated from the parse tree and get XASL file id
14219  * returned */
14220  if (stream.buffer && (err == NO_ERROR))
14221  {
14222  err = prepare_query (contextp, &stream);
14223  if (err != NO_ERROR)
14224  {
14225  assert (er_errid () != NO_ERROR);
14226  err = er_errid ();
14227  }
14228  }
14229 
14230  /* mark the end of another level of xasl packing */
14232 
14233  /* As a result of query preparation of the server, the XASL cache for this query will be created or updated. */
14234 
14235  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
14236  if (stream.buffer)
14237  {
14238  free_and_init (stream.buffer);
14239  }
14240  statement->flag.use_plan_cache = 0;
14241  }
14242  else
14243  {
14244  if (err == NO_ERROR)
14245  {
14246  statement->flag.use_plan_cache = 1;
14247  }
14248  else
14249  {
14250  statement->flag.use_plan_cache = 0;
14251  }
14252  }
14253 
14254  /* save the XASL_ID that is allocated and returned by prepare_query() into 'statement->xasl_id' to be used by
14255  * do_execute_select() */
14256  statement->xasl_id = stream.xasl_id;
14257 
14258  return err;
14259 } /* do_prepare_select() */
14260 
14261 /*
14262  * do_prepare_session_statement () - prepare step for a prepared session
14263  * statement
14264  * return : error code or NO_ERROR
14265  * parser (in) : parser context
14266  * statement (in) : prepared statement
14267  */
14268 int
14270 {
14271  assert (statement->node_type == PT_EXECUTE_PREPARE);
14272  if (statement->xasl_id != NULL)
14273  {
14274  /* already "prepared" */
14275  return NO_ERROR;
14276  }
14277  statement->xasl_id = (XASL_ID *) malloc (sizeof (XASL_ID));
14278  if (statement->xasl_id == NULL)
14279  {
14281  return ER_OUT_OF_VIRTUAL_MEMORY;
14282  }
14283  XASL_ID_COPY (statement->xasl_id, &statement->info.execute.xasl_id);
14284  return NO_ERROR;
14285 }
14286 
14287 /*
14288  * do_execute_session_statement () - execute a prepared session statement
14289  * return :
14290  * parser (in) : parser context
14291  * statement (in) : statement to execute
14292  */
14293 int
14295 {
14296  int err;
14297  QFILE_LIST_ID *list_id;
14298  int query_flag, into_cnt, i, au_save;
14299  PT_NODE *into;
14300  const char *into_label;
14301  DB_VALUE *vals, *v;
14302  CACHE_TIME clt_cache_time;
14304  bool query_trace = false;
14305 
14306  assert (parser->query_id == NULL_QUERY_ID);
14308 
14309  /* check if it is not necessary to execute this statement */
14310  if (statement->xasl_id == NULL)
14311  {
14312  statement->etc = NULL;
14313  return NO_ERROR;
14314  }
14315 
14316  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
14317  {
14318  query_trace = true;
14319  }
14320 
14321  query_flag = DEFAULT_EXEC_MODE;
14322 
14323  if (parser->flag.is_holdable)
14324  {
14325  query_flag |= RESULT_HOLDABLE;
14326  }
14327  if (parser->flag.is_xasl_pinned_reference)
14328  {
14329  query_flag |= XASL_CACHE_PINNED_REFERENCE;
14330  }
14331  if (parser->flag.is_auto_commit)
14332  {
14333  query_flag |= TRAN_AUTO_COMMIT;
14334  }
14335 
14336  if (query_trace == true)
14337  {
14338  do_set_trace_to_query_flag (&query_flag);
14340  }
14341 
14342  /* flush necessary objects before execute */
14343  if (ws_has_updated ())
14344  {
14345  (void) parser_walk_tree (parser, statement, pt_flush_classes, NULL, NULL, NULL);
14346  }
14347 
14348  if (parser->flag.abort)
14349  {
14350  assert (er_errid () != NO_ERROR);
14351  return er_errid ();
14352  }
14353 
14354  /* Request that the server executes the stored XASL, which is the execution plan of the prepared query, with the host
14355  * variables given by users as parameter values for the query. As a result, query id and result file id
14356  * (QFILE_LIST_ID) will be returned. */
14357 
14358  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
14359  assert (parser->query_id == NULL_QUERY_ID);
14360  list_id = NULL;
14361 
14362  CACHE_TIME_RESET (&clt_cache_time);
14363  if (statement->flag.clt_cache_check)
14364  {
14365  clt_cache_time = statement->cache_time;
14366  statement->flag.clt_cache_check = 0;
14367  }
14368  CACHE_TIME_RESET (&statement->cache_time);
14369  statement->flag.clt_cache_reusable = 0;
14370 
14371  err =
14372  execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
14373  parser->host_variables, &list_id, query_flag, &clt_cache_time, &statement->cache_time);
14374 
14375  AU_RESTORE (au_save);
14376 
14377  if (CACHE_TIME_EQ (&clt_cache_time, &statement->cache_time))
14378  {
14379  statement->flag.clt_cache_reusable = 1;
14380  }
14381 
14382  /* save the returned QFILE_LIST_ID into 'statement->etc' */
14383  statement->etc = (void *) list_id;
14384 
14385  if (err < NO_ERROR)
14386  {
14387  assert (er_errid () != NO_ERROR);
14388  return er_errid ();
14389  }
14390  /* if select ... into label ... has some result val then enter {label,val} pair into the label_table */
14391  into = statement->info.execute.into_list;
14392  into_cnt = pt_length_of_list (into);
14393  if (into_cnt == 0)
14394  {
14395  return err;
14396  }
14397 
14398  vals = (DB_VALUE *) malloc (into_cnt * sizeof (DB_VALUE));
14399  if (vals == NULL)
14400  {
14402  return ER_FAILED;
14403  }
14404  if (!cursor_open (&cursor_id, list_id, false, statement->info.execute.oids_included))
14405  {
14406  free_and_init (vals);
14407  return err;
14408  }
14409  cursor_id.query_id = parser->query_id;
14410  if (cursor_next_tuple (&cursor_id) != DB_CURSOR_SUCCESS
14411  || cursor_get_tuple_value_list (&cursor_id, into_cnt, vals) != NO_ERROR)
14412  {
14413  free_and_init (vals);
14414  return err;
14415  }
14416  cursor_close (&cursor_id);
14417 
14418  for (i = 0, v = vals; i < into_cnt && into; i++, v++, into = into->next)
14419  {
14420  if (into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL)
14421  {
14423  }
14424  db_value_clear (v);
14425  }
14426 
14427  free_and_init (vals);
14428 
14429  return err;
14430 }
14431 
14432 /*
14433  * do_execute_select() - Execute the prepared SELECT statement
14434  * return: Error code
14435  * parser(in/out): Parser context
14436  * statement(in/out): A statement to do
14437  *
14438  * Note:
14439  */
14440 int
14442 {
14443  int err;
14444  QFILE_LIST_ID *list_id;
14445  int query_flag, into_cnt, i, au_save;
14446  PT_NODE *into;
14447  const char *into_label;
14448  DB_VALUE *vals, *v;
14449  CACHE_TIME clt_cache_time;
14450  bool query_trace = false;
14451 
14452  assert (parser->query_id == NULL_QUERY_ID);
14453 
14454  /* check if it is not necessary to execute this statement, e.g. false where or not prepared correctly */
14455  if (!statement->xasl_id)
14456  {
14457  statement->etc = NULL;
14458  return NO_ERROR;
14459  }
14460 
14461  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
14462  {
14463  query_trace = true;
14464  }
14465 
14466  /* adjust query flag */
14467  query_flag = DEFAULT_EXEC_MODE;
14468 
14469  if (statement->flag.si_datetime == 1 || statement->flag.si_tran_id == 1)
14470  {
14471  statement->info.query.flag.reexecute = 1;
14472  statement->info.query.flag.do_not_cache = 1;
14473  }
14474 
14475  if (statement->info.query.flag.reexecute == 1)
14476  {
14477  query_flag |= NOT_FROM_RESULT_CACHE;
14478  }
14479 
14480  if (statement->info.query.flag.do_cache == 1)
14481  {
14482  query_flag |= RESULT_CACHE_REQUIRED;
14483  }
14484 
14485  if (statement->info.query.flag.do_not_cache == 1 || statement->info.query.oids_included)
14486  {
14487  query_flag |= RESULT_CACHE_INHIBITED;
14488  }
14489  if (parser->flag.is_holdable)
14490  {
14491  query_flag |= RESULT_HOLDABLE;
14492  }
14493  if (parser->flag.is_xasl_pinned_reference)
14494  {
14495  query_flag |= XASL_CACHE_PINNED_REFERENCE;
14496  }
14497 
14498  if (parser->flag.dont_collect_exec_stats)
14499  {
14500  query_flag |= DONT_COLLECT_EXEC_STATS;
14501  }
14502 
14503  if (statement->flag.use_auto_commit)
14504  {
14505  query_flag |= EXECUTE_QUERY_WITH_COMMIT;
14506 
14507  if (ws_need_flush ())
14508  {
14509  if (tm_Use_OID_preflush)
14510  {
14512  }
14513 
14514  /* Flush all dirty objects */
14515  /* Flush virtual objects first so that locator_all_flush doesn't see any */
14516  err = locator_all_flush ();
14517  if (err != NO_ERROR)
14518  {
14519  return err;
14520  }
14521  }
14522  }
14523 
14524  if (parser->flag.is_auto_commit)
14525  {
14526  query_flag |= TRAN_AUTO_COMMIT;
14527  }
14528 
14529  if (query_trace == true)
14530  {
14531  do_set_trace_to_query_flag (&query_flag);
14533  }
14534 
14535  /* flush necessary objects before execute */
14536  if (ws_has_updated ())
14537  {
14538  (void) parser_walk_tree (parser, statement, pt_flush_classes, NULL, NULL, NULL);
14539  }
14540 
14541  if (parser->flag.abort)
14542  {
14543  assert (er_errid () != NO_ERROR);
14544  return er_errid ();
14545  }
14546 
14547  /* Request that the server executes the stored XASL, which is the execution plan of the prepared query, with the host
14548  * variables given by users as parameter values for the query. As a result, query id and result file id
14549  * (QFILE_LIST_ID) will be returned. do_prepare_select() has saved the XASL file id (XASL_ID) in 'statement->xasl_id'
14550  */
14551 
14552  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
14553 
14554  assert (parser->query_id == NULL_QUERY_ID);
14555  list_id = NULL;
14556 
14557  CACHE_TIME_RESET (&clt_cache_time);
14558  if (statement->flag.clt_cache_check)
14559  {
14560  clt_cache_time = statement->cache_time;
14561  statement->flag.clt_cache_check = 0;
14562  }
14563  CACHE_TIME_RESET (&statement->cache_time);
14564  statement->flag.clt_cache_reusable = 0;
14565 
14566  err =
14567  execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
14568  parser->host_variables, &list_id, query_flag, &clt_cache_time, &statement->cache_time);
14569 
14570  AU_RESTORE (au_save);
14571 
14572  if (CACHE_TIME_EQ (&clt_cache_time, &statement->cache_time))
14573  {
14574  statement->flag.clt_cache_reusable = 1;
14575  }
14576 
14577  /* save the returned QFILE_LIST_ID into 'statement->etc' */
14578  statement->etc = (void *) list_id;
14579 
14580  if (err < NO_ERROR)
14581  {
14582  assert (er_errid () != NO_ERROR);
14583  return er_errid ();
14584  }
14585 
14586  /* if SELECT ... INTO label ... has some result val, then enter {label,val} pair into the label_table */
14587  into = statement->info.query.into_list;
14588  if ((into_cnt = pt_length_of_list (into)) > 0 && (vals = (DB_VALUE *) malloc (into_cnt * sizeof (DB_VALUE))) != NULL)
14589  {
14590  if (pt_get_one_tuple_from_list_id (parser, statement, vals, into_cnt))
14591  {
14592  for (i = 0, v = vals; i < into_cnt && into; i++, v++, into = into->next)
14593  {
14594  if (into->node_type == PT_NAME && (into_label = into->info.name.original) != NULL)
14595  {
14597  }
14598  db_value_clear (v);
14599  }
14600  }
14601  else if (into->node_type == PT_NAME)
14602  {
14604  into->info.name.original);
14605  }
14606  free_and_init (vals);
14607  }
14608 
14609  return err;
14610 } /* do_execute_select() */
14611 
14612 
14613 
14614 
14615 
14616 /*
14617  * Function Group:
14618  * DO Functions for replication management
14619  *
14620  */
14621 
14622 
14623 /*
14624  * do_replicate_schema() -
14625  * return: Error code
14626  * parser(in): Parser context
14627  * statement(in): The parse tree of a DDL statement
14628  *
14629  * Note:
14630  */
14631 int
14633 {
14634  int error = NO_ERROR;
14636  REPL_INFO_SBR repl_stmt;
14637  PARSER_VARCHAR *name = NULL;
14638  PARSER_VARCHAR **host_val = NULL;
14639  static const char *unknown_name = "-";
14640  char stmt_separator;
14641  char *stmt_end = NULL;
14642  char *sbr_text = NULL;
14643 
14644  if (log_does_allow_replication () == false)
14645  {
14646  return NO_ERROR;
14647  }
14648 
14649  if (statement->sql_user_text == NULL || statement->sql_user_text_len == 0)
14650  {
14651  /* this should be loaddb. */
14652  return NO_ERROR;
14653  }
14654 
14655  switch (statement->node_type)
14656  {
14657  case PT_CREATE_ENTITY:
14658  name = pt_print_bytes (parser, statement->info.create_entity.entity_name);
14660  break;
14661 
14662  case PT_ALTER:
14663  name = pt_print_bytes (parser, statement->info.alter.entity_name);
14665  break;
14666 
14667  case PT_RENAME:
14668  name = pt_print_bytes (parser, statement->info.rename.old_name);
14670  break;
14671 
14672  case PT_DROP:
14673  /* No replication log will be written when there's no applicable table for "drop if exists" */
14674  if (statement->info.drop.if_exists && statement->info.drop.spec_list == NULL)
14675  {
14676  return NO_ERROR;
14677  }
14679  break;
14680 
14681  case PT_CREATE_INDEX:
14682  name = pt_print_bytes (parser, statement->info.index.indexed_class);
14684  break;
14685 
14686  case PT_ALTER_INDEX:
14687  name = pt_print_bytes (parser, statement->info.index.indexed_class);
14689  break;
14690 
14691  case PT_DROP_INDEX:
14692  name = pt_print_bytes (parser, statement->info.index.indexed_class);
14694  break;
14695 
14696  case PT_CREATE_SERIAL:
14698  break;
14699 
14700  case PT_ALTER_SERIAL:
14702  break;
14703 
14704  case PT_DROP_SERIAL:
14706  break;
14707 
14710  break;
14711 
14714  break;
14715 
14718  break;
14719 
14720  case PT_CREATE_USER:
14722  break;
14723 
14724  case PT_ALTER_USER:
14726  break;
14727 
14728  case PT_DROP_USER:
14730  break;
14731 
14732  case PT_GRANT:
14733  repl_stmt.statement_type = CUBRID_STMT_GRANT;
14734  break;
14735 
14736  case PT_REVOKE:
14737  repl_stmt.statement_type = CUBRID_STMT_REVOKE;
14738  break;
14739 
14740  case PT_CREATE_TRIGGER:
14742  break;
14743 
14744  case PT_RENAME_TRIGGER:
14746  break;
14747 
14748  case PT_DROP_TRIGGER:
14750  break;
14751 
14752  case PT_REMOVE_TRIGGER:
14754  break;
14755 
14756  case PT_ALTER_TRIGGER:
14758  break;
14759 
14760  case PT_TRUNCATE:
14761  if (!truncate_need_repl_log (statement))
14762  {
14763  return NO_ERROR;
14764  }
14765 
14766  assert (statement->info.spec.entity_name);
14767  name = pt_print_bytes (parser, statement->info.spec.entity_name->info.spec.entity_name);
14769  break;
14770 
14771  case PT_UPDATE_STATS:
14773  break;
14774 
14775  case PT_INSERT:
14776  repl_stmt.statement_type = CUBRID_STMT_INSERT;
14777  break;
14778  case PT_DELETE:
14779  repl_stmt.statement_type = CUBRID_STMT_DELETE;
14780  break;
14781  case PT_UPDATE:
14782  repl_stmt.statement_type = CUBRID_STMT_UPDATE;
14783  break;
14784 
14785  case PT_DROP_VARIABLE: /* DROP VARIABLE statements are not replicated intentionally. */
14786  default:
14787  return NO_ERROR;
14788  }
14789 
14790  repl_info.repl_info_type = REPL_INFO_TYPE_SBR;
14791  if (name == NULL)
14792  {
14793  repl_stmt.name = (char *) unknown_name;
14794  }
14795  else
14796  {
14797  repl_stmt.name = (char *) pt_get_varchar_bytes (name);
14798  }
14799 
14800  if (parser->host_var_count == 0)
14801  {
14802  /* it may contain multiple statements */
14803  if (strlen (statement->sql_user_text) > statement->sql_user_text_len)
14804  {
14805  stmt_end = &statement->sql_user_text[statement->sql_user_text_len];
14806  stmt_separator = *stmt_end;
14807  *stmt_end = '\0';
14808  }
14809  repl_stmt.stmt_text = statement->sql_user_text;
14810  }
14811  else
14812  {
14813  /*
14814  * if the query string includes the host variables, while processing the variable holder '?'
14815  * the values of the host variables can be replaced into the user's original query string
14816  * the pt_print_db_value(...) returns the value string and its length.
14817  * the length includes quotes in case of the char string.
14818  */
14819  char *sql_text = statement->sql_user_text;
14820  int sql_len = statement->sql_user_text_len;
14821  int i, n, nth;
14822  int var_len = 0;
14823  bool begin_quote = false;
14824 
14825  host_val = (PARSER_VARCHAR **) malloc (sizeof (PARSER_VARCHAR *) * parser->host_var_count);
14826  if (host_val == NULL)
14827  {
14828  return ER_OUT_OF_VIRTUAL_MEMORY;
14829  }
14830 
14831  for (i = 0; i < parser->host_var_count; i++)
14832  {
14833  host_val[i] = pt_print_db_value (parser, &parser->host_variables[i]);
14834  var_len += host_val[i]->length;
14835  }
14836 
14837  sbr_text = (char *) malloc (sql_len + var_len);
14838  if (sbr_text == NULL)
14839  {
14840  error = ER_OUT_OF_VIRTUAL_MEMORY;
14841  goto end;
14842  }
14843 
14844  n = nth = 0;
14845 
14846  for (i = 0; i < sql_len; i++)
14847  {
14848  if (sql_text[i] == '\'')
14849  {
14850  if (!begin_quote)
14851  {
14852  begin_quote = true;
14853  }
14854  else
14855  {
14856  begin_quote = false;
14857  }
14858  }
14859 
14860  if (sql_text[i] == '?' && !begin_quote)
14861  {
14862  if (nth < parser->host_var_count)
14863  {
14864  strncpy (&sbr_text[n], (char *) host_val[nth]->bytes, host_val[nth]->length);
14865  n += host_val[nth++]->length;
14866  }
14867  else
14868  {
14869  error = ER_IT_UNKNOWN_VARIABLE;
14870  goto end;
14871  }
14872  }
14873  else
14874  {
14875  sbr_text[n++] = sql_text[i];
14876  }
14877  }
14878 
14879  sbr_text[n] = 0;
14880  repl_stmt.stmt_text = sbr_text;
14881  }
14882 
14883  repl_stmt.db_user = db_get_user_name ();
14884 
14885  if (pt_is_ddl_statement (statement) != 0)
14886  {
14888  }
14889  else
14890  {
14891  repl_stmt.sys_prm_context = NULL;
14892  }
14893 
14894  assert_release (repl_stmt.db_user != NULL);
14895 
14896  repl_info.info = (char *) &repl_stmt;
14897 
14898  error = locator_flush_replication_info (&repl_info);
14899 
14900  if (stmt_end != NULL)
14901  {
14902  *stmt_end = stmt_separator;
14903  }
14904 
14905  db_string_free (repl_stmt.db_user);
14906 
14907 end:
14908  if (sbr_text)
14909  {
14910  free (sbr_text);
14911  }
14912 
14913  if (host_val)
14914  {
14915  free (host_val);
14916  }
14917 
14918  if (repl_stmt.sys_prm_context)
14919  {
14920  free (repl_stmt.sys_prm_context);
14921  }
14922 
14923  return error;
14924 }
14925 
14926 
14927 
14928 
14929 
14930 /*
14931  * Function Group:
14932  * Implements the scope statement.
14933  *
14934  */
14935 
14936 /*
14937  * do_scope() - scopes a statement
14938  * return: Error code if scope fails
14939  * parser(in/out): Parser context
14940  * statement(in): The parse tree of a scope statement
14941  *
14942  * Note:
14943  */
14944 int
14945 do_scope (PARSER_CONTEXT * parser, PT_NODE * statement)
14946 {
14947  int error = NO_ERROR;
14948  PT_NODE *stmt;
14949 
14950  if (!statement || (statement->node_type != PT_SCOPE) || !((stmt = statement->info.scope.stmt))
14951  || (stmt->node_type != PT_TRIGGER_ACTION))
14952  {
14953  return ER_GENERIC_ERROR;
14954  }
14955  else
14956  {
14957  switch (stmt->info.trigger_action.action_type)
14958  {
14959  case PT_REJECT:
14960  case PT_INVALIDATE_XACTION:
14961  case PT_PRINT:
14962  break;
14963 
14964  case PT_EXPRESSION:
14965  do_Trigger_involved = true;
14966 #if 0
14967  if (prm_get_integer_value (PRM_ID_XASL_MAX_PLAN_CACHE_ENTRIES) > 0)
14968  {
14969 
14970  /* prepare a statement to execute */
14971  error = do_prepare_statement (parser, stmt->info.trigger_action.expression);
14972  if (error >= NO_ERROR)
14973  {
14974  /* execute the prepared statement */
14975  error = do_execute_statement (parser, stmt->info.trigger_action.expression);
14976  }
14977  }
14978  else
14979  {
14980  error = do_statement (parser, stmt->info.trigger_action.expression);
14981  }
14982 #else
14983  error = do_statement (parser, stmt->info.trigger_action.expression);
14984 #endif
14985  /* Do not reset do_Trigger_involved here. This is intention. */
14986  break;
14987 
14988  default:
14989  break;
14990  }
14991 
14992  return error;
14993  }
14994 }
14995 
14996 
14997 
14998 
14999 
15000 /*
15001  * Function Group:
15002  * Implements the DO statement.
15003  *
15004  */
15005 
15006 /*
15007  * do_execute_do() - execute the DO statement
15008  * return: Error code if scope fails
15009  * parser(in/out): Parser context
15010  * statement(in): The parse tree of the DO statement
15011  *
15012  * Note:
15013  */
15014 int
15015 do_execute_do (PARSER_CONTEXT * parser, PT_NODE * statement)
15016 {
15017  int error = NO_ERROR;
15018  XASL_NODE *xasl = NULL;
15019  QFILE_LIST_ID *list_id = NULL;
15020  int save;
15021  QUERY_FLAG query_flag;
15022 
15023  XASL_STREAM stream;
15024 
15025  assert (parser->query_id == NULL_QUERY_ID);
15026 
15027  init_xasl_stream (&stream);
15028 
15029  AU_DISABLE (save);
15030  parser->au_save = save;
15031 
15032  /* mark the beginning of another level of xasl packing */
15034 
15035  /* always sync exec */
15036  query_flag = DEFAULT_EXEC_MODE;
15037 
15038  /* don't cache anything */
15039  query_flag |= NOT_FROM_RESULT_CACHE;
15040  query_flag |= RESULT_CACHE_INHIBITED;
15041 
15042  if (parser->flag.is_auto_commit)
15043  {
15044  query_flag |= TRAN_AUTO_COMMIT;
15045  }
15046 
15047  pt_null_etc (statement);
15048 
15049  /* generate statement's XASL */
15050  xasl = parser_generate_do_stmt_xasl (parser, statement);
15051 
15052  if (pt_has_error (parser))
15053  {
15054  pt_report_to_ersys (parser, PT_EXECUTION);
15055  error = er_errid ();
15056  goto end;
15057  }
15058  else if (xasl == NULL)
15059  {
15060  assert (er_errid () != NO_ERROR);
15061  error = er_errid ();
15062  goto end;
15063  }
15064 
15065  if (prm_get_bool_value (PRM_ID_QUERY_TRACE) == true && parser->query_trace == true)
15066  {
15067  do_set_trace_to_query_flag (&query_flag);
15069  }
15070 
15071 
15072  /* map XASL to stream */
15073  error = xts_map_xasl_to_stream (xasl, &stream);
15074  if (error != NO_ERROR)
15075  {
15076  goto end;
15077  }
15078 
15079  error =
15080  prepare_and_execute_query (stream.buffer, stream.buffer_size, &parser->query_id,
15081  parser->host_var_count + parser->auto_param_count, parser->host_variables, &list_id,
15082  query_flag);
15083 
15084  if (error != NO_ERROR)
15085  {
15086  goto end;
15087  }
15088 
15089  statement->etc = list_id;
15090 
15091 end:
15092  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
15093  if (stream.buffer)
15094  {
15095  free_and_init (stream.buffer);
15096  }
15097 
15098  /* mark the end of another level of xasl packing */
15100  AU_ENABLE (save);
15101 
15102  return error;
15103 }
15104 
15105 /*
15106  * do_set_session_variables () - execute a set session variables statement
15107  * return : error code or no error
15108  * parser (in) : parser
15109  * statement (in) : statement
15110  */
15111 int
15113 {
15114  int error = NO_ERROR;
15115  DB_VALUE *variables = NULL;
15116  int count = 0, i = 0;
15117  PT_NODE *assignment = NULL;
15118 
15119  assert (statement != NULL);
15120  assert (statement->node_type == PT_SET_SESSION_VARIABLES);
15121 
15122  count = 0;
15123  /* count assignments */
15124  assignment = statement->info.set_variables.assignments;
15125  while (assignment)
15126  {
15127  count++;
15128  assignment = assignment->next;
15129  }
15130  /* we will store assignments in an array containing name1, value1, name2, value2... */
15131  variables = (DB_VALUE *) malloc (count * 2 * sizeof (DB_VALUE));
15132  if (variables == NULL)
15133  {
15135  error = ER_OUT_OF_VIRTUAL_MEMORY;
15136  goto cleanup;
15137  }
15138 
15139  /* initialize variables in case we need to exit with error */
15140  for (i = 0; i < count * 2; i++)
15141  {
15142  db_make_null (&variables[i]);
15143  }
15144 
15145  for (i = 0, assignment = statement->info.set_variables.assignments; assignment; i += 2, assignment = assignment->next)
15146  {
15147  pr_clone_value (pt_value_to_db (parser, assignment->info.expr.arg1), &variables[i]);
15148  pt_evaluate_tree_having_serial (parser, assignment->info.expr.arg2, &variables[i + 1], 1);
15149 
15150  if (pt_has_error (parser))
15151  {
15152  /* if error occurred, don't send junk to server */
15153  pt_report_to_ersys (parser, PT_EXECUTION);
15154  error = er_errid ();
15155  goto cleanup;
15156  }
15157  }
15158 
15159  error = csession_set_session_variables (variables, count * 2);
15160 
15161 cleanup:
15162  if (variables != NULL)
15163  {
15164  for (i = 0; i < count * 2; i++)
15165  {
15166  pr_clear_value (&variables[i]);
15167  }
15168  free_and_init (variables);
15169  }
15170  return error;
15171 }
15172 
15173 /*
15174  * do_drop_session_variables () - execute a drop session variables statement
15175  * return : error code or no error
15176  * parser (in) : parser
15177  * statement (in) : statement
15178  */
15179 int
15181 {
15182  int error = NO_ERROR;
15183  DB_VALUE *values = NULL;
15184  int count = 0, i = 0;
15185  PT_NODE *variables = NULL;
15186 
15187  assert (statement != NULL);
15189 
15190  count = 0;
15191  /* count assignments */
15192  variables = statement->info.drop_session_var.variables;
15193  while (variables)
15194  {
15195  count++;
15196  variables = variables->next;
15197  }
15198  /* we will store assignments in an array containing name1, value1, name2, value2... */
15199  values = (DB_VALUE *) malloc (count * sizeof (DB_VALUE));
15200  if (values == NULL)
15201  {
15203  error = ER_OUT_OF_VIRTUAL_MEMORY;
15204  goto cleanup;
15205  }
15206 
15207  for (i = 0, variables = statement->info.drop_session_var.variables; variables; i++, variables = variables->next)
15208  {
15209  pr_clone_value (pt_value_to_db (parser, variables), &values[i]);
15210  }
15211 
15212  error = csession_drop_session_variables (values, count);
15213 
15214 cleanup:
15215  if (values != NULL)
15216  {
15217  for (i = 0; i < count; i++)
15218  {
15219  pr_clear_value (&values[i]);
15220  }
15221  free_and_init (values);
15222  }
15223  return error;
15224 }
15225 
15226 /*
15227  * MERGE STATEMENT
15228  */
15229 
15230 /* used to generate unique savepoint names */
15231 static int merge_savepoint_number = 0;
15232 
15233 /*
15234  * do_check_merge_trigger() -
15235  * return: Error code
15236  * parser(in): Parser context
15237  * statement(in): Parse tree of a statement
15238  *
15239  * Note: The function checks if there is any active trigger with event
15240  * TR_EVENT_STATEMENT_INSERT/UPDATE/DELETE defined on the target.
15241  * If there is one, raise the trigger. Otherwise, perform the
15242  * given do_ function.
15243  */
15244 int
15245 do_check_merge_trigger (PARSER_CONTEXT * parser, PT_NODE * statement, PT_DO_FUNC * do_func)
15246 {
15247  int err;
15248 
15250  {
15252  return ER_BLOCK_NOWHERE_STMT;
15253  }
15254 
15255  if (statement->flag.use_auto_commit)
15256  {
15257  /* no active trigger is involved. Avoid lock and fetch request. */
15258  err = do_func (parser, statement);
15259  }
15260  else
15261  {
15262  err = check_merge_trigger (do_func, parser, statement);
15263  }
15264 
15265  return err;
15266 }
15267 
15268 /*
15269  * check_merge_trigger() -
15270  * return: Error code
15271  * do_func(in): Function to do
15272  * parser(in): Parser context used by do_func
15273  * statement(in): Parse tree of a statement used by do_func
15274  *
15275  * Note: The function checks if there is any active trigger for UPDATE,
15276  * INSERT, or DELETE statements of a MERGE statement.
15277  */
15278 static int
15279 check_merge_trigger (PT_DO_FUNC * do_func, PARSER_CONTEXT * parser, PT_NODE * statement)
15280 {
15281  int err, result = NO_ERROR;
15282  TR_STATE *state;
15283  const char *savepoint_name = NULL;
15284  PT_NODE *flat = NULL;
15285  DB_OBJECT *class_ = NULL;
15286 
15287  /* Prepare a trigger state for any triggers that must be raised in this statement */
15288 
15289  state = NULL;
15290 
15291  flat = (statement->info.merge.into) ? statement->info.merge.into->info.spec.flat_entity_list : NULL;
15292  class_ = (flat) ? flat->info.name.db_object : NULL;
15293  if (class_ == NULL)
15294  {
15295  PT_INTERNAL_ERROR (parser, "invalid spec id");
15296  result = ER_FAILED;
15297  goto exit;
15298  }
15299 
15300  if (statement->info.merge.update.assignment)
15301  {
15302  /* UPDATE statement triggers */
15303  result = tr_prepare_statement (&state, TR_EVENT_STATEMENT_UPDATE, class_, 0, NULL);
15304  if (result != NO_ERROR)
15305  {
15306  goto exit;
15307  }
15308  /* DELETE statement triggers */
15309  if (statement->info.merge.update.has_delete)
15310  {
15311  result = tr_prepare_statement (&state, TR_EVENT_STATEMENT_DELETE, class_, 0, NULL);
15312  if (result != NO_ERROR)
15313  {
15314  goto exit;
15315  }
15316  }
15317  }
15318  if (statement->info.merge.insert.value_clauses)
15319  {
15320  /* INSERT statement triggers */
15321  result = tr_prepare_statement (&state, TR_EVENT_STATEMENT_INSERT, class_, 0, NULL);
15322  if (result != NO_ERROR)
15323  {
15324  goto exit;
15325  }
15326  }
15327 
15328  if (state == NULL)
15329  {
15330  /* no triggers */
15331  result = do_check_internal_statements (parser, statement, do_func);
15332  }
15333  else
15334  {
15335  /* the operations performed in 'tr_before', 'do_check_internal_statements' and 'tr_after' should be all contained
15336  * in one transaction */
15337  if (tr_Current_depth <= 1)
15338  {
15339  savepoint_name = mq_generate_name (parser, "UtrP", &tr_savepoint_number);
15340  if (savepoint_name == NULL)
15341  {
15342  result = ER_GENERIC_ERROR;
15343  goto exit;
15344  }
15345  result = tran_system_savepoint (savepoint_name);
15346  if (result != NO_ERROR)
15347  {
15348  goto exit;
15349  }
15350  }
15351 
15352  /* fire BEFORE STATEMENT triggers */
15353  result = tr_before (state);
15354  if (result == NO_ERROR)
15355  {
15356  result = do_check_internal_statements (parser, statement, do_func);
15357  if (result < NO_ERROR)
15358  {
15359  tr_abort (state);
15360  state = NULL; /* state was freed */
15361  }
15362  else
15363  {
15364  /* fire AFTER STATEMENT triggers */
15365  /* try to preserve the usual result value */
15366  err = tr_after (state);
15367  if (err != NO_ERROR)
15368  {
15369  result = err;
15370  }
15371  if (tr_get_execution_state ())
15372  {
15373  state = NULL; /* state was freed */
15374  }
15375  }
15376  }
15377  else
15378  {
15379  /* state was freed */
15380  state = NULL;
15381  }
15382  }
15383 
15384 exit:
15385  if (state)
15386  {
15387  /* We need to free state and decrease the tr_Current_depth. */
15388  tr_abort (state);
15389  }
15390 
15391  if (result < NO_ERROR && savepoint_name != NULL && (result != ER_LK_UNILATERALLY_ABORTED))
15392  {
15393  /* savepoint from tran_savepoint() */
15394  (void) tran_abort_upto_system_savepoint (savepoint_name);
15395  }
15396  return result;
15397 }
15398 
15399 /*
15400  * do_merge () - MERGE statement
15401  * return:
15402  * parser(in):
15403  * statement(in):
15404  *
15405  */
15406 int
15407 do_merge (PARSER_CONTEXT * parser, PT_NODE * statement)
15408 {
15409  int err = NO_ERROR;
15410  PT_NODE *not_nulls = NULL, *lhs, *spec = NULL;
15411  int has_unique;
15412  const char *savepoint_name = NULL;
15413  DB_OBJECT *class_obj;
15414  QFILE_LIST_ID *list_id = NULL;
15415  PT_NODE *upd_select_stmt = NULL;
15416  PT_NODE *ins_select_stmt = NULL;
15417  PT_NODE *select_names = NULL, *select_values = NULL;
15418  PT_NODE *const_names = NULL, *const_values = NULL;
15419  PT_NODE *flat, *values_list = NULL;
15420  PT_NODE **links = NULL;
15421  PT_NODE *hint_arg;
15422  QUERY_ID ins_query_id = NULL_QUERY_ID;
15423  QUERY_ID upd_query_id = NULL_QUERY_ID;
15424  QUERY_ID query_id_self = parser->query_id;
15425  int no_vals, no_consts;
15426  int wait_msecs = -2, old_wait_msecs = -2;
15427  float hint_waitsecs;
15428  int result = 0;
15429  bool insert_only = false;
15430  PT_NODE *copy_assigns, *save_assigns;
15431 
15433 
15434  /* savepoint for statement atomicity */
15435  savepoint_name = mq_generate_name (parser, "UmsP", &merge_savepoint_number);
15436  if (savepoint_name == NULL)
15437  {
15438  err = ER_GENERIC_ERROR;
15439  goto exit;
15440  }
15441  err = tran_system_savepoint (savepoint_name);
15442  if (err != NO_ERROR)
15443  {
15444  goto exit;
15445  }
15446 
15447  AU_DISABLE (parser->au_save);
15448 
15449  if (pt_false_where (parser, statement))
15450  {
15451  insert_only = true;
15452  if (!statement->info.merge.insert.value_clauses)
15453  {
15454  /* nothing to execute */
15455  goto exit;
15456  }
15457  }
15458 
15459  spec = statement->info.merge.into;
15460  flat = spec->info.spec.flat_entity_list;
15461  if (flat == NULL)
15462  {
15463  err = ER_GENERIC_ERROR;
15464  goto exit;
15465  }
15466  class_obj = flat->info.name.db_object;
15467 
15468  /* check update part */
15469  if (statement->info.merge.update.assignment && !insert_only)
15470  {
15471  /* check if the target class has UNIQUE constraint */
15472  err = update_check_for_constraints (parser, &has_unique, &not_nulls, statement);
15473  /* not needed */
15474  if (not_nulls)
15475  {
15476  parser_free_tree (parser, not_nulls);
15477  not_nulls = NULL;
15478  }
15479  if (err != NO_ERROR)
15480  {
15481  goto exit;
15482  }
15483  if (has_unique)
15484  {
15485  statement->info.merge.flags |= PT_MERGE_INFO_HAS_UNIQUE;
15486  }
15487 
15488  lhs = statement->info.merge.update.assignment->info.expr.arg1;
15489  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
15490  {
15491  lhs = lhs->info.expr.arg1;
15492  }
15493  if (lhs->info.name.meta_class == PT_META_ATTR)
15494  {
15495  statement->info.merge.update.do_class_attrs = true;
15496  }
15497 
15498  if (!statement->info.merge.update.do_class_attrs)
15499  {
15500  /* make the SELECT statement for OID list to be updated */
15501  no_vals = 0;
15502  no_consts = 0;
15503 
15504  /* make a copy of assignment list to be able to iterate later */
15505  copy_assigns = parser_copy_tree_list (parser, statement->info.merge.update.assignment);
15506 
15507  err =
15508  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &no_vals,
15509  &no_consts, statement->info.merge.update.assignment, &links);
15510  if (err != NO_ERROR)
15511  {
15512  parser_free_tree (parser, copy_assigns);
15513  goto exit;
15514  }
15515 
15516  /* save assignment list and replace within statement with the copy */
15517  save_assigns = statement->info.merge.update.assignment;
15518  statement->info.merge.update.assignment = copy_assigns;
15519 
15520  upd_select_stmt = pt_to_merge_update_query (parser, select_values, &statement->info.merge);
15521 
15522  /* restore assignment list and destroy the copy */
15523  statement->info.merge.update.assignment = save_assigns;
15524  parser_free_tree (parser, copy_assigns);
15525 
15526  /* restore tree structure; pt_get_assignment_lists() */
15527  pt_restore_assignment_links (statement->info.merge.update.assignment, links, -1);
15528 
15529  AU_ENABLE (parser->au_save);
15530  upd_select_stmt = mq_translate (parser, upd_select_stmt);
15531  AU_DISABLE (parser->au_save);
15532  if (upd_select_stmt == NULL)
15533  {
15534  err = er_errid ();
15535  if (err == NO_ERROR)
15536  {
15537  if (pt_has_error (parser))
15538  {
15539  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, upd_select_stmt);
15540  err = er_errid ();
15541  }
15542  ASSERT_ERROR_AND_SET (err);
15543  }
15544  goto exit;
15545  }
15546  }
15547  }
15548 
15549  /* check insert part */
15550  if (statement->info.merge.insert.value_clauses)
15551  {
15552  PT_NODE *attrs = statement->info.merge.insert.attr_list;
15553 
15554  err = check_for_cons (parser, &has_unique, &not_nulls, attrs, flat->info.name.db_object);
15555  if (not_nulls)
15556  {
15557  parser_free_tree (parser, not_nulls);
15558  not_nulls = NULL;
15559  }
15560  if (err != NO_ERROR)
15561  {
15562  goto exit;
15563  }
15564  if (has_unique)
15565  {
15566  statement->info.merge.flags |= PT_MERGE_INFO_HAS_UNIQUE;
15567  }
15568 
15569  /* check not nulls attrs are present in attr list */
15570  err = check_missing_non_null_attrs (parser, spec, attrs, false);
15571  if (err != NO_ERROR)
15572  {
15573  goto exit;
15574  }
15575 
15576  /* get results from insert's select query */
15577  if (err >= NO_ERROR && (values_list = statement->info.merge.insert.value_clauses) != NULL)
15578  {
15579  ins_select_stmt = pt_to_merge_insert_query (parser, values_list->info.node_list.list, &statement->info.merge);
15580  AU_ENABLE (parser->au_save);
15581  ins_select_stmt = mq_translate (parser, ins_select_stmt);
15582  AU_DISABLE (parser->au_save);
15583 
15584  if (ins_select_stmt == NULL)
15585  {
15586  assert (er_errid () != NO_ERROR);
15587  err = er_errid ();
15588  if (err == NO_ERROR)
15589  {
15590  err = ER_GENERIC_ERROR;
15591  }
15592  goto exit;
15593  }
15594 
15595  ins_select_stmt->etc = NULL;
15596 
15597  /* enable authorization checking during methods in queries */
15598  AU_ENABLE (parser->au_save);
15599 
15600  query_id_self = parser->query_id;
15601  parser->query_id = NULL_QUERY_ID;
15602  err = do_select_for_ins_upd (parser, ins_select_stmt);
15603  ins_query_id = parser->query_id;
15604  parser->query_id = query_id_self;
15605 
15606  AU_DISABLE (parser->au_save);
15607 
15608  if (err < NO_ERROR)
15609  {
15610  goto exit;
15611  }
15612 
15613  if (ins_select_stmt->etc == NULL)
15614  {
15615  assert (er_errid () != NO_ERROR);
15616  err = er_errid ();
15617  if (err == NO_ERROR)
15618  {
15619  if (qo_need_skip_execution () == false)
15620  {
15621  err = ER_GENERIC_ERROR;
15622  }
15623  }
15624 
15625  goto exit;
15626  }
15627  }
15628  }
15629 
15630  /* IX lock on the class */
15632  {
15633  assert (er_errid () != NO_ERROR);
15634  err = er_errid ();
15635  if (err == NO_ERROR)
15636  {
15637  err = ER_GENERIC_ERROR;
15638  }
15639  goto exit;
15640  }
15641 
15642  if (statement->info.merge.update.assignment && !insert_only)
15643  {
15644  if (!statement->info.merge.update.do_class_attrs)
15645  {
15646  /* flush necessary objects before execute */
15647  err = sm_flush_objects (class_obj);
15648  if (err != NO_ERROR)
15649  {
15650  goto exit;
15651  }
15652 
15653  /* enable authorization checking during methods in queries */
15654  AU_ENABLE (parser->au_save);
15655 
15656  query_id_self = parser->query_id;
15657  parser->query_id = NULL_QUERY_ID;
15658  err = do_select_for_ins_upd (parser, upd_select_stmt);
15659  upd_query_id = parser->query_id;
15660  parser->query_id = query_id_self;
15661 
15662  AU_DISABLE (parser->au_save);
15663 
15664  if (err < NO_ERROR)
15665  {
15666  /* query failed, an error has already been set */
15667  goto exit;
15668  }
15669 
15670  list_id = (QFILE_LIST_ID *) upd_select_stmt->etc;
15671  parser_free_tree (parser, upd_select_stmt);
15672  upd_select_stmt = NULL;
15673  }
15674  }
15675 
15676  hint_arg = statement->info.merge.waitsecs_hint;
15677  if ((statement->info.merge.hint & PT_HINT_LK_TIMEOUT) && PT_IS_HINT_NODE (hint_arg))
15678  {
15679  hint_waitsecs = (float) atof (hint_arg->info.name.original);
15680  if (hint_waitsecs > 0)
15681  {
15682  wait_msecs = (int) (hint_waitsecs * 1000);
15683  }
15684  else
15685  {
15686  wait_msecs = (int) hint_waitsecs;
15687  }
15688  if (wait_msecs >= -1)
15689  {
15690  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
15691  (void) tran_reset_wait_times (wait_msecs);
15692  }
15693  }
15694 
15695  /* do update part */
15696  if (statement->info.merge.update.assignment && !insert_only)
15697  {
15698  query_id_self = parser->query_id;
15699  parser->query_id = upd_query_id;
15700  if (statement->info.merge.update.do_class_attrs)
15701  {
15702  /* update class attributes */
15703  err = update_class_attributes (parser, statement);
15704  }
15705  else
15706  {
15707  /* OID list update */
15708  err = update_objs_for_list_file (parser, list_id, statement, true);
15709  }
15710 
15711  /* set result count */
15712  if (err >= NO_ERROR)
15713  {
15714  result += err;
15715  }
15716 
15717  parser->query_id = upd_query_id;
15718  pt_end_query (parser, query_id_self);
15719  }
15720 
15721  /* do insert part */
15722  if (err >= NO_ERROR && (values_list = statement->info.merge.insert.value_clauses) != NULL)
15723  {
15724  PT_NODE *save_list;
15725  PT_MISC_TYPE save_type;
15726 
15727  /* save node list */
15728  save_type = values_list->info.node_list.list_type;
15729  save_list = values_list->info.node_list.list;
15730 
15731  values_list->info.node_list.list_type = PT_IS_SUBQUERY;
15732  values_list->info.node_list.list = ins_select_stmt;
15733 
15735  /* execute subquery & insert its results into target class */
15736  query_id_self = parser->query_id;
15737  parser->query_id = ins_query_id;
15738  err = insert_subquery_results (parser, statement, values_list, flat, &savepoint_name);
15739  parser->query_id = query_id_self;
15740  if (parser->flag.abort)
15741  {
15742  assert (er_errid () != NO_ERROR);
15743  err = er_errid ();
15744  }
15745  else if (err >= NO_ERROR)
15746  {
15747  result += err;
15748  }
15749 
15750  /* restore node list */
15751  values_list->info.node_list.list_type = save_type;
15752  values_list->info.node_list.list = save_list;
15753 
15754  parser_free_tree (parser, ins_select_stmt);
15755  ins_select_stmt = NULL;
15756 
15757  /* pt_end_query() already called by insert_subquery_results() */
15758  }
15759 
15760  if (old_wait_msecs >= -1)
15761  {
15762  (void) tran_reset_wait_times (old_wait_msecs);
15763  }
15764 
15765  if (err >= NO_ERROR)
15766  {
15767  err = db_is_vclass (class_obj);
15768  if (err > 0)
15769  {
15770  err = sm_flush_objects (class_obj);
15771  }
15772  }
15773 
15774 exit:
15775  if (upd_select_stmt != NULL)
15776  {
15777  parser_free_tree (parser, upd_select_stmt);
15778  }
15779 
15780  if (list_id != NULL)
15781  {
15782  cursor_free_self_list_id (list_id);
15783  if (upd_query_id != NULL_QUERY_ID && !tran_was_latest_query_ended ())
15784  {
15785  qmgr_end_query (upd_query_id);
15786  }
15787  }
15788 
15789  if (ins_select_stmt != NULL)
15790  {
15791  if (ins_select_stmt->etc != NULL)
15792  {
15793  cursor_free_self_list_id (ins_select_stmt->etc);
15794  if (ins_query_id != NULL_QUERY_ID && !tran_was_latest_query_ended ())
15795  {
15796  qmgr_end_query (ins_query_id);
15797  }
15798  }
15799  parser_free_tree (parser, ins_select_stmt);
15800  }
15801 
15802  if ((err < NO_ERROR) && er_errid () != NO_ERROR)
15803  {
15804  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number, er_msg (),
15805  NULL);
15806  }
15807  /* If error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
15808  * transaction. */
15809  if (err < NO_ERROR && savepoint_name && err != ER_LK_UNILATERALLY_ABORTED)
15810  {
15811  (void) db_abort_to_savepoint (savepoint_name);
15812  }
15813 
15814  AU_ENABLE (parser->au_save);
15815 
15816  return (err < NO_ERROR) ? err : result;
15817 }
15818 
15819 /*
15820  * do_prepare_merge() - Prepare the MERGE statement
15821  * return: Error code
15822  * parser(in): Parser context
15823  * statement(in/out): Parse tree of a MERGE statement
15824  *
15825  */
15826 int
15827 do_prepare_merge (PARSER_CONTEXT * parser, PT_NODE * statement)
15828 {
15829  int err = NO_ERROR;
15830  PT_NODE *non_nulls_upd = NULL, *non_nulls_ins = NULL, *lhs, *flat, *spec;
15831  int has_unique = 0, has_trigger = 0, has_virt = 0, au_save;
15832  bool server_insert, server_update, server_op, insert_only = false;
15833 
15834  PT_NODE *select_statement = NULL;
15835  PT_NODE *select_names = NULL, *select_values = NULL;
15836  PT_NODE *const_names = NULL, *const_values = NULL;
15837  PT_NODE **links = NULL;
15838  PT_NODE *default_expr_attrs = NULL;
15839  DB_OBJECT *class_obj;
15840  PT_NODE *copy_assigns, *save_assigns;
15841 
15842  int no_vals, no_consts, is_vclass = 0;
15843 
15844  COMPILE_CONTEXT *contextp;
15845  XASL_STREAM stream;
15846 
15847  contextp = &parser->context;
15848 
15849  init_xasl_stream (&stream);
15850 
15851  if (parser == NULL || statement == NULL)
15852  {
15854  return ER_OBJ_INVALID_ARGUMENTS;
15855  }
15856 
15857  contextp->sql_user_text = statement->sql_user_text;
15858  contextp->sql_user_text_len = statement->sql_user_text_len;
15859 
15860  if (pt_false_where (parser, statement))
15861  {
15862  statement->info.merge.flags |= PT_MERGE_INFO_INSERT_ONLY;
15863  if (!statement->info.merge.insert.value_clauses)
15864  {
15865  /* nothing to prepare */
15866  goto cleanup;
15867  }
15868  insert_only = true;
15869  }
15870 
15871  if (statement->xasl_id)
15872  {
15873  /* already prepared */
15874  goto cleanup;
15875  }
15876 
15877  /* check into for triggers and virtual class */
15878  AU_SAVE_AND_DISABLE (au_save);
15879 
15880  spec = statement->info.merge.into;
15881  flat = spec->info.spec.flat_entity_list;
15882  class_obj = (flat) ? flat->info.name.db_object : NULL;
15883 
15884  if (statement->info.merge.update.assignment && !insert_only)
15885  {
15886  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_UPDATE);
15887  if (err == NO_ERROR && !has_trigger)
15888  {
15889  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_STATEMENT_UPDATE);
15890  }
15891  if (err == NO_ERROR && !has_trigger && statement->info.merge.update.has_delete)
15892  {
15893  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_DELETE);
15894  if (err == NO_ERROR && !has_trigger)
15895  {
15896  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_STATEMENT_DELETE);
15897  }
15898  }
15899  }
15900  if (err == NO_ERROR && !has_trigger && statement->info.merge.insert.value_clauses)
15901  {
15902  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_INSERT);
15903  if (err == NO_ERROR && !has_trigger)
15904  {
15905  err = sm_class_has_triggers (class_obj, &has_trigger, TR_EVENT_STATEMENT_INSERT);
15906  }
15907  }
15908 
15909  if (err == NO_ERROR)
15910  {
15911  is_vclass = db_is_vclass (class_obj);
15912  if (is_vclass < 0)
15913  {
15914  err = is_vclass;
15915  }
15916  else
15917  {
15918  has_virt = is_vclass || ((flat) ? (flat->info.name.virt_object != NULL) : false);
15919  }
15920  }
15921 
15922  AU_RESTORE (au_save);
15923 
15924  if (err != NO_ERROR)
15925  {
15926  goto cleanup;
15927  }
15928 
15929  err = do_evaluate_default_expr (parser, flat);
15930  if (err != NO_ERROR)
15931  {
15932  goto cleanup;
15933  }
15934 
15935  /* check update part */
15936  if (statement->info.merge.update.assignment && !insert_only)
15937  {
15938  /* check if the target class has UNIQUE constraint */
15939  err = update_check_for_constraints (parser, &has_unique, &non_nulls_upd, statement);
15940  if (err != NO_ERROR)
15941  {
15942  goto cleanup;
15943  }
15944  if (has_unique)
15945  {
15946  statement->info.merge.flags |= PT_MERGE_INFO_HAS_UNIQUE;
15947  }
15948 
15949  server_update = (!has_trigger && !has_virt
15950  && !update_check_having_meta_attr (parser, statement->info.merge.update.assignment));
15951 
15952  lhs = statement->info.merge.update.assignment->info.expr.arg1;
15953  if (PT_IS_N_COLUMN_UPDATE_EXPR (lhs))
15954  {
15955  lhs = lhs->info.expr.arg1;
15956  }
15957 
15958  /* if we are updating class attributes, not need to prepare */
15959  if (lhs->info.name.meta_class == PT_META_ATTR)
15960  {
15961  statement->info.merge.update.do_class_attrs = true;
15962  goto cleanup;
15963  }
15964  }
15965  else
15966  {
15967  server_update = !has_trigger && !has_virt;
15968  }
15969 
15970  /* check insert part */
15971  if (statement->info.merge.insert.value_clauses)
15972  {
15973  PT_NODE *attr, *attrs = statement->info.merge.insert.attr_list;
15974 
15976  {
15977  /* server insert cannot handle insert into a shared attribute */
15978  server_insert = true;
15979  attr = attrs;
15980  while (attr)
15981  {
15982  if (attr->node_type != PT_NAME || attr->info.name.meta_class != PT_NORMAL)
15983  {
15984  server_insert = false;
15985  break;
15986  }
15987  attr = attr->next;
15988  }
15989  }
15990  else
15991  {
15992  server_insert = false;
15993  }
15994 
15995  err = check_for_cons (parser, &has_unique, &non_nulls_ins, attrs, flat->info.name.db_object);
15996  if (err != NO_ERROR)
15997  {
15998  goto cleanup;
15999  }
16000  if (has_unique)
16001  {
16002  statement->info.merge.flags |= PT_MERGE_INFO_HAS_UNIQUE;
16003  }
16004 
16005  /* check not nulls attrs are present in attr list */
16006  err = check_missing_non_null_attrs (parser, spec, attrs, false);
16007  if (err != NO_ERROR)
16008  {
16009  goto cleanup;
16010  }
16011  }
16012  else
16013  {
16014  server_insert = !has_trigger && !has_virt;
16015  }
16016 
16017  server_op = (server_insert && server_update);
16018 
16019  if (server_op)
16020  {
16021  statement->info.merge.flags |= PT_MERGE_INFO_SERVER_OP;
16022 
16023  /* make query string */
16024  parser->flag.dont_prt_long_string = 1;
16025  parser->flag.long_string_skipped = 0;
16026  parser->flag.print_type_ambiguity = 0;
16028  contextp->sql_hash_text = (char *) statement->alias_print;
16029  err = SHA1Compute ((unsigned char *) contextp->sql_hash_text, (unsigned) strlen (contextp->sql_hash_text),
16030  &contextp->sha1);
16031  if (err != NO_ERROR)
16032  {
16033  ASSERT_ERROR ();
16034  return err;
16035  }
16036  parser->flag.dont_prt_long_string = 0;
16037  if (parser->flag.long_string_skipped || parser->flag.print_type_ambiguity)
16038  {
16039  statement->flag.cannot_prepare = 1;
16040  statement->info.merge.flags &= ~PT_MERGE_INFO_SERVER_OP;
16041  goto cleanup;
16042  }
16043 
16044  /* lookup in XASL cache */
16045  contextp->recompile_xasl = statement->flag.recompile;
16046  if (statement->flag.recompile == 0)
16047  {
16048  err = prepare_query (contextp, &stream);
16049  if (err != NO_ERROR)
16050  {
16051  ASSERT_ERROR_AND_SET (err);
16052  }
16053  else if (contextp->recompile_xasl == true)
16054  {
16055  /* recompile requested by server */
16056  if (stream.xasl_id != NULL)
16057  {
16058  free_and_init (stream.xasl_id);
16059  }
16060  }
16061  }
16062 
16063  if (stream.xasl_id == NULL && err == NO_ERROR)
16064  {
16065  if (statement->info.merge.insert.value_clauses)
16066  {
16067  err = pt_find_omitted_default_expr (parser, flat->info.name.db_object,
16068  statement->info.merge.insert.attr_list, &default_expr_attrs);
16069  if (err != NO_ERROR)
16070  {
16071  statement->flag.use_plan_cache = 0;
16072  statement->xasl_id = NULL;
16073  goto cleanup;
16074  }
16075  }
16076 
16077  /* mark the beginning of another level of xasl packing */
16079 
16080  /* generate MERGE XASL */
16081  contextp->xasl = pt_to_merge_xasl (parser, statement, &non_nulls_upd, &non_nulls_ins, default_expr_attrs);
16082 
16083  stream.buffer = NULL;
16084 
16085  if (contextp->xasl && (err >= NO_ERROR))
16086  {
16087  err = xts_map_xasl_to_stream (contextp->xasl, &stream);
16088  if (err != NO_ERROR)
16089  {
16091  }
16092 
16093  /* clear constant values */
16094  if (contextp->xasl->proc.merge.update_xasl)
16095  {
16096  int i;
16097  UPDATE_PROC_NODE *update = &contextp->xasl->proc.merge.update_xasl->proc.update;
16098 
16099  for (i = update->num_assigns - 1; i >= 0; i--)
16100  {
16101  if (update->assigns[i].constant)
16102  {
16103  pr_clear_value (update->assigns[i].constant);
16104  }
16105  }
16106  }
16107  }
16108  else
16109  {
16110 #if 0 /* TODO */
16111  assert (er_errid () != NO_ERROR);
16112 #endif
16113  err = er_errid ();
16114  if (err != NO_ERROR)
16115  {
16116  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number,
16117  er_msg (), NULL);
16118  }
16119  }
16120 
16121  /* cache the XASL */
16122  if (stream.buffer && (err >= NO_ERROR))
16123  {
16124  err = prepare_query (contextp, &stream);
16125  if (err != NO_ERROR)
16126  {
16127  assert (er_errid () != NO_ERROR);
16128  err = er_errid ();
16129  }
16130  }
16131 
16132  /* mark the end of another level of xasl packing */
16134 
16135  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
16136  if (stream.buffer)
16137  {
16138  free_and_init (stream.buffer);
16139  }
16140  statement->flag.use_plan_cache = 0;
16141  statement->xasl_id = stream.xasl_id;
16142  }
16143  else
16144  {
16145  if (err == NO_ERROR)
16146  {
16147  statement->flag.use_plan_cache = 1;
16148  statement->xasl_id = stream.xasl_id;
16149  }
16150  else
16151  {
16152  statement->flag.use_plan_cache = 0;
16153  }
16154 
16155  goto cleanup;
16156  }
16157  }
16158  else
16159  {
16160  if (statement->info.merge.update.assignment && !insert_only)
16161  {
16162  /* make the SELECT statement for OID list to be updated */
16163  no_vals = 0;
16164  no_consts = 0;
16165 
16166  /* make a copy of assignment list to be able to iterate later */
16167  copy_assigns = parser_copy_tree_list (parser, statement->info.merge.update.assignment);
16168 
16169  err =
16170  pt_get_assignment_lists (parser, &select_names, &select_values, &const_names, &const_values, &no_vals,
16171  &no_consts, statement->info.merge.update.assignment, &links);
16172  if (err != NO_ERROR)
16173  {
16174  parser_free_tree (parser, copy_assigns);
16175  goto cleanup;
16176  }
16177 
16178  /* save assignment list and replace within statement with the copy */
16179  save_assigns = statement->info.merge.update.assignment;
16180  statement->info.merge.update.assignment = copy_assigns;
16181 
16182  select_statement = pt_to_merge_update_query (parser, select_values, &statement->info.merge);
16183 
16184  /* restore assignment list and destroy the copy */
16185  statement->info.merge.update.assignment = save_assigns;
16186  parser_free_tree (parser, copy_assigns);
16187 
16188  /* restore tree structure; pt_get_assignment_lists() */
16189  pt_restore_assignment_links (statement->info.merge.update.assignment, links, -1);
16190 
16191  AU_SAVE_AND_ENABLE (au_save);
16192  select_statement = mq_translate (parser, select_statement);
16193  AU_RESTORE (au_save);
16194  if (select_statement)
16195  {
16196  /* get XASL_ID by calling do_prepare_select() */
16197  err = do_prepare_select (parser, select_statement);
16198 
16199  /* save the XASL_ID to be used by do_execute_merge() */
16200  statement->xasl_id = select_statement->xasl_id;
16201  select_statement->xasl_id = NULL;
16202 
16203  /* deallocate the SELECT statement */
16204  parser_free_tree (parser, select_statement);
16205  }
16206  else
16207  {
16208  err = er_errid ();
16209  if (err == NO_ERROR)
16210  {
16211  assert (pt_has_error (parser));
16212 
16213  err = ER_FAILED;
16214  }
16215  goto cleanup;
16216  }
16217  }
16218 
16219  /* nothing to do for merge insert part */
16220  }
16221 
16222 cleanup:
16223  if (non_nulls_upd)
16224  {
16225  parser_free_tree (parser, non_nulls_upd);
16226  non_nulls_upd = NULL;
16227  }
16228  if (non_nulls_ins)
16229  {
16230  parser_free_tree (parser, non_nulls_ins);
16231  non_nulls_ins = NULL;
16232  }
16233  return err;
16234 }
16235 
16236 /*
16237  * do_execute_merge() - Execute the prepared MERGE statement
16238  * return: Error code
16239  * parser(in): Parser context
16240  * statement(in): Parse tree of a MERGE statement
16241  *
16242  */
16243 int
16244 do_execute_merge (PARSER_CONTEXT * parser, PT_NODE * statement)
16245 {
16246  int err = NO_ERROR, result = 0, error = NO_ERROR;
16247  PT_NODE *flat, *spec = NULL, *values_list = NULL;
16248  const char *savepoint_name;
16249  DB_OBJECT *class_obj;
16250  QFILE_LIST_ID *list_id = NULL;
16251  int au_save;
16252  int wait_msecs = -2, old_wait_msecs = -2;
16253  float hint_waitsecs;
16254  PT_NODE *ins_select_stmt = NULL, *hint_arg;
16255  QUERY_ID ins_query_id = NULL_QUERY_ID;
16256  QUERY_ID query_id_self = parser->query_id;
16257  bool insert_only = (statement->info.merge.flags & PT_MERGE_INFO_INSERT_ONLY);
16258 
16259  assert (parser->query_id == NULL_QUERY_ID);
16260 
16262 
16263  if (insert_only && !statement->info.merge.insert.value_clauses)
16264  {
16265  /* nothing to execute */
16266  goto exit;
16267  }
16268 
16269  /* savepoint for statement atomicity */
16270  savepoint_name = mq_generate_name (parser, "UmsP", &merge_savepoint_number);
16271  if (savepoint_name == NULL)
16272  {
16273  err = ER_GENERIC_ERROR;
16274  goto exit;
16275  }
16276  err = tran_system_savepoint (savepoint_name);
16277  if (err != NO_ERROR)
16278  {
16279  goto exit;
16280  }
16281 
16282  spec = statement->info.merge.into;
16283  flat = spec->info.spec.flat_entity_list;
16284  if (flat == NULL)
16285  {
16286  err = ER_GENERIC_ERROR;
16287  goto exit;
16288  }
16289  class_obj = flat->info.name.db_object;
16290 
16291  if (statement->info.merge.flags & PT_MERGE_INFO_SERVER_OP)
16292  {
16293  /* server side execution */
16294  int query_flag = DEFAULT_EXEC_MODE;
16295 
16296  /* check if it is not necessary to execute this statement */
16297  if (statement->xasl_id == NULL)
16298  {
16299  statement->etc = NULL;
16300  goto exit;
16301  }
16302 
16303  if (parser->flag.is_xasl_pinned_reference)
16304  {
16305  query_flag |= XASL_CACHE_PINNED_REFERENCE;
16306  }
16307 
16308  query_flag |= NOT_FROM_RESULT_CACHE;
16309  query_flag |= RESULT_CACHE_INHIBITED;
16310 
16311  if (statement->flag.use_auto_commit)
16312  {
16313  query_flag |= EXECUTE_QUERY_WITH_COMMIT;
16314  }
16315 
16316  if (parser->flag.is_auto_commit)
16317  {
16318  query_flag |= TRAN_AUTO_COMMIT;
16319  }
16320 
16321  if (ws_need_flush ())
16322  {
16323  // When a transaction is under auto-commit mode, flush all dirty objects to server.
16324  // Otherwise, flush associated objects.
16325 
16326  if (statement->flag.use_auto_commit)
16327  {
16328  err = tran_flush_to_commit ();
16329  }
16330  else
16331  {
16332  err = sm_flush_objects (class_obj);
16333  }
16334 
16335  if (err != NO_ERROR)
16336  {
16337  // flush error
16338  goto exit;
16339  }
16340  }
16341 
16342  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
16343 
16344  if (statement->info.merge.insert.value_clauses)
16345  {
16347  }
16348 
16349  assert (parser->query_id == NULL_QUERY_ID);
16350  list_id = NULL;
16351 
16352  err = execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
16353  parser->host_variables, &list_id, query_flag, NULL, NULL);
16354 
16355  AU_RESTORE (au_save);
16356  if (err != NO_ERROR)
16357  {
16358  goto exit;
16359  }
16360 
16361  /* free returned QFILE_LIST_ID */
16362  if (list_id)
16363  {
16364  if (list_id->tuple_cnt > 0)
16365  {
16367  {
16368  /* Nothing to flush. Avoids flush, since may fetch the class. */
16370  }
16371  else
16372  {
16373  err = sm_flush_and_decache_objects (class_obj, true);
16374  }
16375 
16376  }
16377  if (err >= NO_ERROR)
16378  {
16379  result += list_id->tuple_cnt;
16380  }
16381  cursor_free_self_list_id (list_id);
16382  list_id = NULL;
16383  }
16384 
16385  /* end the query; reset query_id and call qmgr_end_query() */
16386  pt_end_query (parser, query_id_self);
16387  }
16388  else
16389  {
16390  /* client side execution */
16391 
16392  if (statement->info.merge.update.assignment && !insert_only && !statement->info.merge.update.do_class_attrs)
16393  {
16394  int query_flag = DEFAULT_EXEC_MODE;
16395 
16396  /* flush necessary objects before execute */
16397  err = sm_flush_objects (class_obj);
16398  if (err != NO_ERROR)
16399  {
16400  goto exit;
16401  }
16402 
16403  if (parser->flag.is_xasl_pinned_reference)
16404  {
16405  query_flag |= XASL_CACHE_PINNED_REFERENCE;
16406  }
16407 
16408  query_flag |= NOT_FROM_RESULT_CACHE;
16409  query_flag |= RESULT_CACHE_INHIBITED;
16410 
16411  AU_SAVE_AND_ENABLE (au_save); /* this insures authorization checking for method */
16412 
16413  assert (parser->query_id == NULL_QUERY_ID);
16414  list_id = NULL;
16415  err =
16416  execute_query (statement->xasl_id, &parser->query_id, parser->host_var_count + parser->auto_param_count,
16417  parser->host_variables, &list_id, query_flag, NULL, NULL);
16418  AU_RESTORE (au_save);
16419  if (err != NO_ERROR)
16420  {
16421  goto exit;
16422  }
16423  }
16424 
16425  /* make sure we have a correct lock on the class */
16427  {
16428  assert (er_errid () != NO_ERROR);
16429  err = er_errid ();
16430  goto exit;
16431  }
16432 
16433  /* get results from insert's select query */
16434  if (err >= NO_ERROR && (values_list = statement->info.merge.insert.value_clauses) != NULL)
16435  {
16436  ins_select_stmt = pt_to_merge_insert_query (parser, values_list->info.node_list.list, &statement->info.merge);
16437  AU_SAVE_AND_ENABLE (au_save);
16438  ins_select_stmt = mq_translate (parser, ins_select_stmt);
16439  AU_RESTORE (au_save);
16440 
16441  if (ins_select_stmt == NULL)
16442  {
16443  err = er_errid ();
16444  if (err == NO_ERROR)
16445  {
16446  assert (pt_has_error (parser));
16447 
16448  err = ER_FAILED;
16449  }
16450  goto exit;
16451  }
16452 
16453  ins_select_stmt->etc = NULL;
16454 
16455  query_id_self = parser->query_id;
16456  parser->query_id = NULL_QUERY_ID;
16457  err = do_select (parser, ins_select_stmt);
16458  ins_query_id = parser->query_id;
16459  parser->query_id = query_id_self;
16460 
16461  if (err < NO_ERROR)
16462  {
16463  goto exit;
16464  }
16465 
16466  if (ins_select_stmt->etc == NULL)
16467  {
16468  assert (er_errid () != NO_ERROR);
16469  err = er_errid ();
16470  if (err == NO_ERROR)
16471  {
16472  err = ER_GENERIC_ERROR;
16473  }
16474  goto exit;
16475  }
16476  }
16477 
16478  hint_arg = statement->info.merge.waitsecs_hint;
16479  if ((statement->info.merge.hint & PT_HINT_LK_TIMEOUT) && PT_IS_HINT_NODE (hint_arg))
16480  {
16481  hint_waitsecs = (float) atof (hint_arg->info.name.original);
16482  if (hint_waitsecs > 0)
16483  {
16484  wait_msecs = (int) (hint_waitsecs * 1000);
16485  }
16486  else
16487  {
16488  wait_msecs = (int) hint_waitsecs;
16489  }
16490  if (wait_msecs >= -1)
16491  {
16492  old_wait_msecs = TM_TRAN_WAIT_MSECS ();
16493  (void) tran_reset_wait_times (wait_msecs);
16494  }
16495  }
16496 
16497  /* update part */
16498  if (statement->info.merge.update.assignment && !insert_only)
16499  {
16500  AU_SAVE_AND_DISABLE (au_save);
16501 
16502  if (statement->info.merge.update.do_class_attrs)
16503  {
16504  /* update class attributes */
16505  err = update_class_attributes (parser, statement);
16506  }
16507  else
16508  {
16509  /* OID list update */
16510  err = update_objs_for_list_file (parser, list_id, statement, true);
16511  }
16512 
16513  AU_RESTORE (au_save);
16514 
16515  /* set result count */
16516  if (err >= NO_ERROR)
16517  {
16518  result += err;
16519  }
16520 
16521  if (!statement->info.merge.update.do_class_attrs)
16522  {
16523  /* free returned QFILE_LIST_ID */
16524  if (list_id)
16525  {
16526  if (err >= NO_ERROR && list_id->tuple_cnt > 0)
16527  {
16528  err = sm_flush_and_decache_objects (class_obj, true);
16529  }
16530  cursor_free_self_list_id (list_id);
16531  list_id = NULL;
16532  }
16533  }
16534  pt_end_query (parser, query_id_self);
16535  }
16536 
16537  /* insert part */
16538  if (err >= NO_ERROR && (values_list = statement->info.merge.insert.value_clauses) != NULL)
16539  {
16540  PT_NODE *save_list;
16541  PT_MISC_TYPE save_type;
16542 
16543  /* save node list */
16544  save_type = values_list->info.node_list.list_type;
16545  save_list = values_list->info.node_list.list;
16546 
16547  values_list->info.node_list.list_type = PT_IS_SUBQUERY;
16548  values_list->info.node_list.list = ins_select_stmt;
16549 
16550  AU_SAVE_AND_DISABLE (au_save);
16551 
16553  query_id_self = parser->query_id;
16554  parser->query_id = ins_query_id;
16555  /* execute subquery & insert its results into target class */
16556  err = insert_subquery_results (parser, statement, values_list, flat, &savepoint_name);
16557  parser->query_id = query_id_self;
16558  if (parser->flag.abort)
16559  {
16560  assert (er_errid () != NO_ERROR);
16561  err = er_errid ();
16562  }
16563  else if (err >= NO_ERROR)
16564  {
16565  result += err;
16566  }
16567 
16568  AU_RESTORE (au_save);
16569 
16570  /* restore node list */
16571  values_list->info.node_list.list_type = save_type;
16572  values_list->info.node_list.list = save_list;
16573 
16574  parser_free_tree (parser, ins_select_stmt);
16575  ins_select_stmt = NULL;
16576  }
16577 
16578  if (old_wait_msecs >= -1)
16579  {
16580  (void) tran_reset_wait_times (old_wait_msecs);
16581  }
16582 
16583  if (err >= NO_ERROR)
16584  {
16585  err = db_is_vclass (class_obj);
16586  if (err > 0)
16587  {
16588  err = sm_flush_objects (class_obj);
16589  }
16590  }
16591  }
16592 
16593 exit:
16594  if (ins_select_stmt != NULL)
16595  {
16596  if (ins_select_stmt->etc != NULL)
16597  {
16598  cursor_free_self_list_id (ins_select_stmt->etc);
16599  if (ins_query_id != NULL_QUERY_ID && !tran_was_latest_query_ended ())
16600  {
16601  qmgr_end_query (ins_query_id);
16602  }
16603  }
16604  parser_free_tree (parser, ins_select_stmt);
16605  }
16606 
16607  if (list_id != NULL)
16608  {
16609  cursor_free_self_list_id (list_id);
16610  }
16611 
16612  /* If err == er_errid () and parser has error, we already record the parser error to sys error, no need to call
16613  * pt_record_error (..) */
16614  if ((err < NO_ERROR) && (error = er_errid ()) != NO_ERROR && (err != error || !pt_has_error (parser)))
16615  {
16616  pt_record_error (parser, parser->statement_number, statement->line_number, statement->column_number, er_msg (),
16617  NULL);
16618  }
16619  /* If error and a savepoint was created, rollback to savepoint. No need to rollback if the TM aborted the
16620  * transaction. */
16621  if (err < NO_ERROR && savepoint_name && err != ER_LK_UNILATERALLY_ABORTED)
16622  {
16623  db_abort_to_savepoint (savepoint_name);
16624  }
16625 
16626  return (err < NO_ERROR) ? err : result;
16627 }
16628 
16629 /*
16630  * do_set_names() - Set the client charset and collation.
16631  * return: Error code if it fails
16632  * parser(in): Parser context
16633  * statement(in): Parse tree of a set transaction statement
16634  *
16635  * Note:
16636  */
16637 int
16638 do_set_names (PARSER_CONTEXT * parser, PT_NODE * statement)
16639 {
16640  int error = ER_GENERIC_ERROR;
16641  int charset_id, collation_id;
16642 
16643  if (statement->info.set_names.charset_node != NULL)
16644  {
16645  error =
16647  statement->info.set_names.collation_node, &charset_id, &collation_id);
16648  }
16649 
16650  if (error == NO_ERROR)
16651  {
16652  /* size of ('intl_collation=') + collation name */
16653  char sys_prm_chg[15 + COLL_NAME_SIZE];
16654 
16655  snprintf (sys_prm_chg, sizeof (sys_prm_chg) - 1, "intl_collation=%s", lang_get_collation_name (collation_id));
16656  error = db_set_system_parameters (sys_prm_chg);
16657  }
16658 
16659  return (error != NO_ERROR) ? ER_OBJ_INVALID_ARGUMENTS : NO_ERROR;
16660 }
16661 
16662 /*
16663  * do_set_timezone() - Set the client timezone.
16664  * return: Error code if it fails
16665  * parser(in): Parser context
16666  * statement(in): Parse tree of a set transaction statement
16667  *
16668  * Note:
16669  */
16670 int
16671 do_set_timezone (PARSER_CONTEXT * parser, PT_NODE * statement)
16672 {
16673 #define MAX_LEN 100
16674  int error = NO_ERROR;
16675  PT_NODE *tz_node;
16676  char *timezone;
16677  char sys_prm_chg[MAX_LEN];
16678 
16679  tz_node = statement->info.set_timezone.timezone_node;
16680  assert (statement != NULL && tz_node != NULL && tz_node->info.value.data_value.str != NULL);
16681 
16682  timezone = (char *) tz_node->info.value.data_value.str->bytes;
16683  snprintf (sys_prm_chg, sizeof (sys_prm_chg) - 1, "timezone=%s", timezone);
16684  error = db_set_system_parameters (sys_prm_chg);
16685 
16686 #undef MAX_LEN
16687  return (error != NO_ERROR) ? ER_OBJ_INVALID_ARGUMENTS : NO_ERROR;
16688 }
16689 
16690 /*
16691  * pt_append_odku_references () - append references to SELECT specs from
16692  * on duplicate key assignments to the SELECT
16693  * list
16694  * return :
16695  * parser (in) :
16696  * node (in) :
16697  * arg (in) :
16698  * continue_walk (in) :
16699  *
16700  * Note: This function rewrites the update assignments of an
16701  * INSERT...SELECT... ON DUPLICATE KEY UPDATE statement so that they can be
16702  * evaluated as constants. In order for this to be done, all right hand
16703  * references to attributes from the SELECT specs are added to the
16704  * SELECT list and replaced in assignments with PT_TUPLE_VALUE nodes. We can
16705  * only handle PT_NAME and PT_DOT_ (PT_NAME.PT_NAME) nodes here. We should
16706  * not encounter complex path expressions here but we will not throw an error
16707  * if we do. Complex path expression will either be foldable or we will throw
16708  * an error when we try to evaluate them.
16709  */
16710 static PT_NODE *
16711 pt_append_odku_references (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
16712 {
16713  ODKU_TUPLE_VALUE_ARG *odku_arg;
16714  PT_NODE *insert_spec = NULL;
16715  PT_NODE *select = NULL, *select_list = NULL, *select_spec = NULL, *spec = NULL;
16716  PT_NODE *name_node = NULL;
16717 
16718  *continue_walk = PT_CONTINUE_WALK;
16719 
16720  if (node == NULL || arg == NULL)
16721  {
16722  *continue_walk = PT_STOP_WALK;
16723  return node;
16724  }
16725 
16726  odku_arg = (ODKU_TUPLE_VALUE_ARG *) arg;
16727 
16728  if (odku_arg->insert_stmt->node_type != PT_INSERT)
16729  {
16730  assert (false);
16732  *continue_walk = PT_STOP_WALK;
16733  return NULL;
16734  }
16735 
16737  {
16738  *continue_walk = PT_STOP_WALK;
16739  return node;
16740  }
16741 
16742  insert_spec = odku_arg->insert_stmt->info.insert.spec;
16743 
16744  select = odku_arg->insert_stmt->info.insert.value_clauses->info.node_list.list;
16745  if (!PT_IS_SELECT (select))
16746  {
16747  *continue_walk = PT_STOP_WALK;
16748  return node;
16749  }
16750 
16751  select_list = pt_get_select_list (parser, select);
16752  if (select_list == NULL)
16753  {
16754  assert (false);
16756  return NULL;
16757  }
16758 
16759  if (node->node_type == PT_NAME)
16760  {
16761  name_node = node;
16762  }
16763  else if (node->node_type == PT_DOT_)
16764  {
16765  if (node->info.dot.arg1 == NULL || node->info.dot.arg1->node_type != PT_NAME)
16766  {
16767  return node;
16768  }
16769 
16770  /* do not visit leaves */
16771  *continue_walk = PT_LIST_WALK;
16772  name_node = node->info.dot.arg1;
16773  }
16774  else
16775  {
16776  return node;
16777  }
16778 
16779  if (name_node->info.name.spec_id == insert_spec->info.spec.id)
16780  {
16781  /* node belongs to the insert class, nothing to be done here */
16782  return node;
16783  }
16784 
16785  select_spec = select->info.query.q.select.from;
16786  for (spec = select_spec; spec != NULL; spec = spec->next)
16787  {
16788  if (name_node->info.name.spec_id == spec->info.spec.id)
16789  {
16790  *continue_walk = PT_LIST_WALK;
16791  return pt_make_tuple_value_reference (parser, node, select_list, odku_arg->cursor_p);
16792  }
16793  }
16794 
16795  /* There might be names which do not belong to either the select specs or the insert specs: ON DUPLICATE UPDATE set
16796  * column = (SELECT ...) */
16797  return node;
16798 }
16799 
16800 /*
16801  * do_evaluate_insert_values () - Evaluates list of values for insert.
16802  *
16803  * return : Error code.
16804  * parser (in) : Parser context.
16805  * insert_statement (in) : Parse tree node for insert statement.
16806  *
16807  * NOTE: The values corresponding to each attribute are evaluated from "left"
16808  * to "right", in the order given by user.
16809  * First step is to replace attribute names with values (see
16810  * do_replace_names_for_insert_values_pre).
16811  * Nodes in values list will be replaced with PT_INSERT_VALUES nodes
16812  * that store the original node (for reevaluation) and the evaluated
16813  * value.
16814  */
16815 static int
16816 do_evaluate_insert_values (PARSER_CONTEXT * parser, PT_NODE * insert_statement)
16817 {
16818  PT_NODE *val = NULL, *prev = NULL;
16819  PT_NODE *result = NULL, *save_next = NULL;
16820  EVAL_INSERT_VALUE eval;
16821  DB_VALUE eval_value;
16822  PT_NODE *attr_list = NULL, *value_list = NULL, *value_clause = NULL;
16823  PT_NODE *temp = NULL;
16824  bool free_temp = false;
16825 
16826  attr_list = insert_statement->info.insert.attr_list;
16827  value_clause = insert_statement->info.insert.value_clauses;
16828  if (attr_list == NULL || value_clause == NULL || value_clause->info.node_list.list_type == PT_IS_SUBQUERY)
16829  {
16830  /* nothing to evaluate */
16831  return NO_ERROR;
16832  }
16833 
16834  /* initialize attr_list in EVAL_INSERT_VALUE object */
16835  eval.spec_id = insert_statement->info.insert.spec->info.spec.id;
16836  eval.attr_list = attr_list;
16837  eval.value_list = NULL;
16838  eval.reevaluate_needed = false;
16839  eval.replace_names = false;
16840  eval.crt_attr_index = 0;
16841 
16842  db_make_null (&eval_value);
16843 
16844  /* evaluate lists of values */
16845  for (value_list = value_clause; value_list != NULL; value_list = value_list->next)
16846  {
16847  if (value_list->info.node_list.list_type != PT_IS_VALUE)
16848  {
16849  continue;
16850  }
16851  assert (value_list->node_type == PT_NODE_LIST);
16852  assert (value_list->info.node_list.list_type == PT_IS_VALUE);
16853  eval.value_list = value_list->info.node_list.list;
16854  eval.crt_attr_index = 0;
16855 
16856  /* evaluate values in val_list */
16857  for (prev = NULL, val = value_list->info.node_list.list; val != NULL; val = save_next, eval.crt_attr_index++)
16858  {
16859  save_next = val->next;
16860 
16861  if (PT_IS_INSERT_VALUE_NODE (val))
16862  {
16863  /* this is not the first evaluation */
16864  if (val->info.insert_value.is_evaluated)
16865  {
16866  /* already evaluated, do nothing */
16867  continue;
16868  }
16869  /* need to reevaluate */
16870  if (val->info.insert_value.replace_names)
16871  {
16872  /* duplicate original node because it will be altered */
16873  temp = parser_copy_tree (parser, val->info.insert_value.original_node);
16874  if (temp == NULL)
16875  {
16876  if (!pt_has_error (parser))
16877  {
16879  sizeof (PT_NODE));
16880  }
16881  goto end_error;
16882  }
16883  free_temp = true;
16884  /* replace names */
16885  temp =
16887  NULL);
16888  if (pt_has_error (parser))
16889  {
16890  goto end_error;
16891  }
16892  }
16893  else
16894  {
16895  temp = val->info.insert_value.original_node;
16896  }
16897  /* obtain evaluated value */
16898  pt_evaluate_tree_having_serial (parser, temp, &val->info.insert_value.value, 1);
16899  if (free_temp)
16900  {
16901  /* free temp */
16902  parser_free_tree (parser, temp);
16903  temp = NULL;
16904  free_temp = false;
16905  }
16906  if (pt_has_error (parser))
16907  {
16908  /* evaluation failed */
16909  goto end_error;
16910  }
16911  val->info.insert_value.is_evaluated = true;
16912  /* evaluation ok, continue to next value */
16913  continue;
16914  }
16915 
16916  /* this must be first evaluation */
16917  val->next = NULL;
16918  eval.reevaluate_needed = false;
16919  eval.replace_names = false;
16920 
16921  if (!PT_IS_CONST (val))
16922  {
16923  /* duplicate value as it may be altered when names are replaced */
16924  temp = parser_copy_tree (parser, val);
16925 
16926  free_temp = true;
16927  temp =
16929  if (pt_has_error (parser))
16930  {
16931  /* error replacing names */
16932  val->next = save_next;
16933  goto end_error;
16934  }
16935  }
16936  else
16937  {
16938  temp = val;
16939  free_temp = false;
16940  if (!PT_IS_VALUE_NODE (temp))
16941  {
16942  eval.reevaluate_needed = true;
16943  }
16944  }
16945 
16946  assert (temp != NULL);
16947  /* evaluate temp to obtain a value */
16948  db_value_clear (&eval_value);
16949  pt_evaluate_tree_having_serial (parser, temp, &eval_value, 1);
16950  if (pt_has_error (parser))
16951  {
16952  val->next = save_next;
16953  goto end_error;
16954  }
16955 
16956  if (free_temp)
16957  {
16958  parser_free_tree (parser, temp);
16959  temp = NULL;
16960  free_temp = false;
16961  }
16962 
16963  result = pt_insert_value (parser, NULL);
16964  if (result == NULL)
16965  {
16966  if (!pt_has_error (parser))
16967  {
16969  pt_short_print (parser, val));
16970  }
16971  val->next = save_next;
16972  goto end_error;
16973  }
16974  if (db_value_clone (&eval_value, &result->info.insert_value.value) != NO_ERROR)
16975  {
16977  pt_short_print (parser, val));
16978  parser_free_tree (parser, result);
16979  val->next = save_next;
16980  goto end_error;
16981  }
16982  result->info.insert_value.is_evaluated = true;
16983  if (eval.reevaluate_needed || PT_IS_VALUE_NODE (val))
16984  {
16985  /* save original node */
16986  result->info.insert_value.original_node = val;
16987  }
16988  else
16989  {
16990  /* save a PT_VALUE node instead of original node in order to avoid reevaluation */
16991  result->info.insert_value.original_node = pt_dbval_to_value (parser, &eval_value);
16992  if (result->info.insert_value.original_node == NULL)
16993  {
16994  if (!pt_has_error (parser))
16995  {
16997  pt_short_print (parser, val));
16998  }
16999  parser_free_tree (parser, result);
17000  val->next = save_next;
17001  goto end_error;
17002  }
17003  }
17005 
17006  result->line_number = val->line_number;
17007  result->column_number = val->column_number;
17008 
17009  /* replace val */
17010  result->next = save_next;
17011 
17012  if (prev == NULL)
17013  {
17014  eval.value_list = value_list->info.node_list.list = result;
17015  }
17016  else
17017  {
17018  prev->next = result;
17019  }
17020  prev = result;
17021  }
17022  pr_clear_value (&eval_value);
17023  }
17024  return NO_ERROR;
17025 
17026 end_error:
17027  pr_clear_value (&eval_value);
17028  if (temp != NULL && free_temp)
17029  {
17030  parser_free_tree (parser, temp);
17031  }
17032  if (er_errid () != NO_ERROR)
17033  {
17034  return er_errid ();
17035  }
17036  return ER_FAILED;
17037 }
17038 
17039 /*
17040  * do_clear_insert_values () - Resets PT_INSERT_VALUE nodes in value clauses
17041  * to be reevaluation on next execution.
17042  *
17043  * return : Void.
17044  * parser (in) : Parser context.
17045  * insert_statement (in) : Parse tree node for insert statement.
17046  *
17047  * Note: Only some nodes are reseted. If the evaluated value is never changing
17048  * the node remains "evaluated".
17049  */
17050 static void
17051 do_clear_insert_values (PARSER_CONTEXT * parser, PT_NODE * insert_statement)
17052 {
17053  PT_NODE *value_list = NULL, *value = NULL;
17054  if (insert_statement == NULL || insert_statement->node_type != PT_INSERT)
17055  {
17056  return;
17057  }
17058  if (insert_statement->info.insert.value_clauses == NULL)
17059  {
17060  return;
17061  }
17062 
17063  for (value_list = insert_statement->info.insert.value_clauses; value_list != NULL; value_list = value_list->next)
17064  {
17065  if (value_list->info.node_list.list_type != PT_IS_VALUE)
17066  {
17067  continue;
17068  }
17069  for (value = value_list->info.node_list.list; value != NULL; value = value->next)
17070  {
17071  if (PT_IS_INSERT_VALUE_NODE (value) && !PT_IS_VALUE_NODE (value->info.insert_value.original_node))
17072  {
17073  /* prepare node for reevaluation */
17074  value->info.insert_value.is_evaluated = false;
17075  db_value_clear (&value->info.insert_value.value);
17076  db_make_null (&value->info.insert_value.value);
17077  }
17078  }
17079  }
17080 }
17081 
17082 /*
17083  * insert_rewrite_names_in_value_clauses () - Rewrites some names in insert
17084  * VALUE clause.
17085  *
17086  * return : void.
17087  * parser (in) : Parser context.
17088  * insert_statement (in) : Insert statement.
17089  *
17090  * NOTE: Names that are replaced:
17091  * 1. References to attribute from insert spec that are unassigned are
17092  * replaced with default values.
17093  * e.g.: INSERT INTO t (a, b) VALUES (b, a + 1) => In a = b, b is not
17094  * assigned yet and is replaced with DEFAULT(b). In b = a + 1,
17095  * a is assigned and is not replaced here.
17096  * 2. META_CLASS names are replaced with class object.
17097  * 3. PT_PARAMETER names that point to object type values are replaced.
17098  */
17099 void
17101 {
17102  PT_NODE *attr_list = NULL, *value_clauses = NULL, *value_list = NULL;
17103  PT_NODE *value = NULL, *value_tmp = NULL, *save_next = NULL, *prev = NULL;
17104 
17105  EVAL_INSERT_VALUE eval;
17106  if (insert_statement == NULL || insert_statement->node_type != PT_INSERT)
17107  {
17108  return;
17109  }
17110 
17111  attr_list = insert_statement->info.insert.attr_list;
17112  value_clauses = insert_statement->info.insert.value_clauses;
17113  if (attr_list == NULL || value_clauses == NULL)
17114  {
17115  return;
17116  }
17117 
17118  eval.spec_id = insert_statement->info.insert.spec->info.spec.id;
17119  eval.attr_list = attr_list;
17120  eval.value_list = NULL;
17121 
17122  for (value_list = value_clauses; value_list != NULL; value_list = value_list->next)
17123  {
17124  if (value_list->info.node_list.list_type != PT_IS_VALUE)
17125  {
17126  continue;
17127  }
17128  prev = NULL;
17129  for (value = value_list->info.node_list.list, eval.crt_attr_index = 0; value != NULL;
17130  value = save_next, eval.crt_attr_index++)
17131  {
17132  save_next = value->next;
17133  if (PT_IS_VALUE_NODE (value) || PT_IS_HOSTVAR (value))
17134  {
17135  prev = value;
17136  continue;
17137  }
17138  value->next = NULL;
17139 
17140  value = parser_walk_tree (parser, value, do_replace_names_for_insert_values_pre, &eval, NULL, NULL);
17141  if (!pt_has_error (parser))
17142  {
17143  value_tmp = pt_semantic_type (parser, value, NULL);
17144  if (value_tmp == NULL)
17145  {
17146  /* In this case, pt_has_error (parser) is true, we need recovery the link list firstly, then return. */
17147  ;
17148  }
17149  else
17150  {
17151  value = value_tmp;
17152  }
17153  }
17154  value->next = save_next;
17155  if (prev == NULL)
17156  {
17157  value_list->info.node_list.list = value;
17158  }
17159  else
17160  {
17161  prev->next = value;
17162  }
17163  if (pt_has_error (parser))
17164  {
17165  return;
17166  }
17167  prev = value;
17168  }
17169  }
17170 }
17171 
17172 /*
17173  * do_replace_names_for_insert_values_pre () - Used by parser_walk_tree to
17174  * evaluate names in insert values
17175  *
17176  * return : node or replaced name .
17177  * parser (in) : parser context.
17178  * node (in) : node in parse tree.
17179  * arg (in) : EVAL_INSERT_VALUE.
17180  * continue_walk (in) : continue walk.
17181  *
17182  * NOTE: Name replacement will be done after the next rules:
17183  * 1. If name belongs to insert attribute list and if name was assigned
17184  * before current attribute, use the assigned value to replace name.
17185  * 2. If name was not assigned yet, replace it with default value.
17186  * 3. If could not find a default value for name, then
17187  * pt_evaluate_tree_having_serial will have to evaluate the name.
17188  */
17189 static PT_NODE *
17190 do_replace_names_for_insert_values_pre (PARSER_CONTEXT * parser, PT_NODE * node, void *arg, int *continue_walk)
17191 {
17192  int count, found, error = NO_ERROR;
17193  PT_NODE *attr = NULL, *val = NULL, *result = NULL;
17194  EVAL_INSERT_VALUE *eval = (EVAL_INSERT_VALUE *) arg;
17195  DB_OBJECT *obj;
17197  int is_class = 0;
17198 
17199  if (node == NULL || *continue_walk == PT_STOP_WALK || pt_has_error (parser))
17200  {
17201  return node;
17202  }
17203 
17204  switch (node->node_type)
17205  {
17206  case PT_NAME:
17207  *continue_walk = PT_LIST_WALK;
17208  if (node->info.name.spec_id != eval->spec_id)
17209  {
17210  eval->reevaluate_needed = true;
17211  switch (node->info.name.meta_class)
17212  {
17213  case PT_META_CLASS:
17214  case PT_CLASSOID_ATTR:
17215  /* object is the class itself */
17216  obj = node->info.name.db_object;
17217  if (obj == NULL)
17218  {
17219  /* do nothing */
17220  return node;
17221  }
17222  is_class = db_is_any_class (obj);
17223  if (is_class < 0)
17224  {
17225  return node;
17226  }
17227  if (!is_class)
17228  {
17230  pt_short_print (parser, node));
17231  return node;
17232  }
17233  db_make_object (&db_value, obj);
17234  break;
17235  case PT_PARAMETER:
17236  pt_evaluate_tree_having_serial (parser, node, &db_value, 1);
17237  if (DB_VALUE_TYPE (&db_value) == DB_TYPE_VOBJ)
17238  {
17239  error = vid_vobj_to_object (&db_value, &obj);
17240  if (error != NO_ERROR)
17241  {
17243  pt_short_print (parser, node));
17244  }
17245  db_make_object (&db_value, obj);
17246  }
17247  else if (DB_VALUE_TYPE (&db_value) == DB_TYPE_OBJECT)
17248  {
17249  obj = db_get_object (&db_value);
17250  obj = db_real_instance (obj);
17251  db_make_object (&db_value, obj);
17252  }
17253  break;
17254  default:
17255  /* do nothing here */
17256  return node;
17257  }
17258  /* replace node with value in db_value */
17259  result = pt_dbval_to_value (parser, &db_value);
17260  if (result == NULL)
17261  {
17262  if (!pt_has_error (parser))
17263  {
17265  pt_short_print (parser, node));
17266  }
17267  return node;
17268  }
17269  PT_NODE_MOVE_NUMBER_OUTERLINK (result, node);
17270  parser_free_tree (parser, node);
17271  return result;
17272  }
17273  /* look for node in attr list and stop when count reaches node_index */
17274  found = 0;
17275  val = eval->value_list;
17276  for (attr = eval->attr_list, count = 0; attr != NULL && count < eval->crt_attr_index; attr = attr->next, count++)
17277  {
17278  if (pt_name_equal (parser, node, attr))
17279  {
17280  found = true;
17281  break;
17282  }
17283  if (val != NULL)
17284  {
17285  val = val->next;
17286  }
17287  }
17288  /* replace found attributes with the corresponding values in value_list. if attribute is not found, it is
17289  * replaced with default value. if value_list is NULL, only default values are replaced */
17290  if (found && val != NULL)
17291  {
17292  /* replace node with value */
17293  if (!PT_IS_VALUE_NODE (val) && (!PT_IS_INSERT_VALUE_NODE (val) || !val->info.insert_value.is_evaluated))
17294  {
17295  /* cannot evaluate */
17297  pt_short_print (parser, node));
17298  /* do not replace node */
17299  return node;
17300  }
17301  if (PT_IS_VALUE_NODE (val))
17302  {
17303  /* value node */
17304  result = parser_copy_tree (parser, val);
17305  }
17306  else
17307  {
17308  /* insert_value node */
17309  eval->reevaluate_needed = true;
17310  eval->replace_names = true;
17311  result = pt_dbval_to_value (parser, &val->info.insert_value.value);
17312  }
17313  if (result == NULL)
17314  {
17315  if (!pt_has_error (parser))
17316  {
17318  }
17319  /* do not replace node */
17320  return node;
17321  }
17322  /* replace node */
17323  PT_NODE_MOVE_NUMBER_OUTERLINK (result, node);
17324  parser_free_tree (parser, node);
17325  return result;
17326  }
17327  else if (!found)
17328  {
17329  /* try to replace node with default value */
17330  if (pt_resolve_default_value (parser, node) == NO_ERROR)
17331  {
17332  if (node->info.name.default_value != NULL)
17333  {
17334  /* replace node with default value */
17335  result = node->info.name.default_value;
17336  node->info.name.default_value = NULL;
17337  }
17338  else
17339  {
17340  /* replace with a NULL value */
17341  result = parser_new_node (parser, PT_VALUE);
17342  if (result == NULL)
17343  {
17344  if (!pt_has_error (parser))
17345  {
17347  sizeof (PT_NODE));
17348  }
17349  return node;
17350  }
17351  result->type_enum = PT_TYPE_NULL;
17352  }
17353  PT_NODE_MOVE_NUMBER_OUTERLINK (result, node);
17354  parser_free_tree (parser, node);
17355  return result;
17356  }
17357  }
17358  /* could not assign a value, leave the node as it is */
17359  break;
17360 
17361  case PT_EXPR:
17362  case PT_FUNCTION:
17363  /* continue walk if current node is expression or function */
17364  *continue_walk = PT_CONTINUE_WALK;
17365  break;
17366 
17367  /* stop advancing in the tree if node is not a name, expression or function */
17368 
17369  case PT_VALUE:
17370  *continue_walk = PT_LIST_WALK;
17371  break;
17372 
17373  default:
17374  /* reevaluation may be needed for each execution */
17375  eval->reevaluate_needed = true;
17376  *continue_walk = PT_LIST_WALK;
17377  break;
17378  }
17379 
17380  return node;
17381 }
17382 
17383 /*
17384  * do_vacuum () - Executes a VACUUM statement.
17385  *
17386  * return : Error code.
17387  * parser (in) : Parser context.
17388  * statement (in) : VACUUM parse tree node.
17389  */
17390 static int
17391 do_vacuum (PARSER_CONTEXT * parser, PT_NODE * statement)
17392 {
17393  int error = NO_ERROR;
17394 
17395  assert (parser != NULL && statement != NULL && PT_IS_VACUUM_NODE (statement));
17396 
17397  error = cvacuum ();
17398 
17399  return error;
17400 }
17401 
17402 /*
17403  * do_set_query_trace() - Set query trace
17404  * return: NO_ERROR
17405  * parser(in): Parser context
17406  * statement(in): Parse tree of a set statement
17407  *
17408  */
17409 int
17411 {
17412 #if defined(SA_MODE)
17413  return NO_ERROR;
17414 #else
17415  if (statement->info.trace.on_off == PT_TRACE_ON)
17416  {
17418 
17419  if (statement->info.trace.format == PT_TRACE_FORMAT_TEXT)
17420  {
17422  }
17423  else if (statement->info.trace.format == PT_TRACE_FORMAT_JSON)
17424  {
17426  }
17427  }
17428  else
17429  {
17431  }
17432 
17433  return NO_ERROR;
17434 #endif /* SA_MODE */
17435 }
17436 
17437 /*
17438  * do_kill() - Kill transaction or query
17439  * return: Error code or number of killed transaction
17440  * parser(in): Parser context
17441  * statement(in): Parse tree of a set statement
17442  *
17443  */
17444 int
17445 do_kill (PARSER_CONTEXT * parser, PT_NODE * statement)
17446 {
17447 #if defined(SA_MODE)
17448  return NO_ERROR;
17449 #else
17450  int error;
17451  PT_NODE *id_list;
17452  bool interrupt_only;
17453  int i = 0;
17454  int num_killed;
17455  int *tran_index_array;
17456  int array_size;
17457  bool is_dba_group_member;
17458 
17459  id_list = statement->info.killstmt.tran_id_list;
17460  array_size = pt_length_of_list (id_list);
17461 
17462  assert (array_size >= 1); /* verified in syntax check */
17463 
17464  is_dba_group_member = au_is_dba_group_member (Au_user);
17465 
17466  tran_index_array = (int *) malloc (sizeof (int) * array_size);
17467  if (tran_index_array == NULL)
17468  {
17469  error = ER_OUT_OF_VIRTUAL_MEMORY;
17470  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, sizeof (int) * array_size);
17471  return error;
17472  }
17473 
17474  for (i = 0; id_list != NULL; id_list = id_list->next, i++)
17475  {
17476  assert (i < array_size);
17477  assert (id_list->type_enum == PT_TYPE_INTEGER);
17478 
17479  tran_index_array[i] = id_list->info.value.data_value.i;
17480  }
17481 
17482  interrupt_only = statement->info.killstmt.kill_type == KILLSTMT_QUERY ? true : false;
17483 
17484  error =
17485  thread_kill_or_interrupt_tran (tran_index_array, array_size, is_dba_group_member, interrupt_only, &num_killed);
17486  if (error == NO_ERROR)
17487  {
17488  error = num_killed;
17489  }
17490 
17491  free_and_init (tran_index_array);
17492 
17493  return error;
17494 #endif
17495 }
17496 
17497 /*
17498  * do_set_trace_to_query_flag() -
17499  * return: void
17500  * query_flag(in):
17501  */
17502 static void
17504 {
17505  int trace_format;
17506 
17508 
17509  if (trace_format == QUERY_TRACE_TEXT)
17510  {
17511  *query_flag |= XASL_TRACE_TEXT;
17512  }
17513  else if (trace_format == QUERY_TRACE_JSON)
17514  {
17515  *query_flag |= XASL_TRACE_JSON;
17516  }
17517 }
17518 
17519 /*
17520  * do_send_plan_trace_to_session() - send plan dump to server session
17521  * return: void
17522  * parser(in):
17523  */
17524 static void
17526 {
17527  DB_VALUE var[2];
17528  char *plan_str = NULL;
17529  int i = 0;
17530  QUERY_TRACE_FORMAT format;
17531  size_t sizeloc;
17532  FILE *fp;
17533 
17534  if (parser->num_plan_trace < 1)
17535  {
17536  return;
17537  }
17538 
17539  format = parser->plan_trace[0].format;
17540 
17541  if (format == QUERY_TRACE_TEXT)
17542  {
17543  if (parser->num_plan_trace > 1)
17544  {
17545  fp = port_open_memstream (&plan_str, &sizeloc);
17546 
17547  if (fp)
17548  {
17549  for (i = 0; i < parser->num_plan_trace; i++)
17550  {
17551  assert (parser->plan_trace[i].format == format);
17552  fprintf (fp, "%s\n", parser->plan_trace[i].trace.text_plan);
17553  free_and_init (parser->plan_trace[i].trace.text_plan);
17554  }
17555 
17556  port_close_memstream (fp, &plan_str, &sizeloc);
17557  }
17558  }
17559  else
17560  {
17561  plan_str = parser->plan_trace[0].trace.text_plan;
17562  parser->plan_trace[0].trace.text_plan = NULL;
17563  }
17564  }
17565  else if (format == QUERY_TRACE_JSON)
17566  {
17567  json_t *jplan;
17568 
17569  if (parser->num_plan_trace > 1)
17570  {
17571  jplan = json_array ();
17572 
17573  for (i = 0; i < parser->num_plan_trace; i++)
17574  {
17575  assert (parser->plan_trace[i].format == format);
17576  json_array_append_new (jplan, parser->plan_trace[i].trace.json_plan);
17577  parser->plan_trace[i].trace.json_plan = NULL;
17578  }
17579  }
17580  else
17581  {
17582  jplan = parser->plan_trace[0].trace.json_plan;
17583  parser->plan_trace[0].trace.json_plan = NULL;
17584  }
17585 
17586  plan_str = json_dumps (jplan, JSON_INDENT (2) | JSON_PRESERVE_ORDER);
17587 
17588  json_object_clear (jplan);
17589  json_decref (jplan);
17590  }
17591 
17592  parser->num_plan_trace = 0;
17593 
17594  if (plan_str != NULL)
17595  {
17596  db_make_char (&var[0], 10, "trace_plan", 10, LANG_COERCIBLE_CODESET, LANG_COERCIBLE_COLL);
17597  db_make_string (&var[1], plan_str);
17598 
17600  free_and_init (plan_str);
17601  }
17602 }
17603 
17604 /*
17605  * do_insert_checks () : - Does preliminary checks for an insert statement.
17606  *
17607  * return : NO_ERROR or error code.
17608  * parser(in) : Parser context.
17609  * statement(in) : Parse tree of the insert statement to be checked.
17610  * class_(in) :
17611  * update(in/out) : Update attribute.
17612  * values(in) : Values to be inserted.
17613  */
17614 
17615 static int
17616 do_insert_checks (PARSER_CONTEXT * parser, PT_NODE * statement, PT_NODE ** class_, PT_NODE ** update, PT_NODE * values)
17617 {
17618  int error = NO_ERROR;
17619  int upd_has_uniques = 0;
17620  bool has_default_values_list = false;
17621  int trigger_involved = 0;
17622  *update = NULL;
17623 
17624  /* Check if server allows an insert. */
17625  error = is_server_insert_allowed (parser, statement);
17626  if (error != NO_ERROR)
17627  {
17628  ASSERT_ERROR ();
17629  goto exit;
17630  }
17631 
17632  /* Check whether the statement can be executed with commit. */
17634  {
17635  /* Check statement insert trigger. */
17636  error = sm_class_has_triggers ((*class_)->info.name.db_object, &trigger_involved, TR_EVENT_STATEMENT_INSERT);
17637  if (error != NO_ERROR)
17638  {
17639  ASSERT_ERROR ();
17640  goto exit;
17641  }
17642 
17643  if (!trigger_involved && !(statement->info.insert.hint & PT_HINT_USE_SBR))
17644  {
17645  statement->info.insert.execute_with_commit_allowed = 1;
17646  }
17647  }
17648 
17649  /* Check non null attrs. */
17651  {
17652  has_default_values_list = true;
17653  }
17654 
17655  error = check_missing_non_null_attrs (parser, statement->info.insert.spec, statement->info.insert.attr_list,
17656  has_default_values_list);
17657  if (error != NO_ERROR)
17658  {
17659  ASSERT_ERROR ();
17660  goto exit;
17661  }
17662 
17663  /* Test if server UPDATE is allowed */
17664 
17665  if (statement->info.insert.odku_assignments != NULL)
17666  {
17667  *update = do_create_odku_stmt (parser, statement);
17668  if (*update == NULL)
17669  {
17670  error = ER_FAILED;
17671  goto exit;
17672  }
17673 
17675  {
17676  int server_allowed = 0;
17677 
17678  error = is_server_update_allowed (parser, &statement->info.insert.odku_non_null_attrs, &upd_has_uniques,
17679  &server_allowed, *update);
17680  if (error != NO_ERROR)
17681  {
17682  ASSERT_ERROR ();
17683  goto exit;
17684  }
17685 
17686  if (!server_allowed)
17687  {
17689  goto exit;
17690  }
17691  }
17692  }
17693 
17694  /* Check to see if the class into which we are inserting is part of an inheritance chain. We do not allow these
17695  * statements to be executed in these cases as we might have undefined behavior, such as trying to update a
17696  * column that belongs to a child for a duplicate key in the parent table that does not have that column. */
17697 
17698  if (statement->info.insert.do_replace || statement->info.insert.odku_assignments != NULL)
17699  {
17700  int allowed = 0;
17701 
17702  error = is_replace_or_odku_allowed ((*class_)->info.name.db_object, &allowed);
17703  if (error != NO_ERROR)
17704  {
17705  ASSERT_ERROR ();
17706  goto exit;
17707  }
17708 
17709  if (!allowed)
17710  {
17712  ASSERT_ERROR_AND_SET (error);
17713  goto exit;
17714  }
17715  }
17716 
17717  /* fetch the class for instance write purpose - IX_LOCK */
17718  if (!locator_fetch_class ((*class_)->info.name.db_object, DB_FETCH_CLREAD_INSTWRITE))
17719  {
17720  ASSERT_ERROR_AND_SET (error);
17721  goto exit;
17722  }
17723 
17724 exit:
17725  return error;
17726 }
static void do_clear_insert_values(PARSER_CONTEXT *parser, PT_NODE *insert_statement)
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
int au_check_serial_authorization(MOP serial_object)
static int set_iso_level(PARSER_CONTEXT *parser, DB_TRAN_ISOLATION *tran_isolation, bool *async_ws, PT_NODE *statement, const DB_VALUE *level)
LC_FETCH_VERSION_TYPE
Definition: locator.h:178
MIN_MAX_COLUMN_INFO min_max_val
Definition: dbtype_def.h:867
DB_C_FLOAT db_get_float(const DB_VALUE *value)
#define ER_REGU_SYSTEM
Definition: error_code.h:193
int do_replicate_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
int do_check_merge_trigger(PARSER_CONTEXT *parser, PT_NODE *statement, PT_DO_FUNC *do_func)
OUTPTR_LIST * outptr_list
Definition: xasl.h:968
PT_GET_OPT_LVL_INFO get_opt_lvl
Definition: parse_tree.h:3302
PT_NODE * next
Definition: parse_tree.h:3447
#define SERIAL_ATTR_CLASS_NAME
int tr_set_depth(int depth)
PT_NAME_INFO name
Definition: parse_tree.h:3318
#define RESET_HOST_VARIABLES_IF_INTERNAL_STATEMENT(parser_)
Definition: parse_tree.h:539
struct db_value DB_VALUE
Definition: dbtype_def.h:1079
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
int tran_system_savepoint(const char *savept_name)
PT_NODE * pt_find_spec_in_statement(PARSER_CONTEXT *parser, const PT_NODE *stmt, const PT_NODE *name)
bool classobj_has_unique_constraint(SM_CONSTRAINT *constraints)
PT_MISC_TYPE format
Definition: parse_tree.h:3214
#define PT_NODE_TR_EVENT_TYPE(node)
int db_make_datetime(DB_VALUE *value, const DB_DATETIME *datetime)
unsigned execute_with_commit_allowed
Definition: parse_tree.h:2348
int do_drop_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_VALUE val
Definition: dbtype_def.h:1092
#define ER_TP_CANT_COERCE
Definition: error_code.h:250
#define CHECK_MODIFICATION_ERROR()
Definition: db.h:121
PT_EVENT_TYPE event_type
Definition: parse_tree.h:2176
PT_ATTACH_INFO attach
Definition: parse_tree.h:3271
int db_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const DB_DOMAIN *desired_domain)
Definition: db_macro.c:1779
#define NO_ERROR
Definition: error_code.h:46
PT_UNION_INFO union_
Definition: parse_tree.h:2782
int do_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned dont_collect_exec_stats
Definition: parse_tree.h:3621
#define SERIAL_ATTR_OWNER
#define AU_DISABLE(save)
Definition: authenticate.h:106
int thread_kill_or_interrupt_tran(int *tran_index_list, int num_tran_index, bool is_dba_group_member, bool interrupt_only, int *num_killed)
int do_execute_do(PARSER_CONTEXT *parser, PT_NODE *statement)
bool pt_recompile_for_limit_optimizations(PARSER_CONTEXT *parser, PT_NODE *statement, int xasl_flag)
PT_METHOD_CALL_INFO method_call
Definition: parse_tree.h:3316
CST_ITEM_ENUM
int do_remove_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
int db_2pc_prepare_to_commit_transaction(int global_transaction_id)
Definition: db_admin.c:1426
int tr_find_event_triggers(DB_TRIGGER_EVENT event, DB_OBJECT *class_mop, const char *attribute, bool active, DB_OBJLIST **list)
struct db_value_list * next
Definition: dbtype_def.h:1091
static int delete_object_tuple(DB_OBJECT *obj)
PT_NODE * class_specs
Definition: parse_tree.h:2332
SERVER_PREFERENCE
PT_UPDATE_INFO update
Definition: parse_tree.h:3353
int do_scope(PARSER_CONTEXT *parser, PT_NODE *statement)
static int update_class_attributes(PARSER_CONTEXT *parser, PT_NODE *statement)
int do_alter_serial(PARSER_CONTEXT *parser, PT_NODE *statement)
int sm_att_id(MOP classop, const char *name)
bool ws_has_updated(void)
Definition: work_space.c:2536
PT_MERGE_INFO merge
Definition: parse_tree.h:3315
unsigned server_update
Definition: parse_tree.h:2881
UINTPTR id
Definition: parse_tree.h:2144
char * sql_user_text
Definition: parse_tree.h:3444
bool sm_att_auto_increment(MOP classop, const char *name)
PT_RENAME_INFO rename
Definition: parse_tree.h:3327
static int do_insert_at_server(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_MISC_TYPE schema
Definition: parse_tree.h:2354
PT_CHECK_OPTION_INFO check_option
Definition: parse_tree.h:3276
int do_get_serial_cached_num(int *cached_num, MOP serial_obj)
#define PT_MERGE_INFO_HAS_UNIQUE
Definition: parse_tree.h:2946
XASL_NODE_HEADER * xasl_header
Definition: xasl.h:611
int do_check_update_trigger(PARSER_CONTEXT *parser, PT_NODE *statement, PT_DO_FUNC *do_func)
#define MSGCAT_RUNTIME_RT_SERIAL_NOT_DEFINED
PT_NODE * attr_name
Definition: parse_tree.h:1858
static const char * get_savepoint_name_from_db_value(DB_VALUE *val)
DB_VALUE_COMPARE_RESULT tp_value_compare(const DB_VALUE *value1, const DB_VALUE *value2, int allow_coercion, int total_order)
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
unsigned is_autoincrement_set
DB_OBJECT * object
Definition: parse_tree.h:2864
static int do_replace_into(PARSER_CONTEXT *parser, DB_OTMPL *tmpl, PT_NODE *spec, PT_NODE *class_specs)
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
#define CACHE_TIME_RESET(T)
Definition: cache_time.h:40
#define ASSERT_ERROR()
DB_OBJLIST * inheritance
Definition: class_object.h:718
int do_drop_session_variables(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * into_list
Definition: parse_tree.h:2771
#define AU_SAVE_AND_ENABLE(save)
Definition: authenticate.h:119
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
int pt_resolve_default_value(PARSER_CONTEXT *parser, PT_NODE *name)
QFILE_TUPLE_VALUE_TYPE_LIST type_list
Definition: query_list.h:428
PT_NODE * assignment
Definition: parse_tree.h:2861
#define ER_INVALID_PARTITION_REQUEST
Definition: error_code.h:1123
QUERY_ID query_id
Definition: query_list.h:438
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
int do_set_timezone(PARSER_CONTEXT *parser, PT_NODE *statement)
int do_drop_variable(PARSER_CONTEXT *parser, PT_NODE *stmt)
PT_NODE * spec
Definition: parse_tree.h:3182
int do_prepare_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
int do_reset_auto_increment_serial(MOP serial_obj)
int tp_value_domain_name(const DB_VALUE *value, char *buffer, int maxlen)
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2339
int do_check_delete_trigger(PARSER_CONTEXT *parser, PT_NODE *statement, PT_DO_FUNC *do_func)
static int build_xasl_for_server_delete(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * val
Definition: parse_tree.h:2837
void tran_get_tran_settings(int *lock_wait_in_msecs, TRAN_ISOLATION *tran_isolation, bool *async_ws)
DB_OBJECT * db_real_instance(DB_OBJECT *obj)
Definition: db_virt.c:247
#define MSGCAT_SEMANTIC_SERIAL_CACHED_NUM_INVALID_RANGE
PT_SERIAL_INFO serial
Definition: parse_tree.h:3334
XASL_NODE * pt_to_insert_xasl(PARSER_CONTEXT *parser, PT_NODE *statement)
char * MOBJ
Definition: work_space.h:174
#define PT_TR_TARGET_CLASS(target)
bool tr_get_execution_state(void)
int db_savepoint_transaction_internal(const char *savepoint_name)
Definition: db_admin.c:1166
static void unlink_list(PT_NODE *list)
#define MSGCAT_SEMANTIC_SERIAL_MIN_VAL_UNDERFLOW
int execute_query(const XASL_ID *xasl_id, QUERY_ID *query_idp, int var_cnt, const DB_VALUE *varptr, QFILE_LIST_ID **list_idp, QUERY_FLAG flag, CACHE_TIME *clt_cache_time, CACHE_TIME *srv_cache_time)
Definition: query_cl.c:105
bool obt_Last_insert_id_generated
static int do_select_internal(PARSER_CONTEXT *parser, PT_NODE *statement, bool for_ins_upd)
void dbmeth_print(DB_OBJECT *self, DB_VALUE *result, DB_VALUE *msg)
int do_savepoint(PARSER_CONTEXT *parser, PT_NODE *statement)
int get_index_size_of_value(const DB_VALUE *value) const
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
int do_execute_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_MISC_TYPE
Definition: parse_tree.h:983
#define PT_ERROR(parser, node, msg)
Definition: parse_tree.h:54
int do_call_method(PARSER_CONTEXT *parser, PT_NODE *statement)
int qmgr_end_query(QUERY_ID query_id)
PT_NODE * mq_translate(PARSER_CONTEXT *parser, PT_NODE *volatile node)
char * intl_mbs_chr(const char *mbs, wchar_t wc)
Definition: intl_support.c:149
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)
static int insert_local(PARSER_CONTEXT *parser, PT_NODE *statement)
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 db_make_bigint(DB_VALUE *value, const DB_BIGINT num)
int db_get_int(const DB_VALUE *value)
#define MSGCAT_RUNTIME_SERIAL_S_SERIAL_I
#define ER_QPROC_DB_SERIAL_NOT_FOUND
Definition: error_code.h:964
int( PT_DO_FUNC)(PARSER_CONTEXT *, PT_NODE *)
int sm_update_all_statistics(bool with_fullscan)
PT_NODE * into_list
Definition: parse_tree.h:3164
void obt_begin_insert_values(void)
PT_NODE * where
Definition: parse_tree.h:2337
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
PT_NODE * trigger_priority
Definition: parse_tree.h:1843
PT_NODE * xaction_modes
Definition: parse_tree.h:2802
PT_NODE * assignment
Definition: parse_tree.h:2928
PT_NODE * charset_node
Definition: parse_tree.h:2955
int do_get_stats(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_C_DOUBLE db_get_double(const DB_VALUE *value)
#define ER_FAILED
Definition: error_code.h:47
REGU_VARIABLE_LIST next
Definition: regu_var.hpp:221
int do_rename(const PARSER_CONTEXT *parser, const PT_NODE *statement)
#define AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH
Definition: transform.h:179
int obt_populate_known_arguments(OBJ_TEMPLATE *template_ptr)
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
int do_set_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
int csession_reset_cur_insert_id(void)
int do_prepare_to_commit(PARSER_CONTEXT *parser, PT_NODE *statement)
int n_btstats
Definition: statistics.h:80
SM_CLASS_CONSTRAINT * classobj_find_cons_primary_key(SM_CLASS_CONSTRAINT *cons_list)
int db_set_suppress_repl_on_transaction(int set)
Definition: db_admin.c:1460
PARSER_VARCHAR * pt_print_db_value(PARSER_CONTEXT *parser, const struct db_value *val)
static char * extract_att_name(const char *str)
#define SERIAL_ATTR_COMMENT
PT_HINT_ENUM hint
Definition: parse_tree.h:2340
PT_NODE * search_cond
Definition: parse_tree.h:2925
#define MSGCAT_SEMANTIC_SERIAL_START_VAL_INVALID
PT_GET_XACTION_INFO get_xaction
Definition: parse_tree.h:3305
DB_FETCH_MODE cursor_set_prefetch_lock_mode(CURSOR_ID *cursor_id_p, DB_FETCH_MODE mode)
Definition: cursor.c:1267
PT_MISC_TYPE option
Definition: parse_tree.h:2301
int do_set_xaction(PARSER_CONTEXT *parser, PT_NODE *statement)
int cursor_next_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1482
TP_DOMAIN * domain
Definition: class_object.h:444
union xasl_node::@155 proc
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
void qo_set_optimization_param(void *, QO_PARAM,...)
Definition: query_graph.c:316
PT_HINT_ENUM hint
Definition: parse_tree.h:2074
unsigned is_xasl_pinned_reference
Definition: parse_tree.h:3616
QUERY_TRACE_FORMAT format
Definition: parse_tree.h:3519
PT_NODE * pt_get_select_list(PARSER_CONTEXT *parser, PT_NODE *query)
Definition: query_result.c:404
PT_NODE * arg2
Definition: parse_tree.h:2664
int db_value_clone(DB_VALUE *src, DB_VALUE *dest)
Definition: db_macro.c:1564
#define OR_BUF_INIT(buf, data, size)
SM_CONSTRAINT_TYPE
Definition: class_object.h:274
#define PT_NODE_PRINT_TO_ALIAS(p, n, c)
Definition: parse_tree.h:578
#define PT_NODE_SR_INCREMENT_VAL(node)
#define MSGCAT_RUNTIME_XACT_INVALID_ISO_LVL_MSG
void pt_reset_error(PARSER_CONTEXT *parser)
#define IS_INVALIDATE_ACTION_STATEMENT(statement)
void tr_abort(TR_STATE *state)
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
PT_NODE * upd_col_name
SM_PARTITION * partition
Definition: class_object.h:760
int db_set_system_parameters(const char *data)
Definition: db_admin.c:2682
#define ASSERT_ERROR_AND_SET(error_code)
unsigned dont_prt_long_string
Definition: parse_tree.h:3606
static int check_trigger(DB_TRIGGER_EVENT event, PT_DO_FUNC *do_func, PARSER_CONTEXT *parser, PT_NODE *statement)
static int map_iso_levels(PARSER_CONTEXT *parser, PT_NODE *statement, DB_TRAN_ISOLATION *tran_isolation, PT_NODE *node)
void pt_record_error(PARSER_CONTEXT *parser, int stmt_no, int line_no, int col_no, const char *msg, const char *context)
#define SERIAL_ATTR_CACHED_NUM
void tz_get_session_tz_region(TZ_REGION *tz_region)
Definition: tz_support.c:767
#define assert_release(e)
Definition: error_manager.h:96
static int make_cst_item_value(DB_OBJECT *obj, const char *str, DB_VALUE *db_val)
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
#define SM_MAX_IDENTIFIER_LENGTH
PT_NODE * with
Definition: parse_tree.h:2075
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
int do_drop_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_NODE * spec
Definition: parse_tree.h:2859
#define MSGCAT_MVCC_RUNTIME_XACT_ISO_LVL_MSG
union pt_plan_trace_info::@133 trace
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
int db_is_any_class(MOP obj)
Definition: db_info.c:356
int do_select(PARSER_CONTEXT *parser, PT_NODE *statement)
int pt_is_ddl_statement(const PT_NODE *node)
DB_CONSTRAINT * db_get_constraints(DB_OBJECT *obj)
Definition: db_info.c:1909
static int delete_real_class(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
OBJ_TEMPASSIGN ** assignments
int do_rollback(PARSER_CONTEXT *parser, PT_NODE *statement)
int tr_rename_trigger(DB_OBJECT *trigger_object, const char *name, bool call_from_api)
static int check_timeout_value(PARSER_CONTEXT *parser, PT_NODE *statement, DB_VALUE *val)
int numeric_db_value_compare(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
static int has_unique_constraint(DB_OBJECT *mop)
int tr_get_depth(void)
struct pt_query_info::@123 flag
static double get_priority(PARSER_CONTEXT *parser, PT_NODE *node)
static int select_delete_list(PARSER_CONTEXT *parser, QFILE_LIST_ID **result_p, PT_NODE *delete_stmt)
#define ER_AUTO_INCREMENT_NEWVAL_MUST_LT_MAXVAL
Definition: error_code.h:1316
bool au_is_dba_group_member(MOP user)
static int update_savepoint_number
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
char * info
Definition: replication.h:54
#define PT_IS_INSERT_VALUE_NODE(n)
Definition: parse_tree.h:333
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
PT_EXECUTE_INFO execute
Definition: parse_tree.h:3297
#define PT_NODE_COND(node)
#define PT_TR_TARGET_ATTR(target)
#define SM_IS_CONSTRAINT_UNIQUE_FAMILY(c)
Definition: class_object.h:111
int do_execute_select(PARSER_CONTEXT *parser, PT_NODE *statement)
static int do_create_midxkey_for_constraint(DB_OTMPL *tmpl, SM_CLASS_CONSTRAINT *constraint, DB_VALUE *key)
int sm_flush_and_decache_objects(MOP obj, int decache)
PT_SPEC_FLAG
Definition: parse_tree.h:1517
#define PT_NODE_COND_TIME(node)
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
bool tran_was_latest_query_ended(void)
#define OID_SET_NULL(oidp)
Definition: oid.h:85
#define MSGCAT_RUNTIME_PARM_IS_NOT_SET
void pt_exit_packing_buf(void)
PT_NODE * class_specs
Definition: parse_tree.h:2062
int mq_evaluate_expression_having_serial(PARSER_CONTEXT *parser, PT_NODE *expr, DB_VALUE *values, int values_count, DB_OBJECT *object, UINTPTR spec_id)
int mq_evaluate_check_option(PARSER_CONTEXT *parser, PT_NODE *check_where, DB_OBJECT *object, PT_NODE *view_class)
int do_alter(PARSER_CONTEXT *parser, PT_NODE *alter)
void sm_downcase_name(const char *name, char *buf, int maxlen)
PT_SCOPE_INFO scope
Definition: parse_tree.h:3333
KILLSTMT_TYPE kill_type
Definition: parse_tree.h:2821
bool do_class_attrs
Definition: parse_tree.h:2932
int do_get_xaction(PARSER_CONTEXT *parser, PT_NODE *statement)
#define cursor_free_self_list_id(list_id)
Definition: cursor.h:108
TP_DOMAIN * tp_domain_resolve_value(const DB_VALUE *val, TP_DOMAIN *dbuf)
int do_update_auto_increment_serial_on_rename(MOP serial_obj, const char *class_name, const char *att_name)
bool is_xasl_pinned_reference
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
#define TR_LOWEST_PRIORITY
#define ER_TR_TRIGGER_NOT_FOUND
Definition: error_code.h:592
PT_NODE * class_
Definition: parse_tree.h:2898
struct pt_merge_info::@125 update
#define CAST_STRLEN
Definition: porting.h:470
DB_OBJECT * dbt_finish_object(DB_OTMPL *def)
Definition: db_obj.c:560
#define ER_QPROC_SERIAL_ALREADY_EXIST
Definition: error_code.h:966
#define AU_RESTORE(save)
Definition: authenticate.h:133
unsigned int custom_print
Definition: parse_tree.h:3556
TP_DOMAIN * tp_domain_copy(const TP_DOMAIN *domain, bool check_cache)
#define PT_IS_NULL_NODE(e)
Definition: parse_tree.h:122
enum lc_prefetch_flags LC_PREFETCH_FLAGS
Definition: locator.h:339
static bool truncate_need_repl_log(PT_NODE *statement)
int tz_conv_tz_time_w_zone_name(const DB_TIME *time_source, const char *source_zone, int len_source, const char *dest_zone, int len_dest, DB_TIME *time_dest)
Definition: tz_support.c:1528
XASL_NODE * update_xasl
Definition: xasl.h:438
unsigned is_auto_commit
Definition: parse_tree.h:3624
int tr_prepare_statement(TR_STATE **state_p, DB_TRIGGER_EVENT event, DB_OBJECT *class_mop, int attcount, const char **attnames)
struct sm_class_constraint * next
Definition: class_object.h:530
int numeric_db_value_coerce_to_num(DB_VALUE *src, DB_VALUE *dest, DB_DATA_STATUS *data_status)
int SHA1Compute(const unsigned char *message_array, size_t length, SHA1Hash *hash)
Definition: sha1.c:372
TP_DOMAIN tp_Integer_domain
int pt_append_omitted_on_update_expr_assignments(PARSER_CONTEXT *parser, PT_NODE *assigns, PT_NODE *from)
int er_errid(void)
static int is_server_update_allowed(PARSER_CONTEXT *parser, PT_NODE **non_null_attrs, int *has_uniques, int *const server_allowed, const PT_NODE *statement)
int do_get_optimization_param(PARSER_CONTEXT *parser, PT_NODE *statement)
#define MSGCAT_RUNTIME_REPREAD_S_READCOM_I
PT_NODE * insert_mode
Definition: parse_tree.h:2343
static int update_object_tuple(PARSER_CONTEXT *parser, CLIENT_UPDATE_INFO *assigns, int assigns_count, CLIENT_UPDATE_CLASS_INFO *upd_classes_info, int classes_cnt, const int turn_off_unique_check, const int turn_off_serializable_conflict_check, UPDATE_TYPE update_type, bool should_delete)
#define MSGCAT_RUNTIME_RT_SERIAL_ALTER_NOT_ALLOWED
void db_string_free(char *string)
Definition: db_admin.c:2596
int tran_abort(void)
PT_NODE_LIST_INFO node_list
Definition: parse_tree.h:3320
#define OR_MULTI_BOUND_BIT_BYTES(count)
void dbt_abort_object(DB_OTMPL *def)
Definition: db_obj.c:616
#define bool
Definition: dbi_compat.h:31
PT_NODE * into_var
Definition: parse_tree.h:2900
int numeric_db_value_sub(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
PT_NODE * pt_to_merge_update_query(PARSER_CONTEXT *parser, PT_NODE *select_list, PT_MERGE_INFO *info)
static int delete_savepoint_number
PT_REMOVE_TRIGGER_INFO remove_trigger
Definition: parse_tree.h:3326
static int do_insert_template(PARSER_CONTEXT *parser, DB_OTMPL **otemplate, PT_NODE *statement, const char **savepoint_name, int *row_count_ptr)
int do_merge(PARSER_CONTEXT *parser, PT_NODE *statement)
#define PT_MERGE_INFO_INSERT_ONLY
Definition: parse_tree.h:2948
int tz_conv_tz_datetime_w_region(const DB_DATETIME *src_dt, const TZ_REGION *src_tz_region, const TZ_REGION *dest_tz_region, DB_DATETIME *dest_dt, TZ_ID *src_tz_id_out, TZ_ID *dest_tz_id_out)
Definition: tz_support.c:3812
PT_ATTACH_INFO prepare_to_commit
Definition: parse_tree.h:3324
int do_create_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
CST_ITEM_ENUM item
static void do_send_plan_trace_to_session(PARSER_CONTEXT *parser)
PT_MISC_TYPE option
Definition: parse_tree.h:2287
int tr_get_trace(void)
HFID * sm_get_ch_heap(MOP classmop)
int pt_split_delete_stmt(PARSER_CONTEXT *parser, PT_NODE *delete_stmt)
enum tp_domain_status TP_DOMAIN_STATUS
#define WS_ISDIRTY(mop)
Definition: work_space.h:259
const char * pt_show_misc_type(PT_MISC_TYPE p)
#define er_log_debug(...)
int db_timestamp_encode_sys(const DB_DATE *date, const DB_TIME *timeval, DB_TIMESTAMP *utime, TZ_ID *dest_tz_id)
Definition: db_date.c:617
PT_NODE * pt_find_node_type_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void obt_retain_after_finish(OBJ_TEMPLATE *template_ptr)
#define SERIAL_ATTR_NAME
#define PT_NODE_ACTION(node)
#define IS_PRINT_ACTION_STATEMENT(statement)
PT_NODE * tran_id_list
Definition: parse_tree.h:2822
PT_NODE * attr_list
Definition: parse_tree.h:2333
int do_drop(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_VALUE * host_variables
Definition: parse_tree.h:3560
PT_NODE * spec_list
Definition: parse_tree.h:2097
void prm_set_integer_value(PARAM_ID prm_id, int value)
int tr_drop_trigger(DB_OBJECT *obj, bool call_from_api)
DB_OBJECT * virt_object
Definition: parse_tree.h:2548
UPDATE_PROC_NODE update
Definition: xasl.h:1022
int tr_before(TR_STATE *state)
int ml_find(DB_OBJLIST *list, MOP mop)
Definition: work_space.c:4465
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
static int extract_bt_idx(const char *str)
PT_NODE * class_specs
Definition: parse_tree.h:2860
XASL_NODE_HEADER header
Definition: xasl.h:951
int do_update_stats(PARSER_CONTEXT *parser, PT_NODE *statement)
#define AU_ALTER
Definition: authenticate.h:73
#define ER_AUTO_INCREMENT_STARTVAL_MUST_LT_MAXVAL
Definition: error_code.h:1163
#define SET_HOST_VARIABLES_IF_INTERNAL_STATEMENT(parser_)
Definition: parse_tree.h:528
PT_NODE * data_type
Definition: parse_tree.h:3453
static PT_NODE * do_create_odku_stmt(PARSER_CONTEXT *parser, PT_NODE *insert)
int db_attribute_is_non_null(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1355
PT_NODE * del_stmt_list
Definition: parse_tree.h:2073
#define ER_AU_ALTER_FAILURE
Definition: error_code.h:222
struct parser_context::@134 flag
static int update_object_by_oid(PARSER_CONTEXT *parser, PT_NODE *statement, UPDATE_TYPE update_type)
static int do_vacuum(PARSER_CONTEXT *parser, PT_NODE *statement)
int do_prepare_merge(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_DOT_INFO dot
Definition: parse_tree.h:3287
#define ER_DO_UNDEFINED_CST_ITEM
Definition: error_code.h:1040
unsigned abort
Definition: parse_tree.h:3603
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
DB_ELO * db_get_elo(const DB_VALUE *value)
int pt_associate_label_with_value_check_reference(const char *label, DB_VALUE *val)
#define ERROR0(error, code)
Definition: error_manager.h:48
int db_elo_delete(DB_ELO *elo)
Definition: db_elo.c:115
bool pt_false_where(PARSER_CONTEXT *parser, PT_NODE *statement)
static int update_real_class(PARSER_CONTEXT *parser, PT_NODE *statement, bool savepoint_started)
#define MSGCAT_SEMANTIC_SERIAL_INC_VAL_INVALID
#define PT_NODE_SR_CACHED_NUM_VAL(node)
static int check_missing_non_null_attrs(const PARSER_CONTEXT *parser, const PT_NODE *spec, PT_NODE *attr_list, const bool has_default_values_list)
static int insert_subquery_results(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *values_list, PT_NODE *class_, const char **savepoint_name)
char * intl_mbs_ncpy(char *mbs1, const char *mbs2, size_t n)
Definition: intl_support.c:489
PT_NODE * non_null_attrs
Definition: parse_tree.h:2344
CLASS_STATS * sm_get_statistics_force(MOP classop)
SERVER_INSERT_ALLOWED server_allowed
Definition: parse_tree.h:2347
#define PT_TR_ATTR_NAME(attr)
int dbt_put_internal(DB_OTMPL *def, const char *name, DB_VALUE *value)
Definition: db_obj.c:670
int do_truncate(PARSER_CONTEXT *parser, PT_NODE *statement)
TP_DOMAIN tp_Double_domain
#define CT_SERIAL_NAME
Definition: transform.h:135
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
PT_KILLSTMT_INFO killstmt
Definition: parse_tree.h:3361
int intl_identifier_lower(const char *src, char *dst)
int tr_set_status(DB_OBJECT *trigger_object, DB_TRIGGER_STATUS status, bool call_from_api)
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
PT_NODE * collation_node
Definition: parse_tree.h:2956
PT_TYPE_ENUM type_enum
Definition: parse_tree.h:3457
LOCK
unsigned force_check_not_null
void pt_report_to_ersys(const PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type)
Definition: query_result.c:287
MIN_MAX_COLUMN_TYPE type
Definition: dbtype_def.h:857
int do_execute_update(PARSER_CONTEXT *parser, PT_NODE *statement)
const char * lang_get_collation_name(const int coll_id)
PT_NODE * indexed_class
Definition: parse_tree.h:1927
static int delete_list_by_oids(PARSER_CONTEXT *parser, PT_NODE *statement, QFILE_LIST_ID *list_id, bool savepoint_started)
const char * mq_generate_name(PARSER_CONTEXT *parser, const char *root, int *version)
enum query_trace_format QUERY_TRACE_FORMAT
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
#define COLL_NAME_SIZE
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
#define ER_PT_SEMANTIC
Definition: error_code.h:581
unsigned char bytes[1]
Definition: parse_tree.h:3431
DB_OBJECT * tr_find_trigger(const char *name)
const int REGU_VARIABLE_UPD_INS_LIST
Definition: regu_var.hpp:166
char oids_included
Definition: parse_tree.h:2750
#define PT_ERRORmf3(parser, node, setNo, msgNo, arg1, arg2, arg3)
Definition: parse_tree.h:66
unsigned use_auto_commit
Definition: parse_tree.h:3485
void port_close_memstream(FILE *fp, char **ptr, size_t *sizeloc)
Definition: porting.c:2220
static int insert_savepoint_number
int do_set_optimization_param(PARSER_CONTEXT *parser, PT_NODE *statement)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
int tran_reset_wait_times(int wait_in_msecs)
MOP Au_dba_user
Definition: authenticate.c:334
unsigned int DB_TIMESTAMP
Definition: dbtype_def.h:759
#define PT_MERGE_INFO_SERVER_OP
Definition: parse_tree.h:2947
int db_unix_timestamp(const DB_VALUE *src_date, DB_VALUE *result_timestamp)
void pt_free_statement_xasl_id(PT_NODE *statement)
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
PT_NODE * arg1
Definition: parse_tree.h:2663
int do_execute_session_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
void qo_do_auto_parameterize(PARSER_CONTEXT *parser, PT_NODE *where)
CLIENT_UPDATE_CLASS_INFO * cls_info
#define PT_IS_SELECT(n)
Definition: parse_tree.h:284
int pt_check_grammar_charset_collation(PARSER_CONTEXT *parser, PT_NODE *charset_node, PT_NODE *coll_node, int *charset, int *coll_id)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
PT_ALTER_INFO alter
Definition: parse_tree.h:3268
#define ER_INCREMENT_VALUE_CANNOT_BE_ZERO
Definition: error_code.h:1144
Definition: db_set.h:35
static PT_NODE * test_check_option(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_NODE * arg2
Definition: parse_tree.h:2198
PT_MISC_TYPE instances
Definition: parse_tree.h:2355
int num_assigns
Definition: xasl.h:372
int do_prepare_delete(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE *parent)
static int update_check_for_constraints(PARSER_CONTEXT *parser, int *has_unique, PT_NODE **not_nulls, const PT_NODE *statement)
#define PT_IS_VACUUM_NODE(n)
Definition: parse_tree.h:497
int do_execute_insert(PARSER_CONTEXT *parser, PT_NODE *statement)
int db_value_put_encoded_time(DB_VALUE *value, const DB_TIME *time)
Definition: db_macro.c:1357
#define ER_QPROC_SERIAL_NOT_FOUND
Definition: error_code.h:965
DB_OBJECT * db_object
Definition: parse_tree.h:2546
int obt_quit(OBJ_TEMPLATE *template_ptr)
#define DB_MAX_NUMERIC_PRECISION
Definition: dbtype_def.h:522
static int check_serial_invariants(SERIAL_INVARIANT *invariants, int num_invariants, int *ret_msg_id)
#define SERIAL_ATTR_MAX_VAL
static int init_update_data(PARSER_CONTEXT *parser, PT_NODE *statement, CLIENT_UPDATE_INFO **assigns_data, int *assigns_count, CLIENT_UPDATE_CLASS_INFO **cls_data, int *cls_count, DB_VALUE **values, int *values_cnt, bool has_delete)
#define PT_ERRORmf2(parser, node, setNo, msgNo, arg1, arg2)
Definition: parse_tree.h:65
int tran_abort_upto_system_savepoint(const char *savepoint_name)
#define XASL_ID_COPY(X1, X2)
Definition: xasl.h:562
#define MSGCAT_RUNTIME_OUT_OF_MEMORY
XASL_NODE * pt_to_delete_xasl(PARSER_CONTEXT *parser, PT_NODE *statement)
#define assert(x)
#define MAX_LEN
void dbmeth_class_name(DB_OBJECT *self, DB_VALUE *result)
static void init_compile_context(PARSER_CONTEXT *parser)
#define PT_NODE_SR_MAX_VAL(node)
XASL_NODE * pt_to_update_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **non_null_attrs)
int tr_find_all_triggers(DB_OBJLIST **list)
void obt_set_force_flush(OBJ_TEMPLATE *template_ptr)
int sm_att_constrained(MOP classop, const char *name, SM_ATTRIBUTE_FLAG cons)
#define MSGCAT_SEMANTIC_SERIAL_MAX_VAL_OVERFLOW
char * pt_chop_trailing_dots(PARSER_CONTEXT *parser, const char *msg)
#define LANG_COERCIBLE_CODESET
#define OR_ENABLE_BOUND_BIT(bitptr, element)
PT_SPEC_FLAG flag
Definition: parse_tree.h:2155
static void get_activity_info(PARSER_CONTEXT *parser, DB_TRIGGER_ACTION *type, const char **source, PT_NODE *statement)
XASL_NODE * dptr_list
Definition: xasl.h:976
static void initialize_serial_invariant(SERIAL_INVARIANT *invariant, DB_VALUE val1, DB_VALUE val2, PT_OP_TYPE cmp_op, int val1_msgid, int val2_msgid, int error_type)
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)
int do_attach(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * pt_rewrite_to_auto_param(PARSER_CONTEXT *parser, PT_NODE *value)
#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)
static PT_NODE * make_vmops(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int do_rename_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
static char ** find_update_columns(int *count_ptr, PT_NODE *statement)
int sm_class_has_triggers(DB_OBJECT *classop, int *status_ptr, DB_TRIGGER_EVENT event_type)
PT_CREATE_TRIGGER_INFO create_trigger
Definition: parse_tree.h:3280
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)
int do_grant(const PARSER_CONTEXT *parser, const PT_NODE *statement)
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)
PT_NODE * odku_assignments
Definition: parse_tree.h:2341
static bool update_check_having_meta_attr(PARSER_CONTEXT *parser, PT_NODE *assignment)
char * db_get_user_and_host_name(void)
Definition: db_admin.c:1932
#define MSGCAT_SEMANTIC_METH_TARGET_NOT_OBJ
PT_MISC_TYPE trigger_status
Definition: parse_tree.h:1845
#define ER_IT_DATA_OVERFLOW
Definition: error_code.h:505
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
PT_SET_XACTION_INFO set_xaction
Definition: parse_tree.h:3341
#define MSGCAT_SET_PARSER_RUNTIME
PARSER_CONTEXT * parent_parser
int tp_domain_name(const TP_DOMAIN *domain, char *buffer, int maxlen)
DB_TYPE db_value_type(const DB_VALUE *value)
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
int jsp_call_stored_procedure(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: jsp_cl.c:326
int xasl_flag
Definition: xasl.h:69
int pt_get_one_tuple_from_list_id(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *vals, int cnt)
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
PT_NODE * pt_insert_value(PARSER_CONTEXT *parser, PT_NODE *node)
int do_prepare_update(PARSER_CONTEXT *parser, PT_NODE *statement)
#define SERIAL_ATTR_CYCLIC
unsigned is_desc
PT_NODE * method_name
Definition: parse_tree.h:2363
int sm_is_partitioned_class(MOP op)
const char * original
Definition: parse_tree.h:2544
PT_NODE * using_index
Definition: parse_tree.h:2064
static int do_create_serial_internal(MOP *serial_object, const char *serial_name, DB_VALUE *current_val, DB_VALUE *inc_val, DB_VALUE *min_val, DB_VALUE *max_val, const int cyclic, const int cached_num, const int started, const char *comment, const char *class_name, const char *att_name)
#define ER_QPROC_SERIAL_RANGE_OVERFLOW
Definition: error_code.h:967
int tran_commit(bool retain_lock)
int sm_update_statistics(MOP classop, bool with_fullscan)
#define ER_IT_UNKNOWN_VARIABLE
Definition: error_code.h:508
BTREE_SEARCH
int intl_identifier_casecmp(const char *str1, const char *str2)
PT_NODE * into_var
Definition: parse_tree.h:2335
bool tran_was_latest_query_committed(void)
#define PT_IS_HINT_NODE(n)
Definition: parse_tree.h:406
#define DB_INT32_MAX
Definition: dbtype_def.h:633
int prepare_query(COMPILE_CONTEXT *context, XASL_STREAM *stream)
Definition: query_cl.c:52
void pt_evaluate_tree_having_serial(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_value, int vals_cnt)
#define MSGCAT_RUNTIME_RESOURCES_EXHAUSTED
int pt_count_assignments(PARSER_CONTEXT *parser, PT_NODE *assignments)
Definition: parse_tree.c:1413
#define TM_TRAN_WAIT_MSECS()
UPDATE_ASSIGNMENT * assigns
Definition: xasl.h:373
PT_NODE * comment
Definition: parse_tree.h:1992
void db_free_attribute_descriptor(DB_ATTDESC *descriptor)
Definition: db_obj.c:835
PT_EVENT_TYPE
Definition: parse_tree.h:1272
static int update_at_server(PARSER_CONTEXT *parser, PT_NODE *from, PT_NODE *statement, PT_NODE **non_null_attrs, int has_uniques)
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
PT_DROP_SESSION_VAR_INFO drop_session_var
Definition: parse_tree.h:3289
int do_kill(PARSER_CONTEXT *parser, PT_NODE *statement)
int locator_flush_class(MOP class_mop)
Definition: locator_cl.c:5068
const char * db_error_string(int level)
Definition: db_admin.c:2116
int do_check_insert_trigger(PARSER_CONTEXT *parser, PT_NODE *statement, PT_DO_FUNC *do_func)
DB_TRAN_ISOLATION
Definition: dbtran_def.h:26
static enum scanner_mode mode
PT_NODE * parser_copy_tree(PARSER_CONTEXT *parser, const PT_NODE *tree)
unsigned do_cache
Definition: parse_tree.h:2763
static int merge_savepoint_number
PT_NODE * pt_semantic_type(PARSER_CONTEXT *parser, PT_NODE *tree, SEMANTIC_CHK_INFO *sc_info)
PT_EXECUTE_TRIGGER_INFO execute_trigger
Definition: parse_tree.h:3298
CLIENT_UPDATE_INFO * first_assign
#define ER_BLOCK_DDL_STMT
Definition: error_code.h:1384
int do_create_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
#define PT_NODE_SR_MIN_VAL(node)
DB_OBJECT * db_get_object(const DB_VALUE *value)
PT_NODE * from
Definition: parse_tree.h:2686
unsigned if_exists
Definition: parse_tree.h:1998
int db_abort_to_savepoint(const char *savepoint_name)
Definition: db_admin.c:1237
PT_ISOLATION_LVL_INFO isolation_lvl
Definition: parse_tree.h:3311
static int convert_speclist_to_objlist(DB_OBJLIST **triglist, PT_NODE *specnode)
int au_check_authorization(MOP op, DB_AUTH auth)
#define PT_IS_CONST(n)
Definition: parse_tree.h:364
MOP ws_class_mop(MOP mop)
Definition: work_space.c:2907
UINTPTR spec_id
Definition: parse_tree.h:2543
#define PT_IS_VALUE_NODE(n)
Definition: parse_tree.h:330
#define PT_NODE_TR_PRI(node)
DB_VALUE * db_value_copy(DB_VALUE *value)
Definition: db_macro.c:1537
PT_NODE * value_clauses
Definition: parse_tree.h:2938
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
QUERY_ID query_id
Definition: cursor.h:54
int locator_flush_replication_info(REPL_INFO *repl_info)
Definition: locator_cl.c:6869
#define PT_NODE_TR_NAME(node)
#define TP_DOMAIN_TYPE(dom)
void db_set_read_fetch_instance_version(LC_FETCH_VERSION_TYPE read_Fetch_Instance_Version)
Definition: db_vdb.c:3904
#define MSGCAT_RUNTIME_SERIAL_IS_AUTO_INCREMENT_OBJ
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
void pt_enter_packing_buf(void)
int db_get_attribute_descriptor(DB_OBJECT *obj, const char *attname, int class_attribute, int for_update, DB_ATTDESC **descriptor)
Definition: db_obj.c:763
#define MSGCAT_RUNTIME_DBT_PUT_ERROR
int db_datetime_to_timestamp(const DB_VALUE *src_datetime, DB_VALUE *result_timestamp)
DB_VALUE * db_value_create(void)
Definition: db_macro.c:1517
static QFILE_LIST_ID * get_select_list_to_update(PARSER_CONTEXT *parser, PT_NODE *from, PT_NODE *column_names, PT_NODE *column_values, PT_NODE *with, PT_NODE *where, PT_NODE *order_by, PT_NODE *orderby_for, PT_NODE *using_index, PT_NODE *class_specs, PT_NODE *update_stmt)
int tran_abort_only_client(bool is_server_down)
static PT_NODE * pt_append_odku_references(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void db_update_row_count_cache(const int row_count)
Definition: db_admin.c:2924
static void cleanup(int signo)
Definition: broker.c:717
PARSER_VARCHAR * str
Definition: parse_tree.h:3036
int locator_assign_all_permanent_oids(void)
Definition: locator_cl.c:6836
SP_PARSER_CTX * parser
PT_NODE * arg1
Definition: parse_tree.h:2197
PT_ATTR_DEF_INFO attr_def
Definition: parse_tree.h:3272
int do_check_internal_statements(PARSER_CONTEXT *parser, PT_NODE *statement, PT_DO_FUNC do_func)
#define NULL
Definition: freelistheap.h:34
#define pt_is_const_not_hostvar(n)
Definition: parse_tree.h:274
void obt_disable_serializable_conflict_checking(OBJ_TEMPLATE *template_ptr)
PT_GET_TRIGGER_INFO get_trigger
Definition: parse_tree.h:3304
int csession_set_session_variables(DB_VALUE *variables, const int count)
void db_value_print(const DB_VALUE *value)
Definition: db_macro.c:1663
const char * er_msg(void)
int tr_Current_depth
int do_update(PARSER_CONTEXT *parser, PT_NODE *statement)
struct pr_type * type
Definition: object_domain.h:76
PT_NODE * order_by
Definition: parse_tree.h:2875
CACHE_TIME cache_time
Definition: parse_tree.h:3458
#define LANG_COERCIBLE_COLL
DB_OBJECT * db_get_class(MOP obj)
Definition: db_info.c:589
PT_NODE * value_clauses
Definition: parse_tree.h:2334
unsigned recompile
Definition: parse_tree.h:3461
void tz_get_system_tz_region(TZ_REGION *tz_region)
Definition: tz_support.c:758
CUBRID_STMT_TYPE pt_node_to_cmd_type(PT_NODE *node)
Definition: parse_dbi.c:2736
#define ER_REGU_NOT_IMPLEMENTED
Definition: error_code.h:194
int db_drop(DB_OBJECT *obj)
Definition: db_obj.c:190
#define ER_OBJ_OBJECT_NOT_FOUND
Definition: error_code.h:873
if(extra_options)
Definition: dynamic_load.c:958
#define CACHE_TIME_EQ(T1, T2)
Definition: cache_time.h:37
PT_INDEX_INFO index
Definition: parse_tree.h:3308
unsigned has_trigger
Definition: parse_tree.h:2879
static int do_find_unique_constraint_violations(DB_OTMPL *tmpl, bool for_update, OID **oids, int *oids_count)
#define MSGCAT_RUNTIME_INVALID_AUTO_INCREMENT_ALTER
static DB_TRIGGER_TIME convert_misc_to_tr_time(const PT_MISC_TYPE pt_time)
int do_change_auto_increment_serial(PARSER_CONTEXT *const parser, MOP serial_obj, PT_NODE *node_new_val)
static int merge_mop_list_extension(DB_OBJLIST *new_objlist, DB_OBJLIST **list)
#define PT_VALUE_GET_BYTES(node)
Definition: parse_tree.h:250
#define PT_NODE_SR_CYCLIC(node)
struct pr_type * type
Definition: class_object.h:443
int sm_get_class_flag(MOP op, SM_CLASS_FLAG flag)
#define PT_NODE_SR_START_VAL(node)
PT_MISC_TYPE action_type
Definition: parse_tree.h:2845
int do_evaluate_default_expr(PARSER_CONTEXT *parser, PT_NODE *class_name)
#define MSGCAT_RUNTIME_NOT_ALLOWED_ACCESS_TO_PARTITION
const char * string
unsigned recompile_xasl_pinned
Definition: parse_tree.h:3620
static DB_TRIGGER_EVENT convert_event_to_tr_event(const PT_EVENT_TYPE ev)
void pt_end_query(PARSER_CONTEXT *parser, QUERY_ID query_id_self)
PT_CREATE_ENTITY_INFO create_entity
Definition: parse_tree.h:3279
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
PARSER_VARCHAR * pt_print_bytes(PARSER_CONTEXT *parser, const PT_NODE *node)
#define err(fd,...)
Definition: porting.h:431
int au_fetch_instance_force(MOP op, MOBJ *obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE fetch_version_type)
PT_NODE * trigger_spec_list
Definition: parse_tree.h:2113
int db_value_put_encoded_date(DB_VALUE *value, const DB_DATE *date)
Definition: db_macro.c:1383
bool tm_Use_OID_preflush
int sm_decache_instances_after_query_executed_with_commit(MOP class_mop)
#define TM_TRAN_READ_FETCH_VERSION()
#define DONT_DECACHE
Definition: locator_cl.h:49
void pt_null_etc(PT_NODE *node)
int tr_set_trace(bool trace)
int db_send_arglist(MOP obj, const char *name, DB_VALUE *returnval, DB_VALUE_LIST *args)
Definition: db_obj.c:417
#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
int ml_ext_add(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4877
static int do_check_for_empty_classes_in_delete(PARSER_CONTEXT *parser, PT_NODE *statement)
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
struct xasl_node * xasl
PT_NODE * pt_get_next_assignment(PT_ASSIGNMENTS_HELPER *ea)
Definition: parse_tree.c:1360
#define PT_NODE_TR_STATUS(node)
PT_NODE * arg1
Definition: parse_tree.h:2085
PT_QUERY_INFO query
Definition: parse_tree.h:3325
int numeric_db_value_mul(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
PT_TRIGGER_SPEC_LIST_INFO trigger_spec_list
Definition: parse_tree.h:3350
need_clear_type need_clear
Definition: dbtype_def.h:1084
PT_NODE * into_var
Definition: parse_tree.h:2162
PT_EVENT_TARGET_INFO event_target
Definition: parse_tree.h:3296
struct db_objlist * next
Definition: dbtype_def.h:442
char * db_get_user_name(void)
Definition: db_admin.c:1911
unsigned is_holdable
Definition: parse_tree.h:3615
int do_revoke(const PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_NODE * with
Definition: parse_tree.h:2878
PT_EVALUATE_INFO evaluate
Definition: parse_tree.h:3293
#define MAX_DOMAIN_NAME_SIZE
#define MAX_SERIAL_INVARIANT
static int insert_object_attr(const PARSER_CONTEXT *parser, DB_OTMPL *otemplate, DB_VALUE *value, PT_NODE *name, DB_ATTDESC *attr_desc)
int tr_after(TR_STATE *state)
PT_AUTO_INCREMENT_INFO auto_increment
Definition: parse_tree.h:3275
int db_is_deleted(DB_OBJECT *obj)
Definition: db_info.c:531
int sm_flush_objects(MOP obj)
int do_set_session_variables(PARSER_CONTEXT *parser, PT_NODE *statement)
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
PT_RENAME_TRIGGER_INFO rename_trigger
Definition: parse_tree.h:3328
#define cmp
Definition: mprec.h:351
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
#define MSGCAT_CATALOG_CUBRID
const char * text
Definition: parse_tree.h:3056
bool qo_need_skip_execution(void)
Definition: query_graph.c:297
int obj_set_shared(MOP op, const char *name, DB_VALUE *value)
static PT_NODE * do_check_insert_server_allowed(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int tran_flush_to_commit(void)
int vid_vobj_to_object(const DB_VALUE *vobj, DB_OBJECT **mop)
int db_2pc_attach_transaction(int global_transaction_id)
Definition: db_admin.c:1403
#define SERIAL_ATTR_CURRENT_VAL
PT_SET_NAMES_INFO set_names
Definition: parse_tree.h:3335
int db_make_time(DB_VALUE *value, const int hour, const int minute, const int second)
#define PT_NODE_SR_NO_CYCLIC(node)
bool is_stmt_based_repl_type(const PT_NODE *node)
SM_CONSTRAINT * constraints
Definition: class_object.h:454
DB_VALUE * pt_find_value_of_label(const char *label)
PT_NODE * pt_make_tuple_value_reference(PARSER_CONTEXT *parser, PT_NODE *name, PT_NODE *select_list, CURSOR_ID *cursor_p)
int tr_set_comment(DB_OBJECT *trigger_object, const char *comment, bool call_from_api)
int tran_internal_abort_upto_savepoint(const char *savepoint_name, SAVEPOINT_TYPE savepoint_type, bool client_decache_all_but_norealclasses)
#define MSGCAT_RUNTIME_REPREAD_S_REPREAD_I
int prepare_and_execute_query(char *stream, int stream_size, QUERY_ID *query_id, int var_cnt, DB_VALUE *varptr, QFILE_LIST_ID **result, QUERY_FLAG flag)
Definition: query_cl.c:152
TP_DOMAIN tp_Float_domain
static int do_on_duplicate_key_update(PARSER_CONTEXT *parser, DB_OTMPL *tpl, PT_NODE *update_stmt)
#define DB_SERIAL_MIN
#define SERIAL_ATTR_INCREMENT_VAL
int tran_reset_isolation(TRAN_ISOLATION isolation, bool async_ws)
int ws_mop_compare(MOP mop1, MOP mop2)
Definition: work_space.c:3144
#define OR_CLEAR_BOUND_BIT(bitptr, element)
int jsp_create_stored_procedure(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: jsp_cl.c:500
int locator_flush_instance(MOP mop)
Definition: locator_cl.c:5236
unsigned si_datetime
Definition: parse_tree.h:3464
PT_NODE * parser_append_node(PT_NODE *node, PT_NODE *list)
int tr_set_priority(DB_OBJECT *trigger_object, double priority, bool call_from_api)
struct db_object * op
Definition: dbtype_def.h:443
PT_NODE * check_where
Definition: parse_tree.h:2943
char * pt_short_print(PARSER_CONTEXT *parser, const PT_NODE *node)
DB_TRIGGER_TIME
Definition: dbtype_def.h:388
unsigned do_not_cache
Definition: parse_tree.h:2764
int ncolumns
Definition: dbtype_def.h:864
MOP Au_user
Definition: authenticate.c:343
SM_CLASS_CONSTRAINT * constraints
Definition: class_object.h:757
int csession_drop_session_variables(DB_VALUE *variables, const int count)
#define TP_IS_CHAR_TYPE(typeid)
PT_NODE * orderby_for
Definition: parse_tree.h:2876
#define ER_DO_INSERT_TOO_MANY
Definition: error_code.h:890
XASL_NODE * parser_generate_xasl(PARSER_CONTEXT *parser, PT_NODE *node)
PT_NODE * parser_new_node(PARSER_CONTEXT *parser, PT_NODE_TYPE node_type)
int set_put_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2719
static void error(const char *msg)
Definition: gencat.c:331
PT_SET_SYS_PARAMS_INFO set_sys_params
Definition: parse_tree.h:3338
bool tran_was_latest_query_aborted(void)
#define PT_NODE_MOVE_NUMBER_OUTERLINK(t, s)
Definition: parse_tree.h:572
COMPILE_CONTEXT context
Definition: parse_tree.h:3591
int db_make_float(DB_VALUE *value, const DB_C_FLOAT num)
int do_execute_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned is_click_counter
Definition: parse_tree.h:3477
unsigned int flags
Definition: class_object.h:459
#define PT_IS_HOSTVAR(n)
Definition: parse_tree.h:342
PT_NODE * check_where
Definition: parse_tree.h:2867
#define MSGCAT_RUNTIME_TIMEOUT_VALUE_MSG
TP_DOMAIN * tp_domain_construct(DB_TYPE domain_type, DB_OBJECT *class_obj, int precision, int scale, TP_DOMAIN *setdomain)
const unsigned char * pt_get_varchar_bytes(const PARSER_VARCHAR *string)
Definition: parse_tree.c:1089
int db_make_midxkey(DB_VALUE *value, DB_MIDXKEY *midxkey)
int do_set_names(PARSER_CONTEXT *parser, PT_NODE *statement)
static PT_NODE * do_set_insert_server_not_allowed(PARSER_CONTEXT *parser, PT_NODE *node, void *void_arg, int *continue_walk)
#define UNIQUE_SAVEPOINT_ALTER_TRIGGER
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2944
DB_OTMPL * dbt_create_object_internal(DB_OBJECT *classobj)
bool db_value_is_null(const DB_VALUE *value)
PT_UPDATE_STATS_INFO update_stats
Definition: parse_tree.h:3354
#define UNIQUE_SAVEPOINT_EXTERNAL_STATEMENT
#define PT_NODE_SR_NO_MAX(node)
#define AU_SELECT
Definition: authenticate.h:69
PT_NODE * old_name
Definition: parse_tree.h:2622
#define ARG_FILE_LINE
Definition: error_manager.h:44
DB_VALUE * variable
PT_NODE * auto_increment
Definition: parse_tree.h:1861
#define ER_AU_DBA_ONLY
Definition: error_code.h:204
static int tr_savepoint_number
#define MSGCAT_RUNTIME_ISO_LVL_SET_TO_MSG
PT_NODE * odku_non_null_attrs
Definition: parse_tree.h:2345
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
#define DB_BIGINT_MAX
Definition: dbtype_def.h:640
int repl_info_type
Definition: replication.h:55
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)
#define ER_INVALID_SERIAL_VALUE
Definition: error_code.h:987
void ws_decache(MOP mop)
Definition: work_space.c:2701
#define ER_REGU_NO_SPACE
Definition: error_code.h:192
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
PT_MISC_TYPE option
Definition: parse_tree.h:2809
const char * default_expr_format
Definition: dbtype_def.h:1206
#define MSGCAT_SEMANTIC_SERIAL_MIN_VAL_INVALID
#define DB_INT16_MAX
Definition: dbtype_def.h:630
BTREE_SEARCH btree_find_multi_uniques(OID *class_oid, int pruning_type, BTID *btids, DB_VALUE *keys, int count, SCAN_OPERATION_TYPE op_type, OID **oids, int *oids_count)
int locator_all_flush(void)
Definition: locator_cl.c:5457
PT_DROP_INFO drop
Definition: parse_tree.h:3288
unsigned int DB_TIME
Definition: dbtype_def.h:754
unsigned clt_cache_reusable
Definition: parse_tree.h:3467
#define AU_ENABLE(save)
Definition: authenticate.h:113
int db_abort_to_savepoint_internal(const char *savepoint_name)
Definition: db_admin.c:1210
PT_NODE * stmt
Definition: parse_tree.h:2679
LC_FIND_CLASSNAME locator_lockhint_classes(int num_classes, const char **many_classnames, LOCK *many_locks, int *need_subclasses, LC_PREFETCH_FLAGS *flags, int quit_on_errors, LOCK lock_rr_tran)
Definition: locator_cl.c:6260
BTREE_STATS * bt_stats
Definition: statistics.h:81
void insert_rewrite_names_in_value_clauses(PARSER_CONTEXT *parser, PT_NODE *insert_statement)
int buffer_size
Definition: xasl.h:614
int do_drop_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
int sm_update_all_catalog_statistics(bool with_fullscan)
static int is_server_insert_allowed(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * into
Definition: parse_tree.h:2923
int do_commit(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned int DB_DATE
Definition: dbtype_def.h:771
#define MSGCAT_SET_PARSER_SEMANTIC
PT_MISC_TYPE on_off
Definition: parse_tree.h:3213
int sm_class_has_unique_constraint(MOBJ classobj, MOP classop, bool check_subclasses, bool *has_unique)
static int do_set_pruning_type(PARSER_CONTEXT *parser, PT_NODE *spec, CLIENT_UPDATE_CLASS_INFO *cls)
PT_NODE * to_return_var
Definition: parse_tree.h:2366
int do_drop_serial(PARSER_CONTEXT *parser, PT_NODE *statement)
int intl_identifier_lower_string_size(const char *src)
DB_DATA_STATUS
PT_NODE * using_index
Definition: parse_tree.h:2863
static int is_replace_or_odku_allowed(DB_OBJECT *obj, int *allowed)
DB_VALUE sys_datetime
Definition: parse_tree.h:3580
unsigned server_delete
Definition: parse_tree.h:2077
#define free_and_init(ptr)
Definition: memory_alloc.h:147
struct pt_merge_info::@126 insert
#define strlen(s1)
Definition: intl_support.c:43
#define BTID_COPY(btid_ptr1, btid_ptr2)
#define MSGCAT_RUNTIME__CAN_NOT_EVALUATE
PT_COMMIT_WORK_INFO commit_work
Definition: parse_tree.h:3277
char * prm_get_string_value(PARAM_ID prm_id)
char * parser_print_tree_with_quotes(PARSER_CONTEXT *parser, const PT_NODE *node)
unsigned long_string_skipped
Definition: parse_tree.h:3607
PT_NODE * default_value
Definition: parse_tree.h:2553
DB_OBJECT * pt_check_user_owns_class(PARSER_CONTEXT *parser, PT_NODE *cls_ref)
#define STATS_WITH_FULLSCAN
Definition: statistics.h:34
SM_COMPONENT header
Definition: class_object.h:441
PT_NODE * pt_point(PARSER_CONTEXT *parser, const PT_NODE *in_tree)
int do_prepare_insert(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned si_tran_id
Definition: parse_tree.h:3465
int do_set_query_trace(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * attr_list
Definition: parse_tree.h:2937
const char * tz_get_system_timezone(void)
Definition: tz_support.c:749
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
PT_OP_TYPE
Definition: parse_tree.h:1320
int intl_mbs_ncasecmp(const char *mbs1, const char *mbs2, size_t n)
Definition: intl_support.c:441
int obj_inst_lock(MOP op, int for_write)
DB_DOMAIN * domain
Definition: dbtype_def.h:865
DB_TRIGGER_EVENT
Definition: dbtype_def.h:356
#define PT_NODE_TR_TARGET(node)
const int * db_constraint_asc_desc(DB_CONSTRAINT *constraint)
Definition: db_info.c:2070
int do_insert(PARSER_CONTEXT *parser, PT_NODE *root_statement)
static int update_object_attribute(PARSER_CONTEXT *parser, DB_OTMPL *otemplate, PT_NODE *name, DB_ATTDESC *attr_desc, DB_VALUE *value)
PT_SET_TIMEZONE_INFO set_timezone
Definition: parse_tree.h:3336
PT_ALTER_TRIGGER_INFO alter_trigger
Definition: parse_tree.h:3269
unsigned int date
Definition: dbtype_def.h:776
PT_TRACE_INFO trace
Definition: parse_tree.h:3360
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
int do_get_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
int log_get_mvcc_snapshot(void)
PT_NODE * pt_flush_classes(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
PT_MISC_TYPE option
Definition: parse_tree.h:2790
unsigned clt_cache_check
Definition: parse_tree.h:3466
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
void pt_init_assignments_helper(PARSER_CONTEXT *parser, PT_ASSIGNMENTS_HELPER *helper, PT_NODE *assignment)
Definition: parse_tree.c:1336
int db_get(DB_OBJECT *object, const char *attpath, DB_VALUE *value)
Definition: db_obj.c:233
int do_prepare_session_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
void ml_ext_free(DB_OBJLIST *list)
Definition: work_space.c:4806
int lang_set_flag_from_lang(const char *lang_str, bool has_user_format, bool has_user_lang, int *flag)
PT_ROLLBACK_WORK_INFO rollback_work
Definition: parse_tree.h:3331
int do_create_serial(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_NODE * search_cond
Definition: parse_tree.h:2063
bool prm_get_bool_value(PARAM_ID prm_id)
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
PT_DROP_TRIGGER_INFO drop_trigger
Definition: parse_tree.h:3290
#define AU_SAVE_AND_DISABLE(save)
Definition: authenticate.h:126
PT_MISC_TYPE list_type
Definition: parse_tree.h:2324
PT_GET_STATS_INFO get_stats
Definition: parse_tree.h:3303
DB_VALUE * db_attribute_default(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1209
static int call_method(PARSER_CONTEXT *parser, PT_NODE *statement)
void er_clear(void)
void obt_disable_unique_checking(OBJ_TEMPLATE *template_ptr)
#define PT_IS_N_COLUMN_UPDATE_EXPR(n)
Definition: parse_tree.h:422
const char * tz_get_session_local_timezone(void)
Definition: tz_support.c:739
MOP vid_build_virtual_mop(MOP bmop, MOP vclass_mop)
unsigned cannot_prepare
Definition: parse_tree.h:3462
PT_DELETE_INFO delete_
Definition: parse_tree.h:3285
int do_evaluate(PARSER_CONTEXT *parser, PT_NODE *statement)
int serial_decache(OID *oid)
XASL_ID * xasl_id
Definition: xasl.h:610
int xts_map_xasl_to_stream(const XASL_NODE *xasl_tree, XASL_STREAM *stream)
int dbt_dput_internal(DB_OTMPL *def, DB_ATTDESC *attribute, DB_VALUE *value)
Definition: db_obj.c:977
#define ER_AUTO_INCREMENT_SERIAL_ALREADY_EXIST
Definition: error_code.h:1143
DB_OBJECT * class_mop
PT_SET_OPT_LVL_INFO set_opt_lvl
Definition: parse_tree.h:3337
void * etc
Definition: parse_tree.h:3450
TR_TRIGGER * tr_map_trigger(DB_OBJECT *object, int fetch)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2067
PT_NODE * error_msgs
Definition: parse_tree.h:3550
void cursor_close(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1381
PT_NODE * timezone_node
Definition: parse_tree.h:2961
char * parser_print_tree(PARSER_CONTEXT *parser, const PT_NODE *node)
static int check_merge_trigger(PT_DO_FUNC *do_func, PARSER_CONTEXT *parser, PT_NODE *statement)
char * buffer
Definition: xasl.h:613
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
PT_NODE * spec
Definition: parse_tree.h:2061
PT_NODE * trigger_spec_list
Definition: parse_tree.h:2616
int heap_has_instance(HFID *hfid, OID *class_oid, int has_visible_instance)
#define MSGCAT_SEMANTIC_SERIAL_MAX_VAL_INVALID
DB_OBJLIST * users
Definition: class_object.h:712
#define ER_PT_UNKNOWN_STATEMENT
int i
Definition: dynamic_load.c:954
PT_VALUE_INFO value
Definition: parse_tree.h:3358
int locator_flush_all_instances(MOP class_mop, bool decache)
Definition: locator_cl.c:5278
int pt_length_of_select_list(PT_NODE *list, int hidden_col)
static PT_NODE * do_replace_names_for_insert_values_pre(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
int db_to_char(const DB_VALUE *src_value, const DB_VALUE *format_or_length, const DB_VALUE *lang_str, DB_VALUE *result_str, const TP_DOMAIN *domain)
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)
unsigned use_plan_cache
Definition: parse_tree.h:3468
DB_TYPE id
#define PT_NODE_ACTION_TIME(node)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
PT_NODE * expression
Definition: parse_tree.h:2161
while(1)
Definition: cnvlex.c:816
DB_OTMPL * dbt_edit_object(MOP object)
Definition: db_obj.c:533
int heap_num_objects
Definition: statistics.h:89
XASL_ID * xasl_id
Definition: parse_tree.h:3454
#define ER_BLOCK_NOWHERE_STMT
Definition: error_code.h:1385
struct tp_domain * next
Definition: object_domain.h:74
int do_update_maxvalue_of_auto_increment_serial(PARSER_CONTEXT *parser, MOP *serial_object, const char *class_name, PT_NODE *att)
#define IS_REJECT_ACTION_STATEMENT(statement)
#define ER_OBJ_MISSING_NON_NULL_ASSIGN
Definition: error_code.h:296
#define SERIAL_ATTR_STARTED
const char * name
Definition: class_object.h:385
DB_TRIGGER_STATUS
Definition: dbtype_def.h:344
int db_get_error(const DB_VALUE *value)
int sm_flush_for_multi_update(MOP class_mop)
#define HA_DISABLED()
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
PT_TRUNCATE_INFO truncate
Definition: parse_tree.h:3351
static int do_prepare_insert_internal(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned print_type_ambiguity
Definition: parse_tree.h:3608
PT_PLAN_TRACE_INFO plan_trace[MAX_NUM_PLAN_TRACE]
Definition: parse_tree.h:3596
int QUERY_FLAG
Definition: query_list.h:585
int do_execute_merge(PARSER_CONTEXT *parser, PT_NODE *statement)
int sql_user_text_len
Definition: parse_tree.h:3445
struct sm_attribute * order_link
Definition: class_object.h:461
unsigned return_generated_keys
Definition: parse_tree.h:3622
char * sysprm_print_parameters_for_ha_repl(void)
int do_alter_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
static void do_set_trace_to_query_flag(QUERY_FLAG *query_flag)
bool do_Trigger_involved
#define PT_NODE_SR_NAME(node)
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_make_timestamp(DB_VALUE *value, const DB_C_TIMESTAMP timeval)
int db_make_int(DB_VALUE *value, const int num)
PT_HINT_ENUM hint
Definition: parse_tree.h:2945
int do_alter_trigger(PARSER_CONTEXT *parser, PT_NODE *statement)
int jsp_alter_stored_procedure(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: jsp_cl.c:598
#define pt_has_error(parser)
Definition: parser.h:507
PT_SAVEPOINT_INFO savepoint
Definition: parse_tree.h:3332
static int update_objs_for_list_file(PARSER_CONTEXT *parser, QFILE_LIST_ID *list_id, PT_NODE *statement, bool savepoint_started)
MOP sm_find_class(const char *name)
const char * alias_print
Definition: parse_tree.h:3455
int do_select_for_ins_upd(PARSER_CONTEXT *parser, PT_NODE *statement)
#define STATS_WITH_SAMPLING
Definition: statistics.h:35
DB_OBJECT * tr_create_trigger(const char *name, DB_TRIGGER_STATUS status, double priority, DB_TRIGGER_EVENT event, DB_OBJECT *class_mop, const char *attribute, DB_TRIGGER_TIME cond_time, const char *cond_source, DB_TRIGGER_TIME action_time, DB_TRIGGER_ACTION action_type, const char *action_source, const char *comment)
void au_change_trigger_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *trigger, DB_VALUE *owner)
int db_make_char(DB_VALUE *value, const int char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
#define OID_ISNULL(oidp)
Definition: oid.h:81
PT_NODE * trigger_spec_list
Definition: parse_tree.h:1842
#define SET_AUTO_INCREMENT_SERIAL_NAME(SR_NAME, CL_NAME, AT_NAME)
Definition: transform.h:176
PT_NODE * entity_name
Definition: parse_tree.h:1750
PT_SET_TRIGGER_INFO set_trigger
Definition: parse_tree.h:3339
int sm_att_unique_constrained(MOP classop, const char *name)
DB_OBJECT * db_find_unique(MOP classmop, const char *attname, DB_VALUE *value)
Definition: db_obj.c:1092
bool log_does_allow_replication(void)
Definition: log_comm.c:270
XASL_NODE * parser_generate_do_stmt_xasl(PARSER_CONTEXT *parser, PT_NODE *node)
PT_TRIGGER_ACTION_INFO trigger_action
Definition: parse_tree.h:3349
PT_NODE * pt_bind_param_node(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
void prm_set_bool_value(PARAM_ID prm_id, bool value)
#define TRAN_ASYNC_WS_BIT
Definition: dbtran_def.h:60
int dbt_set_label(DB_OTMPL *def, DB_VALUE *label)
Definition: db_obj.c:713
#define MSGCAT_SEMANTIC_SERIAL_ALREADY_EXIST
unsigned has_unique
Definition: parse_tree.h:2880
static int is_attr_not_in_insert_list(const PARSER_CONTEXT *parser, PT_NODE *name_list, const char *name)
int numeric_coerce_string_to_num(const char *astring, int astring_length, INTL_CODESET codeset, DB_VALUE *result)
PT_NODE * pt_dbval_to_value(PARSER_CONTEXT *parser, const DB_VALUE *val)
Definition: parse_dbi.c:574
SM_ATTRIBUTE * ordered_attributes
Definition: class_object.h:753
int db_abs_dbval(DB_VALUE *result, DB_VALUE *value)
Definition: arithmetic.c:565
DB_VALUE * default_value
Definition: esql_cli.c:348
DB_TRIGGER_ACTION
Definition: dbtype_def.h:397
PT_SET_SESSION_VARIABLE_INFO set_variables
Definition: parse_tree.h:3340
int tr_check_authorization(DB_OBJECT *trigger_object, int alter_flag)
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)
int column_number
Definition: parse_tree.h:3442
int pt_length_of_list(const PT_NODE *list)
struct parser_node::@132 flag
#define SERIAL_ATTR_ATT_NAME
PT_NODE * entity_name
Definition: parse_tree.h:2130
int pt_find_omitted_default_expr(PARSER_CONTEXT *parser, DB_OBJECT *class_obj, PT_NODE *specified_attrs, PT_NODE **default_expr_attrs)
static CST_ITEM cst_item_tbl[]
PT_NODE * object_parameter
Definition: parse_tree.h:2865
#define DB_CURSOR_END
Definition: dbtype_def.h:167
MOP do_get_serial_obj_id(DB_IDENTIFIER *serial_obj_id, DB_OBJECT *serial_class_mop, const char *serial_name)
int do_prepare_select(PARSER_CONTEXT *parser, PT_NODE *statement)
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
int db_compile_and_execute_local(const char *CSQL_query, void *result, DB_QUERY_ERROR *query_error)
Definition: db_vdb.c:3068
void pt_free_orphans(PARSER_CONTEXT *parser)
struct json_t * json_plan
Definition: parse_tree.h:3523
PT_NODE * pt_to_merge_insert_query(PARSER_CONTEXT *parser, PT_NODE *select_list, PT_MERGE_INFO *info)
static DB_TRIGGER_STATUS convert_misc_to_tr_status(const PT_MISC_TYPE pt_status)
PT_EVENT_SPEC_INFO event_spec
Definition: parse_tree.h:3295
SM_CLASS * class_
void pt_restore_assignment_links(PT_NODE *assigns, PT_NODE **links, int count)
bool cursor_open(CURSOR_ID *cursor_id_p, QFILE_LIST_ID *list_id_p, bool updatable, bool is_oid_included)
Definition: cursor.c:1194
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
int do_set_sys_params(PARSER_CONTEXT *parser, PT_NODE *statement)
int tr_drop_deferred_activities(DB_OBJECT *trigger_object, DB_OBJECT *target)
int do_create_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
bool ws_need_flush(void)
Definition: work_space.c:3813
PT_TIMEOUT_INFO timeout
Definition: parse_tree.h:3348
#define MSGCAT_SEMANTIC_SERIAL_INC_VAL_ZERO
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)
REGU_VARIABLE_LIST valptrp
Definition: regu_var.hpp:116
char * buf
Definition: dbtype_def.h:866
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
PT_NODE * parser_copy_tree_list(PARSER_CONTEXT *parser, PT_NODE *tree)
#define PT_NODE_SR_NO_MIN(node)
#define DB_SERIAL_MAX
static int do_insert_checks(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **class_, PT_NODE **update, PT_NODE *values)
int do_create_entity(PARSER_CONTEXT *parser, PT_NODE *node)
ATTR_STATS * attr_stats
Definition: statistics.h:92
QUERY_ID query_id
Definition: parse_tree.h:3559
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
int do_alter_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
const char ** p
Definition: dynamic_load.c:945
static void init_xasl_stream(XASL_STREAM *stream)
int do_execute_delete(PARSER_CONTEXT *parser, PT_NODE *statement)
void tp_domain_free(TP_DOMAIN *dom)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
int do_create_auto_increment_serial(PARSER_CONTEXT *parser, MOP *serial_object, const char *class_name, PT_NODE *att)
int do_delete(PARSER_CONTEXT *parser, PT_NODE *statement)
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
static int check_for_cons(PARSER_CONTEXT *parser, int *has_unique, PT_NODE **non_null_attrs, const PT_NODE *attr_list, DB_OBJECT *class_obj)
unsigned reexecute
Definition: parse_tree.h:2762
static int do_evaluate_insert_values(PARSER_CONTEXT *parser, PT_NODE *insert_statement)
unsigned int time
Definition: dbtype_def.h:777
#define SERIAL_ATTR_MIN_VAL
PT_NODE * waitsecs_hint
Definition: parse_tree.h:2869
int cvacuum(void)
CLIENT_UPDATE_INFO * next
int cursor_get_tuple_value_list(CURSOR_ID *cursor_id_p, int size, DB_VALUE *value_list_p)
Definition: cursor.c:1778
int tr_execute_deferred_activities(DB_OBJECT *trigger_object, DB_OBJECT *target)
#define PT_NODE_SR_NO_CACHE(node)
#define TM_TRAN_ISOLATION()
const char * rel_major_release_string(void)
DB_ATTDESC * attr_desc
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)
PT_INSERT_VALUE_INFO insert_value
Definition: parse_tree.h:3310
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
DB_VALUE * constant
Definition: xasl.h:253
PT_NODE * derived_table
Definition: parse_tree.h:2134
#define ER_REPLACE_ODKU_NOT_ALLOWED
Definition: error_code.h:1313
PT_NODE * original_node
Definition: parse_tree.h:3227
static XASL_NODE * statement_to_update_xasl(PARSER_CONTEXT *parser, PT_NODE *statement, PT_NODE **non_null_attrs)
FILE * port_open_memstream(char **ptr, size_t *sizeloc)
Definition: porting.c:2198
PT_NODE * save_name
Definition: parse_tree.h:2672
#define ER_QPROC_CANNOT_UPDATE_SERIAL
Definition: error_code.h:969
PT_NODE * search_cond
Definition: parse_tree.h:2862
PT_NODE * range_var
Definition: parse_tree.h:2135
PT_NODE * event_target
Definition: parse_tree.h:2175
int jsp_drop_stored_procedure(PARSER_CONTEXT *parser, PT_NODE *statement)
Definition: jsp_cl.c:451